something with gestures

This commit is contained in:
vitrinekast 2024-10-28 23:32:02 +01:00
parent 52d7c9e9a1
commit b1c2eedde5
3 changed files with 106 additions and 35 deletions

45
rule-listener/data.py Normal file
View File

@ -0,0 +1,45 @@
rules = {
"main/fan/1": [
{ # after the fan has been on 2 times, another fan should be turned on
"count": 2, # the amount of times
"state": "on", # it has had this state
"doTopic": "main/fan/2", # i will send to topic
"doMessage": "on", # this message
"delay": False, # after this amount of seconds
"reset": True, # and i should reset my count afterwards
},
{ # After the fan is turned off, the next fan should be turned on
"count": 4, # the amount of times
"state": "off", # it has had this state
"doTopic": "main/fan/2", # i will send to topic
"doMessage": "on", # this message
"delay": 4, # after this amount of seconds
"reset": True, # and i should reset my count afterwards
},
{ # Turn the fan off every time after 1 minute
"count": False, # the amount of times. If its false, just do it.
"state": "on", # it has had this state
"doTopic": "main/fan/1", # i will send to topic
"doMessage": "off", # this message
"delay": 4, # after this amount of seconds
"reset": False, # and i should reset my count afterwards
},
{ # Turn the fan on every time after 6 minute
"count": 3, # the amount of times. If its false, just do it.
"state": "on", # it has had this state
"doTopic": "main/fan/1", # i will send to topic
"doMessage": "off", # this message
"delay": 360, # after this amount of seconds
"reset": False, # and i should reset my count afterwards
},
{ # Every 5 minutes, do gesture X
"count": 1,
"state": "on",
"doTopic": "gesture/fan/1",
"doMessage": "on",
"delay": 5 * 60,
"reset": True
}
]
}

View File

@ -1,12 +0,0 @@
{
"main/fan/1": [
{ # after the fan has been on 2 times, another fan should be turned on
"count": 2, # the amount of times
"state": "on", # it has had this state
"doTopic": "main/fan/2", # i will send to topic
"doMessage": "on", # this message
"delay": 3, # after this amount of seconds
"reset": True # and i should reset my count afterwards
}
]
}

View File

@ -1,23 +1,46 @@
import paho.mqtt.client as mqtt
import asyncio
import secrets
import rules
import data
from random import randrange
state = {}
rules = data.rules
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
async def on_gesture_message():
state = False
delay = 3
for i in range(randrange(4,8)):
await asyncio.sleep(delay)
delay = delay * 0.7
if state:
print("do left")
state = False
else:
print("do right")
state = True
print("done")
def on_connect(client, userdata, flags, reason_code, properties):
print(f"Connected with result code {reason_code}")
client.subscribe("main/#")
mqttc.message_callback_add("gesture/#", on_gesture_message)
client.subscribe("gesture/#")
async def publish_later(topic, msg, delay):
print(f"publish_later: Processing message with topic {topic} after {delay} seconds delay")
await asyncio.sleep(delay)
print(f"publish_later: completed delay")
publish(topic, msg)
async def publish_later(rule):
print(f"publish_later: Processing message with doTopic {rule['doTopic']} after {rule['delay']} seconds delay")
await asyncio.sleep(rule['delay'])
del rule['doingDelay']
publish(rule['doTopic'], rule['doMessage'])
def publish(topic, msg):
print(f"publish {topic} {msg}")
result = mqttc.publish(topic, msg)
status = result[0]
@ -27,34 +50,49 @@ def publish(topic, msg):
def check_against_rules(msg):
if msg.topic in rules:
print(f"... ... Found {len(rules[msg.topic])} rules on this topic")
for rule in rules[msg.topic]:
print(f"... ... Rule is met when the count is above {rule['count']}. Current count is {state[msg.topic]['count']}")
print(f"Found {len(rules[msg.topic])} rules on this topic"),
willReset = False
if state[msg.topic]['count'] > rule['count']:
for rule in rules[msg.topic]:
print(f"Rule: when the count is > {rule['count']}. Current = {state[msg.topic]['count'][msg.payload]} on payload {msg.payload}"),
if (state[msg.topic]['count'][msg.payload] >= rule['count'] or rule['count'] == False) and msg.payload == rule['state']:
if(rule['reset']):
state[msg.topic]['count'] = 0
willReset = True
if rule['delay']:
asyncio.run_coroutine_threadsafe(publish_later(rule['doTopic'], rule['doMessage'], rule['delay']), loop)
if not 'doingDelay' in rule:
rule['doingDelay'] = True
asyncio.run_coroutine_threadsafe(publish_later(rule), loop)
else:
print('not scheduling')
else:
publish(rule['doTopic'], rule['doMessage'])
if willReset:
state[msg.topic]['count'][msg.payload] = 0
else:
print("... ... i have no rules for this topic")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print("on_message")
print("on message")
if msg.retain:
return False
if msg.topic in state:
state[msg.topic]["count"] += 1
else:
state[msg.topic] = {}
state[msg.topic]["count"] = 0
check_against_rules(msg)
msg.payload = str(msg.payload.decode("utf-8"))
if len(msg.payload) > 140:
print("way to long of a message, not gonna store that")
return False
if msg.topic not in state:
state[msg.topic] = {'count': {}}
state[msg.topic]['count'].setdefault(msg.payload, 0)
state[msg.topic]['count'][msg.payload] += 1
check_against_rules(msg)
async def main():
global loop
@ -69,7 +107,7 @@ async def main():
# Start the MQTT loop in a background thread
mqttc.loop_start()
# Keep the asyncio event loop running
await asyncio.Event().wait()