Watch state change
This commit is contained in:
parent
cb03c12d16
commit
b9fd9c40ae
@ -1,18 +1,44 @@
|
||||
from .action import Action, Publish, TasmotaShutter
|
||||
import json
|
||||
|
||||
from .scene import Scene
|
||||
from .action import Publish, TasmotaShutter
|
||||
from .watch import Watch
|
||||
|
||||
class Sleep(Scene):
|
||||
|
||||
ON = [
|
||||
Publish('cmnd/tasmota/screen/Screen/POWER').Payload('OFF').Qos(2)\
|
||||
Publish('cmnd/tasmota/screen/Screen/POWER').Payload('OFF').Qos(1)\
|
||||
.CheckResponse('stat/tasmota/screen/Screen/POWER', 'OFF', 3),
|
||||
Publish('cmnd/tasmota/light/LivingroomFireplace/POWER').Payload('OFF').Qos(2),
|
||||
Publish('cmnd/tasmota/light/LivingroomFireplace/POWER').Payload('OFF').Qos(1),
|
||||
|
||||
#Shutter
|
||||
TasmotaShutter('Bedroom1x1').Close(),
|
||||
TasmotaShutter('Bedroom1x2').Close(),
|
||||
TasmotaShutter('Staircase1').Close(),
|
||||
TasmotaShutter('Bathroom').Close(),
|
||||
|
||||
#Chambre
|
||||
Publish('zwave2mqtt/7/67/1/1/set').Payload('17').Qos(1)\
|
||||
.CheckResponse('zwave2mqtt/7/67/1/1', lambda p: json.loads(p)['value'] == 17, 3),
|
||||
#RdC
|
||||
Publish('zwave2mqtt/6/67/1/1/set').Payload('19').Qos(1)\
|
||||
.CheckResponse('zwave2mqtt/6/67/1/1', lambda p: json.loads(p)['value'] == 19, 3),
|
||||
Publish('zwave2mqtt/5/67/1/1/set').Payload('19').Qos(1)\
|
||||
.CheckResponse('zwave2mqtt/5/67/1/1', lambda p: json.loads(p)['value'] == 19, 3),
|
||||
]
|
||||
|
||||
WATCH = [
|
||||
('stat/tasmota/screen/Screen/POWER', 'OFF')
|
||||
#HomeCinema
|
||||
Watch('stat/tasmota/screen/Screen/POWER', 'OFF'),
|
||||
#Lights
|
||||
Watch('stat/tasmota/light/LivingroomFireplace/POWER', 'OFF'),
|
||||
#Shutter
|
||||
Watch('cmnd/tasmota/shutter/Bedroom1x1/ShutterOpen'),
|
||||
Watch('cmnd/tasmota/shutter/Bedroom1x2/ShutterOpen'),
|
||||
Watch('cmnd/tasmota/shutter/Staircase1/ShutterOpen'),
|
||||
Watch('cmnd/tasmota/shutter/Bathroom/ShutterOpen'),
|
||||
#Thermostat
|
||||
Watch('zwave2mqtt/7/67/1/1', lambda p: json.loads(p)['value'] == 17),
|
||||
Watch('zwave2mqtt/6/67/1/1', lambda p: json.loads(p)['value'] == 19),
|
||||
Watch('zwave2mqtt/5/67/1/1', lambda p: json.loads(p)['value'] == 19),
|
||||
]
|
||||
|
@ -8,10 +8,10 @@ from citadel.mqtt import Configuration
|
||||
from . import Sleep
|
||||
|
||||
def main(\
|
||||
mqtt_user: str = typer.Option(... , envvar="DEVICES_MQTT_USER"),\
|
||||
mqtt_pwd: str = typer.Option(... , envvar="DEVICES_MQTT_PWD"),\
|
||||
mqtt_host: str = typer.Option(... , envvar="DEVICES_MQTT_HOST"),\
|
||||
mqtt_port: int = typer.Option(... , envvar="DEVICES_MQTT_PORT"),\
|
||||
mqtt_user: str = typer.Option(... , envvar="SCENE_MQTT_USER"),\
|
||||
mqtt_pwd: str = typer.Option(... , envvar="SCENE_MQTT_PWD"),\
|
||||
mqtt_host: str = typer.Option(... , envvar="SCENE_MQTT_HOST"),\
|
||||
mqtt_port: int = typer.Option(... , envvar="SCENE_MQTT_PORT"),\
|
||||
is_systemd: bool = typer.Option(False, help="Is running as systemd unit", envvar="LAUNCHED_BY_SYSTEMD")\
|
||||
):
|
||||
|
||||
|
@ -10,6 +10,7 @@ import paho.mqtt.client as mqtt
|
||||
from citadel.mqtt import Configuration
|
||||
|
||||
from .action import Action
|
||||
from .watch import Watch
|
||||
|
||||
class Scene(threading.Thread, mqtt.Client):
|
||||
""" A scene run as a thread, has his own mqtt session
|
||||
@ -47,6 +48,7 @@ class Scene(threading.Thread, mqtt.Client):
|
||||
logger = logging.getLogger('scene.%s' % self.mqtt_name)
|
||||
self.logger = logger
|
||||
|
||||
# we need a queue for publishing message from different thread
|
||||
self.__pub_queue = queue.Queue()
|
||||
self.__state = Scene.STATE_DEACTIVATE
|
||||
|
||||
@ -66,13 +68,10 @@ class Scene(threading.Thread, mqtt.Client):
|
||||
self.subscribe(self.TOPIC_CMND.format(mqtt_name=self.mqtt_name), 2)
|
||||
|
||||
for watch in self.WATCH:
|
||||
self.subscribe(watch[0], 1)
|
||||
self.subscribe(watch.topic, 1)
|
||||
|
||||
run = True
|
||||
while run:
|
||||
#Mqtt client loop
|
||||
self.loop()
|
||||
|
||||
#Check publish queue
|
||||
try:
|
||||
(args, kwargs) = self.__pub_queue.get(block=False)
|
||||
@ -104,20 +103,23 @@ class Scene(threading.Thread, mqtt.Client):
|
||||
self.__state = Scene.STATE_ACTIVATE
|
||||
self.__send_state()
|
||||
|
||||
#Mqtt client loop
|
||||
self.loop()
|
||||
|
||||
|
||||
def threaded_publish(self, *args, **kwargs):
|
||||
self.__pub_queue.put((args, kwargs))
|
||||
|
||||
def on_message(self, mqttc, obj, msg):
|
||||
payload = msg.payload.decode().lower()
|
||||
payload = msg.payload.decode()
|
||||
topic = msg.topic
|
||||
|
||||
# on CMND
|
||||
if topic == self.TOPIC_CMND.format(mqtt_name=self.mqtt_name):
|
||||
if payload == 'on':
|
||||
if payload.lower() == 'on':
|
||||
self.logger.info('CMND activate ON')
|
||||
self.__activate()
|
||||
elif payload == 'off':
|
||||
elif payload.lower() == 'off':
|
||||
self.logger.info('CMND activate OFF')
|
||||
self.__deactivate()
|
||||
elif payload == '':
|
||||
@ -126,18 +128,12 @@ class Scene(threading.Thread, mqtt.Client):
|
||||
else:
|
||||
self.logger.warn('CMND activate invalide')
|
||||
|
||||
elif self.scene_state and self.__check_watched(topic, payload):
|
||||
elif self.scene_state == Scene.STATE_ACTIVATE:
|
||||
for watch in self.WATCH:
|
||||
if topic == watch.topic and not watch.check(topic, payload):
|
||||
self.logger.info('Watched topic %s with invalid payload %s deactivating', topic, payload)
|
||||
self.__deactivate()
|
||||
|
||||
def __check_watched(self, topic, payload):
|
||||
""" return True if is a watched topic with an invalid payload """
|
||||
for watch in self.WATCH:
|
||||
if topic == watch[0]:
|
||||
if payload != watch[1].lower():
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
break
|
||||
|
||||
def __activate(self):
|
||||
if self.scene_state:
|
||||
|
23
src/citadel/scene/watch.py
Normal file
23
src/citadel/scene/watch.py
Normal file
@ -0,0 +1,23 @@
|
||||
from typing import Union, Callable
|
||||
|
||||
class Watch(object):
|
||||
|
||||
def __init__(self, topic: str, payload: Union[str, Callable[[str],bool]] = None):
|
||||
self.__topic = topic
|
||||
|
||||
if callable(payload):
|
||||
self.__check_payload = payload
|
||||
elif payload == None:
|
||||
self.__check_payload = lambda _: False
|
||||
else:
|
||||
self.__check_payload = lambda x: x == payload
|
||||
|
||||
@property
|
||||
def topic(self) -> str:
|
||||
return self.__topic
|
||||
|
||||
def check(self, topic: str, payload: str) -> bool:
|
||||
if topic == self.topic and self.__check_payload(payload):
|
||||
return True
|
||||
else:
|
||||
return False
|
Loading…
x
Reference in New Issue
Block a user