Update current temperature for Z-Wave thermostats

Sorry, I’ve already answer this question on my own. The script is working well, thanks for your work!

I have a problem with my Z-Wave Danfoss LC13 valve after upgrading Hassio to 0.103.0. It only has a battery sensor entity now. There is no climate entity anymore. Even after removing and adding the valve to the Z-wave network. Do you guys have the same problem?

1 Like

I have updated to 0.103.5 but the if I change the state in homekit I get an error image
I did not have this issue before the update. I found this in the change log:

Is this change an issue for the python script?

UPDATE:

I had to remove the climate device from homekit and added it again like this:

Resetting accessories

On Home Assistant 0.97.x or later, you may use the service homekit.reset_accessory with one or more entity_ids to reset accessories whose configuration may have changed. This can be useful when changing a media_player’s device class to tv , linking a battery, or whenever HomeAssistant add supports for new HomeKit features to existing entities.

On earlier versions of Home Assistant, you can reset accessories by removing the entity from HomeKit (via filter) and then re-adding the accessory.

With either strategy, the accessory will behave as if it’s the first time the accessory has been set up, so you will need to restore the name, group, room, scene, and/or automation settings.

I don’t know, I don’t use HomeKit.

The hvac_modes, where to add that line?

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.