Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update opentherm_gw.sensor to use entity_description #124283

Merged
merged 1 commit into from
Aug 20, 2024

Conversation

mvn23
Copy link
Contributor

@mvn23 mvn23 commented Aug 20, 2024

Proposed change

Modernize the opentherm_gw integration by using entity_description for the sensor platform

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

Copy link
Member

@joostlek joostlek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just leaving a bunch of questions on what sensors return. We could use some nice device classes like enum to enhance their usability

Comment on lines +54 to +67
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_MASTER_MEMBERID,
friendly_name_format="Thermostat Member ID {}",
),
),
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_SLAVE_MEMBERID,
friendly_name_format="Boiler Member ID {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those 2 sensors return the member IDs as reported by the thermostat and the boiler, respectively. From what I gather so far it seems to be an ID that the OpenTherm Association assigns to its members (equipment manufacturers).
In my setup, the thermostat reports member ID 13 (99% sure it's a Honeywell) and the boiler returns 24(Vaillant I believe), I can't verify the manufacturers right now as I won't be home for another while.
It is a value between 0 and 255, where ID 0 is reserved for a customer non-specific device. I have not been able to find a complete list of IDs and manufacturers as the OpenTherm Association is remarkably closed for an entity with a name like that...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these sensors can be deprecated in the future to be replaced with a device info manufacturer. You could use logging in the library to identify new member IDs and complete the list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by logging? Like notifying users through HA and asking them to report their values and manufacturers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I do this in Withings, since they have some undocumented values, so if the value is not in the enum, I will log a message asking people to open an issue in the lib repo

Comment on lines +68 to +74
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_SLAVE_OEM_FAULT,
friendly_name_format="Boiler OEM Fault Code {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boiler manufacturers can return a manufacturer-specific fault code between 0 and 255, which will be reported in this sensor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a list of them? Can we do an attempt to collect all the possible values from users and then complete the manufacturer specific list and add names to them so they can be contextualized?

Copy link
Contributor Author

@mvn23 mvn23 Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As they are manufacturer-specific and hopefully rare I doubt that's feasible. It would have to be combined with the manufacturer info, basically requiring a separate list of codes to be populated for every manufacturer out there.

I haven't found a list of them for any manufacturer so far.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont they have a manual with these codes?

Comment on lines +361 to +367
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_OEM_DIAG,
friendly_name_format="OEM Diagnostic Code {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sensor reports a manufacturer-specific diagnostic/service code from the boiler. Possible values are between 0 and 65535.

Comment on lines +404 to +413
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_TOTAL_BURNER_HOURS,
friendly_name_format="Total Burner Hours {}",
device_class=SensorDeviceClass.DURATION,
state_class=SensorStateClass.TOTAL,
native_unit_of_measurement=UnitOfTime.HOURS,
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this only increase? Should this use total_increasing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It normally only increases, but it wraps after 65535. Some boilers allow resetting the value to 0, but support for this is not mandatory (and we don't provide a mechanism for it in HA apart from sending a raw protocol command through SERVICE_SEND_TRANSP_CMD). I chose SensorStateClass.TOTAL as per the dev docs for a value that only increases.

Comment on lines +444 to +459
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_MASTER_OT_VERSION,
friendly_name_format="Thermostat OpenTherm Version {}",
suggested_display_precision=SENSOR_FLOAT_SUGGESTED_DISPLAY_PRECISION,
),
),
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_SLAVE_OT_VERSION,
friendly_name_format="Boiler OpenTherm Version {}",
suggested_display_precision=SENSOR_FLOAT_SUGGESTED_DISPLAY_PRECISION,
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does a version have a display precision?

Are the thermostat and the boiler 2 separate devices? Should we split them up and use the device_info sw_version for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The display precision is there because the version is reported in the protocol as a float. OpenTherm floats are only accurate to 1/256th, so the precision is there to make sure a value of 0.1 doesn't show as 0,1015625 or 0,09765625.

The thermostat and boiler are indeed 2 different devices, the OpenTherm Gateway sits in between them.
I could separate them into 3 devices, but as support for a lot of features is optional and differ hugely between different manufacturers and models, most of them would end up with loads of unknown values. Neither my thermostat nor my boiler report their OpenTherm Version, for example.

If it is still considered a good idea to split these devices, then I suggest to make it a separate PR as that operation will be a bit more involved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yea definitely, I just picked this PR to leave comments because I can leave comments for every sensor. I think it would be nice to create separate devices for them, also because in the end we want to move to _attr_has_entity_name = True, which means that naming is going to change to {device} {entity name}. So if we could have a device for a boiler, thermostat and otgw, we can make it nicer and also allow the user to place the device in the right area. (as I can imagine you probably have your thermostat in the living room, but your boiler in the attic)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like, every comment I leave here is not a blocker, it's just asking the right questions to give hints and a bit of direction to how we can make it even better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like the way to go is different devices. So far I have used the source info in the friendly name and entity_id to differentiate between values known by the thermostat and boiler respectively (they are not always the same), but different devices could make that separation clearer. There has actually already been some confusion about this that lead to a bug report in the past.

Comment on lines +488 to +494
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_MODE,
friendly_name_format="Gateway/Monitor Mode {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the possible states

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 (Monitor mode), 1 (Gateway mode) or R (reset), the latter being a transient mode that is used to reset the OpenTherm Gateway.
I would have to dig deeper to see if this sensor could possibly have value R.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be a good example for a refactor. So we have the ENUM device class. This sets up the sensor with a predefined list of options, which can be translated. Because the sensor has predefined options, we can use this in automations. So if you want to create an automation based on the state of an entity, we can just show a dropdown because we already know every possible state for example.

It would require a breaking change, as the value would go from 0 to monitor_mode (or monitor, whatever you prefer) and then we add the state translations in the strings.json. But since this would be breaking, please do this in a separate PR (I would recommend adding this after we sorted out device translations and potentially the split of devices)

Comment on lines +460 to +488
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_MASTER_PRODUCT_TYPE,
friendly_name_format="Thermostat Product Type {}",
),
),
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_MASTER_PRODUCT_VERSION,
friendly_name_format="Thermostat Product Version {}",
),
),
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_SLAVE_PRODUCT_TYPE,
friendly_name_format="Boiler Product Type {}",
),
),
(
[gw_vars.BOILER, gw_vars.THERMOSTAT],
OpenThermSensorEntityDescription(
key=gw_vars.DATA_SLAVE_PRODUCT_VERSION,
friendly_name_format="Boiler Product Version {}",
),
),
(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look static and don't belong in a sensor tbh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They could be used to populate the device info when splitting off the thermostat and boiler into separate devices, but in my case all of these are unknown as support is not mandatory for manufacturers.

Comment on lines +495 to +578
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_DHW_OVRD,
friendly_name_format="Gateway Hot Water Override Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_ABOUT,
friendly_name_format="Gateway Firmware Version {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_BUILD,
friendly_name_format="Gateway Firmware Build {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_CLOCKMHZ,
friendly_name_format="Gateway Clock Speed {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_A,
friendly_name_format="Gateway LED A Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_B,
friendly_name_format="Gateway LED B Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_C,
friendly_name_format="Gateway LED C Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_D,
friendly_name_format="Gateway LED D Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_E,
friendly_name_format="Gateway LED E Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_LED_F,
friendly_name_format="Gateway LED F Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_GPIO_A,
friendly_name_format="Gateway GPIO A Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_GPIO_B,
friendly_name_format="Gateway GPIO B Mode {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hot Water Override Mode: 0/1 (override active in off/on mode) or A (override inactive)

Firmware version/build/clock speed: Info about the OpenTherm Gateway firmware/hardware. Could possibly be integrated in device info?

LED/GPIO modes: configured modes for the different LEDs and GPIO pins on the gateway. LED mode is one of RXTBOFHWCEMP and GPIO mode is in the range 0 through 8.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like good examples for enum sensors as well

Comment on lines +590 to +617
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_SETP_OVRD_MODE,
friendly_name_format="Gateway Room Setpoint Override Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_SMART_PWR,
friendly_name_format="Gateway Smart Power Mode {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_THRM_DETECT,
friendly_name_format="Gateway Thermostat Detection {}",
),
),
(
[gw_vars.OTGW],
OpenThermSensorEntityDescription(
key=gw_vars.OTGW_VREF,
friendly_name_format="Gateway Reference Voltage Setting {}",
),
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Room Setpoint Override Mode: One of T (Temporary Override), C (Constant/Permanent override) or N (Override disabled)

Smart Power Mode: The active smart power mode (low/medium/high)

Thermostat Detection: The thermostat detection mode in use by the gateway. Some thermostats have quirks that need to be handled, but detection is not always reliable. The active mode can be changed between C (force Remeha Celsia 20), I (force Remeha iSense), S (force standard thermostat) or D (auto-detect).

Reference voltage setting: The gateway has an adjustable reference voltage that is used to receive protocol messages. This reports that setting in a range between 0 and 9, where actual voltages depend on the PIC used in the gateway.

Copy link
Member

@joostlek joostlek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine for now, we've discussed improvement points. I think when you start creating the separate devices, it would be nice to also split up the list into 3 so it's clear what entity creates what

@joostlek joostlek merged commit b1d9e55 into home-assistant:dev Aug 20, 2024
26 checks passed
@mvn23 mvn23 deleted the opentherm-sensor-update branch August 21, 2024 10:18
@github-actions github-actions bot locked and limited conversation to collaborators Aug 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

temp. sensor group fails during boot
2 participants