Update current temperature for Z-Wave thermostats

I don’t remember where exactly, here my python file to compare

"""
Update Z-Wave thermostats (e.g. Danfoss 014G0013) state and current temperature
from sensor.
Arguments:
 - rooms           - list of rooms (required)
 - thermostat      - thermostat entity_id (required)
 - sensor          - temperature sensors entity_id (required)
 - heat_state      - name of heating state, default 'heat' (optional)
 - idle_state      - name of idle state, default 'off' (optional)
 - idle_heat_temp  - temperature value between 'idle' and 'heat' states,
                     default 8 (optional)
 - state_only      - with state_only set to 'true' app will update only
                     state of the thermostat, default false (optional)
 - temp_only       - with temp_only set to 'true' app will update only
                     current_temperature of the thermostat, default false
                     (optional)
 - wait_for_zwave  - defines whether the script has to wait for the
                     initialization of the Z-wave component
                     after Home Assistant restart, default True (optional)

Configuration example:

thermostats_update:
  module: thermostats-update
  class: ThermostatsUpdate
  rooms:
    kitchen:
      thermostat: climate.thermostat_kitchen
      sensor: sensor.temperature_kitchen
    room:
      thermostat: climate.thermostat_room
      sensor: sensor.temperature_room
    bathroom:
      thermostat: climate.thermostat_bathroom
      sensor: sensor.temperature.bathroom
  heat_state: 'auto'
  idle_state: 'idle'
  idle_heat_temp: 10
  state_only: true
  wait_for_zwave: true

"""
import appdaemon.plugins.hass.hassapi as hass

ATTR_CURRENT_TEMP = "current_temperature"
ATTR_DEBUG = "debug"
ATTR_HVAC_MODE = "hvac_mode"
ATTR_HVAC_MODES = "hvac_modes"
ATTR_IDLE_HEAT_TEMP_DEFAULT = 8
ATTR_LOG_DEBUG = "DEBUG"
ATTR_LOG_INFO = "INFO"
ATTR_TEMPERATURE = "temperature"
ATTR_THERMOSTAT = "thermostat"
ATTR_WAIT_FOR_ZWAVE = "wait_for_zwave"
ATTR_HEAT_STATE = "heat_state"
ATTR_IDLE_STATE = "idle_state"
ATTR_IDLE_HEAT_TEMP = "idle_heat_temp"
ATTR_ROOMS = "rooms"
ATTR_SENSOR = "sensor"
ATTR_STATE_ONLY = "state_only"
ATTR_TEMP_ONLY = "temp_only"
ATTR_UNKNOWN = "unknown"
HVAC_HEAT = "heat"
HVAC_OFF = "off"


class ThermostatsUpdate(hass.Hass):
    def initialize(self):
        self.zwave_handle = None

        if ATTR_WAIT_FOR_ZWAVE in self.args:
            self.wait_for_zwave = self.args[ATTR_WAIT_FOR_ZWAVE]
        else:
            self.wait_for_zwave = True
        if ATTR_STATE_ONLY in self.args:
            self.state_only = self.args[ATTR_STATE_ONLY]
        else:
            self.state_only = False
        if ATTR_TEMP_ONLY in self.args:
            self.temp_only = self.args[ATTR_TEMP_ONLY]
        else:
            self.temp_only = False
        if self.temp_only and self.state_only:
            self.error("You can use state_only: true or temp_only: true, not both!")
            return
        if ATTR_HEAT_STATE in self.args:
            self.heat_state = self.args[ATTR_HEAT_STATE]
        else:
            self.heat_state = HVAC_HEAT
        if ATTR_IDLE_STATE in self.args:
            self.idle_state = self.args[ATTR_IDLE_STATE]
        else:
            self.idle_state = HVAC_OFF
        try:
            if ATTR_IDLE_HEAT_TEMP in self.args:
                self.idle_heat_temp = int(self.args[ATTR_IDLE_HEAT_TEMP])
            else:
                self.idle_heat_temp = ATTR_IDLE_HEAT_TEMP_DEFAULT
        except ValueError:
            self.error("Wrong arguments! Argument idle_heat_temp has to be an integer.")
            return
        self.log_level = ATTR_LOG_DEBUG
        if ATTR_DEBUG in self.args:
            if self.args[ATTR_DEBUG]:
                self.log_level = ATTR_LOG_INFO

        if self.wait_for_zwave and not self.zwave_entities_ready():
            self.log("Waiting for zwave.network_ready event...")
            self.zwave_handle = self.listen_event(
                self.start_listen_states, "zwave.network_ready"
            )
        else:
            self.start_listen_states(event=None, data=None, kwargs=None)

    def start_listen_states(self, event, data, kwargs):
        if self.zwave_handle is not None:
            self.cancel_listen_event(self.zwave_handle)
        self.log("Checking thermostats and sensors...")
        try:
            for room in self.args[ATTR_ROOMS]:
                thermostat = self.args[ATTR_ROOMS][room][ATTR_THERMOSTAT]
                if not self.entity_exists(thermostat):
                    self.error(
                        "Wrong arguments! Entity {} does not exist.".format(thermostat)
                    )
                    return
                if not self.state_only:
                    sensor = self.args[ATTR_ROOMS][room][ATTR_SENSOR]
                    if not self.entity_exists(sensor):
                        self.error(
                            "Wrong arguments! Entity {} does not exist.".format(sensor)
                        )
                        return
                self.listen_state(
                    self.thermostat_state_changed,
                    thermostat,
                    attribute=ATTR_CURRENT_TEMP,
                    new=None,
                )
                if not self.state_only:
                    self.listen_state(self.sensor_state_changed, sensor)
                if self.get_state(thermostat, attribute=ATTR_CURRENT_TEMP) is None:
                    self.thermostat_state_changed(
                        thermostat,
                        attribute=ATTR_CURRENT_TEMP,
                        old=None,
                        new=None,
                        kwargs=None,
                    )
            self.log("Ready for action...")
        except KeyError:
            self.error(
                "Wrong arguments! You must supply a valid sensors"
                "thermostats entities for each room."
            )

    def thermostat_state_changed(self, entity, attribute, old, new, kwargs):
        if not self.state_only:
            for room in self.args[ATTR_ROOMS]:
                if entity == self.args[ATTR_ROOMS][room][ATTR_THERMOSTAT]:
                    sensor_id = self.args[ATTR_ROOMS][room][ATTR_SENSOR]

        target_temp = self.get_state(entity, attribute=ATTR_TEMPERATURE)
        org_state = self.get_state(entity)
        if not self.state_only:
            sensor_temp = self.get_state(sensor_id)
            if sensor_temp and sensor_temp != ATTR_UNKNOWN:
                if not new or (
                    new != ATTR_UNKNOWN and float(new) != float(sensor_temp)
                ):
                    self.update_thermostat(entity, org_state, target_temp, sensor_temp)
            else:
                self.log("No temperature data on the sensor {}.".format(sensor_id))
        else:
            self.update_thermostat(entity, org_state, target_temp, None)

    def sensor_state_changed(self, entity, attribute, old, new, kwargs):
        for room in self.args[ATTR_ROOMS]:
            if entity == self.args[ATTR_ROOMS][room][ATTR_SENSOR]:
                thermostat_id = self.args[ATTR_ROOMS][room][ATTR_THERMOSTAT]

        current_temp = self.get_state(thermostat_id, attribute=ATTR_CURRENT_TEMP)
        target_temp = self.get_state(thermostat_id, attribute=ATTR_TEMPERATURE)
        org_state = self.get_state(thermostat_id)
        if new and new != ATTR_UNKNOWN:
            if not current_temp or (
                current_temp != ATTR_UNKNOWN and float(current_temp) != float(new)
            ):
                self.update_thermostat(thermostat_id, org_state, target_temp, new)
        else:
            self.log("No temperature data on the sensor {}.".format(entity))

    def update_thermostat(self, entity, state, target_temp, current_temp):
        self.log(
            "Updating state and current temperature for {}...".format(entity),
            self.log_level,
        )
        attrs = {}
        if not self.state_only:
            attrs[ATTR_CURRENT_TEMP] = float(current_temp)
        if not self.temp_only:
            state = self.find_thermostat_state(float(target_temp))
            attrs[ATTR_HVAC_MODE] = state
            attrs[ATTR_HVAC_MODES] = [self.heat_state, self.idle_state]
        self.set_state(entity, state=state, attributes=attrs)

    def find_thermostat_state(self, target_temp):
        if target_temp > self.idle_heat_temp:
            return self.heat_state
        else:
            return self.idle_state

    def zwave_entities_ready(self):
        resault = True
        entities = self.get_state("zwave")
        try:
            for entity in entities:
                if not entities[entity]["attributes"]["is_ready"]:
                    resault = False
        except KeyError:
            resault = False
        return resault

Hello again.

Tried this once again and now I think its up and running. No error messages in Home Assistant.

Directly after I restarted Home assistant I saw a “Automatic” in the thermostat card but next time I looked it was gone.
So is it working, or how do I know its working?

apps.yaml

thermostats_update:
  module: thermostats-update
  class: ThermostatsUpdate
  rooms:
    hall:
      thermostat: climate.termostat_hall
      sensor: sensor.tvattstuga_temperature
  heat_state: 'auto'
  idle_state: 'idle'
  idle_heat_temp: 8
  state_only: true
  wait_for_zwave: true

Appdeamon-version is installed via HACS. Appdeamon 4 installed via Add-On Store.

Log from AppDeamon

2020-09-06 12:19:36.219180 INFO HASS: Connected to Home Assistant 0.114.3
2020-09-06 12:19:41.417287 INFO HASS: Evaluating startup conditions
2020-09-06 12:19:41.477279 INFO HASS: Startup condition met: hass state=RUNNING
2020-09-06 12:19:41.479359 INFO HASS: All startup conditions met
2020-09-06 12:19:41.629603 INFO AppDaemon: Processing restart for HASS
2020-09-06 12:19:41.637859 INFO AppDaemon: Terminating thermostats_update
2020-09-06 12:19:41.657531 INFO AppDaemon: Initializing app thermostats_update using class ThermostatsUpdate from module thermostats-update
2020-09-06 12:19:41.711170 INFO thermostats_update: Waiting for zwave.network_ready event...
2020-09-06 12:21:29.048206 INFO thermostats_update: Checking thermostats and sensors...
2020-09-06 12:21:29.062305 WARNING AppDaemon: Log formatting error - 'not all arguments converted during string formatting'
2020-09-06 12:21:29.063778 WARNING AppDaemon: message: Updating state and current temperature for climate.termostat_hall..., args: ('DEBUG',)
2020-09-06 12:21:29.329945 INFO thermostats_update: Ready for action...

Some problem with string formatting?
I have no idea!
Plz help

oh here is my code for the simple_thermostat

type: 'custom:simple-thermostat'
entity: climate.termostat_hall
step_size: 1
sensors:
  - entity: sensor.tvattstuga_temperature
    name: Reference sensor

thermostat

Using a Danfoss LC13 model, and with this shouldnt the “Temperature” show the temperature?

After a reboot this (in red) showed itself again but after a while it was gone again.

thermostat2

This was added in Appdeamon log rencentlyg:

2020-09-06 16:41:47.365961 WARNING AppDaemon: Excessive time spent in utility loop: 2200.0ms, 12.0ms in check_app_updates(), 2188.0ms in other

Sorry but I don’t use AppDaemon and this script anymore. I don’t know when I will have time to look at this problem.

:tired_face:

Hi, What do you use now then?
because you use the danfoss thermostat right?
How do you get them inside HA working,
I have them online in Zwave but I can’t put the temperature setpoint.
He stays in ‘sleep’ mode.

hope you can help me out

What do you mean it stays in sleep mode? This is normal, after a few minutes the thermostat will set the target temperature. This script never had anything to do with setting a target temperature.

image

heya,
No I’m not using your script.
Just the zwave device Danfoss after pair,
Ok how do you set a setpoint then?
I see you have doorsensors.
When the door is open you can set a lower temp set.
For energy saving.
I shall upload a picture when i’m home.
greets Remco


Thats what I ment.
Sleeping… ZZZZZ
He does not come online.
Greets Remco

climate/set_temperature service. Please read the documentation. Your posts in this thread are off topic.

Hi everyone,

I got the script working, but as others in this thread, I would like to fix the problem of the Danfoss thermostat not working in Google Assistant.
I see there are some references to replacing some lines, but it’s not clear to me where this is. I’m using the Python Script version.

Use the Deamon. Then Google Home Works

Dear Bieniu,

I cannot get this working. Could you please have a look? I’m trying to get it work as a python script.

I added at configuration.yaml the following:

# Enable python scripts
python_script:

service: python_script.thermostat_update
data:
  thermostat: climate.schlafen_rechts_heating_mode_com_600
  sensor: sensor.schlafen_rechts_temperature_605
  heat_stat: 'auto'
  idle_state: 'idle'
  idle_heat_temp: 10
  state_only: false

I suppose I have to repeat this as I have 9 thermostats in the house (Heltun z-wave)?

I added the folder python_scripts, so the result is: /config/python_scripts

I uploaded the file thermostat_update.py without making any changes to this.

I added to automations.yaml the following:

- id: update_thermostats
  alias: 'Update Thermostats'
  trigger:
    platform: state
    entity_id:
      - climate.schlafen_rechts_heating_mode_com_600
      - sensor.schlafen_rechts_temperature_605
  condition:
    condition: template
    value_template: >-
      {% if "thermostat" in trigger.entity_id and trigger.to_state.attributes.current_temperature == none %}
         true
      {% elif "sensor" in trigger.entity_id %}
         true
      {% else %}
         false
      {% endif %}
  action:
    service: python_script.thermostat_update
    data_template:
      heat_state: 'auto'
      idle_state: 'idle'
      idle_heat_temp: 10
      thermostat: >-
         {% if "thermostat" in trigger.entity_id %}
            {{ trigger.entity_id }}
         {% else %}
            climate.thermostat_{{ trigger.entity_id | replace('sensor.temperature_', '') }}
         {% endif %}
      sensor: >-
         {% if "sensor" in trigger.entity_id %}
            {{ trigger.entity_id }}
         {% else %}
            sensor.temperature_{{ (trigger.entity_id | replace('climate.thermostat_', '')) }}
         {% endif %}

Now, I’m expecting it works but it doesn’t… I really don’t know what to do else.
Thank you.

I’m not sure if this script still works.

Am I completely on the wrong track? Is python not the way forward and only the method with AppDaemon 4? I saw I had to install AppDaemon 4 as well when using your add-on from HACS, that’s why I have chosen to go for the python way as explained in this thread. I thought it would be easier. But if you say the App Daemon is the only way to go forward, please let me know.

I can see this thread hasn’t been used for a while… should I look somewhere else? is it outdated? I’m looking for a bit more explanation for the installation. I have been searching the whole day, so any help is very welcome.

Thanks in advance!

@Kitser, what did you add to the configuration.yaml? (besides adding “python_script:” to enable HA for python)

I’m using python script and added the code to the automation.yaml and edited it to my temperature/sensors. I can see the Python script is being triggered as the last date/time is set, I cannot find a log (logger set to default: info)

I can see the script is reading the correct temperature but not setting it.

Could it have something to do with the naming of my entities? I see in this thread with python it shouldn’t matter…

climate.schlafen_rechts_heating_mode_com_600
sensor.schlafen_rechts_temperature_605

Your automation should looks like this:

- id: update_thermostats
  alias: 'Update Thermostats'
  trigger:
    platform: state
    entity_id:
      - climate.schlafen_rechts_heating_mode_com_600
      - sensor.schlafen_rechts_temperature_605
  condition:
    condition: template
    value_template: >-
      {% if "climate" in trigger.entity_id and trigger.to_state.attributes.current_temperature == none %}
         true
      {% elif "sensor" in trigger.entity_id %}
         true
      {% else %}
         false
      {% endif %}
  action:
    service: python_script.thermostat_update
    data_template:
      heat_state: 'auto'
      idle_state: 'idle'
      idle_heat_temp: 10
      thermostat: 'climate.schlafen_rechts_heating_mode_com_600'
      sensor: 'sensor.schlafen_rechts_temperature_605'

Thank Bieniu, I think I have another fundamental problem and it’s more because of integration of Fibaro with Heltun into HA.

I found out the following. If I look at Fibaro I can see the following:

You see several components of one Heltun thermostat (like the temperature of 12,8 C, the heating mode and heating mode temperature. I have it squared in red.

What I found out is the following. When setting the heating mode (rectangle at the right), like the following:

Screenshot 2021-12-01 at 13.00.20

it changes the status in the Lovelace. However when setting the temperature to 18 C (rectangle on left side), it doesn’t change the set temperature in the Lovelace (it stays 15).

I must conclude the integration is causing the issue…
This is mainly because of Fibaro I guess.
It seems that the entity_id climate.schlafen_rechts_heating_mode_com_600 isn’t representing the rectangle on the left, but the rectangle on the right only. So, the current+set temperature aren’t attached to the Lovelace widget at all.

But the funny thing is, the right rectangle should have the entity_id name something like climate.schlafen_rechts_thermostat_mode_606 (according to Fibaro) and this entity_id cannot be found at all in my configuration (but although it influences the climate.schlafen_rechts_heating_mode_com_600 somehow)… hmmm

I first need to find out why the individual Heltun items aren’t integrated automatically into HA.

The fact I have to cope with, is that one Heltun thermostat with several functions are split into Fibaro as separate items like brightness, humidity, temperature, thermostat mode and set temperature. I have got even more functions, but which I hide in Fibaro and luckily didn’t integrate into HA. An example is “Dry Air”, which I can set separately the temperature. So different from the “Heating Mode COM” (from common).

@Bieniu

I have further researched my issue.
Your automation works for me now (partially), however I still don’t have it working completely. Basically, it’s an issue between Fibaro and HA integration. I’m quite sure and I have documented this issue here:

Let’s wait for any reply. If nobody can help, I think I need to report at Github. Do you agree after reading the new thread?

Thx.

Hi,
I am a new user and trying to connect my danfoss devices to HA. I have a thermostat (014g0013) and a temperature sensor (Danfoss Icon 088U1081) . I installed Z-Wave stick and used Z-Wave-JS and Z-Wave to MQTT. I can connect to these devices, but they are not recognized. My HA does not read anything from these devices. Can you help me ?

I have:
Z-Wave JS to MQTT Current version: 0.37.0,
HA 2022.3.7

Is it possible to integrate with danfoss in this version? If so, what do I have to do step by step?