Help with mqtt garage door logic

#1

I am fairly new to node-red but have had a lot of success with it so far with thermostats, thermometers and my esp8266/mqtt garage door controller.

I want to implement in NR this logic: "At 9pm every night, if the garage door is open, close it and email me that I forgot".

I would like to try to do this using native NR components as much as possible, and avoiding use of Flow or Globabl context memory.

If I was writing this using a RESTful api for my opener/controller, it would look simply something like this:

// 9pm triggered through a scheduler
  if ( get_garage_door_state() == OPEN )
     set_garage_door_state( CLOSED)

Below is what I have so far, trying to use a Trigger node. It works at 9pm but the problem is since I also receive state messages from the controller at various times throughoutt the rest of the day and it re-closes the door throughout the day :slight_smile:

I have a couple' ideas but they get pretty messy so I wonder if there is a style or approach that I am overlooking. Thoughts?

First time to try this export function so I hope this works:

[{"id":"b2e3b511.840318","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"3e7ab128.7e8ce6","type":"trigger","z":"b2e3b511.840318","op1":"","op2":"close","op1type":"nul","op2type":"str","duration":"10","extend":false,"units":"s","reset":"close","bytopic":"all","name":"If door is not closed within 10 seconds","x":494,"y":211,"wires":[["1578fa93.951035","bac45e27.c94a88"]]},{"id":"19e8bf8.f2bc7c1","type":"inject","z":"b2e3b511.840318","name":"Every night at 9pm","topic":"","payload":"query","payloadType":"str","repeat":"","crontab":"00 21 * * *","once":false,"onceDelay":0.1,"x":153,"y":127,"wires":[["315a43e7.84109c","3e7ab128.7e8ce6"]]},{"id":"315a43e7.84109c","type":"mqtt out","z":"b2e3b511.840318","name":"MQTT request the door state","topic":"pv/garage/door/cmd","qos":"","retain":"","broker":"bbd15021.27a95","x":471,"y":128,"wires":[]},{"id":"35235003.de4628","type":"mqtt in","z":"b2e3b511.840318","name":"MQTT door state open or closed","topic":"pv/garage/door/state","qos":"0","broker":"bbd15021.27a95","x":142,"y":210,"wires":[["3e7ab128.7e8ce6"]]},{"id":"cf2cffe6.ccbd88","type":"comment","z":"b2e3b511.840318","name":"Every night close the garage door if left open","info":"door controller mqtt is\n\nemits:\n- pv/garage/door/state open\n- pv/garage/door/state close\n\nresponds to commands:\n- pv/garage/door/cmd  open\n- pv/garage/door/cmd  close\n- pv/garage/door/cmd  query\n\n\n","x":191,"y":38,"wires":[]},{"id":"1578fa93.951035","type":"debug","z":"b2e3b511.840318","name":"MQTT close the door (simulated)","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":868,"y":212,"wires":[]},{"id":"bac45e27.c94a88","type":"debug","z":"b2e3b511.840318","name":"Email me \"You Forgot!\" (simulated)","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":870,"y":283,"wires":[]},{"id":"bbd15021.27a95","type":"mqtt-broker","z":"","name":"Clopi MqBroker","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

The garage controller message api is listed in the comment. I think I could enhance that api with "you-should-be-closed-now" command with a "but-I-wasnt-closed" message in response, but for now I am trying to learn some specific NR lessons here.

Thanks!
John

0 Likes

#2

I hope you are planning on something to check that a car - or something else - isn't parked half-in and half-out of the garage. I'd hate to hear that the door closed at 9:00 PM on your car damaging both the car and the door....

2 Likes

#3

Flow and Global context are very friendly and useful, why don't you want to use them?

2 Likes

#4

Well, this seems to be your problem I think. Why are state messages throughout the day impacting an action that only takes place at 9pm?

I would think that all you need is a very simple flow:

trigger at 9pm -> send door close

No need to worry if it is open or not unless the door close api would damage the mechanism if re-triggered. It is the API, or better, the actual door controller, that should do the closed check if the mechanism needs it.

If that isn't an option, then you NEED to maintain state in Node-RED. This is not good practice since it is too easy for state to get out of step with reality. However, if you have to then you should use a global or flow variable, possibly with the new retention feature in case NR has to restart.

0 Likes

#5

I think automatically closing a garage door is fraught with potential peril as has been mentioned. While "modern" garage door openers have a photo sensor that prevents the door from closing (or reverses it if something breaks the beam on the way down) relying on these for safety is not recommended.

I'd suggest doing like I've done and let MQTT messages trigger Email/SMS messages to you as required. I have sensors that tell me when the house is locked via MQTT. If the garage door is open two minutes after locking, an SMS is sent and an audio alert is spoken using espeak-ng so we get notified before we get very far away or start doing other things around the house.

What is special about 9PM? I want my garage door closed all the time that I don't specifically want it open, so a timed schedule is of no use at all. Any time the house is locked I want the garage door closed after a delay to let use leave, so if the house is locked and the garage door is open its a "fault" condition I want to be notified about. I also have an indicator light triggered by MQTT that is on if the garage door is open as sometimes, particularly after grocery shopping, we'll leave the door open without locking up the house as we will be in and out the rest of the day. The grab and run thieves are active 24/7 around here :frowning:

IMHO function nodes and using context memory are the preferred way to do state machine logic in node-red.

1 Like

#6

I prefer MQTT retained variables for system state, then they are both maintained over a reset, but also accessible to all the devices in the system if required.

2 Likes

#7

Actually now that you mention it, I do make use of retained MQTT variables, but I guess my MQTT-fu might be a little weak as I'm not clear as to the order the variables would be reported on a reconnect, so it seemed easier and "safer" for me to use context in a function node with the variables as inputs to do state machine sequence type outputs (which usually end up as another MQTT message in my setup :slight_smile:

0 Likes

#8

I don't think the order is defined, so it could be anything, but as long as your flows are designed so they wait till they have values for everything they need before doing anything then shouldn't matter. I haven't found that to be an issue as far as I remember.

1 Like

#9

Good Morning,
I use one single javascript object for such things. In runtime I update variables and their statuses in the object and when changed, using a RBE node to check, I send it to the broker with the retention flag set. At startup, the flow gets the object and then I set all variables to their states, no problem in what order they arrive, I have them always "in the same order" so to say

Edit: forgot to mention, to avoid an "unnecessary updating of variables" when the object is sent to the broker and then received via the subscription to the same, I use a RBE node also when receiving the object from the broker. No reason to update variables if they are unchanged

Once I played with sending rather large chart data for the dashboard to the broker in this way, allowing restoring of charts at restarts, but the poor Pi3 got a bit sluggish after a while

0 Likes