diff --git a/rule-listener/rules.py b/rule-listener/rules.py new file mode 100644 index 0000000..0a87709 --- /dev/null +++ b/rule-listener/rules.py @@ -0,0 +1,12 @@ +{ + "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 + } + ] +} diff --git a/rule-listener/script.py b/rule-listener/script.py index bde0b78..cc9926d 100644 --- a/rule-listener/script.py +++ b/rule-listener/script.py @@ -1,40 +1,20 @@ import paho.mqtt.client as mqtt -import sched, time +import asyncio import secrets - -s = sched.scheduler(time.time, time.sleep) +import rules state = {} -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": 3, # after this amount of seconds - "reset": True # and i should reset my count afterwards - }, - { # 30 seconds after the fan has been turned on, turn it off again. - "count": 1, # the amount of times - "state": "on", # it has had this state - "doTopic": "main/fan/11", # i will send to topic - "doMessage": "off", # this message - "delay": 30, # after this amount of seconds - "reset": False # and i should reset my count afterwards - }, - ] -} +mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) def on_connect(client, userdata, flags, reason_code, properties): print(f"Connected with result code {reason_code}") client.subscribe("main/#") - -def publish_later(topic, msg, delay): - print(f"TODO: make this run {delay} seconds later") - # s.enter(delay, 1, publish, kwargs={'topic': topic, 'msg': msg}) - # s.run() + +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) def publish(topic, msg): @@ -47,47 +27,51 @@ 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") + 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"... ... Rule is met when the count is above {rule['count']}. Current count is {state[msg.topic]['count']}") if state[msg.topic]['count'] > rule['count']: - print(f"i matched a rule") if(rule['reset']): state[msg.topic]['count'] = 0 if rule['delay']: - publish_later(rule['doMessage'], rule['doMessage'], rule['delay']) + asyncio.run_coroutine_threadsafe(publish_later(rule['doTopic'], rule['doMessage'], rule['delay']), loop) else: publish(rule['doTopic'], rule['doMessage']) else: - print("i have no rules for this topic") - - print("finished rule checking") - + 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") if msg.retain: return False if msg.topic in state: - print("i already exist") state[msg.topic]["count"] += 1 else: - print("i do not") state[msg.topic] = {} state[msg.topic]["count"] = 0 check_against_rules(msg) +async def main(): + global loop + loop = asyncio.get_running_loop() # Store the main event loop + mqttc.on_connect = on_connect + mqttc.on_message = on_message -mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) -mqttc.on_connect = on_connect -mqttc.on_message = on_message + mqttc.username_pw_set(secrets.mqtt_username, secrets.mqtt_password) + print("connect to klank.school") + mqttc.connect("mqtt.klank.school", 7000, 60) -mqttc.username_pw_set(secrets.mqtt_username, secrets.mqtt_password) + # Start the MQTT loop in a background thread + mqttc.loop_start() -mqttc.connect("mqtt.klank.school", 7000, 60) + # Keep the asyncio event loop running + await asyncio.Event().wait() -mqttc.loop_forever() \ No newline at end of file +# Run the main function +asyncio.run(main()) \ No newline at end of file