esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
415 stars 26 forks source link

Blink Code Decoder #2209

Open wernerhp opened 1 year ago

wernerhp commented 1 year ago

Describe the problem you have/What new integration you would like

I have a device that uses a Status LED to blink codes. The code sequence provides state information. I would like to be able to use a GPIO pin (preferred) or light sensor (optional) to decode the blink codes.

Please describe your use case for this integration and alternatives you've tried:

I have a gate motor that I am controlling using an ESP32. The motor's control board has a Status LED that blinks. I want to interpret the blink codes so the state can be used for automations.

Codes qre as follows Off - Gate is closed On - Gate is partially or fully open Continuous slow flash - Gate is opening Continuous fast flash - Gate is closing One flash every two seconds - Pillar light override is activated Two flashes every two seconds - No mains present Three flashes every two seconds - Battery voltage is low

I've read through all the docs and tried numerous components, but none seem to be up to the task. On and Off states can be achieved using debounce filters on a binary sensor, but no solution could be found for flashing sequences.

I would like this processed on the device and have a text or select sensor show the status. I believe this will have a wider application than just my use case, e.g. processing from the Status LED component, a VCR blink light, morse code etc.

Additional context

I've tried to visualise the blink codes as described above image-1

nagyrobi commented 1 year ago

I think you can implement this with on_multi_click automation of Binary Sensor. See the Double Clicked example. You could detect 1, 2, 3, 4 "clicks" within a second, with various pulse widths, and then take actions based on that.

wernerhp commented 1 year ago

Thanks, I'll give that a shot.
Is there a way to log sensor data with milisecond timestamps? It would help me get the timings right.

wernerhp commented 1 year ago

So I tried the following, but I only get it to set the Status Text Sensor to Open. It doesn't go to Closed even though the Status LED is OFF permanently. It also doesn't trigger any of the other states. logger.log doesn't output any of these messages in my logs

Click to expand ```yml logger: level: VERBOSE binary_sensor: - platform: gpio pin: ${led_pin} id: status_led internal: true publish_initial_state: true on_multi_click: - timing: - ON for at most 250ms - OFF for at least 500ms then: - text_sensor.template.publish: id: status state: "Pillar light override" - timing: - ON for at most 250ms - OFF for at most 250ms - ON for at most 250ms - OFF for at least 500ms then: - text_sensor.template.publish: id: status state: "No Mains" - timing: - ON for at most 500ms - OFF for at most 500ms - ON for at most 500ms - OFF for at most 500ms - ON for at most 500ms - OFF for at least 500ms then: - text_sensor.template.publish: id: status state: "Battery Low" - timing: - ON for at least 250ms - OFF for at most 500ms - ON for at least 250ms - OFF for at most 500ms - ON for at least 250ms - OFF for at most 500ms - ON for at least 250ms - OFF for at most 500ms then: - text_sensor.template.publish: id: status state: "Opening" - timing: - ON for at least 125ms - OFF for at most 250ms - ON for at least 125ms - OFF for at most 250ms - ON for at least 125ms - OFF for at most 250ms - ON for at least 125ms - OFF for at most 250ms then: - text_sensor.template.publish: id: status state: "Closing" - timing: - OFF for at least 1000ms then: - text_sensor.template.publish: id: status state: "Closed" - timing: - ON for at least 1000ms then: - text_sensor.template.publish: id: status state: "Open" ```
nagyrobi commented 1 year ago

Please head on to our Discord support channel for faster response.

wernerhp commented 1 year ago

Is there any way to get on_multi_click to return after the first match? I have multiple timings that are very similar and then they all match and trigger, where it should stop after the first match.

wernerhp commented 1 year ago

So far I've tried various combinations of on_multi_click, but can't get a consistent result. It seems like the on_multi_click automation stops firing once the LED / Input remains in the OFF state. Publish initial state doesn't seem to work as the on_multi_click doesn't fire. I'm able to get some of the states to work, but it doesn't work consistently.

PS: I took your advice, but there seems to be no response on Discord.

Here's my latest for reference. On startup the Status is "Unknown". The Closed state doesn't always fire when the status_led remains off

Click to expand ```yml binary_sensor: - platform: gpio pin: ${led_pin} id: status_led name: "Status LED" entity_category: diagnostic icon: mdi:led-outline internal: false publish_initial_state: true on_multi_click: - timing: # Pillar light override - ON for 125ms to 250ms - OFF for 1750ms to 1875ms then: - logger.log: "Pillar light override" - text_sensor.template.publish: id: status state: "Pillar light override" - timing: # No Mains - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 1250ms to 1625ms then: - logger.log: "No Mains" - text_sensor.template.publish: id: status state: "No Mains" - timing: # Battery Low - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 750ms to 1375ms then: - logger.log: "Battery Low" - text_sensor.template.publish: id: status state: "Battery Low" - timing: # Closing - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms - ON for 125ms to 250ms - OFF for 125ms to 250ms then: - logger.log: "Closing" - text_sensor.template.publish: id: status state: "Closing" - timing: # Opening - ON for 250ms to 500ms - OFF for 250ms to 500ms - ON for 250ms to 500ms - OFF for 250ms to 500ms - ON for 250ms to 500ms - OFF for 250ms to 500ms - ON for 250ms to 500ms - OFF for 250ms to 500ms then: - logger.log: "Opening" - text_sensor.template.publish: id: status state: "Opening" - timing: # Closed - OFF for at least 2000ms then: - logger.log: "Closed" - text_sensor.template.publish: id: status state: "Closed" - timing: # Open - ON for at least 2000ms then: - logger.log: "Open" - text_sensor.template.publish: id: status state: "Open" ```
nagyrobi commented 1 year ago

PS: I took your advice, but there seems to be no response on Discord.

Looed for your messages, but could't find them. Are U on the right server?

wernerhp commented 1 year ago

https://discord.com/channels/429907082951524364/429907082955718657/1098605849389322322

nagyrobi commented 1 year ago

Oh, that's a different question.... "Blink Code Decoder"...?

wernerhp commented 1 year ago

https://discord.com/channels/429907082951524364/429907082955718657/1097626615997026386

RoganDawes commented 1 year ago

I implemented something similar to what you are asking for (might even be the same - Centurion gate motor), using the following principles:

I haven't tried to extract the other status indicators (Mains failure, etc), but I think you should be able to get them without too much difficulty following the ideas above. My writeup is available here: https://mybroadband.co.za/forum/threads/esphome-and-centurion-d5.1231471

wernerhp commented 1 year ago

I got it working good enough with fitlers, delays and on_multi_click and many hours of trial and error. https://github.com/wernerhp/esphome.centurion_d5_evo

pnkpig commented 3 months ago

I implemented something similar to what you are asking for (might even be the same - Centurion gate motor), using the following principles:

* Every time the GPIO changes, run a script. The script is set to restart if it is already running. The script begins with a delay of about 3 seconds, primarily because the actual flashing of the LED changes in duration as the gate motor accelerates and decelerates, and the flashes can go as long as 2 seconds. If the delay completes (i.e. the LED is static), the script sets a state variable for the gate based on the state of the LED: Open if ON, Closed if OFF.

* Then, it calculates the interval in between state changes. If it is longer than 2.5 seconds, discard the event, otherwise, if it is less than 200ms (fast flash), the gate is opening, if greater than 300ms (slow flash), the gate is closing.

I haven't tried to extract the other status indicators (Mains failure, etc), but I think you should be able to get them without too much difficulty following the ideas above. My writeup is available here: https://mybroadband.co.za/forum/threads/esphome-and-centurion-d5.1231471

Hi RoganDawes, can you please send through an alternate link to your yaml file, I would like to check it out, however mybroadband is not accepting new users for me to open the doc

RoganDawes commented 3 months ago

Hi RoganDawes, can you please send through an alternate link to your yaml file, I would like to check it out, however mybroadband is not accepting new users for me to open the doc

Here you go. gate.txt