zwave-js / zwave-js-ui

Full featured Z-Wave Control Panel UI and MQTT gateway. Built using Nodejs, and Vue/Vuetify
https://zwave-js.github.io/zwave-js-ui
MIT License
919 stars 196 forks source link

Z-Wave-JS-UI Thermostats not Autodiscovering all devices - missing Cooling Setpoint, Fan Control, Fan State, Operating State. #3697

Closed eagle360 closed 1 month ago

eagle360 commented 2 months ago

Version

zwave-js-ui: 9.12.0 zwave-js: 12.5.6 Domoticz 2024.4

Describe the bug

After many months and a lot of searching around I was not able to find any solutions or get any help with this issue and now that summer is on it's way I was running out of time and decided to really dig into this.

First off I can't find any useful documentation for Auto discovery climate topics. Nothing on setpoints, Modes, Operating State, etc. I have looked over (https://www.home-assistant.io/integrations/mqtt/) and it is mostly useless for this issue. Update: Well I finally found this link somehow for the climate configurations. https://www.home-assistant.io/integrations/climate.mqtt/ - It helps but only confirms everything I have found out so far.

The problem is Thermostat Auto discovery is not working with Z-wave-JS-UI and Domoticz. Specifically with Remotec ZTS-110 Z and CT100 thermostats. They both have the same issues: Missing devices in Domoticz:

The missing devices are: Cooling Setpoint, Fan Mode control, Fan Mode state, Operating state.

There are issues with Domoticz but also with z-wave-js-ui.

All the basic Functions of these thermostats are implemented and working in z-wave-js-ui interface and in the MQTT topics but the Auto discovery is not working.

On the z-wave-js-ui side the HASS Device JSON is not complete for these Thermostat devices.

Below is what Z-wave-JS-UI is generating for a climate Home Assistant - Devices entry.

{
  "type": "climate",
  "object_id": "climate",
  "discovery_payload": {
    "min_temp": 5,
    "max_temp": 40,
    "temp_step": 0.5,
    "modes": [
      "off",
      "heat",
      "cool",
      "auto"
    ],
    "mode_state_template": "{{ {0: \"off\", 1: \"heat\", 2: \"cool\", 3: \"auto\"}[value_json.value] | default('off') }}",
    "current_temperature_topic": "zwave/Test/ThermostatTest2/49/0/Air_temperature",
    "current_temperature_template": "{{ value_json.value }}",
    "temperature_state_topic": "zwave/Test/ThermostatTest2/67/0/setpoint/1",
    "temperature_state_template": "{{ value_json.value }}",
    "temperature_command_topic": "zwave/Test/ThermostatTest2/67/0/setpoint/1/set",
    "mode_state_topic": "zwave/Test/ThermostatTest2/64/0/mode",
    "mode_command_topic": "zwave/Test/ThermostatTest2/64/0/mode/set",
    "action_topic": "zwave/Test/ThermostatTest2/66/0/state",
    "action_template": "{{ {0: \"idle\", 1: \"heating\", 2: \"cooling\", 3: \"fan\", 4: \"idle\", 5: \"idle\", 6: \"fan\", 7: \"heating\", 8: \"heating\", 9: \"cooling\", 10: \"heating\", 11: \"heating\"}[value_json.value] | default('idle') }}",
    "temperature_unit": "F",
    "precision": 0.1,
    "device": {
      "identifiers": [
        "zwavejs2mqtt_0xe24caefc_node35"
      ],
      "manufacturer": "Remotec",
      "model": "ZTS-110 Z Wave Thermostat (ZTS-110)",
      "name": "Test-ThermostatTest2",
      "sw_version": "3.14"
    },
    "availability": [
      {
        "payload_available": "true",
        "payload_not_available": "false",
        "topic": "zwave/Test/ThermostatTest2/status",
        "value_template": "{{'true' if value_json.value else 'false'}}"
      },
      {
        "topic": "zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/status",
        "value_template": "{{'online' if value_json.value else 'offline'}}"
      },
      {
        "payload_available": "true",
        "payload_not_available": "false",
        "topic": "zwave/driver/status"
      }
    ],
    "availability_mode": "all",
    "name": "Test-ThermostatTest2_climate",
    "unique_id": "zwavejs2mqtt_0xe24caefc_Node35_climate"
  },
  "values": [
    "49-0-Air temperature",
    "64-0-mode",
    "67-0-setpoint-1",
    "67-0-setpoint-2",
    "67-0-setpoint-1",
    "66-0-state"
  ],
  "mode_map": {
    "off": 0,
    "heat": 1,
    "cool": 2,
    "auto": 3
  },
  "setpoint_topic": {
    "1": "67-0-setpoint-1",
    "2": "67-0-setpoint-2",
    "3": "67-0-setpoint-1"
  },
  "default_setpoint": "67-0-setpoint-1",
  "action_map": {
    "0": "idle",
    "1": "heating",
    "2": "cooling",
    "3": "fan",
    "4": "idle",
    "5": "idle",
    "6": "fan",
    "7": "heating",
    "8": "heating",
    "9": "cooling",
    "10": "heating",
    "11": "heating"
  },
  "discoveryTopic": "climate/Test-ThermostatTest2/climate/config",
  "persistent": false,
  "ignoreDiscovery": false,
  "id": "climate_climate"
}

This JSON config above is missing the second Cooling setpoint : "zwave/Test/ThermostatTest2/67/0/setpoint/2", the Fan Mode : "zwave/Test/ThermostatTest2/68/0/mode" Fan Mode state: "zwave/Test/ThermostatTest2/69/0/state"

Update: Looks like the HA autodiscover specification does not allow for multiple setpoints (very strange) so that seems to indicate that a second climate Home Assistant - Devices entry would be required to create additional setpoints. With Domoticz, at least, a different "unique_id": is required for each climate config topic. I.E "unique_id": "zwavejs2mqtt_0xe24caefc_Node35_climate" & "unique_id": "zwavejs2mqtt_0xe24caefc_Node35_climate2"

After lot of trial and error with the JSON and then getting pointed towards manually creating an Auto discover config topic directly in MQTT I was able to come up with the following to get Domoticz to manually add a second Cooling setpoint and Fan Mode device:

Added MQTT topic with retain : domoticz/climate/Test-ThermostatTest2/climate2/config with

{
  "min_temp": 41,
  "max_temp": 99,
  "temp_step": 1,
  "modes": [
    "Off",
    "Low"
  ],
  "mode_state_template": "{{ {0: \"Off\", 1: \"Low\"}[value_json.value] | default('Off') }}",
  "temperature_state_topic": "zwave/Test/ThermostatTest2/67/0/setpoint/2",
  "temperature_state_template": "{{ value_json.value }}",
  "temperature_command_topic": "zwave/Test/ThermostatTest2/67/0/setpoint/2/set",
  "mode_state_topic": "zwave/Test/ThermostatTest2/68/0/mode",
  "mode_command_topic": "zwave/Test/ThermostatTest2/68/0/mode/set",
  "action_topic": "zwave/Test/ThermostatTest2/66/0/state",
  "temperature_unit": "F",
  "precision": 0.1,
  "device": {
    "identifiers": [
      "zwavejs2mqtt_0xe24caefc_node35"
    ],
    "manufacturer": "Remotec",
    "model": "ZTS-110 Z Wave Thermostat (ZTS-110)",
    "name": "Test-ThermostatTest2",
    "sw_version": "3.14"
  },
  "name": "Test-ThermostatTest2_climate2",
  "unique_id": "zwavejs2mqtt_0xe24caefc_Node35_climate2"
}

I am still missing the Operating State (66) and the Fan State (69). I will work on work arounds for those next.

robertsLando commented 2 months ago

You could provide a custom config to fix the problem and once you get a working one submit a PR

eagle360 commented 2 months ago

I have no way to test this until Domoticz fixes their MQTT-AD for climate topics. I opened an issue for this in the Domoticz gitbub forum, as well, but so far have just been met with denial (and get z-wave-js-ui to fix it).

I also don't see that the MQTT-AD really supports more than one setpoint per config topic so it may be that two config topics are required (or maybe I am just missing something).

It's strange that no one seems to be using any z-wave thermostats anymore. I have been asking around for a model that works but it may just be that none of them work anymore without manual intervention. It would be nice to see some other examples of the config topics for other Thermostats. I assume these same MQTT-AD topics are used for Zigbee as well. Maybe no one is using Zigbee thermostats either?

Also I noticed that the min_temp and max_temp are in C and should be in F.

  "min_temp": 41,
  "max_temp": 104,
  "temp_step": 1,

I have been posting what I have been finding that works to manually hack in these devices in the meantime so maybe other people will find this information useful. If MQTT-AD in Domoticz ever gets fixed and I find a working configuration(s) I will post it/them.

robertsLando commented 2 months ago

Thermostats are complicated with MQTT discovery, that's why a configuration is needed in order to make them work...

Also I noticed that the min_temp and max_temp are in C and should be in F.

I think that who did the template was using C that's why you see that. Check https://github.com/zwave-js/zwave-js-ui/blob/master/api/hass/devices.ts

More info about custom components here: https://zwave-js.github.io/zwave-js-ui/#/homeassistant/homeassistant-mqtt?id=custom-components

eagle360 commented 1 month ago

One problem is Domoticz has no way to do the custom configurations like HA appears to.

So apparently there is more wrong here than initially meets the eye. I don't know if this is just a Domoticz issue or if HA is implemented the same way but apparently someone thought you could get away with a single thermostat setpoint for both heating and cooling. So it appears that Domoticz has implemented the MQTT-AD such that a single thermostat setpoint is used for both heating and cooling setpoints. (Still doesn't explain why Fan mode is not supported). If the mode of the Thermostat is Heating then the single setpoint controls the heating setpoint in the Thermostat and if the thermostat mode is Cooling it controls the cooling setpoint. However in Auto it only controls the heating setpoint in the thermostat so the auto mode can not be used. If you add a second cooling setpoint like I did above now you have two setpoints to use in Auto mode but in Cooling mode Domoticz is mapping the heating setpoint to the cooling so they both are controlling and showing the value of the cooling setpoint. Not sure what kinds of problems this will cause besides just not indicating the correct heating setpoint.

Probably a bigger potential issue is that periodically while in Heating mode Domoticz will set the Cooling setpoint to the heating setpoint so if you then switch to cooling you may end up with a nice electric bill. Especially after a nighttime heating setback temperature like 65.

So I guess if someone just doesn't need the Auto Mode of the Thermostat (or fan control) they can probably live with this broken implementation. However if you live in a climate that needs the Auto mode you will need to add a cooling setpoint. And then just make sure when the mode is switched both the cooling and heating setpoint are updated as they may have been incorrectly set.

robertsLando commented 1 month ago

One problem is Domoticz has no way to do the custom configurations like HA appears to.

Why not? The custom config is on zui side and is needed in order to build the correct config payload on discovery

I also don't understand well what you mean with above comment as on zui side when the mode changes the device is re-discovered with the correct setpoint topic (the device config is mostly needed for this to understand what setpoint to use based on the mode)

https://github.com/zwave-js/zwave-js-ui/blob/fd09755ff8dc1a84eba448a9ba4f59a7fcfbef4b/api/lib/Gateway.ts#L1941-L1961

eagle360 commented 1 month ago

Ok there is a lot going on here. So I see now that zui is changing the MQTT-AD config topic when the thermostat mode is being switched. And I see that it changes it even though I am using an HASS Device JSON with "persistent": true, and stored.

In which case how would I stop this?

Is there a way to set each of the different HASS Device JSON for each thermostat mode?

At this point I just need to stop the different config topics from being sent when the modes change but if there is a way to configure all 4 of the different config topics I guess I could do that as well.

robertsLando commented 1 month ago

Just create a single entry in setpoint_topic with the single topic you want to map and when the mode changes it will not find a valid topic to switch so the new discovery will not happen. See https://zwave-js.github.io/zwave-js-ui/#/homeassistant/homeassistant-mqtt?id=custom-components

eagle360 commented 1 month ago

Ok I think I see what you are talking about.

That seemed to work to keep the setpiont mapped to the heating setpoint in all the modes. Thanks.

eagle360 commented 1 month ago

Not sure this should be closed as there is no Fan Mode configuration in the HASS Device JSON.

Also is there any way to manually add additional Home Assistant - Devices to z-wave-js-ui so the additional climate configuration can be added in z-wave-js-ui?

image

robertsLando commented 1 month ago

Not sure this should be closed as there is no Fan Mode configuration in the HASS Device JSON.

@eagle360 Like explained on docs I cannot support all different devices but I explained to users how to deal with them, this mostly because in order to do good tests of this I would need to have one of this devices with me and that's impossible. I linked you all the informations you need in order to fix the discovery payload to add the fan mode to your thermostat

Also is there any way to manually add additional Home Assistant - Devices to z-wave-js-ui so the additional climate configuration can be added in z-wave-js-ui?

Yes but that's a bit tricky, you should store discovery devices and then manually edit the nodes.json from store UI to add another configuration (you can just clone an existing one and then restart the application and edit it from UI). You can do the opposite BTW https://zwave-js.github.io/zwave-js-ui/#/homeassistant/homeassistant-mqtt?id=manually-create-entities.

eagle360 commented 1 month ago

In case someone else is looking to get their Auto mode thermostat working as described in this post. Follow the instructions above to add the cooling setpoint config topic and then use the following climate HASS Device JSON in z-wave-js-ui so the heating setpoint does not change when the thermostat mode is changed:

{
  "type": "climate",
  "object_id": "climate",
  "discovery_payload": {
    "min_temp": 41,
    "max_temp": 99,
    "temp_step": 1,
    "modes": [
      "off",
      "heat",
      "cool",
      "auto"
    ],
    "mode_state_template": "{{ {0: \"off\", 1: \"heat\", 2: \"cool\", 3: \"auto\"}[value_json.value] | default('off') }}",
    "current_temperature_topic": "zwave/Test/ThermostatTest3/49/0/Air_temperature",
    "current_temperature_template": "{{ value_json.value }}",
    "temperature_state_topic": "zwave/Test/ThermostatTest3/67/0/setpoint/1",
    "temperature_state_template": "{{ value_json.value }}",
    "temperature_command_topic": "zwave/Test/ThermostatTest3/67/0/setpoint/1/set",
    "mode_state_topic": "zwave/Test/ThermostatTest3/64/0/mode",
    "mode_command_topic": "zwave/Test/ThermostatTest3/64/0/mode/set",
    "action_topic": "zwave/Test/ThermostatTest3/66/0/state",
    "action_template": "{{ {0: \"idle\", 1: \"heating\", 2: \"cooling\", 3: \"fan\", 4: \"idle\", 5: \"idle\", 6: \"fan\", 7: \"heating\", 8: \"heating\", 9: \"cooling\", 10: \"heating\", 11: \"heating\"}[value_json.value] | default('idle') }}",
    "temperature_unit": "F",
    "precision": 0.1,
    "device": {
      "identifiers": [
        "zwavejs2mqtt_0xe24caefc_node37"
      ],
      "manufacturer": "Remotec",
      "model": "ZTS-110 Z Wave Thermostat (ZTS-110)",
      "name": "Test-ThermostatTest3",
      "sw_version": "3.14"
    },
    "availability": [
      {
        "payload_available": "true",
        "payload_not_available": "false",
        "topic": "zwave/Test/ThermostatTest3/status",
        "value_template": "{{'true' if value_json.value else 'false'}}"
      },
      {
        "topic": "zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/status",
        "value_template": "{{'online' if value_json.value else 'offline'}}"
      },
      {
        "payload_available": "true",
        "payload_not_available": "false",
        "topic": "zwave/driver/status"
      }
    ],
    "availability_mode": "all",
    "name": "Test-ThermostatTest3_climate",
    "unique_id": "zwavejs2mqtt_0xe24caefc_Node37_climate"
  },
  "values": [
    "49-0-Air temperature",
    "64-0-mode",
    "67-0-setpoint-1",
    "66-0-state"
  ],
  "mode_map": {
    "off": 0,
    "heat": 1,
    "cool": 2,
    "auto": 3
  },
  "setpoint_topic": {
    "1": "67-0-setpoint-1"
  },
  "default_setpoint": "67-0-setpoint-1",
  "action_map": {
    "0": "idle",
    "1": "heating",
    "2": "cooling",
    "3": "fan",
    "4": "idle",
    "5": "idle",
    "6": "fan",
    "7": "heating",
    "8": "heating",
    "9": "cooling",
    "10": "heating",
    "11": "heating"
  },
  "discoveryTopic": "climate/Test-ThermostatTest3/climate/config",
  "persistent": true,
  "ignoreDiscovery": false,
  "id": "climate_climate"
}
eagle360 commented 1 month ago

@robertsLando Thank you very much for your prompt assistance and your over all effort to build and maintain this tool.

robertsLando commented 1 month ago

@eagle360 Thanks to you for also sharing your findings 🙏🏼