Eurotronic Spirit Z-Wave - external temperature sensor

Hi, i’m trying your solution but temperature on my spirit doesn’t change…no idea?
I simply wish send the temperature from my xiaomi zigbee sensor (zigbee2mqtt) to zwave2mqtt eurotronic valve

id: '1662572485012'
alias: température vanne salon
description: ''
trigger:
  - platform: state
    entity_id:
      - sensor.0x00158d000423a4aa_temperature
condition: []
action:
  - service: mqtt.publish
    data:
      topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwavejs2mqtt/api/sendCommand/set
      payload: >-
        { "args": [ { "nodeId": 10, "commandClass": 49, "endpoint": 0 },
        "sendReport", [ "01", "02",        
        "{{states('sensor.0x00158d000423a4aa_temperature')}}" ]]}
  - service: input_number.set_value
    data:
      value: '{{states(''sensor.0x00158d000423a4aa_temperature'')}}'
    target:
      device_id: 273607ff2806e9ad96a2f58b980955c8
mode: single

Is there also a way to set the external temperature by using the zwave_js.set_value service?

I tried this:

service: zwave_js.set_value
data:
  command_class: "49"
  endpoint: "0"
  property: Air temperature
  value: 22
target:
  entity_id: climate.heizung_kueche

But it doesn’t work?!

Uknown error

No, you can’t do that. Use the invoke_cc_api as shown here, and which is the same thing as the mqtt template above.

1 Like

Thanks.

Like this:

service: zwave_js.invoke_cc_api
data:
  command_class: "49"
  endpoint: "0"
  method_name: sendReport
  parameters:
    - 1
    - 0
    - 25
target:
  entity_id: climate.heizung_kueche

Should the schown temperature changed to the new value?
Because it doesn’t.

I don’t own this device, so I don’t know what the device should report in response to the command. Maybe someone else who owns the device can confirm what it should do.

Also, the API doesn’t let you set the precision explicitly. If you need to force the precision, you might try writing a decimal value, like 25.00, or maybe 25.01 (not sure if a round number gets converted). You can view the driver debug logs and see what the message being sent is and whether it set the precision or not.

I had to use a non-zero value to force a precision to be configured, because HA is converting the value to an integer. (Note I don’t have this device, sending the message is possible to any device that supports the Command Class, it just won’t respond to it.)

The service call with value 20.00:

service: zwave_js.invoke_cc_api
data:
  command_class: "49"
  method_name: sendReport
  parameters:
    - 1
    - 0
    - 20.00
  endpoint: "0"
target:
  entity_id: sensor.4_in_1_sensor_air_temperature

In debug logs, we can see HA has already converted the value before it gets to the driver:

2022-09-11 10:19:59.345 DEBUG (MainThread) [zwave_js_server] Publishing message:
{'args': [1, 0, 20],
 'command': 'endpoint.invoke_cc_api',
 'commandClass': 49,
 'endpoint': 0,
 'messageId': 'b4d7b3b15637462ab366feb207847a90',
 'methodName': 'sendReport',
 'nodeId': 3}

In the driver, that results in:

2022-09-11T17:16:36.588Z SERIAL » 0x011100a901030531050101142500000000094c                            (19 bytes)
2022-09-11T17:16:36.589Z DRIVER » [Node 003] [REQ] [SendDataBridge]
                                  │ source node id:   1
                                  │ transmit options: 0x25                                                                                                                                                                                                    │ callback id:      9
                                  └─[MultilevelSensorCCReport]
                                      type:  Air temperature
                                      scale: Celsius
                                      value: 20

You can see the integer value, 20. You can also see the payload bytes:

3105010114
31 -> Command Class 49 (hex 31)
  05 -> Command SENSOR_MULTILEVEL_REPORT
    01 -> Sensor Type == 1 == Air Temperature
      01 -> Precision = 0, Scale = 0, Size = 1 byte
        14 -> Temp value 20 (hex 14)

So if the device requires precision 2, then this won’t work.

HA won’t covert 20.01 to a integer.

service: zwave_js.invoke_cc_api
data:
  command_class: "49"
  method_name: sendReport
  parameters:
    - 1
    - 0
    - 20.01
  endpoint: "0"
target:
  entity_id: sensor.4_in_1_sensor_air_temperature
2022-09-11 10:17:01.376 DEBUG (MainThread) [zwave_js_server] Publishing message:
{'args': [1, 0, 20.01],
 'command': 'endpoint.invoke_cc_api',                                                                                                                                                                                        'commandClass': 49,
 'endpoint': 0,                                                                                                                                                                                                              'messageId': '37d3838495da4c17a130fe6df5fc782c',
 'methodName': 'sendReport',
 'nodeId': 3}

The decimal 20.01 is preserved.

Driver:

2022-09-11T17:17:07.826Z SERIAL » 0x011200a90103063105014207d125000000000ace                          (20 bytes)
2022-09-11T17:17:07.827Z DRIVER » [Node 003] [REQ] [SendDataBridge]
                                  │ source node id:   1
                                  │ transmit options: 0x25
                                  │ callback id:      10
                                  └─[MultilevelSensorCCReport]
                                      type:  Air temperature
                                      scale: Celsius
                                      value: 20.01

The payload is:

3105014207d1
31 -> Command Class 49 (hex 31)
  05 -> Command SENSOR_MULTILEVEL_REPORT
    01 -> Sensor Type == 1 == Air Temperature
      42 -> 0b1000010 -> Precision = 2, Scale = 0, Size = 2 bytes
        07d1 -> Temp value 20 (hex 14) 2001, which is 20.01 with precision 2

Looks like the driver also removes precision if it can. Driver code (using zwavejs2mqtt):

const node = driver.controller.nodes.get(3);
await node.commandClasses["Multilevel Sensor"].sendReport(1, 0, 20.00);

Results in the same payload as the HA service call, 3105010114.

1 Like

i tried 3 methods but honestly I need advices
zwave_js.set_config_parameter
zwave_js.invoke_cc_api
mqtt.publish

Temperature sensor on valve does not change after you send external temperature to it. It will still display the same temperature that it sees.

How you can test it if external temperature works is you can set a really low temperature and hear trv opens, or you can send a really high temperature and hear it closing.

The problem is using standard component for heating in HA. As it shows TRV temperature. To overcome this you can install a custom heating component for home assistant which supports merging the heating valve with an external sensor that you are sending temperature from, for example this one https://github.com/fineemb/lovelace-thermostat-card

1 Like

I decided to prepare my heating system for winter and found out that my method:

to publish temperature via mqtt doesn’t work anymore, with error message:

{
  "success": false,
  "message": "sensorType is not a number (ZW0322)",
  "args": [
    {
      "nodeId": 7,
      "commandClass": 49,
      "endpoint": 0
    },
    "sendReport",
    [
      "01",
      "02",
      "20.9"
    ]
  ],
  "origin": {
    "args": [
      {
        "nodeId": 7,
        "commandClass": 49,
        "endpoint": 0
      },
      "sendReport",
      [
        "01",
        "02",
        "20.9"
      ]
    ]
  }
}

But I tried to publish via service: zwave_js.invoke_cc_api:

data:
  command_class: "49"
  method_name: sendReport
  parameters:
    - 1
    - 2
    - {{states('sensor.healthy_home_coach_temperature')}}
  endpoint: "0"
target:
  entity_id: sensor.thermostat_kidsroom_air_temperature

and it worked

3 Likes

Reading through this huge thread, i managed to set the temperature on my Eurotronics Spirit Zwave devices using an automation and the normal zwave-js integration. (no mqtt or node-red :slight_smile: ) Problem with this setup is of course that home assistant has to be up and running for this to work. thanks everybody for the notes/research.

As everybody points out you first have to set option 8 of the device to -128. this way it will accept the external temperature measurement.

The automation can probably be improved but what it does is it waits for a change in temperature of my multisensor in the room. which is constantly rounded down to one digit after the comma. which the TVR is not accepting as shown in the excellent post of Freshcoast. therefore i chose just to substract 0.01 degrees from my sensor thereby creating a 2 digit after the comma number :slight_smile:

For parameters, 1 is the sensor type (1 == temperature), 0 is the scale (0 == Celsius, 1 == Fahrenheit, 2== Celsuis or Fahrenheit), the third parameter is the temperature as mentioned.

alias: External Temperature Sensors TVR
description: >-
  This automation sets the external temperature sensor on Eurotronic Spirit
  Z-Wave
trigger:
  - platform: state
    entity_id:
      - sensor.kitchen_multisensor_air_temperature
    id: TempKitchen
  - platform: state
    entity_id:
      - sensor.livingroom_multisensor_air_temperature
    id: TempLivingRoom
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: TempKitchen
        sequence:
          - service: zwave_js.invoke_cc_api
            data:
              command_class: "49"
              endpoint: "0"
              method_name: sendReport
              parameters: |-
                [ 
                  1,
                  0,
                  {{(states("sensor.kitchen_multisensor_air_temperature") | float - 0.01 )| round(2)}},
                ]
            target:
              entity_id: climate.kitchen_radiator
      - conditions:
          - condition: trigger
            id: TempLivingRoom
        sequence:
          - service: zwave_js.invoke_cc_api
            data:
              command_class: "49"
              endpoint: "0"
              method_name: sendReport
              parameters: |-
                [ 
                  1,
                  0,
                  {{(states("sensor.livingroom_multisensor_air_temperature") | float - 0.01 )| round(2)}},
                ]
            target:
              entity_id:
                - climate.living_room_thermostatic_valve_left_window
                - climate.living_room_thermostatic_valve_middle_window
                - climate.living_room_thermostatic_valve_right_window
mode: single

@MSe-5-14 have you checked if it works for you this way? For example, if current setpoint is 20C, and it has open valve, send 28.55 to the TRV, does it close?

I think TRV actually needs 1 digit precision, not 2.
@freshcoast is describing the general idea how driver works, when we send 20.00 for example, in response to @Osorkon question. That actually means that I probably need to do something about 20.0 value.
Thing is, Multilevel Sensor v5 always shows internal air temperature of TRV, that’s why it’s 2 digit.
What we are sending with sendReport must contain 1 decimal, and after that, that value is nowhere to be observed in the ZWave JS UI of the TRV entity - we can only test it by trying out setpoint / sent value from automation.

Yes it works for me. when i set the temperature to 28.55 it closes the valve.
after your comment i did try some other values and you are right; it only needs 1 digit. must ahve misunderstood something :slight_smile:

This won’t work because you are sending the parameters and the temperature value as strings, not as an integer or float. It is necessary to remove " near 01, 02 and temperature.
I’m using MQTT-Explorer to connect my MQTT server and it is pretty shows, that zwavejs2mqtt api returns that call is successful or not and error message. So it easy using it to find mistake.

Example working for me (I checked that there is no error from from api side, I will check valve working later):

    - service: mqtt.publish
      data:
        topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwavejs2mqtt/api/sendCommand/set
        payload: >-
          { "args": [ { "nodeId": 9, "commandClass": 49, "endPoint": 0 },
          "sendReport", [ 1, 2,
          {{states('sensor.p1bedroom_temperature_avg')}} ]]}

Ive tweaked my automation a little and this seems to work

alias:  External Temperature Sensors TRV
description: >-
  This automation sets the external temperature sensor on Eurotronic Spirit
  Z-Wave
trigger:
  - platform: state
    entity_id:
      - sensor.bathroom_multisensor_air_temperature
      - sensor.bedroom_multisensor_air_temperature
      - sensor.kitchen_multisensor_air_temperature
      - sensor.livingroom_multisensor_air_temperature
      - sensor.office_multisensor_air_temperature
condition: []
action:
  - service: zwave_js.invoke_cc_api
    data:
      command_class: "49"
      endpoint: "0"
      method_name: sendReport
      parameters:
        - 1
        - 0
        - "{{ states(trigger.entity_id) }}"
    target:
      entity_id: >-
        {{ expand(states.climate)  | selectattr('entity_id', 'in',
        area_entities(area_id(trigger.entity_id)))|map(attribute='entity_id') |
        list }}
mode: single

The log shows i think that the message arrives correctly at the TRV, even if node 3 doesnt seem to be able to deliver the info. ill launch a heal network just to make sure, weird the plug is 1.5m away from the TRV. :slight_smile:

NODE 003 = Fibaro Plug FGWPE-102
NODE 005 = Aeotec MultiSensor 6
NODE 014 = Eurotronics Spirit

2022-12-15T15:39:23.110Z SERIAL « 0x010e00040005063105012200c5cf00eb                                  (16 bytes)
2022-12-15T15:39:23.111Z SERIAL » [ACK]                                                                   (0x06)
2022-12-15T15:39:23.112Z CNTRLR   [Node 005] [Multilevel Sensor] Air temperature: metadata updated  [Endpoint 0]
2022-12-15T15:39:23.112Z CNTRLR   [Node 005] [~] [Multilevel Sensor] Air temperature: 19.8 => 19.7  [Endpoint 0]
2022-12-15T15:39:23.113Z DRIVER « [Node 005] [REQ] [ApplicationCommand]
                                  └─[MultilevelSensorCCReport]
                                      type:  Air temperature
                                      scale: Celsius
                                      value: 19.7
2022-12-15T15:39:23.127Z SERIAL » 0x011d00130e169f032600bf258a9ba346d2e27a93cd68977c0c2560a025f096    (31 bytes)
2022-12-15T15:39:23.129Z DRIVER » [Node 014] [REQ] [SendData]
                                  │ transmit options: 0x25
                                  │ callback id:      240
                                  └─[Security2CCMessageEncapsulation]
                                    │ sequence number: 38
                                    └─[SupervisionCCGet]
                                      │ session id:      28
                                      │ request updates: true
                                      └─[MultilevelSensorCCReport]
                                          type:  Air temperature
                                          scale: Celsius
                                          value: 19.7
2022-12-15T15:39:23.134Z SERIAL « [ACK]                                                                   (0x06)
2022-12-15T15:39:23.141Z SERIAL « 0x0104011301e8                                                       (6 bytes)
2022-12-15T15:39:23.142Z SERIAL » [ACK]                                                                   (0x06)
2022-12-15T15:39:23.142Z DRIVER « [RES] [SendData]
                                    was sent: true
2022-12-15T15:39:24.575Z SERIAL « 0x01180013f000009001ca7f7f7f7f010103030000000202030e52              (26 bytes)
2022-12-15T15:39:24.576Z SERIAL » [ACK]                                                                   (0x06)
2022-12-15T15:39:24.577Z DRIVER « [REQ] [SendData]
                                    callback id:            240
                                    transmit status:        OK, took 1440 ms
                                    repeater node IDs:      3
                                    routing attempts:       2
                                    protocol & route speed: Z-Wave, 40 kbit/s
                                    ACK RSSI:               -54 dBm
                                    ACK RSSI on repeaters:  N/A
                                    ACK channel no.:        1
                                    TX channel no.:         1
                                    route failed here:      3 -> 14
2022-12-15T15:39:24.656Z SERIAL « 0x01190004000e119f03c7008844ba3094626508bafe6d875bca0044            (27 bytes)
2022-12-15T15:39:24.657Z SERIAL » [ACK]                                                                   (0x06)
2022-12-15T15:39:24.657Z DRIVER « [Node 014] [REQ] [ApplicationCommand]
                                  └─[Security2CCMessageEncapsulation]
                                    │ sequence number: 199
                                    └─[SupervisionCCReport]
                                        session id:          28
                                        more updates follow: false
                                        status:              Success
                                        duration:            0s

1 Like

New season coming, and I started HA setup from scratch. Revisited this issue and found your automation to be very convenient - one for all TRVs in one. Thanks!

1 Like

I recently changed the automation a little. Basically to stop too much unnecessary updates being sent over the zwave network. i now first check if the temperature has actually changed before sending the zwave command.

alias: Appartment.SetTempFromRoomSensors
description: >-
  This automation sets the external temperature sensor on Eurotronic Spirit
  Z-Wave
trigger:
  - platform: state
    entity_id:
      - sensor.bathroom_multisensor_air_temperature
      - sensor.bedroom_multisensor_air_temperature
      - sensor.kitchen_multisensor_air_temperature
      - sensor.livingroom_multisensor_air_temperature
      - sensor.office_multisensor_air_temperature
condition:
  - condition: template
    value_template: "{{ trigger.from_state.state|float(0) != trigger.to_state.state|float(0) }}"
action:
  - service: zwave_js.invoke_cc_api
    data:
      command_class: "49"
      endpoint: "0"
      method_name: sendReport
      parameters:
        - 1
        - 0
        - "{{ states(trigger.entity_id) }}"
    target:
      entity_id: >-
        {{ expand(states.climate)  | selectattr('entity_id', 'in',
        area_entities(area_id(trigger.entity_id)))|map(attribute='entity_id') |
        list }}
mode: queued
max: 5

2 Likes

Where can I find these “temperature” association group” ? I want to pair my Spirit with an Everspring ST814. This was possible with my old Homee.

I don’t use the sensor any more. If I remember correctly you had to set the temperature offset in the Spirit to “external sensor” and add the Spirit to the association group in the temperature sensor. Hope that helps

I have strange issue with one of my TVRs. It seems to improperly set opening of the valve. For comparison here is the screenshot of 2 valves, one (Badroom) working as expected and second (Mirek) that misbehavies:

As you can see for Bedroom temperature is set to 21C and valve is 100% opened (blue lines on chart at the bottom of picture). For Mirek I had to set the temperature to 25C to get the valve opened to 65% to get heating working. If I set it to real desired temperature of 21C, then valve gets completely closed, despite temperature being well betol target. BTW on the chart you can see both valves being completely closed for night period, when target temperature is lovered to 19C.

In my setup I use external temperature sensors and set temperature sensor of valve using MQTT automation. So as this process requires to set temperature offset parameter to -128, it leves no room to set offset/correction. I checked all setup parameters of both valves and these looks identical (unless I missed something).

What might cause such strange behaviour of this TVR? Any way to troubleshoot it?

What happens when you set the “Mirek Office” TVR to the “Full Power” preset?
Does the valve open 100%?