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

Fix battery reporting and address an issue with use of fahrenheit as the unit #3043

Merged

Conversation

nkasrawi
Copy link
Contributor

@nkasrawi nkasrawi commented Sep 18, 2021

I recently installed a Centralite Pearl thermostat and I'm in the US so of course we use Fahrenheit here. The battery was always reporting 27% capacity even when the batteries were fresh, so I made a change which now reports 100% on fresh batteries - I'm still waiting to see what happens if/when the batteries drain (they are a battery backup so it may be a while).

I also ran into the issue as a result of using Fahrenheit. Since the zigbee spec requires the use of Celsius for temperatures, the input values for the setpoints have to be set in Celsius. In the case where the user supplied input values are fahrenherit, the automation software (in my case openhab) is responsible for converting them into Celsius. However, the logic in the herdsman converters truncates input Celsius values to +/- 0.5 by doing:

Math.round((value * 2).toFixed(1)) / 2

This resulted in an unfortunate situation because the final effective Fahrenheit value that was being sent to the thermostat in Celsius was often different from the original provided integer value - sometimes by almost one full degree fahrenheit.

My revised solution based on @Koenkk suggestion is to introduce a configuration variable which can be set on the thermostat configuration and which controls conditional logic which will either perform the current logic (if using Celsius) or perform the following alternate logic (if using Fahrenheit):

  1. Convert the input Celsius value back to Fahrenheit
  2. Apply the same rounding logic to truncate the input Fahrenheit value to 0.0/0.5 as appropriate
  3. Convert the rounded Fahrenheit value back to Celsius and round to 2 decimals

This will ensure that the final read back Celsius value, when converted to Fahrenheit will be aligned to 0.0/0.5.

To trigger this specific behavior, include a configuration value for the specific device:

 '0x000d6f000b4f5868':
    friendly_name: upstairs_thermostat
    thermostat_unit: 'fahrenheit'

I also removed the references to unoccupied setpoints since this thermostat doesn't understand that concept.

…values to the setpoints

are not truncated to 0.5 before being set since doing so makes it
very difficult to achieve close to integer fahrenheit settings - owing to the fact
that it appears the only way to set values for thermostats within this framework
is using celsius.
@Koenkk
Copy link
Owner

Koenkk commented Sep 18, 2021

The Zigbee spec is in celsius, therefore all Zigbee devices are controlled through celsius.

Instead of adding a new converter, I suggest to take a more generic approach by modifying the existing converters (e.g. thermostat_occupied_heating_setpoint) by making the unit configurable. This can be done by:

  • To your configuration.yaml
devices:
  '0x12345678':
    friendly_name: 'my thermostat'
    thermostat_unit: 'fahrenheit'

- For the `toZigbee` converters you can access this option via: `meta.options.thermostat_unit`
- For the `fromZigee` converters it is: `options.thermostat_unit`
- If the option is set, convert from Fahrenheit -> celsius.

1) Define a new config value that allows a thermostat to be designated as fahrenheit
2) If the config flag is set, convert the incoming celsius value (which was already converted from an original input fahrenheit value in the controlling software) back to fahrenheit.
3) Now round the converted fahrenheit value to 0 or 0.5 as appropriate
4) Now convert the resulting fahrenheit value back to celsius and round it to two decimal places

The reult is that the thermostat will be set with a setpoint in celsius which will be equivalent to the rounded fahrenheit value based on the original fahrenheit provided by the controlling software.

Example:

User entered input value is 71.8 F
71.8 F = 21.111111111 C
convert 21.11 C (input to zigbee-herdsman-converters) to F: = 71.798 F
Round 71.798 F to 72 F
Concert 72 F to 22.2222222 C
22.22 C = 71.996 F
When the value is read back by the user it will be represnted as 72 F
…values to the setpoints

are not truncated to 0.5 before being set since doing so makes it
very difficult to achieve close to integer fahrenheit settings - owing to the fact
that it appears the only way to set values for thermostats within this framework
is using celsius.
1) Define a new config value that allows a thermostat to be designated as fahrenheit
2) If the config flag is set, convert the incoming celsius value (which was already converted from an original input fahrenheit value in the controlling software) back to fahrenheit.
3) Now round the converted fahrenheit value to 0 or 0.5 as appropriate
4) Now convert the resulting fahrenheit value back to celsius and round it to two decimal places

The reult is that the thermostat will be set with a setpoint in celsius which will be equivalent to the rounded fahrenheit value based on the original fahrenheit provided by the controlling software.

Example:

User entered input value is 71.8 F
71.8 F = 21.111111111 C
convert 21.11 C (input to zigbee-herdsman-converters) to F: = 71.798 F
Round 71.798 F to 72 F
Concert 72 F to 22.2222222 C
22.22 C = 71.996 F
When the value is read back by the user it will be represnted as 72 F
@nkasrawi
Copy link
Contributor Author

My revised solution based on @Koenkk suggestion is to introduce a configuration variable which can be set on the thermostat configuration and which controls conditional logic which will either perform the current logic (if using Celsius) or perform the following alternate logic (if using Fahrenheit):

  1. Convert the input Celsius value back to Fahrenheit
  2. Apply the same rounding logic to truncate the input Fahrenheit value to 0.0/0.5 as appropriate
  3. Convert the rounded Fahrenheit value back to Celsius and round to 2 decimals

This will ensure that the final read back Celsius value, when converted to Fahrenheit will be aligned to 0.0/0.5.

To trigger this specific behavior, include a configuration value for the specific device:

'0x000d6f000b4f5868':
friendly_name: upstairs_thermostat
thermostat_unit: 'fahrenheit'

converters/toZigbee.js Outdated Show resolved Hide resolved
converters/toZigbee.js Outdated Show resolved Hide resolved
@Koenkk Koenkk merged commit 4887272 into Koenkk:master Sep 22, 2021
@Koenkk
Copy link
Owner

Koenkk commented Sep 22, 2021

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants