Tuesday, October 18, 2022

(#44) It's all about the weather this time

Let's make this one short. 

We're still pumping data from legacy sensors into Home Assistant. This time it's data from the two weather stations here.  The long-employed LaCrosse WS2308. Jeez this thing has to be over ten years old by now.  And a newer Acurite 5n1 station.

Both systems use the 433MHz spectrum to send data from their outside sensors to their base stations. Both 433MHz protocols are recognized and decoded by the "rtl_433" open source software.

Rtl_433 can output the intercepted data as JSON payloads which, in turn, can be pumped right into our MQTT (mosquitto) broker.


Those JSON payloads aren't immediately edible by Home Assistant. 

Or, if they are, they require an expertise in programming Home Assistant, that I don't have. So, I've stuck something in the middle.

Something easy. 

Something that subscribes to the RTL JSON payloads and republishes out new JSON payloads in the MQTT Device Discovery Format that Home Assistant understands.

A lesson learned from the previous success was to treat each sensor separately. The Acurite 5n1 sends over: temperature, humidity, wind speed, wind direction and rain totals.  

That's five separate sensors, five different MQTT Device Discovery Configuration Messages.

MQTT Data Payloads

The Acurite 5n1 sends this sensor data across two different JSON payloads via rtl_433. We break out the data to five sensors. It's similar for the WS2308 station (which is labeled as WS2310 by rtl_433). The sensor data for four sensors are scattered across three MQTT messages.

Here's the rtl_433 output for the WS2308 (aka WS2310) station:

{"time" : "2022-10-18T13:47:05", "protocol" : 34, "model" : "LaCrosse-WS2310", "id" : 28, "humidity" : 35, "mod" : "ASK", "freq" : 434.020, "rssi" : -6.215, "snr" : 31.158, "noise" : -37.373}

{"time" : "2022-10-18T13:47:05", "protocol" : 34, "model" : "LaCrosse-WS2310", "id" : 28, "wind_avg_m_s" : 0.000, "wind_dir_deg" : 22.500, "mod" : "ASK", "freq" : 434.019, "rssi" : -6.265, "snr" : 31.108, "noise" : -37.373}

{"time" : "2022-10-18T13:47:06", "protocol" : 34, "model" : "LaCrosse-WS2310", "id" : 28, "temperature_F" : 65.480, "mod" : "ASK", "freq" : 434.020, "rssi" : -6.238, "snr" : 29.886, "noise" : -36.124}

MQTT Device Discovery Configuration Messages

And here's a code snippet to create the configuration MQTT topic and message.



For each station, create the configuration messages for each sensor in that station.

Forward Station Data to Home Assistant

With the configuration messages created and sent to Home Assistant, now just forward the data packets from the weather stations to the new topics specificed in the configuration messages:

Topic: 

home/LaCrosse-WS2310-28/temperature 

Payload:

{"time" : "2022-10-18T14:53:17", "protocol" : 34, "model" : "LaCrosse-WS2310", "id" : 28, "temperature_F" : 66.200, "mod" : "ASK", "freq" : 434.020, "rssi" : -6.537, "snr" : 29.587, "noise" : -36.124}

And don't forget the state message.

Topic:

home/LaCrosse-WS2310-28/state 

Payload: 

{"state":"online"}


The sensors now all show up in Home Assistant!






Tuesday, October 4, 2022

(#43) Home Assistant Legacy Sensors - Part 3

It's working. Mostly.


With success from hooking the Tuya Air Quality Monitor (non-Zigbee) WiFi up to Home Assistant using the MQTT Device Discovery Protocol, it was not a lot of work to get the Eaton Home Heartbeat (HHB) sensors added.

As mentioned before, the HHB sensors are Zigbee based but I'm unable to quickly see how to unpair them from the Eaton base station and see if they'll re-pair to my Sonoff Zigbee dongle.

So, since the code that reads the HHB sensor data by polling the base station has been up and running for eight years, I made the decision to just add in the MQTT packets to support MQTT Device Discovery. And see if the sensors will appear in Home Assistant.

For the impatient, yes it works. The HHB sensors are now showing up in Home Assistant. The HHB Open/Close sensors, the Tilt Sensor, the Power Sensor, the Wet/Dry Sensor and the Motion sensors all are reporting their status in Home Assistant.


The only downside that I've discovered so far is the lag between a change in a sensor's status and when Home Assistant reflects the state change. That's because the old HHB code polls the gateway for sensor status changes.  So there's a couple of seconds of delay between a state change and the UI reflecting the state change.

No biggie. I can live with that.

Implementation - Summarized

The details are irrelevant; they're specific to my original code from 2013. And you can't buy these sensors anymore.

Nonetheless, for the curious, here's a brief summary:

- original code 'discovered' all of the HHB sensors at startup, by polling the gateway

- new Home Assistant (HA) code, added a call to "HA_CreateConfigurationMessage( HHB_Device )" as each sensor was discovered

Configuration messages were type "binary sensor". Here's the one for the HHB Open/Close Sensor:

 const   char *configTemplate_OpenCloseSensor = 
        "{\"availability\":[{\"topic\":\"%s\",\"value_template\":\"{{ value_json.state }}\"}],"       
        "\"device\":{\"identifiers\": [ \"%s\"],"                                                     
        "\"manufacturer\":\"Eaton\",\"model\":\"HHB OpenClose\",\"name\":\"%s\",\"via_device\": \"HHB\" },"  
        "\"device_class\":\"door\",\"enabled_by_default\":true,\"expire_after\" : 3600,\"force_update\" : true," 
        "\"name\":\"%s [%s] OpenClose\","               
        "\"state_topic\":\"HHB/%s\","                   
        "\"unique_id\":\"%s_OpenClose\","           
        "\"payload_on\":\"OPEN\", \"payload_off\":\"CLOSED\","   
        "\"value_template\":\"{{ value_json.state }}\"}";

The "%s" string substitutions were the MAC address for each sensor.

And then published to an MQTT Topic like:

homeassistant/binary_sensor/%s/config

Again, where the subsitution was the device MAC address.

Most of the sensors (all but the Power Sensor) also had a battery configuration message sent.
// The Eaton HHB battery levels are binary - either OK or not
    const   char *configTemplate_Battery = 
        "{\"availability\":[{\"topic\":\"%s\",\"value_template\":\"{{ value_json.state }}\"}],"       
        "\"device\":{\"identifiers\": [ \"%s\"],"                                                     
        "\"manufacturer\":\"Eaton\",\"model\":\"HHB OpenClose\",\"name\":\"%s\",\"via_device\": \"HHB\" },"  
        "\"device_class\":\"battery\",\"enabled_by_default\":true,\"expire_after\" : 3600,\"force_update\" : true," 
        "\"name\":\"%s [%s] Battery\","               
        "\"state_topic\":\"HHB/%s\","                   
        "\"unique_id\":\"%s_Battery\","           
        "\"payload_on\":\"LOW BATTERY\", \"payload_off\":\"BATTERY OK\","   
        "\"value_template\":\"{{ value_json.battery }}\"}";


To a topic of:

homeassistant/binary_sensor/%s/battery/config

That took care of telling Home Assistant to expect new sensors. Then it was a small addition to publish the unchanged data payload to a new MQTT topic.

Data Payloads still look like:

{"topic" : "HHB/STATUS",  "dateTime" : "2022-10-04T13:37:31-0600" , "deviceType" : 23 , "type" : "MOTION SENSOR" , "name" : "Dining Room Motion" , "state" : "MOTION" , "duration" : 60 , "setAlarmAction" : "ALARM ON MOTION" , "unsetAlarmAction" : "NO ALARM ON NO MOTION" , "setCallAction" : "DO NOT CALL ON MOTION" , "unsetCallAction" : "CALL ON NO MOTION" , "online" : "ONLINE" , "battery" : "BATTERY OK" , "triggered" : "TRIGGERED" , "MACAddress" : "0000093BF5" }

And published to a topic like:

HHB/0000093BF5 


There's a new payload to indicate sensor state. I think I could have told HA to parse state from the existing payload, but since this approach worked for the Tuya sensor, I just added it here.

{"state":"online"}

HHB/0000093BF5/STATE 


And that's about it. Like I said - the original code is from 2013 and updated a personal web page. So that's unique to me. And you can't buy these HHB sensors any more.  There's no sense going into more detail.

It's working.

I salvaged the existing sensors and have them integrated with Home Assistant. 




That's good enough for me, for today.





Tuesday, September 27, 2022

(#42) Home Assistant Legacy Sensors - continued

Legacy Sensors - Configuration - Part 2

Home Assistant MQTT Device Discovery


With the MQTT Configuration topics figured out, now it's on to the message payloads. I'll have six configuration payloads to craft for Home Assistant MQTT Device Discovery to work.


There are six sensors in the Tuya Air Quality Monitor, that means six configuration messages to the six MQTT topics created in Part 1.


The unique device ID we created in Part 1 is part of these payloads.  

Something else to decide now is the MQTT topic and JSON payload for the sensor data. When those sensors send their data to the broker, what MQTT topic will they use? What will their data payload format be?

In my case, my Tuya Air Quality Monitor Sensors will publish their values on MQTT topic:

home/eb0b-5a81

And the sensor data payload will look like: 

{"topic": "home/eb0b-5a81", "dateTime": "2022-09-27T15:45:43", "version": "1.0", "state": "online", "temperature": 25.2, "humidity": 38.8, "PM25": 3, "CH2O": 0.002, "VOC": 0.008, "CO2": 359}

Note - the sensor data comes in as a single JSON message to a single MQTT topic.

Configuration Payloads

The documentation for a Sensor Configuration payload is outlined here. Recall that our device ID is "eb0b-05a81"

Each of the six Tuya Air Quality Monitor configuration message carries a payload similar to:

   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version" : "?",
      "via_device": "python"
   },
   "device_class":"volatile_organic_compounds",
   "enabled_by_default":true,
   "expire_after" : 3600,
   "force_update" : true,
   "name":"AirQuality/A volatile organic compounds",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unique_id":"eb0b-05a81_volatile_organic_compounds",
   "unit_of_measurement":"ppm",
   "value_template":"{{ value_json.VOC}}"
}

Let's go through the major sections. I'm sure there's a few different ways to do this, but here's what I did.

Availability

Availability - in this section I tell Home Assistant that the state of this sensor, online or off, will come in a message posted to "home/eb0b-05a81/state". And the state value will be in the JSON payload "state". 

Here's my online payload: { "state":"online" }

And my offline payload: { "state":"offline" }

Note! The topics embedded in these messages do NOT start with "homeassistant" as the root topic. The configuration messages are letting Home Assistant know that it will need to subscribe to these topics to pick up sensor data.

We use the idea of "state" again, farther down in the payload. It's a potential for confusion. A better topic for the "availability" section might have been "home/eb0b-05a81/availability" with an availability value in the payload.

As it is - what I've done is tell Home Assistant that it can find the availability status by subscribing to the MQTT topic and extracting the state message from the payload.

Note that I'm NOT using an availability/state topic specific to this sensor. It's NOT "home/eb0b-05a81/volatile_organic_compound/state".  It could be, but because all six sensors are tied to a single monitor, I chose one topic. All six sensors will go online or offline together.


Device and...


This section holds i
nformation about the device. Home Assistant uses this data to tie it into the device registry.  You can read about the attributes; I chose a handful to populate with data meaningful to me.

Moving down, "device_class" controls the Icon displayed in the UI.  For devices of type 'binary sensor' a list of the classes is here: Home Assistant Binary Sensors Device Class.

For a device type of 'sensor' a list of the classes is here: Home Assistant Sensors Device Class.

"expire_after" : means I want this sensor to show offline if no data comes in after 3600 seconds / 1 hour.  

Setting "name" to "AirQuality/A volatile organic compounds" controls how this sensor is displayed in the UI.   I call this monitor "AirQuality/A". I'll call a second monitor "AirQuality/B".

The  "state_topic":"home/eb0b-05a81" tells Home Assistant that the sensor data will be coming in on this MQTT topic. So Home Assistant needs to subscribe to this topic.

The "unique_id" for this VoC sensor is the device ID with a string appended.  And finally the    "value_template":"{{ value_json.VOC}}" tells Home Assistant to parse the VoC value out of the JSON payload's attribute VOC.


That rounds out one of the six Configuration payloads.  For brevity here are the other five.

Temperature Sensor Configuration Payload

{
   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version":"?",
      "via_device":"python"
   },
   "device_class":"temperature",
   "enabled_by_default":true,
   "expire_after":3600,
   "force_update":true,
   "name":"AirQuality/A_temperature",
   "unique_id":" eb0b-05a81_temperature",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unit_of_measurement":"°C",
   "value_template":"{{ value_json.temperature }}"
}

Humidity Sensor Configuration Payload

{
   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version":"?",
      "via_device":"python"
   },
   "device_class":"humidity",
   "enabled_by_default":true,
   "expire_after":3600,
   "force_update":true,
   "name":"AirQuality/A humidity",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unique_id":"eb0b-05a81_humidity",
   "unit_of_measurement":"%",
   "value_template":"{{ value_json.humidity }}"
}

Carbon Dioxide Sensor Configuration Payload

{
   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version":"?",
      "via_device":"python"
   },
   "device_class":"carbon_dioxide",
   "enabled_by_default":true,
   "expire_after":3600,
   "force_update":true,
   "name":"AirQuality/A carbon dioxide",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unique_id":"eb0b-05a81_carbon_dioxide",
   "unit_of_measurement":"ppm",
   "value_template":"{{ value_json.CO2 }}"
}

Formaldehyde Sensor Configuration Payload

{
   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version":"?",
      "via_device":"python"
   },
   "enabled_by_default":true,
   "expire_after":3600,
   "force_update":true,
   "name":"AirQuality/A formaldehyde",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unique_id":"eb0b-05a81_formaldehyde",
   "unit_of_measurement":"ppm",
   "value_template":"{{ value_json.CH2O}}"
}

Particulate Matter (2.5) Sensor Configuration Payload

{
   "availability":[
      {
         "topic":"home/eb0b-05a81/state",
         "value_template":"{{ value_json.state }}"
      }
   ],
   "device":{
      "identifiers":[
         "eb0b-05a81"
      ],
      "manufacturer":"Tuya",
      "model":"Air Quality Sensor",
      "name":"eb0b-05a81",
      "hw_version":"?",
      "via_device":"python"
   },
   "device_class":"pm25",
   "enabled_by_default":true,
   "expire_after":3600,
   "force_update":true,
   "name":"AirQuality/A particulate 2.5",
   "state_class":"measurement",
   "state_topic":"home/eb0b-05a81",
   "unique_id":"eb0b-05a81_particulate_matter_2_5",
   "unit_of_measurement":"ug/m³",
   "value_template":"{{ value_json.PM25 }}"
}

Now try it!

Use "mosquitto_pub" to see if you can get a sensor to appear in the Home Assistant UI. Something like this:

mosquitto_pub -h mqttbroker.local -d -t "homeassistant/sensor/eb0b-05a81/humidity/config" -m '{"availability":[{"topic":"home/eb0b-05a81/state","value_template":"{{ value_json.state }}"}],"device":{"identifiers": [ "home_eb0b-05a81"], "manufacturer":"Tuya","model":"Air Quality Sensor","name":"eb0b-05a81","hw_version" : "?","via_device": "python" },"device_class":"humidity", "enabled_by_default":true, "expire_after" : 3600, "force_update" : true, "name":"Air Quality/A humidity",   "state_class":"measurement", "state_topic":"home/eb0b-05a81", "unique_id":"eb0b-05a81_humidity",   "unit_of_measurement":"%",   "value_template":"{{ value_json.humidity }}"}'


Flip over to the Home Assistant Overview page and you should see a new sensor - labeled "AirQuality/A humidity".

It should be greyed-out to indicate that it's offline.  Let's bring it online and send it a value

mosquitto_pub -h mqttbroker.local -d -t "home/eb0b-05a81/state" -m '{ "state":"online" }'

mosquitto_pub -h mqttbroker.local -d -t "home/eb0b-05a81" -m '{ "temperature" : 20.0, "humidity" : 37.2 , "CO2" : 364, "state" : "online", "PM25" : 4, "CH2O" : 0.004, "VOC": 0.012 }'

If all went well, you should have a new sensor in the UI!





After all six sensors are configured, you should see something like this:



Note that I'm not using the "Retain Flag" when publishing configuration messages. I'm still debugging things and didn't want this configuration messages persisted by the broker.  Yet.

Monday, September 26, 2022

(#41) Home Assistant - Legacy Sensors

Adding in Legacy Sensors - Part 1

Those Eaton Home Heartbeat sensors, mentioned in post #2 from May 2014, are still working! 


So, it'd be nice to get them feeding data into my new Home Assistant system.  After reading and researching, my current (as of September 2022) thought is to use "MQTT Device Discovery."


MQTT Device Discovery, in Home Assistant, is the ability to add sensors using carefully formatted MQTT messages sent to the broker.  I've already got an MQTT integration into Home Assistant, and I'm using zigbee2mqtt to feed sensor data to Home Assistant. zigbee2mqtt uses MQTT Device Discovery -- so I'll try it too.


Send the right messages to the broker, and the sensors will appear in Home Assistant. No additional fussing required! Cool!


Reading and Sniffing

A little reading, and a little "eavesdropping" of the messages that zigbee2mqtt sends and I'm able to come up
with a prototype.


For a device, I'm going to start with a non-zigbee sensor, my Tuya WiFi Air Quality Monitor. I've already got Python code that logs into the Tuya IoT cloud, pulls the sensor data and sends it out via MQTT packets to my broker.  

The thought is, to leave that code as is, and just modify the MQTT payload so it matches Home Assistant's MQTT Device Discovery format.


Treat each sensor individually

The format is documented, but I'll share the approach I've taken. First an architectural issue of note. This Air Quality monitor has six sensors (temperature, humidity, carbon dioxide, formaldehyde, particulate matter 2.5, and volatile organic compounds).

Current Best Practice is to treat this one unit as six separate sensors. Don't try to lump them together, yet.

Two MQTT Messages 

At least two. Getting a sensor to show up involves (a) sending a "configuration" message to the "config" topic and (b) sending sensor data to a slightly different topic.  You need at least two message types, I'll be using three.

Configuration - Craft the Root MQTT Topic

MQTT Device Discovery starts with publishing configuration messages to topics, topics that Home Assistant is already subscribed to.  The topic format I'm using starts with:

homeassistant/sensor/<device ID>

"homeassistant" is the default root topic. 

"sensor" is a component that has to match one of the known Home Assistant MQTT component types. See here

And <device ID> is the unique way of identifying this sensor (or group of sensors). In my case, I'm using the unique device ID assigned to my Air Quality sensor from the Tuya IoT cloud.


The device ID assigned to my Monitor is eb0b ... 05a81 (abbreviated as "eb0b-05a81" from now on).  That's what I'll use. You can pick anything you link - MAC address, random characters, as long as its unique to the device.

One Config Message Per Sensor

Each sensor will get a subtopic appended in the format of <sensor description>/configFor the Air Quality Monitor, with it's six sensors, I end up with six configuration topics for MQTT:

homeassistant/sensor/eb0b-05a81/temperature/config

homeassistant/sensor/eb0b-05a81/humidity/config

homeassistant/sensor/eb0b-05a81/carbon_dioxide/config

homeassistant/sensor/eb0b-05a81/formaldehyde/config

homeassistant/sensor/eb0b-05a81/particulate_matter_2_5/config

homeassistant/sensor/eb0b-05a81/volatile_organic_compounds/config


The text for the sensor description appears to not matter - pick what you want. But the final subtopic must be "config". And the start of the topic must be "homeassistant/<component type>/<device ID>"

Now that we have the MQTT Configuration Topics hammered out, onto the Configuration message payloads.


Tuesday, August 30, 2022

(#40) Garage Door Revisited

 Time passes - Garage Door Part Deux


Let's see: COVID, getting a son to school in Stockholm, getting the other two kids off to college.  Fixing the electric steps on the RV for the umpteenth time. Starlink testing (works great).  Work. Turning 65. Checking the 401K balance. Oh yeah - hip replacement. Blowing out the tendon in my left knee. Little stuff.

Recall that I've made a run at keeping the garage door closed before. Look here.

Switched the Eaton Home Heartbeat system from a Raspberry Pi 2 to a Pi Zero W 2 - and had things stop working. The FTDI driver on the Zero is slightly different from the driver that loads on the Pi 2. Same "version" of Raspberry Pi OS best I can tell.

On the Pi Zero - the serial port will work for a time, and then garbage data floods the line and communication with the Home Heartbeat dies.  I spent very little time looking into this but switching back to the Pi 2 and a slightly "new" rev of the FTDI driver made the problem go away.

 

Zigbee.  There's a renewed interest in Zigbee here.  More so as the number of WiFi devices multiplies. If someone could invent a wearable Faraday cage, I'd buy it.

Months ago, I grabbed the SonOff Zigbee 3.0 USB dongle and a handful of cheap
Zigbee sensors from Aliexpress.


From there was a short hop to zigbee2mqtt as my commitment to MQTT remains strong. It works. It works great - 'nuff said. Getting that installed was easy, but paring devices, moving configurations to different computers - was a bit of a chore. But it's up and running.


From that hop, a skip to Home Assistant. Same thing - installation was a bit of a learning curve. Eventually I bailed on installing "core" on an spare Ubuntu laptop and grabbed a spare Pi 3B+ and loaded their image.  That is clearly the easiest route to get things up and running.

 

 

And then the final jump to ESPHome.




Wow! What a delightful hunk of software! Again a few hiccups getting my NodeMCU to connect initially but it was because I had loaded an image already and had forgotten how to reset the device into boot mode. Once that was done, the basic firmware image was uploaded and the ESP8266 device was online. It appeared immediately in both ESPHome and Home Assistant.

[ PS: Don't use Firefox - it doesn't support WebSerial.  I downloaded MS Edge and got things closer. I also went through the steps to build and install "esphomeflasher" and that worked great. ]

Sweet. Fantastic job on the development!

See here:



And here:


There are quite a few examples of how to write a YAML configuration for controlling a momentary relay. That's how my garage door works - to raise or lower, it's a momentary press of the button.  Here's my version 0.1 YAML that's working on my test bench:

esphome:
  name: test-8266-hiletgo

esp8266:
  board: nodemcuv2

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "blah blah blah"

ota:
  password: "blah blah blah"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test-8266-Hiletgo"
    password: "blah blah blah"

captive_portal:


switch:
  - platform: gpio
    pin:
      number: 14
      inverted: true      
    id: relay
    name: "Garage Remote"
    icon: "mdi:car-connected"
    restore_mode: always_off
    on_turn_on:
    - delay: 1000ms
    - switch.turn_off: relay

Let's get right to the wiring since that's where I learned a few more things. On these relays, the pin outs are (Thank you RandomNerd Tutorials!):


I run the two wires to the garage door from the relay's common and "normally open" connections. This seemed to have the desired behavior when the power to the NodeMCU was cut (the relay did not trigger).  For now the JD-VCC / VCC jumper is on - meaning the power to the relay is coming from the NodeMCU board. I think this will be fine, as there should be little power on the relay. The door trigger is simply a momentary close (continuity) of the circuit.


Ground on the 4 pin connector goes to GND on the NodeMCU. VCC (on the 4 pin) goes to the 3.3V pin on the NodeMCU.



And IN1 is connected to D5 - GPIO 14. Again thank you to RandomNerd Tutorials for pointing out that the pin you pick does matter!  Some pins are triggered on boot. And this would trigger the door if the NodeMCU lost power, or rebooted. We don't want that.

Quote:  "Some ESP8266 pins output a 3.3V signal when the ESP8266 boots. This may be problematic if you have relays or other peripherals connected to those GPIOs.

Additionally, some pins must be pulled HIGH or LOW in order to boot the ESP8266.

Taking this into account, the safest ESP8266 pins to use with relays are: GPIO 5, GPIO 4, GPIO 14, GPIO 12 and GPIO 13."

 

Note the two lines highlighted in red in the script. "inverted: true" was the only way I could find to have the pin power up as Low.  Without this, when the NodeMCU booted, the relay was powered up and continutiy established -- ie. like holding the garage door remote button down.

Not good.  Using "inverted: true" now powers up with the relay not engaged; no continuity; button not mashed.



And "on_turn_on" seems to be a great way to get the behavior I want from the relay - energize (mash button), hold for a second, then release.

It's time to head out to the garage, unplug the Raspberry Pi solution that's been there for years and try this. One thing I'll lose is the automation and rules I had about closing the door.  I'll have to see if they're able to be recreated in Home Assistant.