add relay_mqtt_http_proxy
This commit is contained in:
parent
a03ec71118
commit
1d508814ca
20
doc/relay_mqtt_http_proxy.md
Normal file
20
doc/relay_mqtt_http_proxy.md
Normal file
@ -0,0 +1,20 @@
|
||||
## config example
|
||||
|
||||
```
|
||||
[mqtt]
|
||||
host = "mqtt.solarmon.ru"
|
||||
port = 8883
|
||||
|
||||
client_id = "relay_mqtt_util"
|
||||
username = ""
|
||||
password = ""
|
||||
|
||||
[relay]
|
||||
devices = ['id1', 'id2']
|
||||
|
||||
[server]
|
||||
listen = "0.0.0.0:8821"
|
||||
|
||||
[logging]
|
||||
verbose = false
|
||||
```
|
@ -86,11 +86,13 @@ class MQTTRelay(MQTTBase):
|
||||
except Exception as e:
|
||||
self._logger.exception(str(e))
|
||||
|
||||
def set_power(self, device_id, enable: bool):
|
||||
def set_power(self, device_id, enable: bool, secret=None):
|
||||
device = next(d for d in self._devices if d.id == device_id)
|
||||
assert device.secret is not None, 'device secret not specified'
|
||||
secret = secret if secret else device.secret
|
||||
|
||||
payload = PowerPayload(secret=device.secret,
|
||||
assert secret is not None, 'device secret not specified'
|
||||
|
||||
payload = PowerPayload(secret=secret,
|
||||
state=enable)
|
||||
self._client.publish(f'hk/{device.id}/relay/power',
|
||||
payload=payload.pack(),
|
||||
|
68
src/relay_mqtt_http_proxy.py
Normal file
68
src/relay_mqtt_http_proxy.py
Normal file
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
from home import http
|
||||
from home.config import config
|
||||
from home.mqtt import MQTTRelay, MQTTRelayDevice, MQTTRelayState
|
||||
from home.mqtt.payload import MQTTPayload
|
||||
from home.mqtt.payload.relay import InitialStatPayload, StatPayload
|
||||
from typing import Optional
|
||||
from home.util import parse_addr
|
||||
|
||||
mqtt_relay: Optional[MQTTRelay] = None
|
||||
relay_states: dict[str, MQTTRelayState] = {}
|
||||
|
||||
|
||||
def on_mqtt_message(device_id, message: MQTTPayload):
|
||||
if isinstance(message, InitialStatPayload) or isinstance(message, StatPayload):
|
||||
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):
|
||||
device_id = req.match_info['id']
|
||||
device_secret = req.query['secret']
|
||||
|
||||
if enable is None:
|
||||
if device_id in relay_states and relay_states[device_id].ever_updated:
|
||||
cur_state = relay_states[device_id].enabled
|
||||
else:
|
||||
cur_state = False
|
||||
enable = not cur_state
|
||||
|
||||
mqtt_relay.set_power(device_id, enable, device_secret)
|
||||
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('relay_mqtt_http_proxy')
|
||||
|
||||
mqtt_relay = MQTTRelay(devices=[MQTTRelayDevice(id=device_id) for device_id in config.get('relay.devices')])
|
||||
mqtt_relay.configure_tls()
|
||||
mqtt_relay.set_message_callback(on_mqtt_message)
|
||||
mqtt_relay.connect_and_loop(loop_forever=False)
|
||||
|
||||
proxy = RelayMqttHttpProxy(parse_addr(config.get('server.listen')))
|
||||
try:
|
||||
proxy.run()
|
||||
except KeyboardInterrupt:
|
||||
mqtt_relay.disconnect()
|
||||
|
Loading…
x
Reference in New Issue
Block a user