home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
71.13k stars 29.8k forks source link

Cannot create a generic sensor via mqtt #85073

Closed jerome-labidurie closed 1 year ago

jerome-labidurie commented 1 year ago

The problem

Hello,

I'm trying to create a generic sensor via mqtt. In the documentation (mqtt & sensor), it's stated that the device_class: None is the way (but can be omitted).

device_class device_class (Optional, default: None) The type/class of the sensor to set the icon in the frontend.

None: Generic sensor. This is the default and doesn’t need to be set.

However, if I try to create a sensor with device_class set to None,

mosquitto_pub -r -h 192.168.1.20 -p 1883 -t "homeassistant/sensor/GenericSensor/config" -m '{"name": "Generic Sensor", "state_topic": "homeassistant/sensor/GenericSensor/state", "availability_topic": "homeassistant/sensor/GenericSensor/available", "unique_id": "GenericSensor", "device_class": "None", "unit_of_measurement": ""}'

the sensor is not created and I have an error in the logs :

2023-01-03 20:43:16.494 ERROR (MainThread) [homeassistant.util.logging] Exception in async_discover when dispatching 'mqtt_discovery_new_sensor_mqtt': ({'name': 'Generic Sensor', 'state_topic': 'homeassistant/sensor/GenericSensor/state', 'availability_topic': 'homeassistant/sensor/GenericSensor/available', 'unique_id': 'GenericSensor', 'device_class': 'None', 'unit_of_measurement': '', 'platform': 'mqtt'},)
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/mqtt/mixins.py", line 328, in async_discover
    config: DiscoveryInfoType = discovery_schema(discovery_payload)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 232, in __call__
    return self._exec((Schema(val) for val in self.validators), v)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 355, in _exec
    raise e if self.msg is None else AllInvalid(self.msg, path=path)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 351, in _exec
    v = func(v)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 272, in __call__
    return self._compiled([], data)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
    return schema(data)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 272, in __call__
    return self._compiled([], data)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
    return base_validate(path, iteritems(data), out)
  File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 433, in validate_mapping
    raise er.MultipleInvalid(errors)
voluptuous.error.MultipleInvalid: expected SensorDeviceClass or one of 'date', 'duration', 'timestamp', 'apparent_power', 'aqi', 'battery', 'carbon_monoxide', 'carbon_dioxide', 'current', 'distance', 'energy', 'frequency', 'gas', 'humidity', 'illuminance', 'moisture', 'monetary', 'nitrogen_dioxide', 'nitrogen_monoxide', 'nitrous_oxide', 'ozone', 'pm1', 'pm10', 'pm25', 'power_factor', 'power', 'precipitation', 'precipitation_intensity', 'pressure', 'reactive_power', 'signal_strength', 'speed', 'sulphur_dioxide', 'temperature', 'volatile_organic_compounds', 'voltage', 'volume', 'water', 'weight', 'wind_speed' for dictionary value @ data['device_class']

In the other end, if I just remove the optional None device class

mosquitto_pub -r -h 192.168.1.20 -p 1883 -t "homeassistant/sensor/GenericSensor/config" -m '{"name": "Generic Sensor", "state_topic": "homeassistant/sensor/GenericSensor/state", "availability_topic": "homeassistant/sensor/GenericSensor/available", "unique_id": "GenericSensor", "unit_of_measurement": ""}'

the sensor is created image

In my opinion, if the device_class can be set to None, the validation should not fail. If it's not allowed, the documentation should be corrected. Maybe something like :

None: Generic sensor. This is the default and must not be set.

I'm not sure which one is he solution.

Best regards

PS: for the record, I ran into this issue by using the mqtt-binding python lib, and also created an issue there

What version of Home Assistant Core has the issue?

2022.12.7

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Container

Integration causing the issue

mqtt

Link to integration documentation on our website

https://www.home-assistant.io/integrations/mqtt

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

see logs error in the description

Additional information

No response

home-assistant[bot] commented 1 year ago

Hey there @home-assistant/core, mind taking a look at this issue as it has been labeled with an integration (sensor) you are listed as a code owner for? Thanks!

Code owner commands Code owners of `sensor` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Change the title of the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign sensor` Removes the current integration label and assignees on the issue, add the integration domain after the command.

(message by CodeOwnersMention)


sensor documentation sensor source (message by IssueLinks)

home-assistant[bot] commented 1 year ago

Hey there @emontnemery, @jbouwh, mind taking a look at this issue as it has been labeled with an integration (mqtt) you are listed as a code owner for? Thanks!

Code owner commands Code owners of `mqtt` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Change the title of the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign mqtt` Removes the current integration label and assignees on the issue, add the integration domain after the command.

(message by CodeOwnersMention)


mqtt documentation mqtt source (message by IssueLinks)

jbouwh commented 1 year ago

"None" is not a valid device class. Just leave the device_class config setting away if it is not meant to be set.

jbouwh commented 1 year ago

@emontnemery Should we add None to the MQTT device_class validation so that it allows a JSON null assignment?

jbouwh commented 1 year ago

85106 allows to set None as device_class. Through discovery and in YAML you should use null in stead of "None", because else it will be treated a string, and "None" is not a valid device_class.

jerome-labidurie commented 1 year ago

Wow, that was a quick fix !

I've just done some tests on the merged branch (BTW, very nice developer doc&tooling :star_struck:)

And everything works ok for me. either by sending the discovery json

mosquitto_pub -r -h 192.168.1.20 -p 1883 -t "homeassistant/sensor/GenericSensor/config" -m '{"name": "Generic Sensor", "state_topic": "homeassistant/sensor/GenericSensor/state", "availability_topic": "homeassistant/sensor/GenericSensor/available", "unique_id": "GenericSensor", "device_class": null, "unit_of_measurement": ""}'

Or via python

client.publish("homeassistant/sensor/GenericSensor/config", json.dumps({"name": "Generic Sensor", "state_topic": "homeassistant/sensor/GenericSensor/state", "availability_topic": "homeassistant/sensor/GenericSensor/available", "unique_id": "GenericSensor", "device_class":None}),retain=True)

Thank you very much for the fix and the speed ;)

Best regards