-
Home Assistant integration
04/14/2019 at 19:17 • 0 commentsThis part turned out to be super easy thanks to serveo.net and tutorial I found here.
First thing was to make my home Raspberry Pi running Hass.io available from internet. Obvious idea was to go through some VPN etc.. But then I stumbled upon service called Ngrok and eventually to Serveo.net that is amaizingly easy to set up and there is Hass.io add-on. But even simple:
ssh -R myalias:80:localhost:8123 serveo.net
did the trick to expose my Hass to internet.
Then I turned to the tutorial mentioned above and done .. easier than expected.
Now it's just "Hey Google .. Activate Standing" :-)
-
Integrating with Home Assistant through ESPHome
04/12/2019 at 10:50 • 0 commentsAmazing https://esphome.io/ project makes it super easy to integrate most of Arduino modules with Home Assistant through ESP8266 or ESP32. tried in on one or two Sonoff devices, but how difficult is to integrate something custom, reading and sending some UART data.
Turns out that it's extremely easy. Just implement custom sensor, that allows you to almost copy paste your Arduino IDE C code, register in yaml config and your height sensor reading data from UART is done.
Sinding messsges is even more easy, as there is already UART switch, that give you option to send message on switch trigger.
Custom sensor:
class TableHeightSensor : public PollingComponent, public UARTDevice, public sensor::Sensor{ public: TableHeightSensor(UARTComponent *parent) : PollingComponent(1000), UARTDevice(parent) {} byte last[3]; float value = 0; float lastPublished = -1; void setup() override { // This will be called by App.setup()) } void loop() override { while (available()) { byte in = read(); if(last[2] == 0xAA && last[1] == 0xA6){ value = (((255*in) + last[0]) / 43.225) - 2; // substracting to make it display same number as controller } last[2] = last[1]; last[1] = last[0]; last[0] = in; yield(); } } void update() override { if(value != lastPublished) { publish_state(value); lastPublished = value; } } };
ESPHome config:
uart: id: uart_bus tx_pin: GPIO5 rx_pin: GPIO4 baud_rate: 9600 sensor: - platform: wifi_signal name: "WiFi Signal ${upper_devicename}" update_interval: 60s - platform: custom lambda: |- auto height_sensor = new TableHeightSensor(id(uart_bus)); App.register_component(height_sensor); return {height_sensor}; sensors: name: "${upper_devicename} height" unit_of_measurement: cm accuracy_decimals: 1 switch: - platform: uart name: "Sitting" id: switch1 icon: mdi:format-vertical-align-bottom data: [0x55, 0xAA, 0xD1, 0xD1, 0xD1] internal: False - platform: uart name: "Standing" id: switch4 icon: mdi:format-vertical-align-top data: [0x55, 0xAA, 0xD7, 0xD7, 0xD7] internal: False # not bothering with exposing more buttons
Now just go to Hass dashboard and integrate one more ESPHome device:
-
Figuring out the controller communication
04/11/2019 at 21:45 • 0 commentsFirst thing after receiving the table and tested it actually works, I opened the controller unit and tried to look it it's the same as some other tables already described around here or elsewhere on the internet.
Unfortunately the wiring was different from table to table, so I tried googling anything I could find on the controller and main unit. No luck again, so I took super cheap oscilloscope ( DSO138mini as I was still waiting for my logic analyser .. ) and tried different pins of the controller.
By pressing controller buttons, I figured it goes:
- GND
- Vcc
- Rx
- Tx
- Button Down
- Button Up
All pins being high when idle, Rx was having quite a lot of messages being sent by the main unit to the controller. Rx contained only messages when I pushed some button. I tried letting the table reach remote position and disconnecting the controller mid-way to see if it had some role in controlling the end position. Turned out not to be true and as soon as the button was pressed on the controller, main unit took care of travelling to given position and stopping.
So next thing was figuring out what are the messages being sent. By checking the scope and the length of pulses, I figured it was 9600bps rate as on most of those controllers. So I've hooked ESP8266 Software serial to these repeating the stuff to Serial console. I tried to display binary output, but it was all over the place. Took me while to test outputting HEX and then compensating padding by 0 for values less than 16. Suddenly all messages were same length with only two bytes changing during the movement with 16bit position in little endian format stored in 3rd and 4th byte of the message:
AA A6 [low byte] [high byte] 0C00
Then I checked the controller's Tx and this is what it sent:
Wake up: 55 AA F0 F0 F0
Sleep: 55 FCMem1: 55AAD1D1D1
Mem2: 55AAD2D2D2
Mem3: 55AAD3D3D3
Mem4: 55AAD7D7D7Stop: 55AAE3E3E3
With some more messages for storing new values to memory, but I was most interested WakeUp, Memory recall and Stop. Turned out WakeUp does not have to be called before triggering memory and sleep is handled by the main unit as well. And as memories we not specific heights, but fixed messages, it turned out to be pretty simple.
After testing the comms with I added one diode to the Tx of of ESP8266, so it worked alongside the normal controller and not keeping it HIGH all the time.
First I bothered with level-adjusting the signals, but turned out that ESP8266 pins can handle up to 5V levels, so I've ditched all the unnecessary stuff and then moved to ESP-12E module and small step-down to fit in to original controller enclosure.
#include <SoftwareSerial.h> SoftwareSerial mySoftwareSerial(5, 16, false); byte last[3]; void setup() { Serial.begin(9600); mySoftwareSerial.begin(9600); Serial.println("\nSoftware serial test started"); } void loop() { if(Serial.available()){ byte in = Serial.read(); if(in == '1'){ Serial.println("\nMemory 1"); mySoftwareSerial.write(0x55); mySoftwareSerial.write(0xAA); mySoftwareSerial.write(0xD1); mySoftwareSerial.write(0xD1); mySoftwareSerial.write(0xD1); } // add more mem recalls to test } if(mySoftwareSerial.available()){ while(mySoftwareSerial.available()){ byte in = mySoftwareSerial.read(); if(in == 0x55){ Serial.println(); } if(in < 16){ Serial.print('0'); } Serial.print(in, HEX); if(last[2] == 0xAA && last[1] == 0xA6){ Serial.print(" Heigh "); Serial.print((255*in) + last[0], DEC); } last[2] = last[1]; last[1] = last[0]; last[0] = in; yield(); } } }