zigbee2mqtt icon indicating copy to clipboard operation
zigbee2mqtt copied to clipboard

Ubisys H1: Setting pi_heating_demand possible according to docs, but not working

Open thmang82 opened this issue 5 months ago • 10 comments

What happened?

SW: zigebee2mqtt Version 2.6.2 HW: Ubisys H1 Thermostat https://www.zigbee2mqtt.io/devices/H1.html

According to the Zigbee2mqttt documentation for Ubisys H1, the "pi_heating_demand" can be set:

pi_heating_demand: Position of the valve (= demanded heat) where 0% is fully closed and 100% is fully open. To control publish a message to topic zigbee2mqtt/FRIENDLY_NAME/set with payload {"pi_heating_demand": VALUE} where VALUE is the % between 0 and 100. To read send a message to zigbee2mqtt/FRIENDLY_NAME/get with payload {"pi_heating_demand": ""}.

When I run that zigbee2mqtt/FRIENDLY_NAME/set command, pi_heating_demand is not changing. The zigbee2mqtt UI also has no setting for pi_heating_demand.

Is this a documentation issue? Or an issue in the implementation?

The H1 is a well build thermostat. Full-metal attachment, hardware seems really solid. But without the ability for controlling pi_heating_demand, it's would be quite feature limited.

@sjorge I have seen you have worked on the H1 implementation. Any idea if it should be possible to control the valve directly?

Best regards, Thomas

PS: Offtopic to the issue above: Any chance for making writing the remote_temperature field possible? It can be bound to a sensor according to the cods, but that has it's drawbacks (e.g. multiple temp sensors cannot be combined)

What did you expect to happen?

No response

How to reproduce it (minimal and precise)

No response

Zigbee2MQTT version

2.6.2

Adapter firmware version

7.4.5 [GA]

Adapter

EmberZNet

Setup

Pi4 with docker

Device database.db entry

No response

Debug log

No response

thmang82 avatar Oct 05 '25 20:10 thmang82

I'm traveling for a month so I can't double check, but I'm 95% certain you can't write to pi_heating_demand. It's weird the docs mention it why the webui doesn't as it should pull from the same data.

sjorge avatar Oct 05 '25 20:10 sjorge

Yeah, looks like it, found the technical documentation here: https://www.ubisys.de/downloads/ubisys-h1-technical-reference.pdf

0x0008 Unsigned8, read-only, reportable PIHeatingDemand Quantifies the amount of heating required from a heating device in order to reach the active heating setpoint, as determined by the PI control loop. This is a steering value in the range 0…100%.

Looks like the only way getting that functionality would be asking them for a firmware update. I will try ...

Would be nice if the documentation could be fixed though. Otherwise there might be more people buying such thermostats for features that they do not support.

Edit: Corrected wrong citation

thmang82 avatar Oct 05 '25 21:10 thmang82

@Koenkk it seems the extend info is correct, does the doc site not get the read/write info from this?

sjorge avatar Oct 05 '25 22:10 sjorge

I am no expert of the code, but this seems to be the relevant code block: https://github.com/sjorge/zigbee-herdsman-converters/blob/2e3ba66444714ec6a3aafb5ccae72d22f0668b5c/src/devices/ubisys.ts#L1151

It looks to me that the "STATE_GET" is not evaluated somehow for the docs?

        zigbeeModel: ["H1"],
        model: "H1",
        vendor: "Ubisys",
        description: "Heating regulator",
        meta: {thermostat: {dontMapPIHeatingDemand: true}},
        fromZigbee: [fz.thermostat, fz.thermostat_weekly_schedule],
        toZigbee: [
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_unoccupied_heating_setpoint,
            tz.thermostat_local_temperature,
            tz.thermostat_system_mode,
            tz.thermostat_weekly_schedule,
            tz.thermostat_clear_weekly_schedule,
            tz.thermostat_running_mode,
            tz.thermostat_pi_heating_demand,
        ],
        exposes: [
            e
                .climate()
                .withSystemMode(["off", "heat"], ea.ALL)
                .withRunningMode(["off", "heat"])
                .withSetpoint("occupied_heating_setpoint", 7, 30, 0.5)
                .withSetpoint("unoccupied_heating_setpoint", 7, 30, 0.5)
                .withLocalTemperature()
                .withPiHeatingDemand(ea.STATE_GET)
                .withWeeklySchedule(["heat"]),
        ], ...```

thmang82 avatar Oct 06 '25 12:10 thmang82

That would indeed be my guess, although I'm not sure where the doc gen script lives.

sjorge avatar Oct 06 '25 23:10 sjorge

The code generator code can be found here: https://github.com/Koenkk/zigbee2mqtt.io/blob/d36fa3a2566c850d4f928fb1e17b166683d818dc/docgen/device_page_exposes.ts#L306

Koenkk avatar Oct 07 '25 20:10 Koenkk

I could only find very few places in the code that evaluates if an attribute is writable (has access.SET). This is the most prominent place: https://github.com/Koenkk/zigbee2mqtt.io/blob/d36fa3a2566c850d4f928fb1e17b166683d818dc/docgen/device_page_exposes.ts#L98 This check only applies for this condition though:

if (['numeric', 'binary', 'text', 'enum'].includes(expose.type)) ...

pi_heating_demand however is a sub-entry under 'climate'.

The getExposeDocs() function does run on 'climate', but it does not run on the sub-elements below climate.

getExposeDocs() handles the sub-elements under climate with dedicated code (the deep link that @Koenkk provided). If i understand that dedicated code correct, there is no check on writability for all sub-elements below climate :-(

Can somebody with more knowledge of the doc-generator code verify this finding?

PS1: "access.SET" can only be found in 3 places in the code. I wonder if there are more places where the ability of setting is not correctly evaluated for sub-entries in the docs? PS2: I understand now why it's only possible to search for "climate" in the device list. Always wondered why I cannot search for the pi_heating_demand, let alone the info if it is writable. There might be some room for improvement?

thmang82 avatar Oct 11 '25 21:10 thmang82

@thmang82: It's because the code for the climate feature and their attributes doesn't consider the access state at all. I rewrite the code right now to take that into consideration.

But you're right, there might be more places where the access state isn't being considered as well. šŸ¤”

DerDreschner avatar Nov 01 '25 15:11 DerDreschner

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Jan 01 '26 00:01 github-actions[bot]

@DerDreschner Any update on the documentation fix?

https://www.zigbee2mqtt.io/devices/H1.html still says: pi_heating_demand: Position of the valve (= demanded heat) where 0% is fully closed and 100% is fully open. To control publish a message to topic zigbee2mqtt/FRIENDLY_NAME/set with payload {"pi_heating_demand": VALUE}

thmang82 avatar Jan 02 '26 20:01 thmang82

I’m not familiar with the docgen at all, I know the expose data is correct (STATE_GET) and the ui also shows it as that.

sjorge avatar Jan 03 '26 09:01 sjorge