-
Notifications
You must be signed in to change notification settings - Fork 0
/
alarm.py
129 lines (105 loc) · 3.26 KB
/
alarm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# author: [email protected]
#
# Make sure your gevent version is >= 1.0
import gevent
from gevent.pywsgi import WSGIServer
from gevent.queue import Queue
from flask import Flask, Response
from flask import render_template
import Envisalink
from AlarmServerConfig import AlarmServerConfig
import argparse
import json
import logging
import time
logger = logging.getLogger('alarmserver')
logger.setLevel(logging.DEBUG)
# Console handler
# Prints all messages (debug level)
ch = logging.StreamHandler();
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter(
fmt='%(asctime)s %(name)s %(levelname)s: %(message)s',
datefmt='%b %d %H:%M:%S')
ch.setFormatter(formatter);
# add handlers to logger
logger.addHandler(ch)
# globals
ENVISALINKCLIENT = None
CONNECTEDCLIENTS={}
# SSE "protocol" is described here: http://mzl.la/UPFyxY
class ServerSentEvent(object):
def __init__(self, data):
self.data = data
self.event = None
self.id = None
self.desc_map = {
self.data : "data",
self.event : "event",
self.id : "id"
}
def encode(self):
if not self.data:
return ""
lines = ["%s: %s" % (v, k)
for k, v in self.desc_map.iteritems() if k]
return "%s\n\n" % "\n".join(lines)
app = Flask(__name__)
subscriptions = []
# Client code consumes like this.
@app.route("/")
def index():
return render_template('index.htm')
@app.route("/debug")
def debug():
return "Currently %d subscriptions" % len(subscriptions)
def publish():
# spin forever
while True:
msg = str(time.time())
for sub in subscriptions[:]:
sub.put(json.dumps(ENVISALINKCLIENT._alarmstate))
gevent.sleep(1)
@app.route("/subscribe")
def subscribe():
def gen():
q = Queue()
subscriptions.append(q)
try:
while True:
result = q.get()
ev = ServerSentEvent(str(result))
yield ev.encode()
except GeneratorExit: # Or maybe use flask signals
subscriptions.remove(q)
return Response(gen(), mimetype="text/event-stream")
@app.route("/api")
def api():
return Response(json.dumps(ENVISALINKCLIENT._alarmstate))
@app.route("/api/refresh")
def refresh():
ENVISALINKCLIENT.send_command('001', '')
return Response(json.dumps({'response' : 'Request to refresh data received'}))
def main():
global ENVISALINKCLIENT
parser = argparse.ArgumentParser('Flask powered Alarm Server')
parser.add_argument('config', help='Configurationf file', default='')
args = parser.parse_args()
logger.info('Using configuration file %s' % args.config)
config = AlarmServerConfig(args.config)
# Create Envisalink client object
ENVISALINKCLIENT = Envisalink.Client(config, CONNECTEDCLIENTS)
gevent.spawn(ENVISALINKCLIENT.connect)
app.debug = True
server = WSGIServer(("", 5000), app, keyfile=config.KEYFILE, certfile=config.CERTFILE)
gevent.spawn(publish)
try:
server.serve_forever()
except KeyboardInterrupt:
print "Crtl+C pressed. Shutting down."
logger.info('Shutting down from Ctrl+C')
server.stop()
raise SystemExit
if __name__ == "__main__":
main()