mliljedahl / telldus-core-mqtt

telldus-core-mqtt is a MQTT broker for telldus-core to integrate with Home Assistant using their MQTT Discovery.
Apache License 2.0
6 stars 5 forks source link

Home Assistant fails to read temperature / support more sensor types #15

Open mgartin opened 11 months ago

mgartin commented 11 months ago

Thank you for this tool!

Initially I posted my problem here, but I'm moving it here:

I have installed this tool in a virtual environment, and the MQTT integration in Home Assistant (HA) correctly identifies lots of sensors from it, however, it fails to read eg. temperature and humidity:

2023-10-13 20:48:47.316 INFO (MainThread) [homeassistant.components.mqtt.discovery] Component has already been discovered: sensor 167_telldus temperature, sending update
2023-10-13 20:48:47.320 INFO (MainThread) [homeassistant.components.mqtt.discovery] Component has already been discovered: sensor 167_telldus humidity, sending update
2023-10-13 20:49:04.245 INFO (MainThread) [homeassistant.components.mqtt.discovery] Component has already been discovered: sensor 136_telldus temperature, sending update
2023-10-13 20:49:18.333 INFO (MainThread) [homeassistant.components.mqtt.discovery] Component has already been discovered: sensor 199_telldus temperature, sending update
2023-10-13 20:49:18.376 ERROR (MainThread) [homeassistant.components.mqtt.models] Exception raised when updating state of sensor.199_temperaturehumidity_telldus_199_temperature, topic: 'telldus/199/temperature/state' with payload: b'{"temperature": "15.5"}'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 593, in state
    numerical_value = float(value)  # type:ignore[arg-type]
                      ^^^^^^^^^^^^
ValueError: could not convert string to float: '{"temperature": "15.5"}'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/mqtt/models.py", line 305, in process_write_state_requests
    entity.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 779, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 879, in _async_write_ha_state
    state, attr = self._async_generate_attributes()
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 820, in _async_generate_attributes
    state = self._stringify_state(available)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 785, in _stringify_state
    if (state := self.state) is None:
                 ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 595, in state
    raise ValueError(
ValueError: Sensor sensor.199_temperaturehumidity_telldus_199_temperature has device class 'temperature', state class 'None' unit '°C' and suggested precision 'None' thus indicating it has a numeric value; however, it has the non-numeric value: '{"temperature": "15.5"}' (<class 'str'>)

The problem seems to be that the payload is the full string: {"temperature": "15.5"}, not just the number.

$ mosquitto_sub -h 192.168.1.2  -F '@Y-@m-@dT@H:@M:@S@z : %I : %t %p '  -t telldus/\#
2023-10-13T20:49:23+0200 : 2023-10-13T20:49:23+0200 : telldus/1/switch/state {"switch": 2} 
2023-10-13T20:49:23+0200 : 2023-10-13T20:49:23+0200 : telldus/151/temperature/state {"temperature": "8.5"} 
2023-10-13T20:49:23+0200 : 2023-10-13T20:49:23+0200 : telldus/199/temperature/state {"temperature": "15.5"} 
2023-10-13T20:49:23+0200 : 2023-10-13T20:49:23+0200 : telldus/199/humidity/state {"humidity": "58"} 
2023-10-13T20:49:23+0200 : 2023-10-13T20:49:23+0200 : telldus/167/temperature/state {"temperature": "12.3"} 

telldus-core-mqtt sends the following:

2023-10-14 09:02:56,027 60 INFO: Send "{"temperature": "20.3"}" to topic "telldus/247/temperature/state"

So, I guess that what we need to do is to identify temperature sensors and craft the payload a bit differently?

mgartin commented 11 months ago

Ok, so I dug a bit further. I'm not sure the problem is that a pure float should be sent. It might be that we shouldn't end up at this place in the HA integration: https://github.com/home-assistant/core/blob/5ed8de83484c88f38bfe3b27692500b992e3f0e8/homeassistant/components/sensor/__init__.py#L621

For some reason the HA code fails to do the right thing, even though telldus-core-mqtt has sent the following:

2023-10-14 09:35:44,007 60 INFO: Send "{"device": {"name": "247_temperaturehumidity", "identifiers": ["247_temperaturehumidity"], "model": "temperaturehumidity", "manufacturer": "fineoffset"}, "unique_id": "247_telldus_temperature", "name": "telldus_247_temperature", "state_topic": "telldus/247/temperature/state", "state_value_template": "{{ value_json.temperature }}", "device_class": "temperature", "unit_of_measurement": "°C"}" to topic "homeassistant/sensor/247_telldus/temperature/config"
2023-10-14 09:35:44,008 60 INFO: Send "{"temperature": "20.4"}" to topic "telldus/247/temperature/state"

which has "state_value_template": "{{ value_json.temperature }}" in it, and as such the MQTT integration should be able to read it, right? What is going wrong here?

mgartin commented 11 months ago

FWIW, I am able to get valid readings in HA with the following hack in telldus-core-mqtt main.py:

@@ -192,10 +199,25 @@ def sensor_event(protocol, model, id_, data_type, value, timestamp, cid):

     topic = s.create_topic(id_, type_string)
     data = s.create_topic_data(type_string, value)
+
+    # Special case for temperature and temperaturehumidity
+    if (
+            'temperaturehumidity' in model
+            or data_type == const.TELLSTICK_TEMPERATURE
+            or data_type == const.TELLSTICK_HUMIDITY
+    ):
+        logging.debug(f'dbg: altering data for {model=}')
+        data = value
+        
     publish_mqtt(mqtt_sensor, topic, data)

It still sends a lot of data that HA cannot read, but in addition it sends pure float values that is read by HA.