NorthernMan54 / homebridge-tasmota

Plugin for Tasmota devices leveraging Home Assistant auto discovery
Apache License 2.0
35 stars 9 forks source link

Error when adding esphome plugs #26

Closed skullydazed closed 3 years ago

skullydazed commented 3 years ago

Describe The Bug:

I have an esp8266 running esphome with some sensors attached. None of the sensors work and all throw the same error. Focusing only on 1 sensor for ease of debugging, but this applies to every device I've tried to use, including the esp32, tuya plugs, and my zwave2mqtt devices which also publish homeassistant autoconfig entries.

To Reproduce:

  1. Flash ESPHome to an esp8266 with the yaml below.
  2. Notice that autoconfiguration is published to homeassistant/binary_sensor/office_sensor/office_motion/config: {"device_class":"motion","name":"Office Motion","state_topic":"office_sensor/binary_sensor/office_motion/state","availability_topic":"office_sensor/status","unique_id":"ESPbinary_sensoroffice_motion","device":{"identifiers":"10521c0287d9","name":"office_sensor","sw_version":"esphome v1.15.3 Jan 26 2021, 15:07:02","model":"PLATFORMIO_D1_MINI","manufacturer":"espressif"}}
  3. Find error messages in debug logs shown below

Expected behavior:

Discovered devices should show up in Home.app, but don't.

Logs:

Show the Homebridge logs here with the DEBUG flag set, remove any sensitive information.
2021-02-01T19:15:54.114Z Tasmota:platform Discovered -> homeassistant/binary_sensor/office_sensor/office_motion/config Office Motion {
  dev_cla: 'motion',
  name: 'Office Motion',
  state_topic: 'office_sensor/binary_sensor/office_motion/state',
  availability_topic: 'office_sensor/status',
  uniq_id: 'ESPbinary_sensoroffice_motion',
  dev: {
    ids: '10521c0287d9',
    name: 'office_sensor',
    sw: 'esphome v1.15.3 Jan 26 2021, 15:07:02',
    mdl: 'PLATFORMIO_D1_MINI',
    mf: 'espressif'
  },
  tasmotaType: 'binary_sensor'
}
[2/1/2021, 11:15:54 AM] [Tasmota] Adding new accessory: Office Motion
2021-02-01T19:15:54.117Z Tasmota:Service fakegatoService exists Office Motion
2021-02-01T19:15:54.118Z Tasmota:mqtt Error: TypeError: Cannot read property 'substr' of undefined
    at tasmotaBinarySensorService.refresh (/usr/lib/node_modules/homebridge-tasmota/src/TasmotaService.ts:110:75)
    at tasmotaBinarySensorService.enableStatus (/usr/lib/node_modules/homebridge-tasmota/src/TasmotaService.ts:78:10)
    at new tasmotaBinarySensorService (/usr/lib/node_modules/homebridge-tasmota/src/tasmotaBinarySensorService.ts:75:10)
    at Mqtt.<anonymous> (/usr/lib/node_modules/homebridge-tasmota/src/platform.ts:282:42)
    at Mqtt.emit (events.js:315:20)
    at MqttClient.<anonymous> (/usr/lib/node_modules/homebridge-tasmota/src/lib/Mqtt.ts:56:24)
    at MqttClient.emit (events.js:315:20)
    at MqttClient._handlePublish (/usr/lib/node_modules/homebridge-tasmota/node_modules/mqtt/lib/client.js:1277:12)
    at MqttClient._handlePacket (/usr/lib/node_modules/homebridge-tasmota/node_modules/mqtt/lib/client.js:410:12)
    at work (/usr/lib/node_modules/homebridge-tasmota/node_modules/mqtt/lib/client.js:321:12)
2021-02-01T19:15:54.119Z Tasmota:mqtt Triggerd by: {"device_class":"motion","name":"Office Motion","state_topic":"office_sensor/binary_sensor/office_motion/state","availability_topic":"office_sensor/status","unique_id":"ESPbinary_sensoroffi
ce_motion","device":{"identifiers":"10521c0287d9","name":"office_sensor","sw_version":"esphome v1.15.3 Jan 26 2021, 15:0
7:02","model":"PLATFORMIO_D1_MINI","manufacturer":"espressif"}}
2021-02-01T19:15:54.120Z Tasmota:platform Discovered -> homeassistant/binary_sensor/wifikit32/wifikit32_motion/config Wi
fikit32 Motion {
  dev_cla: 'motion',
  name: 'Wifikit32 Motion',
  state_topic: 'wifikit32/binary_sensor/wifikit32_motion/state',
  availability_topic: 'wifikit32/status',
  uniq_id: 'ESPbinary_sensorwifikit32_motion',
  dev: {
    ids: '7c9ebdfc04c8',
    name: 'wifikit32',
    sw: 'esphome v1.15.3 Jan 26 2021, 20:58:27',
    mdl: 'Heltec WiFi Kit 32',
    mf: 'espressif'
  },
  tasmotaType: 'binary_sensor'
}

ESPHome Device Config:


esphome:
  name: office_sensor
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "XXX"
  password: "XXX"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Office Sensor Fallback Hotspot"
    password: "XXX"

captive_portal:

# Enable MQTT
mqtt:
  broker: XXX

# Enable SNTP
time:
  - platform: sntp
    id: sntp_time
    timezone: America/Los_Angeles
    servers: ['XXX']

# Enable logging
logger:

# Enable OTA updates
ota:

# Enable i2c
i2c:
  - id: bus_a
    sda: 4
    scl: 5
    scan: True
    frequency: 800000

# Setup Temperature/Pressure/Humidity Sensor
sensor:
  - platform: bme280
    temperature:
      name: "Office Temperature"
      oversampling: 16x
      id: office_temperature
    humidity:
      name: "Office Humidity"
      id: office_humidity
    pressure:
      name: "Office Pressure"
      id: office_pressure
    address: 0x76
    update_interval: 60s

# Setup oled display
font:
  - file: "CourierPrime-Regular.ttf"
    id: my_font
    size: 14

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    i2c_id: bus_a
    address: 0x3C
    id: my_display
    update_interval: 10s
    external_vcc: false
    lambda: |-
            auto time = id(sntp_time).now();
            if (time.is_valid()) {
                auto temp_c = id(office_temperature).state;
                auto temp_f = temp_c * 1.8 + 32.0;
                auto humidity = id(office_humidity).state;
                auto mbar = id(office_pressure).state;
                //auto psi = mbar * 0.0145038;
                //auto atm = mbar / 1013;
                auto inhg = mbar / 33.864;
                it.strftime(30, 0, id(my_font), "%I:%M %p", time);
                it.strftime(20, 15, id(my_font), "%a, %b %d", time);
                it.printf(20, 36, id(my_font), "%.1f F %.0f %%", temp_f, humidity);
                it.printf(20, 49, id(my_font), " %.2f in", inhg);
            }

# Setup the PIR Sensor
binary_sensor:
  - platform: gpio
    pin: D6
    name: "Office Motion"
    device_class: motion```

**Screenshots:**
<!-- If applicable, add screenshots to help explain your problem. -->

**Environment:**

* **Tasmota Version**:
* **Plugin Version**: 0.7.2
* **Homebridge Version**: 1.1.7
* **Node.js Version**: v14.15.4
* **NPM Version**: 6.14.10
* **Operating System**: Debian 10

<!-- Click the "Preview" tab before you submit to ensure the formatting is correct. -->
NorthernMan54 commented 3 years ago

I coded the plugin directly against how Tasmota manages Mqtt autodiscovery, and never looked at ESPHome devices so this is expected. I did fix the issue that triggered the exception, but can not confirm if it works without an ESPhome device but theoretical it should with some minor tweaks. So getting this to work is likely to be a bit of wack a mole thru what ever issues do surface. The detail you provided was extremely helpful in resolving this.

For the fix I coded this against the current beta branch, so to install please use add the @beta tag to the install command ie

npm install -g homebridge-tasmota@beta
skullydazed commented 3 years ago

I'm happy to whack as long as you're happy to provide hammers.

I think maybe something didn't get published, I'm still picking up 0.0.80:

redwood:/var/lib/homebridge:0$ sudo npm install -g homebridge-tasmota@beta
npm WARN deprecated debug@4.1.1: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.1 (node_modules/homebridge-tasmota/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ homebridge-tasmota@0.0.80
added 126 packages from 88 contributors in 10.193s
NorthernMan54 commented 3 years ago

Minor publishing issue, it should now be v0.0.83

skullydazed commented 3 years ago

This is looking better. Discovery seems to work:

2021-02-02T03:11:13.324Z Tasmota:platform Discovered -> homeassistant/binary_sensor/office_sensor/office_motion/config O
ffice Motion {
  dev_cla: 'motion',
  name: 'Office Motion',
  stat_t: 'office_sensor/binary_sensor/office_motion/state',
  avty_t: 'office_sensor/status',
  uniq_id: 'ESPbinary_sensoroffice_motion',
  dev: {
    ids: '10521c0287d9',
    name: 'office_sensor',
    sw: 'esphome v1.15.3 Feb  1 2021, 13:12:37',
    mdl: 'PLATFORMIO_D1_MINI',
    mf: 'espressif'
  },
  tasmotaType: 'binary_sensor'
}
[2/1/2021, 7:11:13 PM] [Tasmota] Adding new accessory: Office Motion
2021-02-02T03:11:13.328Z Tasmota:Service fakegatoService exists Office Motion
2021-02-02T03:11:13.328Z Tasmota:mqtt sendMessage office_sensor/binary_sensor/office_motion/teleperiod 300
2021-02-02T03:11:13.329Z Tasmota:platform discovery devices - this.api.registerPlatformAccessories
HAP Warning: Characteristic 000000E3-0000-1000-8000-0026BB765291 not in required or optional characteristics for service
 00000085-0000-1000-8000-0026BB765291. Adding anyway.
2021-02-02T03:11:13.342Z Tasmota:platform Discovered -> homeassistant/binary_sensor/wifikit32/wifikit32_motion/config Wi
fikit32 Motion {
  dev_cla: 'motion',
  name: 'Wifikit32 Motion',
  stat_t: 'wifikit32/binary_sensor/wifikit32_motion/state',
  avty_t: 'wifikit32/status',
  uniq_id: 'ESPbinary_sensorwifikit32_motion',
  dev: {
    ids: '7c9ebdfc04c8',
    name: 'wifikit32',
    sw: 'esphome v1.15.3 Jan 26 2021, 20:58:27',
    mdl: 'Heltec WiFi Kit 32',
    mf: 'espressif'
  },
  tasmotaType: 'binary_sensor'
}

However it doesn't seem to like ON and OFF as state vars:

2021-02-02T03:11:14.064Z Tasmota:binarySensor MQTT office_sensor/binary_sensor/office_motion/state ON
[2/1/2021, 7:11:14 PM] [Tasmota] ERROR: Message Parse Error office_sensor/binary_sensor/office_motion/state ON
[2/1/2021, 7:11:14 PM] [Tasmota] Marking accessory 'Office Motion' to online
NorthernMan54 commented 3 years ago

Now this is where is gets tricky, as the Tasmota devices are using JSON objects like this for status

tasmota_562CC4/stat/SWITCH1

{"STATE":"ON"}

And the plugin is parsing the config object, and using the 'value_template' and 'stat_t' ( state_topic ) to determine how to parse the status. I borrowed portions of the parser from home assistant, but only implemented the JSON parser as Tasmota devices are doing JSON.

homeassistant/binary_sensor/562CC4_SW_1/config

{"name":"Dining Room Light Sensor Switch1",
"stat_t":"~stat/SWITCH1",
"avty_t":"~tele/LWT",
"pl_avail":"Online",
"pl_not_avail":"Offline",
"uniq_id":"562CC4_SW_1","device":{"identifiers":["562CC4"],"connections":[["mac","CC:50:E3:56:2C:C4"]]},
"~":"tasmota_562CC4/",
"value_template":"{{value_json.STATE}}",
"frc_upd":true,
"pl_on":"ON",
"pl_off":"OFF"}

Does ESP home a similar pattern ?

PS This is from my combo sensor ( BME280, BH1750 LUX and AM312 PIR Motion )

skullydazed commented 3 years ago

I've seen that pattern used for other devices (in fact I use it for a couple of my own projects that do homeassistant auto discovery) but esphome devices use simple strings for the state. When value_template, pl_on, and pl_off are not provided (as they are not in this case) this is what is assumed.

NorthernMan54 commented 3 years ago

If there is an ESPHome setting to send the state in a JSON message, then to getting it work will likely mean just tweaking the discovery message with an override to add the missing discovery elements.

skullydazed commented 3 years ago

After iterating on this over discord things are looking good. With 0.0.98 and the following minor patch all my devices are working great:

redwood:/usr/lib/node_modules/homebridge-tasmota/dist:148$ diff -u tasmotaSwitchService.js.dist tasmotaSwitchService.js
--- tasmotaSwitchService.js.dist    2021-02-04 11:54:48.270118900 -0800
+++ tasmotaSwitchService.js 2021-02-04 12:01:59.835522799 -0800
@@ -45,9 +45,6 @@
         debug('MQTT', topic, message.toString());
         try {
             this.accessory.context.timeout = this.platform.autoCleanup(this.accessory);
-            const interim = {
-                value_json: JSON.parse(message.toString()),
-            };
             let value = message.toString();
             if (this.accessory.context.device[this.uniq_id].val_tpl) {
                 value = this.parseValue(this.accessory.context.device[this.uniq_id].val_tpl, {
@@ -56,6 +53,9 @@
             }
             value = (value === this.accessory.context.device[this.uniq_id].pl_on ? true : false);
             if (typeof this.accessory.context.device[this.uniq_id].pl_on === 'boolean') {
+                const interim = {
+                    value_json: JSON.parse(message.toString()),
+                };
                 value = TasmotaService_1.isTrue(this.parseValue(this.accessory.context.device[this.uniq_id].val_tpl, interim));
             }
             if (this.characteristic.value !== value) {
NorthernMan54 commented 3 years ago

This is should now be 100% functional