1
1
"""
2
2
Doorlockd -- Binary Kitchen's smart door opener
3
3
4
- Copyright (c) Binary Kitchen e.V., 2018
4
+ Copyright (c) Binary Kitchen e.V., 2020
5
5
6
6
Author:
7
7
Ralf Ramsauer <ralf@binary-kitchen.de>
16
16
"""
17
17
18
18
import logging
19
+ import json
20
+ import threading
19
21
20
- from flask import abort , Flask , jsonify , render_template , request
21
- from flask_socketio import SocketIO
22
+ from flask import abort , Flask , jsonify , render_template , request , Response
22
23
from flask_wtf import FlaskForm
23
24
from wtforms import PasswordField , StringField , SubmitField
24
25
from wtforms .validators import DataRequired , Length
28
29
from .Authenticator import AuthMethod
29
30
30
31
log = logging .getLogger ()
31
-
32
32
webapp = Flask (__name__ )
33
- socketio = SocketIO (webapp , async_mode = 'threading' )
33
+ evt = threading .Event ()
34
+ json_push_state = ""
34
35
35
36
36
37
def emit_doorstate (response = None ):
37
- state = logic .state
38
+ global json_push_state
39
+
38
40
if response :
39
41
message = str (response )
40
42
else :
41
- message = str (state )
42
- socketio .emit ('status' , {'led' : state .to_img (), 'message' : message })
43
-
43
+ message = str (logic .state )
44
+
45
+ json_push_state = json .dumps ({
46
+ 'message' : message ,
47
+ 'img' : logic .state .to_img ()})
48
+
49
+ #Notify push clients
50
+ evt .set ()
51
+ evt .clear ()
52
+
53
+ def event_str ():
54
+ return "data: {}\n \n " .format (json_push_state )
55
+
56
+ def push_state ():
57
+ def event_str ():
58
+ return "data: {}\n \n " .format (json_push_state )
59
+
60
+ try :
61
+ yield event_str ()
62
+ while True :
63
+ evt .wait ()
64
+ yield event_str ()
65
+ except GeneratorExit :
66
+ return
44
67
45
68
class AuthenticationForm (FlaskForm ):
46
69
username = StringField ('Username' , [Length (min = 3 , max = 25 )])
@@ -64,33 +87,34 @@ def validate(self):
64
87
65
88
return True
66
89
67
-
68
- @socketio .on ('request_status' )
69
- @socketio .on ('connect' )
70
- def on_connect ():
71
- emit_doorstate ()
72
-
73
-
74
90
@webapp .route ('/display' )
75
91
def display ():
76
92
return render_template ('display.html' ,
77
93
room = room ,
78
94
title = title ,
79
95
welcome = welcome )
80
96
97
+ @webapp .route ('/push' )
98
+ def push ():
99
+ emit_doorstate ()
100
+ resp = Response (push_state (),mimetype = "text/event-stream" )
101
+ resp .headers ['X-Accel-Buffering' ] = 'no'
102
+ resp .headers ['Cache-Control' ] = 'no-cache'
103
+ return resp
104
+
81
105
82
106
@webapp .route ('/api' , methods = ['POST' ])
83
107
def api ():
84
108
def json_response (response , msg = None ):
85
- json = dict ()
86
- json ['err' ] = response .value
87
- json ['msg' ] = str (response ) if msg is None else msg
109
+ json_dict = dict ()
110
+ json_dict ['err' ] = response .value
111
+ json_dict ['msg' ] = str (response ) if msg is None else msg
88
112
if response == DoorlockResponse .Success or \
89
113
response == DoorlockResponse .AlreadyActive :
90
114
# TBD: Remove 'open'. No more users. Still used in App Version 2.1.1!
91
- json ['open' ] = logic .state .is_open ()
92
- json ['status' ] = logic .state .value
93
- return jsonify (json )
115
+ json_dict ['open' ] = logic .state .is_open ()
116
+ json_dict ['status' ] = logic .state .value
117
+ return jsonify (json_dict )
94
118
95
119
user = request .form .get ('user' )
96
120
password = request .form .get ('pass' )
@@ -137,6 +161,7 @@ def home():
137
161
desired_state = authentication_form .desired_state
138
162
log .info (' desired state: %s' % desired_state )
139
163
log .info (' current state: %s' % logic .state )
164
+
140
165
response = logic .request (desired_state , credentials )
141
166
log .info (' response: %s' % response )
142
167
@@ -154,7 +179,7 @@ def home():
154
179
def webapp_run (cfg , my_logic , status , version , template_folder , static_folder ):
155
180
global logic
156
181
logic = my_logic
157
-
182
+
158
183
debug = cfg .boolean ('DEBUG' )
159
184
160
185
host = 'localhost'
@@ -176,4 +201,5 @@ def webapp_run(cfg, my_logic, status, version, template_folder, static_folder):
176
201
webapp .config ['SECRET_KEY' ] = cfg .str ('SECRET_KEY' )
177
202
webapp .template_folder = template_folder
178
203
webapp .static_folder = static_folder
179
- socketio .run (webapp , host = host , port = 8080 , use_reloader = False , debug = debug )
204
+ webapp .debug = debug
205
+ webapp .run (host = host , port = 8080 )
0 commit comments