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
|
#!/usr/bin/env python3
from home import http
from home.config import config
from home.mqtt import MqttPayload, MqttWrapper, MqttNode, MqttModule
from home.mqtt.module.relay import MqttRelayState, MqttRelayModule
from home.mqtt.module.diagnostics import InitialDiagnosticsPayload, DiagnosticsPayload
from typing import Optional, Union
mqtt: Optional[MqttWrapper] = None
mqtt_nodes: dict[str, MqttNode] = {}
relay_modules: dict[str, Union[MqttRelayModule, MqttModule]] = {}
relay_states: dict[str, MqttRelayState] = {}
def on_mqtt_message(node: MqttNode,
message: MqttPayload):
if isinstance(message, InitialDiagnosticsPayload) or isinstance(message, DiagnosticsPayload):
kwargs = dict(rssi=message.rssi, enabled=message.flags.state)
if device_id not in relay_states:
relay_states[device_id] = MqttRelayState()
relay_states[device_id].update(**kwargs)
class RelayMqttHttpProxy(http.HTTPServer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.get('/relay/{id}/on', self.relay_on)
self.get('/relay/{id}/off', self.relay_off)
self.get('/relay/{id}/toggle', self.relay_toggle)
async def _relay_on_off(self,
enable: Optional[bool],
req: http.Request):
node_id = req.match_info['id']
node_secret = req.query['secret']
node = mqtt_nodes[node_id]
relay_module = relay_modules[node_id]
if enable is None:
if node_id in relay_states and relay_states[node_id].ever_updated:
cur_state = relay_states[node_id].enabled
else:
cur_state = False
enable = not cur_state
if not node.secret:
node.secret = node_secret
relay_module.switchpower(enable)
return self.ok()
async def relay_on(self, req: http.Request):
return await self._relay_on_off(True, req)
async def relay_off(self, req: http.Request):
return await self._relay_on_off(False, req)
async def relay_toggle(self, req: http.Request):
return await self._relay_on_off(None, req)
if __name__ == '__main__':
config.load_app('relay_mqtt_http_proxy')
mqtt = MqttWrapper()
for device_id, data in config['relays'].items():
mqtt_node = MqttNode(node_id=device_id)
relay_modules[device_id] = mqtt_node.load_module('relay')
mqtt_nodes[device_id] = mqtt_node
mqtt_node.add_payload_callback(on_mqtt_message)
mqtt.add_node(mqtt_node)
mqtt_node.add_payload_callback(on_mqtt_message)
mqtt.configure_tls()
mqtt.connect_and_loop(loop_forever=False)
proxy = RelayMqttHttpProxy(config.get_addr('server.listen'))
try:
proxy.run()
except KeyboardInterrupt:
mqtt.disconnect()
|