-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
147 lines (118 loc) · 4.38 KB
/
server.py
File metadata and controls
147 lines (118 loc) · 4.38 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import json
import os
import re
from flask import Flask, render_template, request
from flask_mqtt import Mqtt
from flask_socketio import SocketIO
import jq
from utils import parse_listener_coordinates
app = Flask(__name__)
app.config["MQTT_BROKER_URL"] = "mosquitto.shhm.uk"
# app.config["MQTT_BROKER_URL"] = "broker.hivemq.com"
app.config["MQTT_BROKER_PORT"] = 1883 # default port for non-tls connection
app.config["MQTT_KEEPALIVE"] = (
5 # set the time interval for sending a ping to the broker to 5 seconds
)
app.config["TEMPLATES_AUTO_RELOAD"] = True
mqtt = Mqtt(app)
socketio = SocketIO(app)
# can generate this from boilerplate with something like
# while read -r id; do
# jq -n --arg id "${id}" '{id: $id, topic:"", msgON: "", msgOFF: ""}'
# done <<<$(ls static/icons/ | grep '.NA.' | sed 's+\.NA\.png++') | jq --slurp
with open("listeners.json", "r", encoding="utf-8") as f:
listeners = json.load(f)
listeners = parse_listener_coordinates(listeners)
@app.route("/")
def index():
do_socket = request.args.get("socket", 1) # query param like ?socket=0 to disable
do_socket = False if do_socket in ["0", 0] else True
for listener in listeners:
if listener["topic"] == "":
continue
mqtt.subscribe(listener["topic"])
return render_template(
"index.html",
listeners=listeners,
do_socket=do_socket,
)
@app.route("/listeners")
def getlisteners():
colnames = ["id", "lastState", "topic", "jq", "msgON", "msgOFF"]
for listener in listeners:
for key in listener.keys():
if key not in colnames:
colnames.append(key)
return render_template("table.html", colnames=colnames, records=listeners)
@app.route("/listeners.json")
def getlistenersjson():
return listeners
@mqtt.on_connect()
def handle_connect(client, userdata, flags, rc):
# this doesn't do anything sometimes, see
# https://stackoverflow.com/questions/64592277/flask-mqtt-on-connect-is-never-called-when-used-with-socketio
# mqtt.subscribe("#")
for listener in listeners:
if listener["topic"] == "":
continue
mqtt.subscribe(listener["topic"])
pass
@mqtt.on_message()
def handle_mqtt_message(client, userdata, message):
for listener in listeners:
if message.topic != listener["topic"]:
continue
payload = message.payload.decode()
app.logger.info(
"got message for %s: //%s %s", listener["id"], message.topic, payload
)
if jk := listener.get("jq", ""):
payloadjson = json.loads(payload)
payload = jq.compile(jk).input_value(payloadjson).first()
# convert comparisons to arrays
if not isinstance(listener["msgON"], list):
listener["msgON"] = [listener["msgON"]]
if not isinstance(listener["msgOFF"], list):
listener["msgOFF"] = [listener["msgOFF"]]
if payload in listener["msgON"]:
listener["lastState"] = "on"
socketio.emit("status-update", data=[listener, "on"])
elif payload in listener["msgOFF"]:
listener["lastState"] = "off"
socketio.emit("status-update", data=[listener, "off"])
elif payload is None:
# jq could not find object, message is probably about something else
# ignore and leave previous state active
pass
else:
listener["lastState"] = "NA"
socketio.emit("status-update", data=[listener, "NA"])
save_listener_state()
@mqtt.on_log()
def handle_logging(client, userdata, level, buf):
print(level, buf)
def save_listener_state():
states = []
for listener in listeners:
if ls := listener.get("lastState"):
states.append({"listenerid": listener["id"], "lastState": ls})
with open("history.json", "w", encoding="utf-8") as file:
json.dump(states, file)
def load_listener_state():
with open("history.json", "r", encoding="utf-8") as file:
states = json.load(file)
for state in states:
for listener in listeners:
if listener["id"] == state["listenerid"]:
listener["lastState"] = state["lastState"]
print(listeners)
load_listener_state()
if __name__ == "__main__":
mqtt.init_app(app)
socketio.run(
app,
host="0.0.0.0",
port=5000,
use_reloader=False,
debug=True,
)