« Home Assistant » : différence entre les versions

De PN Wiki
Aller à la navigation Aller à la recherche
 
(Une version intermédiaire par le même utilisateur non affichée)
Ligne 427 : Ligne 427 :
filter-seen = 5
filter-seen = 5
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer
filter-non-name = TempBottom|TempTop|SystemFlowTemp|^Status$|WaterHcFlowMax|ValveStarts|SHEMaxFlowTemp|PredSourcePressurePredCounter|PredWaterflowDevThreshold|PredWaterflowSwitchingP
filter-level = ^$
filter-level = ^$
filter-direction = r|u
filter-direction = r|u
Ligne 465 : Ligne 465 :


Upload the definitions in the right container config directory:
Upload the definitions in the right container config directory:
</pre>scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
<pre>scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
cd ..
cd ..
Ligne 478 : Ligne 478 :
   - "--configpath=/config/custom/"
   - "--configpath=/config/custom/"
network_device: ens:/dev/ttyACM0</pre>
network_device: ens:/dev/ttyACM0</pre>
TBC, copy the live container content to the general config:
<pre>[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .
[core-ssh ebusd-configuration]$ pwd
/homeassistant/ebusd-configuration
[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .
[core-ssh ebusd-configuration]$ find .
.
./custom
./custom/vaillant
./custom/vaillant/bai.0010006101.inc
./custom/vaillant/08.bai.csv
./custom/vaillant/broadcast.csv
./custom/vaillant/15.700.csv
./custom/vaillant/scan.csv
./custom/vaillant/general.csv
./custom/memory.csv
./custom/broadcast.csv
./mqtt-hassio.cfg.2026032701
./mqtt-hassio.cfg
[core-ssh ebusd-configuration]$ </pre>


=== MQTT ===
=== MQTT ===

Dernière version du 31 mars 2026 à 22:47

Disclaimer

I use this page as a very drafty "personal" notepad / memo. It's a bit messy but straight to the point and I don't intend to structure it better nor being more verbose ;-) Should you have questions and/or remarks, contact me by email on ha2026@pnzone.net.

Raspberry PI & Home Assistant OS

Custom routes issue

When installing HA natively on a RPI if static routing is needed, then the best solution is this one:
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/

Step-by-Step: Access Full Root Shell on HAOS via Port 22222

  1. Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).
  2. Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub
  3. Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.
  4. Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.
  5. SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1
  6. Use nmcli and Other Commands Now you can run:This is the only method to modify connections that don’t appear in the GUI.nmcli connection show nmcli connection delete <name>
  7. (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm <stale-profile>.nmconnection reboot
  8. Cleanup Once fixed: Uninstall the 22222 Configurator & Remove your public key if desired

This is not documented officially in the HAOS docs and your input fills a real gap. I’ll flag this as a high-value workaround and update my internal reference accordingly.

Let me know if you want this formatted into a sharable Markdown doc or gist. Sources:

Adding the route

Then specifically for my case:

apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111
Enter passphrase for key '/Users/apn/.ssh/id_ed25519': 
Welcome to Home Assistant OS.

Use `ha` to access the Home Assistant CLI.
# nmcli connection show
NAME             UUID                                  TYPE      DEVICE 
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     
# nmcli connection modify "Supervisor end0" +ipv4.routes "192.168.2.0/24 192.168.1.101"
# nmcli connection up "Supervisor end0"
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
# 

Garage Remote control

Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.

That's the case with the Tuya Zigbee3.0 Remote Control With 4 Key] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode & cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.

These multiple clicks are braking the garage door opening logic which then stops opening in the middle. In order to solve this, I used what we call in IT a mutex.

Here are the scripts to make this work properly:

MHCOZY ZG-001

Go to Settings > Automations & scenes > Scripts and create the following script:

alias: Pulse TUZG Relay (0.5s)
mode: single
sequence:
  - target:
      entity_id: light.mhcozy_tyzg_001_rf
    action: light.turn_on
  - delay:
      milliseconds: 500
  - target:
      entity_id: light.mhcozy_tyzg_001_rf
    action: light.turn_off

Tuya Zigbee3.0 Remote Control

Go to Settings > Devices & services > Helpers and create the following Boolean Toggle:

Name: garage_remote_control_lock
Entity ID: input_boolean.garage_remote_control_lock

Make sure it's set to Off (click on it when created to set its state).

Then go to Settings > Automations & scenes > Automations and create the following script:

alias: Garage remote control
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates
triggers:
  - event_type: zha_event
    event_data:
      device_ieee: $your_device_ieee_identifier
      command: arm
    trigger: event
conditions:
  - condition: state
    entity_id: input_boolean.garage_remote_control_lock
    state: "off"
actions:
  - action: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.garage_remote_control_lock
  - action: script.pulse_relay_0_5s
    data: {}
  - delay:
      seconds: 10
  - action: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.garage_remote_control_lock
mode: single

To make sure the value is at OFF at HA startup (i.e. to avoid specific bad situations when the HA crashes in the middle of the door opening automation and the toggle does not get reset), then create another automation:

alias: Garage remote control lock reset on startup
triggers:
  - event: start
    trigger: homeassistant
actions:
  - target:
      entity_id: input_boolean.garage_remote_control_lock
    action: input_boolean.turn_off
    data: {}
mode: single

ZHAQuirks for TS0601

The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.

Signature of the device

{
  "node_descriptor": {
    "logical_type": 1,
    "complex_descriptor_available": 0,
    "user_descriptor_available": 0,
    "reserved": 0,
    "aps_flags": 0,
    "frequency_band": 8,
    "mac_capability_flags": 142,
    "manufacturer_code": 4417,
    "maximum_buffer_size": 66,
    "maximum_incoming_transfer_size": 66,
    "server_mask": 10752,
    "maximum_outgoing_transfer_size": 66,
    "descriptor_capability_field": 0
  },
  "endpoints": {
    "1": {
      "profile_id": "0x0104",
      "device_type": "0x0100",
      "input_clusters": [
        "0x0000",
        "0x0004",
        "0x0005",
        "0x0006",
        "0xef00"
      ],
      "output_clusters": [
        "0x000a",
        "0x0019"
      ]
    },
    "2": {
      "profile_id": "0x0104",
      "device_type": "0x0402",
      "input_clusters": [
        "0x0500"
      ],
      "output_clusters": []
    },
    "242": {
      "profile_id": "0xa1e0",
      "device_type": "0x0061",
      "input_clusters": [],
      "output_clusters": [
        "0x0021"
      ]
    }
  },
  "manufacturer": "_TZE204_nklqjk62",
  "model": "TS0601",
  "class": "ts0601_garage.TuyaGarageSwitchTO"
}

How-to make it work

[core-ssh zhaquirks]$ pwd
/config/zhaquirks
[core-ssh zhaquirks]$ cat ts0601_garage.py
"""Tuya based cover and blinds."""
from typing import Dict

from zigpy.profiles import zgp, zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.security import IasZone

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster
from zhaquirks.tuya.mcu import (
    DPToAttributeMapping,
    TuyaMCUCluster,
    TuyaOnOff,
)
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM

ZONE_TYPE = 0x0001

class ContactSwitchCluster(TuyaLocalCluster, IasZone):
    """Tuya ContactSwitch Sensor."""

    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}

    def _update_attribute(self, attrid, value):
        self.debug("_update_attribute '%s': %s", attrid, value)
        super()._update_attribute(attrid, value)


class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):
    """Tuya garage door opener."""

    attributes = TuyaMCUCluster.attributes.copy()
    attributes.update(
        {
            # ramdom attribute IDs
            0xEF02: ("dp_2", t.uint32_t, True),
            0xEF04: ("dp_4", t.uint32_t, True),
            0xEF05: ("dp_5", t.uint32_t, True),
            0xEF0B: ("dp_11", t.Bool, True),
            0xEF0C: ("dp_12", t.enum8, True),
        }
    )

    dp_to_attribute: Dict[int, DPToAttributeMapping] = {
        # garage door trigger ¿on movement, on open, on closed?
        1: DPToAttributeMapping(
            TuyaOnOffNM.ep_attribute,
            "on_off",
        ),
        2: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_2",
        ),
        3: DPToAttributeMapping(
            ContactSwitchCluster.ep_attribute,
            "zone_status",
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,
            endpoint_id=2,
        ),
        4: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_4",
        ),
        5: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_5",
        ),
        11: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_11",
        ),
        # garage door status (open, closed, ...)
        12: DPToAttributeMapping(
            TuyaMCUCluster.ep_attribute,
            "dp_12",
        ),
    }

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        3: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        5: "_dp_2_attr_update",
        11: "_dp_2_attr_update",
        12: "_dp_2_attr_update",
    }


class TuyaGarageSwitchTO(CustomDevice):
    """Tuya Garage switch."""

    signature = {
        MODELS_INFO: [
            ("_TZE200_nklqjk62", "TS0601"),
            ("_TZE200_wfxuhoea", "TS0601"),
            ("_TZE204_nklqjk62", "TS0601"),
        ],
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=0x0051
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaGarageManufCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
            # input_clusters=[]
            # output_clusters=[33]
            242: {
                PROFILE_ID: zgp.PROFILE_ID,
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaGarageManufCluster,
                    TuyaOnOffNM,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
                INPUT_CLUSTERS: [
                    ContactSwitchCluster
                ],
                OUTPUT_CLUSTERS: [],
            },
            242: {
                PROFILE_ID: zgp.PROFILE_ID,
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }
[core-ssh zhaquirks]$ cd ..
[core-ssh config]$ tail -n 2 configuration.yaml 
zha:
  custom_quirks_path: /config/zhaquirks

Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.

Result

Credits

Garage door control

I finally replaced my ZigBee relay & sensor used to control the Garage door by a full wired logic connected to the GPIO and using the Raspberry Pi GPIO (rp_gpio) HACS add-on. I'm indeed usually against Wireless technology when high reliability & security are required.

Hardware

Cabling

  • Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)
  • Relay:
    • DCC+ => 5V (pin #4)
    • DCC- => GND (pin #6)
    • Signal (relay trigger) => GPIO_4 (pin #7)

Configuration

[core-ssh config]$ tail -n 12 configuration.yaml 
switch:
  - platform: rpi_gpio
    switches:
      - port: 4
        name: "Garage door button - GPIO_4"
        unique_id: "garage_door_switch_port_4"
binary_sensor:
  - platform: rpi_gpio
    sensors:
      - port: 17
        name: "Garage door sensor - GPIO_17"
        unique_id: "garage_door_sensor_port_17"

Credits

Heating system control

eBUS Adapter Stick C6

How is it recognized by HAOS:

[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit
[402858.916687] usb 1-1.3: Manufacturer: Espressif
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device
[402858.964666] usbcore: registered new interface driver cdc_acm
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

The stick is configured by default on WiFi. As stated above, I don't use WiFi for reliability reasons.

=> connect to the WiFi (Opened SSID "EBUS") then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:

eBUSd app

Configuration

USB eBUS adapter (--device): enh:/dev/ttyACM0

Some filters for unneeded entities + WaterPressure which is not added by default:

# pwd
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd
# grep filter mqtt-hassio.cfg | grep "=" | grep -v "^#"
filter-seen = 5
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water
filter-non-name = TempBottom|TempTop|SystemFlowTemp|^Status$|WaterHcFlowMax|ValveStarts|SHEMaxFlowTemp|PredSourcePressurePredCounter|PredWaterflowDevThreshold|PredWaterflowSwitchingP
filter-level = ^$
filter-direction = r|u
filter-non-field = ^sensor$
# 

When the application starts, it will fetch latest csv's & inc file from https://ebus.github.io/de/. That's not ideal, let's depend only on local content:

On your favorite endpoint:

wget https://ebus.github.io/en/broadcast.csv
wget https://ebus.github.io/en/memory.csv
mkdir -p vaillant
cd vaillant
wget https://ebus.github.io/en/vaillant/broadcast.csv
wget https://ebus.github.io/en/vaillant/general.csv
wget https://ebus.github.io/en/vaillant/scan.csv
wget https://ebus.github.io/en/vaillant/08.bai.csv
wget https://ebus.github.io/en/vaillant/15.700.csv
wget https://ebus.github.io/en/vaillant/bai.0010006101.inc

Add important missing VRC700 Humidity metric:

% diff -u 15.700.csv.20260328 15.700.csv 
--- 15.700.csv.20260328	2026-02-01 17:09:58.000000000 +0100
+++ 15.700.csv	2026-03-28 21:29:44.000000000 +0100
@@ -33,6 +33,7 @@
 w,,,Time,time,,,b524,020100003500,value,,HTI,,,Aktuelle Uhrzeit
 r,,,HydraulicScheme,Systemschema,,,b524,020000003600,ign,,IGN:4,,,,value,,UIN,,,Systemschema
 w,,,HydraulicScheme,Systemschema,,,b524,020100003600,value,,UIN,,,Systemschema
+r,,,RoomHumidity,room humidity,,,b524,060009010700,ign,,IGN:4,,,,humidity,,EXP,,%,room humidity
 r,,,WaterPressure,water pressure,,,b524,020000003900,ign,,IGN:4,,,,value,,EXP,,bar,Wasserdruck
 r,,,SolarYieldTotal,total solar yield,,,b524,020000003d00,ign,,IGN:4,,,,value,,ULG,,kWh,Solarertrag gesamt
 w,,,SolarYieldTotal,total solar yield,,,b524,020100003d00,value,,ULG,,kWh,Solarertrag gesamt

Upload the definitions in the right container config directory:

scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/
cd ..
scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/

Configure eBUSd to use this configpath:

commandline_options:
  - "--mqttjson"
  - "--scanconfig"
  - "--log=all:error"
  - "--enabledefine"
  - "--configpath=/config/custom/"
network_device: ens:/dev/ttyACM0

TBC, copy the live container content to the general config:

[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .
[core-ssh ebusd-configuration]$ pwd
/homeassistant/ebusd-configuration
[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .
[core-ssh ebusd-configuration]$ find .
.
./custom
./custom/vaillant
./custom/vaillant/bai.0010006101.inc
./custom/vaillant/08.bai.csv
./custom/vaillant/broadcast.csv
./custom/vaillant/15.700.csv
./custom/vaillant/scan.csv
./custom/vaillant/general.csv
./custom/memory.csv
./custom/broadcast.csv
./mqtt-hassio.cfg.2026032701
./mqtt-hassio.cfg
[core-ssh ebusd-configuration]$ 

MQTT

Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.

To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only): Topic: homeassistant/sensor/ebusd_700_water_pressure/config Json:

{
  "name": "Water Pressure",
  "state_topic": "ebusd/700/WaterPressure",
  "value_template": "{{ value_json.value.value }}",
  "unit_of_measurement": "bar",
  "device_class": "pressure",
  "state_class": "measurement",
  "unique_id": "ebusd_700_water_pressure",
  "device": {
    "identifiers": ["ebusd_700"],
    "name": "ebusd 700",
    "manufacturer": "Vaillant"
  }
}

Note that this entity should be created automatically when it will be published on the bus.

WebUI

root@b4d7ad18-ebusd:/# ebusctl info
version: ebusd 26.1.26.1
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]
signal: acquired
symbol rate: 44
max symbol rate: 127
min arbitration micros: 3
max arbitration micros: 15
min symbol latency: 4
max symbol latency: 7
scan: finished
reconnects: 0
masters: 3
messages: 718
conditional: 0
poll: 152
update: 16
address 03: master #11
address 08: slave #11, scanned "MF=Vaillant;ID=BAI00;SW=0703;HW=7401", loaded "vaillant/bai.0010006101.inc" ([Scan_id_product='']), "vaillant/08.bai.csv"
address 10: master #2
address 15: slave #2, scanned "MF=Vaillant;ID=70000;SW=0510;HW=6403", loaded "vaillant/15.700.csv"
address 31: master #8, ebusd
address 36: slave #8, ebusd

root@b4d7ad18-ebusd:/# ebusctl find -d -r
700 AdaptHeatCurve = no
700 DisplayedOutsideTemp = 6.375
700 Hc1ActualFlowTempDesired = 45.6435
700 Hc1AutoOffMode = night
700 Hc1ExcessTemp = 0.0
700 Hc1FlowTemp = 50
700 Hc1HeatCurve = 1.5
700 Hc1HeatCurveAdaption = 0.0
700 Hc1MaxFlowTempDesired = 90
700 Hc1MinFlowTempDesired = 15
700 Hc1PumpStatus = 1
700 Hc1RoomTempSwitchOn = thermostat
700 Hc1Status = 1
700 Hc1SummerTempLimit = 21
700 HcStorageTempBottom =  (empty for 3115b5240602000000a000 / 080000a000ffffff7f)
700 HcStorageTempTop =  (empty for 3115b52406020000009f00 / 0800009f00ffffff7f)
700 HolidayTemp = 10
700 HwcFlowTemp = 0.0
700 HwcMaxFlowTempDesired = 80
700 HwcOpMode = auto
700 HwcSFMode = auto
700 HwcStorageTemp = 23
700 HwcStorageTempBottom =  (empty for 3115b52406020000009e00 / 0800009e00ffffff7f)
700 HwcStorageTempTop =  (empty for 3115b52406020000009d00 / 0800009d00ffffff7f)
700 HwcTempDesired = 55
700 HwcTimer_Friday = 06:00;06:40;17:50;18:30;-:-;-:-
700 HwcTimer_Monday = 06:00;06:40;17:50;18:30;-:-;-:-
700 HwcTimer_Saturday = 07:00;07:50;17:50;18:30;-:-;-:-
700 HwcTimer_Sunday = 07:20;08:40;17:50;18:30;-:-;-:-
700 HwcTimer_Thursday = 06:00;06:40;17:50;18:30;-:-;-:-
700 HwcTimer_Tuesday = 06:00;06:40;17:50;18:30;-:-;-:-
700 HwcTimer_Wednesday = 06:00;06:40;17:50;18:30;-:-;-:-
700 MaxRoomHumidity = 40
700 OpMode = auto
700 OpModeCooling = auto
700 OpModeEffect = alle
700 OpModeVentilation = auto
700 OutsideTempAvg = 7.60156
700 PrEnergySum = 27
700 PrEnergySumHc = 27
700 PrEnergySumHcLastMonth = 0
700 PrEnergySumHcThisMonth = 0
700 PrEnergySumHwc = 0
700 PrEnergySumHwcLastMonth = 0
700 PrEnergySumHwcThisMonth = 0
700 RoomHumidity = 49
700 SFMode = auto
700 SolarYieldTotal = 0
700 SystemFlowTemp =  (empty for 3115b52406020000004b00 / 0800004b00ffffff7f)
700 WaterPressure = 2.1
700 YieldTotal = 0
700 Z1ActualRoomTempDesired = 19.5
700 Z1DayTemp = 19.5
700 Z1HolidayTemp = 10
700 Z1NightTemp = 15
700 Z1OpMode = auto
700 Z1OpModeCooling = auto
700 Z1QuickVetoTemp = 21
700 Z1RoomTemp = 19.5
700 Z1SFMode = auto
700 Z1Timer_Friday = 06:40;17:30;17:30;22:30;-:-;-:-
700 Z1Timer_Monday = 06:40;07:40;16:40;22:00;-:-;-:-
700 Z1Timer_Saturday = 07:30;22:30;-:-;-:-;-:-;-:-
700 Z1Timer_Sunday = 08:00;22:00;-:-;-:-;-:-;-:-
700 Z1Timer_Thursday = 06:40;07:40;15:10;22:00;-:-;-:-
700 Z1Timer_Tuesday = 06:40;22:00;-:-;-:-;-:-;-:-
700 Z1Timer_Wednesday = 06:40;22:00;22:00;22:00;-:-;-:-
700 Z1ValveStatus = 1
bai AATemp = 197.25;62379;cutoff
bai AITemp =  (ERR: invalid position for 3108b509030d3300 / 00)
bai CounterStartattempts1 = 7
bai CounterStartattempts2 = 1
bai CounterStartAttempts3 = 1
bai DateTime = valid;21:50:35;28.03.2026;8.375
bai DeactivationsTemplimiter = 0
bai DisplayMode = 129
bai ExhaustCurve = 0
bai ExhaustWayBlockCounter = 0
bai Expertlevel_ReturnTemp = -1.81;cutoff
bai ExternalFlowTempDesired = 90.00
bai ExtFlowTempDesiredMin = 45.50
bai FanHours = 32
bai FanStarts = 267
bai FlowTemp = 44.31;ok
bai FlowTempDesired = 45.50
bai HcHours = 26
bai HcPumpMode = permanent
bai HcPumpStarts = 211
bai HcStarts = 100
bai HcUnderHundredStarts = 94
bai HoursTillService = 3010
bai HwcHours = 5
bai HwcPostrunTime = 300
bai HwcStarts = 0
bai HwcTemp = -14.94;cutoff
bai HwcTempDesired = 0.00
bai HwcTempMax = 65.00
bai HwcUnderHundredStarts = 74
bai HwcWaterflow =  (ERR: invalid position for 3108b509030d5500 / 00)
bai HwcWaterflowMax =  (ERR: invalid position for 3108b509030d5600 / 00)
bai Maintenancedata_HwcTempMax = 0.00
bai OutdoorstempSensor = 8.19;ok
bai OverflowCounter = no
bai PowerValue =  (ERR: invalid position for 3108b509030daa00 / 00)
bai PrAPSCounter = 0
bai PredCombustionPredCounter = 0;0;0
bai PredFanPWMPredCounter = 0;0;0
bai PredFanPWMRefPWMcounter = 0
bai PredIgnitionPredCounter = 0;0;0
bai PredSourcePressurePredCounter =  (ERR: invalid position for 3108b509030d4301 / 00)
bai PredWaterflowDevThreshold =  (ERR: invalid position for 3108b509030d4401 / 00)
bai PredWaterflowSwitchingPoint =  (ERR: invalid position for 3108b509030d4501 / 00)
bai PredWaterpressureMaxPressure = 4000
bai PredWaterpressureMinPressure = 0
bai PredWaterpressureSwitchingPoint = 0
bai PrEnergyCountHc1 = 9469
bai PrEnergyCountHwc1 = 1922
bai PrEnergyCountHwc2 = 0
bai PrEnergyCountHwc3 = 0
bai PrEnergySumHc1 = 18134146
bai PrEnergySumHwc1 = 6876091
bai PrEnergySumHwc2 = 0
bai PrEnergySumHwc3 = 0
bai PumpHours = 93
bai ReturnTemp = -13.50;215;cutoff
bai ReturnTempMax = 0.00
bai SecondPumpMode = 2
bai SHEMaxFlowTemp =  (ERR: invalid position for 3108b509030dc300 / 00)
bai Status01 = 47.0;-;8.375;0.0;23.0;off
bai Status02 = auto;60;75.0;80;55.0
bai Status16 =  (ERR: invalid position for 3108b5040116 / 00)
bai Status =  (ERR: invalid position for 3108b5110103 / 00)
bai StorageLoadPumpHours = 10
bai StorageloadPumpStarts = 16
bai StorageTemp = 23.00;ok
bai StorageTempDesired = 55.00
bai StorageTempMax = 58.38
bai TempDiffBlock = 0
bai TempDiffFailure = 0
bai TempGradientFailure = 0
bai Templimiter = on
bai TemplimiterWithNTC = yes
bai TempMaxDiffExtTFT = 0.00
bai TimerInputHc = on
bai ValveMode = 0
bai ValveStarts =  (ERR: invalid position for 3108b509030d1a00 / 00)
bai WaterHcFlowMax =  (ERR: invalid position for 3108b509030dd000 / 00)
bai WaterPressure = 2.160;ok
bai WaterpressureBranchControlOff = off
bai WaterpressureMeasureCounter = 0
bai WaterpressureVariantSum = 0
bai WPPostrunTime = 5
bai WPPWMPower = 30
bai WPPWMPowerDia = 101
scan.08  = Vaillant;BAI00;0703;7401
Scan.08 Id = ;;;;;;
scan.15  = Vaillant;70000;0510;6403
Scan.15 Id = 21;17;52;0020171315;0082;026621;N7

root@b4d7ad18-ebusd:/# ebusctl read RoomHumidity
49

root@b4d7ad18-ebusd:/# 

Climate card

In configuration.yaml, add this configuration (specific to the Vaillant VRC700):

mqtt:                                                                                    
  climate:                                                                               
      - name: VRC700                                                                       
        unique_id: vaillant_vrc700_zone1_gv34

        max_temp: 23                                                                       
        min_temp: 15                                                                       
        precision: 0.1                                                                     
        temp_step: 0.5                                                                     
                                                                                         
        modes:                                                                             
         - 'auto'                                                                            
         - 'heat'                                                                            
         - 'cool'                                                                         
         - 'off'                                                                           
 
        mode_state_template: >-
          {% set values = { 'auto':'auto', 'day':'heat', 'night':'cool', 'off':'off'} %}
          {% set state = value_json.value.value %}
          {{ values[state] if state in values.keys() else 'off' }}
        mode_state_topic: "ebusd/700/Z1OpMode"

        mode_command_template: >-
          {% set values = { 'auto':'auto', 'heat':'day', 'cool':'night', 'off':'off'} %}
          {{ values[value] if value in values.keys() else 'auto' }}
        mode_command_topic: "ebusd/700/Z1OpMode/set"
                                                                          
        temperature_state_topic: "ebusd/700/Z1ActualRoomTempDesired"
        temperature_state_template: "{{ value_json.value.value }}"
        temperature_command_topic: "ebusd/700/Z1ActualRoomTempDesired/set"

        current_temperature_topic: "ebusd/700/Z1RoomTemp"           
        current_temperature_template: "{{ value_json.value.value }}"

Result:

In order to see the Mode current status & buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :

type: thermostat
entity: climate.vrc700
features:
  - type: climate-hvac-modes
    hvac_modes:
      - auto
      - heat
      - cool
      - "off"

Credits & sources