<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki.deprelledelanieppe.be/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Apn</id>
	<title>PN Wiki - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.deprelledelanieppe.be/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Apn"/>
	<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php/Sp%C3%A9cial:Contributions/Apn"/>
	<updated>2026-04-28T12:26:16Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=1007</id>
		<title>FreeBSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=1007"/>
		<updated>2026-04-18T18:33:53Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* PF */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Named =&lt;br /&gt;
== Manually updating a Dynamic controlled zone ==&lt;br /&gt;
&#039;&#039;&amp;quot;If you have to edit the zone files of dynamic zones manually while the DNS server is running, you&#039;ll have to freeze the zones with &#039;&#039;&#039;# rndc freeze &amp;lt;myzone&amp;gt;&#039;&#039;&#039; before editing and unfreeze them with &#039;&#039;&#039;# rndc thaw &amp;lt;myzone&amp;gt;&#039;&#039;&#039; after editing. This is because named(8) has internal state information and external journal files attached to dynamic zones that have to be kept in sync with the zone files&amp;lt;ref&amp;gt;https://forums.freebsd.org/threads/dynamic-dns-with-bind-and-isc-dhcp-server.33849/&amp;lt;/ref&amp;gt;&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Rsync = &lt;br /&gt;
&lt;br /&gt;
To delete files in the target if they disappeared from the source, then add the --delete option to your command. For example:&lt;br /&gt;
&lt;br /&gt;
rsync -avh source/ dest/ --delete&amp;lt;br&amp;gt;&lt;br /&gt;
NB: -avh is for --archive --verbose --human-readable&amp;lt;ref&amp;gt;https://askubuntu.com/a/665918&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Migration of folders to a new server ==&lt;br /&gt;
&lt;br /&gt;
=== One shot ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av /var/db/ports/ root@newice3:/var/db/ports/&lt;br /&gt;
rsync -av /etc/ root@newice3:/etc/oldice3/&lt;br /&gt;
rsync -av /usr/local/etc/ root@newice3:/usr/local/etc/oldice3/&lt;br /&gt;
rsync -av /etc/ssh/ssh_config /etc/ssh/sshd_config newice3:/etc/ssh/&lt;br /&gt;
rsync -av /etc/banner /etc/motd.template /etc/pki/ newice3:/etc/&lt;br /&gt;
rsync -av /etc/pki/ newice3:/etc/pki/&lt;br /&gt;
rsync -av /usr/local/lib/sasl2/smtpd.conf root@newice3:/usr/local/lib/sasl2/&lt;br /&gt;
rsync -av /var/ftp/ newice3:/var/ftp/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1 full + diff at the migration time === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av --exclude={&#039;rc.d&#039;,&#039;oldice3&#039;,&#039;newice3&#039;,&#039;namedb&#039;,&#039;openvpn&#039;,&#039;pkg.conf&#039;,&#039;portsnap.conf&#039;} /usr/local/etc/ root@newice3:/usr/local/etc/ --delete --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.ip.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam_awstats.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /root/ root@newice3:/root/ --delete --dry-run&lt;br /&gt;
rsync -av /home/ root@newice3:/home/ --delete --dry-run&lt;br /&gt;
rsync -av /var/www/ root@newice3:/var/www/ --delete --dry-run&lt;br /&gt;
rsync -av /usr/local/www/ root@newice3:/usr/local/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/ root@newice3:/var/log/oldice3/ --delete --dry-run&lt;br /&gt;
rsync -av /var/awstats/ root@newice3:/var/awstats/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/www/ root@newice3:/var/log/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/fail2ban/ root@newice3:/var/db/fail2ban/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/mysql/ root@newice3:/var/db/mysql/ --delete --dry-run (to do when mysql server is off)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Nginx =&lt;br /&gt;
== Maxmind ==&lt;br /&gt;
Country based filtering can be performed in nginx thanks to the free Maxmind databases.&lt;br /&gt;
&lt;br /&gt;
A cron job shall be used to update these databases on a daily basis&amp;lt;ref&amp;gt;https://herrbischoff.com/2021/05/nginx-how-to-restrict-access-by-geographical-location-on-freebsd/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ZFS snapshots = &lt;br /&gt;
FreeBSD creates a snapshot at each update (freebsd-update fetch &amp;amp;&amp;amp; freebsd-update install). These snapshots are not needed anymore should your system restarts &amp;amp; runs correctly. Moreover they take loads of space on your hardrive.&lt;br /&gt;
&lt;br /&gt;
== Procedure to delete ==&lt;br /&gt;
&lt;br /&gt;
=== List &amp;amp; check ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE                                Active Mountpoint Space Created&lt;br /&gt;
14.3-RELEASE-p6_2025-12-19_121434 -      -          927M  2025-12-19 12:14&lt;br /&gt;
default                           NR     /          814G  2023-12-01 23:34&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Check that the active Boot Envionment is the default (NR set on default).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
NAME                                       USED  AVAIL  REFER  MOUNTPOINT&lt;br /&gt;
zroot/ROOT/default@2025-12-19-12:14:34-0   927M      -   812G  -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Delete ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl destroy 14.3-RELEASE-p6_2025-12-19_121434&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Results ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE      Active Mountpoint Space Created&lt;br /&gt;
default NR     /          813G  2023-12-01 23:34&lt;br /&gt;
root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
no datasets available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reboot or no reboot after a minor system upgrade ? =&lt;br /&gt;
&lt;br /&gt;
After a system upgrade performed thanks to :&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-update fetch&lt;br /&gt;
root@icecube BSD:~ # freebsd-update install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the output of these two commands differs, then reboot your system:&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-version -k&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
root@icecube BSD:~ # uname -r&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= PF =&lt;br /&gt;
After a reboot of FreeBSD, PF may fail to start due to tables being too big (i.e. &amp;gt; 100k entries).&amp;lt;br&amp;gt;&lt;br /&gt;
This is explained here with a quick &amp;amp; dirty non-permanent fix :&amp;lt;br&amp;gt;&lt;br /&gt;
https://forums.freebsd.org/threads/table-loading-in-pf-issues.86101/#post-577832&lt;br /&gt;
# First load the PF Options only (specific to big tables handling):&lt;br /&gt;
&amp;lt;pre&amp;gt;pfctl -Of /etc/pf.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Then restart PF the usual way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf/etc/pf.conf:98: cannot define table firehol4: Cannot allocate memory&lt;br /&gt;
pfctl: Syntax error in config file: pf rules not loaded&lt;br /&gt;
/etc/rc.d/pf: WARNING: Unable to load /etc/pf.conf.&lt;br /&gt;
.&lt;br /&gt;
root@icecube BSD:~ # sed -n &#039;98p&#039; /etc/pf.conf&lt;br /&gt;
table &amp;lt;firehol4&amp;gt; persist file &amp;quot;/etc/pf_table_firehol4&amp;quot;&lt;br /&gt;
root@icecube BSD:~ # wc -l /etc/pf_table_firehol4&lt;br /&gt;
   99856 /etc/pf_table_firehol4&lt;br /&gt;
root@icecube BSD:~ # pfctl -Of /etc/pf.conf&lt;br /&gt;
root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf.&lt;br /&gt;
root@icecube BSD:~ # &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{references}}&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1006</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1006"/>
		<updated>2026-03-31T20:47:33Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = TempBottom|TempTop|SystemFlowTemp|^Status$|WaterHcFlowMax|ValveStarts|SHEMaxFlowTemp|PredSourcePressurePredCounter|PredWaterflowDevThreshold|PredWaterflowSwitchingP&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the application starts, it will fetch latest csv&#039;s &amp;amp; inc file from https://ebus.github.io/de/.&lt;br /&gt;
That&#039;s not ideal, let&#039;s depend only on local content:&lt;br /&gt;
&lt;br /&gt;
On your favorite endpoint:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://ebus.github.io/en/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/memory.csv&lt;br /&gt;
mkdir -p vaillant&lt;br /&gt;
cd vaillant&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/general.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/scan.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/08.bai.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/15.700.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/bai.0010006101.inc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add important missing VRC700 Humidity metric:&lt;br /&gt;
&amp;lt;pre&amp;gt;% diff -u 15.700.csv.20260328 15.700.csv &lt;br /&gt;
--- 15.700.csv.20260328	2026-02-01 17:09:58.000000000 +0100&lt;br /&gt;
+++ 15.700.csv	2026-03-28 21:29:44.000000000 +0100&lt;br /&gt;
@@ -33,6 +33,7 @@&lt;br /&gt;
 w,,,Time,time,,,b524,020100003500,value,,HTI,,,Aktuelle Uhrzeit&lt;br /&gt;
 r,,,HydraulicScheme,Systemschema,,,b524,020000003600,ign,,IGN:4,,,,value,,UIN,,,Systemschema&lt;br /&gt;
 w,,,HydraulicScheme,Systemschema,,,b524,020100003600,value,,UIN,,,Systemschema&lt;br /&gt;
+r,,,RoomHumidity,room humidity,,,b524,060009010700,ign,,IGN:4,,,,humidity,,EXP,,%,room humidity&lt;br /&gt;
 r,,,WaterPressure,water pressure,,,b524,020000003900,ign,,IGN:4,,,,value,,EXP,,bar,Wasserdruck&lt;br /&gt;
 r,,,SolarYieldTotal,total solar yield,,,b524,020000003d00,ign,,IGN:4,,,,value,,ULG,,kWh,Solarertrag gesamt&lt;br /&gt;
 w,,,SolarYieldTotal,total solar yield,,,b524,020100003d00,value,,ULG,,kWh,Solarertrag gesamt&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload the definitions in the right container config directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
cd ..&lt;br /&gt;
scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Configure eBUSd to use this configpath:&lt;br /&gt;
&amp;lt;pre&amp;gt;commandline_options:&lt;br /&gt;
  - &amp;quot;--mqttjson&amp;quot;&lt;br /&gt;
  - &amp;quot;--scanconfig&amp;quot;&lt;br /&gt;
  - &amp;quot;--log=all:error&amp;quot;&lt;br /&gt;
  - &amp;quot;--enabledefine&amp;quot;&lt;br /&gt;
  - &amp;quot;--configpath=/config/custom/&amp;quot;&lt;br /&gt;
network_device: ens:/dev/ttyACM0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TBC, copy the live container content to the general config:&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .&lt;br /&gt;
[core-ssh ebusd-configuration]$ pwd&lt;br /&gt;
/homeassistant/ebusd-configuration&lt;br /&gt;
[core-ssh ebusd-configuration]$ cp -rpf /addon_configs/b4d7ad18_ebusd/* .&lt;br /&gt;
[core-ssh ebusd-configuration]$ find .&lt;br /&gt;
.&lt;br /&gt;
./custom&lt;br /&gt;
./custom/vaillant&lt;br /&gt;
./custom/vaillant/bai.0010006101.inc&lt;br /&gt;
./custom/vaillant/08.bai.csv&lt;br /&gt;
./custom/vaillant/broadcast.csv&lt;br /&gt;
./custom/vaillant/15.700.csv&lt;br /&gt;
./custom/vaillant/scan.csv&lt;br /&gt;
./custom/vaillant/general.csv&lt;br /&gt;
./custom/memory.csv&lt;br /&gt;
./custom/broadcast.csv&lt;br /&gt;
./mqtt-hassio.cfg.2026032701&lt;br /&gt;
./mqtt-hassio.cfg&lt;br /&gt;
[core-ssh ebusd-configuration]$ &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 44&lt;br /&gt;
max symbol rate: 127&lt;br /&gt;
min arbitration micros: 3&lt;br /&gt;
max arbitration micros: 15&lt;br /&gt;
min symbol latency: 4&lt;br /&gt;
max symbol latency: 7&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 718&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 152&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl find -d -r&lt;br /&gt;
700 AdaptHeatCurve = no&lt;br /&gt;
700 DisplayedOutsideTemp = 6.375&lt;br /&gt;
700 Hc1ActualFlowTempDesired = 45.6435&lt;br /&gt;
700 Hc1AutoOffMode = night&lt;br /&gt;
700 Hc1ExcessTemp = 0.0&lt;br /&gt;
700 Hc1FlowTemp = 50&lt;br /&gt;
700 Hc1HeatCurve = 1.5&lt;br /&gt;
700 Hc1HeatCurveAdaption = 0.0&lt;br /&gt;
700 Hc1MaxFlowTempDesired = 90&lt;br /&gt;
700 Hc1MinFlowTempDesired = 15&lt;br /&gt;
700 Hc1PumpStatus = 1&lt;br /&gt;
700 Hc1RoomTempSwitchOn = thermostat&lt;br /&gt;
700 Hc1Status = 1&lt;br /&gt;
700 Hc1SummerTempLimit = 21&lt;br /&gt;
700 HcStorageTempBottom =  (empty for 3115b5240602000000a000 / 080000a000ffffff7f)&lt;br /&gt;
700 HcStorageTempTop =  (empty for 3115b52406020000009f00 / 0800009f00ffffff7f)&lt;br /&gt;
700 HolidayTemp = 10&lt;br /&gt;
700 HwcFlowTemp = 0.0&lt;br /&gt;
700 HwcMaxFlowTempDesired = 80&lt;br /&gt;
700 HwcOpMode = auto&lt;br /&gt;
700 HwcSFMode = auto&lt;br /&gt;
700 HwcStorageTemp = 23&lt;br /&gt;
700 HwcStorageTempBottom =  (empty for 3115b52406020000009e00 / 0800009e00ffffff7f)&lt;br /&gt;
700 HwcStorageTempTop =  (empty for 3115b52406020000009d00 / 0800009d00ffffff7f)&lt;br /&gt;
700 HwcTempDesired = 55&lt;br /&gt;
700 HwcTimer_Friday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Monday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Saturday = 07:00;07:50;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Sunday = 07:20;08:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Thursday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Tuesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Wednesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 MaxRoomHumidity = 40&lt;br /&gt;
700 OpMode = auto&lt;br /&gt;
700 OpModeCooling = auto&lt;br /&gt;
700 OpModeEffect = alle&lt;br /&gt;
700 OpModeVentilation = auto&lt;br /&gt;
700 OutsideTempAvg = 7.60156&lt;br /&gt;
700 PrEnergySum = 27&lt;br /&gt;
700 PrEnergySumHc = 27&lt;br /&gt;
700 PrEnergySumHcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHcThisMonth = 0&lt;br /&gt;
700 PrEnergySumHwc = 0&lt;br /&gt;
700 PrEnergySumHwcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHwcThisMonth = 0&lt;br /&gt;
700 RoomHumidity = 49&lt;br /&gt;
700 SFMode = auto&lt;br /&gt;
700 SolarYieldTotal = 0&lt;br /&gt;
700 SystemFlowTemp =  (empty for 3115b52406020000004b00 / 0800004b00ffffff7f)&lt;br /&gt;
700 WaterPressure = 2.1&lt;br /&gt;
700 YieldTotal = 0&lt;br /&gt;
700 Z1ActualRoomTempDesired = 19.5&lt;br /&gt;
700 Z1DayTemp = 19.5&lt;br /&gt;
700 Z1HolidayTemp = 10&lt;br /&gt;
700 Z1NightTemp = 15&lt;br /&gt;
700 Z1OpMode = auto&lt;br /&gt;
700 Z1OpModeCooling = auto&lt;br /&gt;
700 Z1QuickVetoTemp = 21&lt;br /&gt;
700 Z1RoomTemp = 19.5&lt;br /&gt;
700 Z1SFMode = auto&lt;br /&gt;
700 Z1Timer_Friday = 06:40;17:30;17:30;22:30;-:-;-:-&lt;br /&gt;
700 Z1Timer_Monday = 06:40;07:40;16:40;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Saturday = 07:30;22:30;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Sunday = 08:00;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Thursday = 06:40;07:40;15:10;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Tuesday = 06:40;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Wednesday = 06:40;22:00;22:00;22:00;-:-;-:-&lt;br /&gt;
700 Z1ValveStatus = 1&lt;br /&gt;
bai AATemp = 197.25;62379;cutoff&lt;br /&gt;
bai AITemp =  (ERR: invalid position for 3108b509030d3300 / 00)&lt;br /&gt;
bai CounterStartattempts1 = 7&lt;br /&gt;
bai CounterStartattempts2 = 1&lt;br /&gt;
bai CounterStartAttempts3 = 1&lt;br /&gt;
bai DateTime = valid;21:50:35;28.03.2026;8.375&lt;br /&gt;
bai DeactivationsTemplimiter = 0&lt;br /&gt;
bai DisplayMode = 129&lt;br /&gt;
bai ExhaustCurve = 0&lt;br /&gt;
bai ExhaustWayBlockCounter = 0&lt;br /&gt;
bai Expertlevel_ReturnTemp = -1.81;cutoff&lt;br /&gt;
bai ExternalFlowTempDesired = 90.00&lt;br /&gt;
bai ExtFlowTempDesiredMin = 45.50&lt;br /&gt;
bai FanHours = 32&lt;br /&gt;
bai FanStarts = 267&lt;br /&gt;
bai FlowTemp = 44.31;ok&lt;br /&gt;
bai FlowTempDesired = 45.50&lt;br /&gt;
bai HcHours = 26&lt;br /&gt;
bai HcPumpMode = permanent&lt;br /&gt;
bai HcPumpStarts = 211&lt;br /&gt;
bai HcStarts = 100&lt;br /&gt;
bai HcUnderHundredStarts = 94&lt;br /&gt;
bai HoursTillService = 3010&lt;br /&gt;
bai HwcHours = 5&lt;br /&gt;
bai HwcPostrunTime = 300&lt;br /&gt;
bai HwcStarts = 0&lt;br /&gt;
bai HwcTemp = -14.94;cutoff&lt;br /&gt;
bai HwcTempDesired = 0.00&lt;br /&gt;
bai HwcTempMax = 65.00&lt;br /&gt;
bai HwcUnderHundredStarts = 74&lt;br /&gt;
bai HwcWaterflow =  (ERR: invalid position for 3108b509030d5500 / 00)&lt;br /&gt;
bai HwcWaterflowMax =  (ERR: invalid position for 3108b509030d5600 / 00)&lt;br /&gt;
bai Maintenancedata_HwcTempMax = 0.00&lt;br /&gt;
bai OutdoorstempSensor = 8.19;ok&lt;br /&gt;
bai OverflowCounter = no&lt;br /&gt;
bai PowerValue =  (ERR: invalid position for 3108b509030daa00 / 00)&lt;br /&gt;
bai PrAPSCounter = 0&lt;br /&gt;
bai PredCombustionPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMRefPWMcounter = 0&lt;br /&gt;
bai PredIgnitionPredCounter = 0;0;0&lt;br /&gt;
bai PredSourcePressurePredCounter =  (ERR: invalid position for 3108b509030d4301 / 00)&lt;br /&gt;
bai PredWaterflowDevThreshold =  (ERR: invalid position for 3108b509030d4401 / 00)&lt;br /&gt;
bai PredWaterflowSwitchingPoint =  (ERR: invalid position for 3108b509030d4501 / 00)&lt;br /&gt;
bai PredWaterpressureMaxPressure = 4000&lt;br /&gt;
bai PredWaterpressureMinPressure = 0&lt;br /&gt;
bai PredWaterpressureSwitchingPoint = 0&lt;br /&gt;
bai PrEnergyCountHc1 = 9469&lt;br /&gt;
bai PrEnergyCountHwc1 = 1922&lt;br /&gt;
bai PrEnergyCountHwc2 = 0&lt;br /&gt;
bai PrEnergyCountHwc3 = 0&lt;br /&gt;
bai PrEnergySumHc1 = 18134146&lt;br /&gt;
bai PrEnergySumHwc1 = 6876091&lt;br /&gt;
bai PrEnergySumHwc2 = 0&lt;br /&gt;
bai PrEnergySumHwc3 = 0&lt;br /&gt;
bai PumpHours = 93&lt;br /&gt;
bai ReturnTemp = -13.50;215;cutoff&lt;br /&gt;
bai ReturnTempMax = 0.00&lt;br /&gt;
bai SecondPumpMode = 2&lt;br /&gt;
bai SHEMaxFlowTemp =  (ERR: invalid position for 3108b509030dc300 / 00)&lt;br /&gt;
bai Status01 = 47.0;-;8.375;0.0;23.0;off&lt;br /&gt;
bai Status02 = auto;60;75.0;80;55.0&lt;br /&gt;
bai Status16 =  (ERR: invalid position for 3108b5040116 / 00)&lt;br /&gt;
bai Status =  (ERR: invalid position for 3108b5110103 / 00)&lt;br /&gt;
bai StorageLoadPumpHours = 10&lt;br /&gt;
bai StorageloadPumpStarts = 16&lt;br /&gt;
bai StorageTemp = 23.00;ok&lt;br /&gt;
bai StorageTempDesired = 55.00&lt;br /&gt;
bai StorageTempMax = 58.38&lt;br /&gt;
bai TempDiffBlock = 0&lt;br /&gt;
bai TempDiffFailure = 0&lt;br /&gt;
bai TempGradientFailure = 0&lt;br /&gt;
bai Templimiter = on&lt;br /&gt;
bai TemplimiterWithNTC = yes&lt;br /&gt;
bai TempMaxDiffExtTFT = 0.00&lt;br /&gt;
bai TimerInputHc = on&lt;br /&gt;
bai ValveMode = 0&lt;br /&gt;
bai ValveStarts =  (ERR: invalid position for 3108b509030d1a00 / 00)&lt;br /&gt;
bai WaterHcFlowMax =  (ERR: invalid position for 3108b509030dd000 / 00)&lt;br /&gt;
bai WaterPressure = 2.160;ok&lt;br /&gt;
bai WaterpressureBranchControlOff = off&lt;br /&gt;
bai WaterpressureMeasureCounter = 0&lt;br /&gt;
bai WaterpressureVariantSum = 0&lt;br /&gt;
bai WPPostrunTime = 5&lt;br /&gt;
bai WPPWMPower = 30&lt;br /&gt;
bai WPPWMPowerDia = 101&lt;br /&gt;
scan.08  = Vaillant;BAI00;0703;7401&lt;br /&gt;
Scan.08 Id = ;;;;;;&lt;br /&gt;
scan.15  = Vaillant;70000;0510;6403&lt;br /&gt;
Scan.15 Id = 21;17;52;0020171315;0082;026621;N7&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl read RoomHumidity&lt;br /&gt;
49&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1005</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1005"/>
		<updated>2026-03-28T20:56:53Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the application starts, it will fetch latest csv&#039;s &amp;amp; inc file from https://ebus.github.io/de/.&lt;br /&gt;
That&#039;s not ideal, let&#039;s depend only on local content:&lt;br /&gt;
&lt;br /&gt;
On your favorite endpoint:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://ebus.github.io/en/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/memory.csv&lt;br /&gt;
mkdir -p vaillant&lt;br /&gt;
cd vaillant&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/general.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/scan.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/08.bai.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/15.700.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/bai.0010006101.inc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add important missing VRC700 Humidity metric:&lt;br /&gt;
&amp;lt;pre&amp;gt;% diff -u 15.700.csv.20260328 15.700.csv &lt;br /&gt;
--- 15.700.csv.20260328	2026-02-01 17:09:58.000000000 +0100&lt;br /&gt;
+++ 15.700.csv	2026-03-28 21:29:44.000000000 +0100&lt;br /&gt;
@@ -33,6 +33,7 @@&lt;br /&gt;
 w,,,Time,time,,,b524,020100003500,value,,HTI,,,Aktuelle Uhrzeit&lt;br /&gt;
 r,,,HydraulicScheme,Systemschema,,,b524,020000003600,ign,,IGN:4,,,,value,,UIN,,,Systemschema&lt;br /&gt;
 w,,,HydraulicScheme,Systemschema,,,b524,020100003600,value,,UIN,,,Systemschema&lt;br /&gt;
+r,,,RoomHumidity,room humidity,,,b524,060009010700,ign,,IGN:4,,,,humidity,,EXP,,%,room humidity&lt;br /&gt;
 r,,,WaterPressure,water pressure,,,b524,020000003900,ign,,IGN:4,,,,value,,EXP,,bar,Wasserdruck&lt;br /&gt;
 r,,,SolarYieldTotal,total solar yield,,,b524,020000003d00,ign,,IGN:4,,,,value,,ULG,,kWh,Solarertrag gesamt&lt;br /&gt;
 w,,,SolarYieldTotal,total solar yield,,,b524,020100003d00,value,,ULG,,kWh,Solarertrag gesamt&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload the definitions in the right container config directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
cd ..&lt;br /&gt;
scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Configure eBUSd to use this configpath:&lt;br /&gt;
&amp;lt;pre&amp;gt;commandline_options:&lt;br /&gt;
  - &amp;quot;--mqttjson&amp;quot;&lt;br /&gt;
  - &amp;quot;--scanconfig&amp;quot;&lt;br /&gt;
  - &amp;quot;--log=all:error&amp;quot;&lt;br /&gt;
  - &amp;quot;--enabledefine&amp;quot;&lt;br /&gt;
  - &amp;quot;--configpath=/config/custom/&amp;quot;&lt;br /&gt;
network_device: ens:/dev/ttyACM0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 44&lt;br /&gt;
max symbol rate: 127&lt;br /&gt;
min arbitration micros: 3&lt;br /&gt;
max arbitration micros: 15&lt;br /&gt;
min symbol latency: 4&lt;br /&gt;
max symbol latency: 7&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 718&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 152&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl find -d -r&lt;br /&gt;
700 AdaptHeatCurve = no&lt;br /&gt;
700 DisplayedOutsideTemp = 6.375&lt;br /&gt;
700 Hc1ActualFlowTempDesired = 45.6435&lt;br /&gt;
700 Hc1AutoOffMode = night&lt;br /&gt;
700 Hc1ExcessTemp = 0.0&lt;br /&gt;
700 Hc1FlowTemp = 50&lt;br /&gt;
700 Hc1HeatCurve = 1.5&lt;br /&gt;
700 Hc1HeatCurveAdaption = 0.0&lt;br /&gt;
700 Hc1MaxFlowTempDesired = 90&lt;br /&gt;
700 Hc1MinFlowTempDesired = 15&lt;br /&gt;
700 Hc1PumpStatus = 1&lt;br /&gt;
700 Hc1RoomTempSwitchOn = thermostat&lt;br /&gt;
700 Hc1Status = 1&lt;br /&gt;
700 Hc1SummerTempLimit = 21&lt;br /&gt;
700 HcStorageTempBottom =  (empty for 3115b5240602000000a000 / 080000a000ffffff7f)&lt;br /&gt;
700 HcStorageTempTop =  (empty for 3115b52406020000009f00 / 0800009f00ffffff7f)&lt;br /&gt;
700 HolidayTemp = 10&lt;br /&gt;
700 HwcFlowTemp = 0.0&lt;br /&gt;
700 HwcMaxFlowTempDesired = 80&lt;br /&gt;
700 HwcOpMode = auto&lt;br /&gt;
700 HwcSFMode = auto&lt;br /&gt;
700 HwcStorageTemp = 23&lt;br /&gt;
700 HwcStorageTempBottom =  (empty for 3115b52406020000009e00 / 0800009e00ffffff7f)&lt;br /&gt;
700 HwcStorageTempTop =  (empty for 3115b52406020000009d00 / 0800009d00ffffff7f)&lt;br /&gt;
700 HwcTempDesired = 55&lt;br /&gt;
700 HwcTimer_Friday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Monday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Saturday = 07:00;07:50;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Sunday = 07:20;08:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Thursday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Tuesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Wednesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 MaxRoomHumidity = 40&lt;br /&gt;
700 OpMode = auto&lt;br /&gt;
700 OpModeCooling = auto&lt;br /&gt;
700 OpModeEffect = alle&lt;br /&gt;
700 OpModeVentilation = auto&lt;br /&gt;
700 OutsideTempAvg = 7.60156&lt;br /&gt;
700 PrEnergySum = 27&lt;br /&gt;
700 PrEnergySumHc = 27&lt;br /&gt;
700 PrEnergySumHcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHcThisMonth = 0&lt;br /&gt;
700 PrEnergySumHwc = 0&lt;br /&gt;
700 PrEnergySumHwcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHwcThisMonth = 0&lt;br /&gt;
700 RoomHumidity = 49&lt;br /&gt;
700 SFMode = auto&lt;br /&gt;
700 SolarYieldTotal = 0&lt;br /&gt;
700 SystemFlowTemp =  (empty for 3115b52406020000004b00 / 0800004b00ffffff7f)&lt;br /&gt;
700 WaterPressure = 2.1&lt;br /&gt;
700 YieldTotal = 0&lt;br /&gt;
700 Z1ActualRoomTempDesired = 19.5&lt;br /&gt;
700 Z1DayTemp = 19.5&lt;br /&gt;
700 Z1HolidayTemp = 10&lt;br /&gt;
700 Z1NightTemp = 15&lt;br /&gt;
700 Z1OpMode = auto&lt;br /&gt;
700 Z1OpModeCooling = auto&lt;br /&gt;
700 Z1QuickVetoTemp = 21&lt;br /&gt;
700 Z1RoomTemp = 19.5&lt;br /&gt;
700 Z1SFMode = auto&lt;br /&gt;
700 Z1Timer_Friday = 06:40;17:30;17:30;22:30;-:-;-:-&lt;br /&gt;
700 Z1Timer_Monday = 06:40;07:40;16:40;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Saturday = 07:30;22:30;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Sunday = 08:00;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Thursday = 06:40;07:40;15:10;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Tuesday = 06:40;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Wednesday = 06:40;22:00;22:00;22:00;-:-;-:-&lt;br /&gt;
700 Z1ValveStatus = 1&lt;br /&gt;
bai AATemp = 197.25;62379;cutoff&lt;br /&gt;
bai AITemp =  (ERR: invalid position for 3108b509030d3300 / 00)&lt;br /&gt;
bai CounterStartattempts1 = 7&lt;br /&gt;
bai CounterStartattempts2 = 1&lt;br /&gt;
bai CounterStartAttempts3 = 1&lt;br /&gt;
bai DateTime = valid;21:50:35;28.03.2026;8.375&lt;br /&gt;
bai DeactivationsTemplimiter = 0&lt;br /&gt;
bai DisplayMode = 129&lt;br /&gt;
bai ExhaustCurve = 0&lt;br /&gt;
bai ExhaustWayBlockCounter = 0&lt;br /&gt;
bai Expertlevel_ReturnTemp = -1.81;cutoff&lt;br /&gt;
bai ExternalFlowTempDesired = 90.00&lt;br /&gt;
bai ExtFlowTempDesiredMin = 45.50&lt;br /&gt;
bai FanHours = 32&lt;br /&gt;
bai FanStarts = 267&lt;br /&gt;
bai FlowTemp = 44.31;ok&lt;br /&gt;
bai FlowTempDesired = 45.50&lt;br /&gt;
bai HcHours = 26&lt;br /&gt;
bai HcPumpMode = permanent&lt;br /&gt;
bai HcPumpStarts = 211&lt;br /&gt;
bai HcStarts = 100&lt;br /&gt;
bai HcUnderHundredStarts = 94&lt;br /&gt;
bai HoursTillService = 3010&lt;br /&gt;
bai HwcHours = 5&lt;br /&gt;
bai HwcPostrunTime = 300&lt;br /&gt;
bai HwcStarts = 0&lt;br /&gt;
bai HwcTemp = -14.94;cutoff&lt;br /&gt;
bai HwcTempDesired = 0.00&lt;br /&gt;
bai HwcTempMax = 65.00&lt;br /&gt;
bai HwcUnderHundredStarts = 74&lt;br /&gt;
bai HwcWaterflow =  (ERR: invalid position for 3108b509030d5500 / 00)&lt;br /&gt;
bai HwcWaterflowMax =  (ERR: invalid position for 3108b509030d5600 / 00)&lt;br /&gt;
bai Maintenancedata_HwcTempMax = 0.00&lt;br /&gt;
bai OutdoorstempSensor = 8.19;ok&lt;br /&gt;
bai OverflowCounter = no&lt;br /&gt;
bai PowerValue =  (ERR: invalid position for 3108b509030daa00 / 00)&lt;br /&gt;
bai PrAPSCounter = 0&lt;br /&gt;
bai PredCombustionPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMRefPWMcounter = 0&lt;br /&gt;
bai PredIgnitionPredCounter = 0;0;0&lt;br /&gt;
bai PredSourcePressurePredCounter =  (ERR: invalid position for 3108b509030d4301 / 00)&lt;br /&gt;
bai PredWaterflowDevThreshold =  (ERR: invalid position for 3108b509030d4401 / 00)&lt;br /&gt;
bai PredWaterflowSwitchingPoint =  (ERR: invalid position for 3108b509030d4501 / 00)&lt;br /&gt;
bai PredWaterpressureMaxPressure = 4000&lt;br /&gt;
bai PredWaterpressureMinPressure = 0&lt;br /&gt;
bai PredWaterpressureSwitchingPoint = 0&lt;br /&gt;
bai PrEnergyCountHc1 = 9469&lt;br /&gt;
bai PrEnergyCountHwc1 = 1922&lt;br /&gt;
bai PrEnergyCountHwc2 = 0&lt;br /&gt;
bai PrEnergyCountHwc3 = 0&lt;br /&gt;
bai PrEnergySumHc1 = 18134146&lt;br /&gt;
bai PrEnergySumHwc1 = 6876091&lt;br /&gt;
bai PrEnergySumHwc2 = 0&lt;br /&gt;
bai PrEnergySumHwc3 = 0&lt;br /&gt;
bai PumpHours = 93&lt;br /&gt;
bai ReturnTemp = -13.50;215;cutoff&lt;br /&gt;
bai ReturnTempMax = 0.00&lt;br /&gt;
bai SecondPumpMode = 2&lt;br /&gt;
bai SHEMaxFlowTemp =  (ERR: invalid position for 3108b509030dc300 / 00)&lt;br /&gt;
bai Status01 = 47.0;-;8.375;0.0;23.0;off&lt;br /&gt;
bai Status02 = auto;60;75.0;80;55.0&lt;br /&gt;
bai Status16 =  (ERR: invalid position for 3108b5040116 / 00)&lt;br /&gt;
bai Status =  (ERR: invalid position for 3108b5110103 / 00)&lt;br /&gt;
bai StorageLoadPumpHours = 10&lt;br /&gt;
bai StorageloadPumpStarts = 16&lt;br /&gt;
bai StorageTemp = 23.00;ok&lt;br /&gt;
bai StorageTempDesired = 55.00&lt;br /&gt;
bai StorageTempMax = 58.38&lt;br /&gt;
bai TempDiffBlock = 0&lt;br /&gt;
bai TempDiffFailure = 0&lt;br /&gt;
bai TempGradientFailure = 0&lt;br /&gt;
bai Templimiter = on&lt;br /&gt;
bai TemplimiterWithNTC = yes&lt;br /&gt;
bai TempMaxDiffExtTFT = 0.00&lt;br /&gt;
bai TimerInputHc = on&lt;br /&gt;
bai ValveMode = 0&lt;br /&gt;
bai ValveStarts =  (ERR: invalid position for 3108b509030d1a00 / 00)&lt;br /&gt;
bai WaterHcFlowMax =  (ERR: invalid position for 3108b509030dd000 / 00)&lt;br /&gt;
bai WaterPressure = 2.160;ok&lt;br /&gt;
bai WaterpressureBranchControlOff = off&lt;br /&gt;
bai WaterpressureMeasureCounter = 0&lt;br /&gt;
bai WaterpressureVariantSum = 0&lt;br /&gt;
bai WPPostrunTime = 5&lt;br /&gt;
bai WPPWMPower = 30&lt;br /&gt;
bai WPPWMPowerDia = 101&lt;br /&gt;
scan.08  = Vaillant;BAI00;0703;7401&lt;br /&gt;
Scan.08 Id = ;;;;;;&lt;br /&gt;
scan.15  = Vaillant;70000;0510;6403&lt;br /&gt;
Scan.15 Id = 21;17;52;0020171315;0082;026621;N7&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl read RoomHumidity&lt;br /&gt;
49&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1004</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1004"/>
		<updated>2026-03-28T20:56:08Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the application starts, it will fetch latest csv&#039;s &amp;amp; inc file from https://ebus.github.io/de/.&lt;br /&gt;
That&#039;s not ideal, let&#039;s depend only on local content:&lt;br /&gt;
&lt;br /&gt;
On your favorite endpoint:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://ebus.github.io/en/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/memory.csv&lt;br /&gt;
mkdir -p vaillant&lt;br /&gt;
cd vaillant&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/broadcast.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/general.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/scan.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/08.bai.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/15.700.csv&lt;br /&gt;
wget https://ebus.github.io/en/vaillant/bai.0010006101.inc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add important missing VRC700 Humidity metric:&lt;br /&gt;
&amp;lt;pre&amp;gt;% diff -u 15.700.csv.20260328 15.700.csv &lt;br /&gt;
--- 15.700.csv.20260328	2026-02-01 17:09:58.000000000 +0100&lt;br /&gt;
+++ 15.700.csv	2026-03-28 21:29:44.000000000 +0100&lt;br /&gt;
@@ -33,6 +33,7 @@&lt;br /&gt;
 w,,,Time,time,,,b524,020100003500,value,,HTI,,,Aktuelle Uhrzeit&lt;br /&gt;
 r,,,HydraulicScheme,Systemschema,,,b524,020000003600,ign,,IGN:4,,,,value,,UIN,,,Systemschema&lt;br /&gt;
 w,,,HydraulicScheme,Systemschema,,,b524,020100003600,value,,UIN,,,Systemschema&lt;br /&gt;
+r,,,RoomHumidity,room humidity,,,b524,060009010700,ign,,IGN:4,,,,humidity,,EXP,,%,room humidity&lt;br /&gt;
 r,,,WaterPressure,water pressure,,,b524,020000003900,ign,,IGN:4,,,,value,,EXP,,bar,Wasserdruck&lt;br /&gt;
 r,,,SolarYieldTotal,total solar yield,,,b524,020000003d00,ign,,IGN:4,,,,value,,ULG,,kWh,Solarertrag gesamt&lt;br /&gt;
 w,,,SolarYieldTotal,total solar yield,,,b524,020100003d00,value,,ULG,,kWh,Solarertrag gesamt&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upload the definitions in the right container config directory:&lt;br /&gt;
&amp;lt;/pre&amp;gt;scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
scp -P 22222 *.inc root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/vaillant/&lt;br /&gt;
cd ..&lt;br /&gt;
scp -P 22222 *.csv root@192.168.1.111:/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd/custom/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Configure eBUSd to use this configpath:&lt;br /&gt;
&amp;lt;pre&amp;gt;commandline_options:&lt;br /&gt;
  - &amp;quot;--mqttjson&amp;quot;&lt;br /&gt;
  - &amp;quot;--scanconfig&amp;quot;&lt;br /&gt;
  - &amp;quot;--log=all:error&amp;quot;&lt;br /&gt;
  - &amp;quot;--enabledefine&amp;quot;&lt;br /&gt;
  - &amp;quot;--configpath=/config/custom/&amp;quot;&lt;br /&gt;
network_device: ens:/dev/ttyACM0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 44&lt;br /&gt;
max symbol rate: 127&lt;br /&gt;
min arbitration micros: 3&lt;br /&gt;
max arbitration micros: 15&lt;br /&gt;
min symbol latency: 4&lt;br /&gt;
max symbol latency: 7&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 718&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 152&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl find -d -r&lt;br /&gt;
700 AdaptHeatCurve = no&lt;br /&gt;
700 DisplayedOutsideTemp = 6.375&lt;br /&gt;
700 Hc1ActualFlowTempDesired = 45.6435&lt;br /&gt;
700 Hc1AutoOffMode = night&lt;br /&gt;
700 Hc1ExcessTemp = 0.0&lt;br /&gt;
700 Hc1FlowTemp = 50&lt;br /&gt;
700 Hc1HeatCurve = 1.5&lt;br /&gt;
700 Hc1HeatCurveAdaption = 0.0&lt;br /&gt;
700 Hc1MaxFlowTempDesired = 90&lt;br /&gt;
700 Hc1MinFlowTempDesired = 15&lt;br /&gt;
700 Hc1PumpStatus = 1&lt;br /&gt;
700 Hc1RoomTempSwitchOn = thermostat&lt;br /&gt;
700 Hc1Status = 1&lt;br /&gt;
700 Hc1SummerTempLimit = 21&lt;br /&gt;
700 HcStorageTempBottom =  (empty for 3115b5240602000000a000 / 080000a000ffffff7f)&lt;br /&gt;
700 HcStorageTempTop =  (empty for 3115b52406020000009f00 / 0800009f00ffffff7f)&lt;br /&gt;
700 HolidayTemp = 10&lt;br /&gt;
700 HwcFlowTemp = 0.0&lt;br /&gt;
700 HwcMaxFlowTempDesired = 80&lt;br /&gt;
700 HwcOpMode = auto&lt;br /&gt;
700 HwcSFMode = auto&lt;br /&gt;
700 HwcStorageTemp = 23&lt;br /&gt;
700 HwcStorageTempBottom =  (empty for 3115b52406020000009e00 / 0800009e00ffffff7f)&lt;br /&gt;
700 HwcStorageTempTop =  (empty for 3115b52406020000009d00 / 0800009d00ffffff7f)&lt;br /&gt;
700 HwcTempDesired = 55&lt;br /&gt;
700 HwcTimer_Friday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Monday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Saturday = 07:00;07:50;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Sunday = 07:20;08:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Thursday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Tuesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Wednesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 MaxRoomHumidity = 40&lt;br /&gt;
700 OpMode = auto&lt;br /&gt;
700 OpModeCooling = auto&lt;br /&gt;
700 OpModeEffect = alle&lt;br /&gt;
700 OpModeVentilation = auto&lt;br /&gt;
700 OutsideTempAvg = 7.60156&lt;br /&gt;
700 PrEnergySum = 27&lt;br /&gt;
700 PrEnergySumHc = 27&lt;br /&gt;
700 PrEnergySumHcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHcThisMonth = 0&lt;br /&gt;
700 PrEnergySumHwc = 0&lt;br /&gt;
700 PrEnergySumHwcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHwcThisMonth = 0&lt;br /&gt;
700 RoomHumidity = 49&lt;br /&gt;
700 SFMode = auto&lt;br /&gt;
700 SolarYieldTotal = 0&lt;br /&gt;
700 SystemFlowTemp =  (empty for 3115b52406020000004b00 / 0800004b00ffffff7f)&lt;br /&gt;
700 WaterPressure = 2.1&lt;br /&gt;
700 YieldTotal = 0&lt;br /&gt;
700 Z1ActualRoomTempDesired = 19.5&lt;br /&gt;
700 Z1DayTemp = 19.5&lt;br /&gt;
700 Z1HolidayTemp = 10&lt;br /&gt;
700 Z1NightTemp = 15&lt;br /&gt;
700 Z1OpMode = auto&lt;br /&gt;
700 Z1OpModeCooling = auto&lt;br /&gt;
700 Z1QuickVetoTemp = 21&lt;br /&gt;
700 Z1RoomTemp = 19.5&lt;br /&gt;
700 Z1SFMode = auto&lt;br /&gt;
700 Z1Timer_Friday = 06:40;17:30;17:30;22:30;-:-;-:-&lt;br /&gt;
700 Z1Timer_Monday = 06:40;07:40;16:40;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Saturday = 07:30;22:30;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Sunday = 08:00;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Thursday = 06:40;07:40;15:10;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Tuesday = 06:40;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Wednesday = 06:40;22:00;22:00;22:00;-:-;-:-&lt;br /&gt;
700 Z1ValveStatus = 1&lt;br /&gt;
bai AATemp = 197.25;62379;cutoff&lt;br /&gt;
bai AITemp =  (ERR: invalid position for 3108b509030d3300 / 00)&lt;br /&gt;
bai CounterStartattempts1 = 7&lt;br /&gt;
bai CounterStartattempts2 = 1&lt;br /&gt;
bai CounterStartAttempts3 = 1&lt;br /&gt;
bai DateTime = valid;21:50:35;28.03.2026;8.375&lt;br /&gt;
bai DeactivationsTemplimiter = 0&lt;br /&gt;
bai DisplayMode = 129&lt;br /&gt;
bai ExhaustCurve = 0&lt;br /&gt;
bai ExhaustWayBlockCounter = 0&lt;br /&gt;
bai Expertlevel_ReturnTemp = -1.81;cutoff&lt;br /&gt;
bai ExternalFlowTempDesired = 90.00&lt;br /&gt;
bai ExtFlowTempDesiredMin = 45.50&lt;br /&gt;
bai FanHours = 32&lt;br /&gt;
bai FanStarts = 267&lt;br /&gt;
bai FlowTemp = 44.31;ok&lt;br /&gt;
bai FlowTempDesired = 45.50&lt;br /&gt;
bai HcHours = 26&lt;br /&gt;
bai HcPumpMode = permanent&lt;br /&gt;
bai HcPumpStarts = 211&lt;br /&gt;
bai HcStarts = 100&lt;br /&gt;
bai HcUnderHundredStarts = 94&lt;br /&gt;
bai HoursTillService = 3010&lt;br /&gt;
bai HwcHours = 5&lt;br /&gt;
bai HwcPostrunTime = 300&lt;br /&gt;
bai HwcStarts = 0&lt;br /&gt;
bai HwcTemp = -14.94;cutoff&lt;br /&gt;
bai HwcTempDesired = 0.00&lt;br /&gt;
bai HwcTempMax = 65.00&lt;br /&gt;
bai HwcUnderHundredStarts = 74&lt;br /&gt;
bai HwcWaterflow =  (ERR: invalid position for 3108b509030d5500 / 00)&lt;br /&gt;
bai HwcWaterflowMax =  (ERR: invalid position for 3108b509030d5600 / 00)&lt;br /&gt;
bai Maintenancedata_HwcTempMax = 0.00&lt;br /&gt;
bai OutdoorstempSensor = 8.19;ok&lt;br /&gt;
bai OverflowCounter = no&lt;br /&gt;
bai PowerValue =  (ERR: invalid position for 3108b509030daa00 / 00)&lt;br /&gt;
bai PrAPSCounter = 0&lt;br /&gt;
bai PredCombustionPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMRefPWMcounter = 0&lt;br /&gt;
bai PredIgnitionPredCounter = 0;0;0&lt;br /&gt;
bai PredSourcePressurePredCounter =  (ERR: invalid position for 3108b509030d4301 / 00)&lt;br /&gt;
bai PredWaterflowDevThreshold =  (ERR: invalid position for 3108b509030d4401 / 00)&lt;br /&gt;
bai PredWaterflowSwitchingPoint =  (ERR: invalid position for 3108b509030d4501 / 00)&lt;br /&gt;
bai PredWaterpressureMaxPressure = 4000&lt;br /&gt;
bai PredWaterpressureMinPressure = 0&lt;br /&gt;
bai PredWaterpressureSwitchingPoint = 0&lt;br /&gt;
bai PrEnergyCountHc1 = 9469&lt;br /&gt;
bai PrEnergyCountHwc1 = 1922&lt;br /&gt;
bai PrEnergyCountHwc2 = 0&lt;br /&gt;
bai PrEnergyCountHwc3 = 0&lt;br /&gt;
bai PrEnergySumHc1 = 18134146&lt;br /&gt;
bai PrEnergySumHwc1 = 6876091&lt;br /&gt;
bai PrEnergySumHwc2 = 0&lt;br /&gt;
bai PrEnergySumHwc3 = 0&lt;br /&gt;
bai PumpHours = 93&lt;br /&gt;
bai ReturnTemp = -13.50;215;cutoff&lt;br /&gt;
bai ReturnTempMax = 0.00&lt;br /&gt;
bai SecondPumpMode = 2&lt;br /&gt;
bai SHEMaxFlowTemp =  (ERR: invalid position for 3108b509030dc300 / 00)&lt;br /&gt;
bai Status01 = 47.0;-;8.375;0.0;23.0;off&lt;br /&gt;
bai Status02 = auto;60;75.0;80;55.0&lt;br /&gt;
bai Status16 =  (ERR: invalid position for 3108b5040116 / 00)&lt;br /&gt;
bai Status =  (ERR: invalid position for 3108b5110103 / 00)&lt;br /&gt;
bai StorageLoadPumpHours = 10&lt;br /&gt;
bai StorageloadPumpStarts = 16&lt;br /&gt;
bai StorageTemp = 23.00;ok&lt;br /&gt;
bai StorageTempDesired = 55.00&lt;br /&gt;
bai StorageTempMax = 58.38&lt;br /&gt;
bai TempDiffBlock = 0&lt;br /&gt;
bai TempDiffFailure = 0&lt;br /&gt;
bai TempGradientFailure = 0&lt;br /&gt;
bai Templimiter = on&lt;br /&gt;
bai TemplimiterWithNTC = yes&lt;br /&gt;
bai TempMaxDiffExtTFT = 0.00&lt;br /&gt;
bai TimerInputHc = on&lt;br /&gt;
bai ValveMode = 0&lt;br /&gt;
bai ValveStarts =  (ERR: invalid position for 3108b509030d1a00 / 00)&lt;br /&gt;
bai WaterHcFlowMax =  (ERR: invalid position for 3108b509030dd000 / 00)&lt;br /&gt;
bai WaterPressure = 2.160;ok&lt;br /&gt;
bai WaterpressureBranchControlOff = off&lt;br /&gt;
bai WaterpressureMeasureCounter = 0&lt;br /&gt;
bai WaterpressureVariantSum = 0&lt;br /&gt;
bai WPPostrunTime = 5&lt;br /&gt;
bai WPPWMPower = 30&lt;br /&gt;
bai WPPWMPowerDia = 101&lt;br /&gt;
scan.08  = Vaillant;BAI00;0703;7401&lt;br /&gt;
Scan.08 Id = ;;;;;;&lt;br /&gt;
scan.15  = Vaillant;70000;0510;6403&lt;br /&gt;
Scan.15 Id = 21;17;52;0020171315;0082;026621;N7&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl read RoomHumidity&lt;br /&gt;
49&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1003</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1003"/>
		<updated>2026-03-28T20:51:37Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* WebUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 44&lt;br /&gt;
max symbol rate: 127&lt;br /&gt;
min arbitration micros: 3&lt;br /&gt;
max arbitration micros: 15&lt;br /&gt;
min symbol latency: 4&lt;br /&gt;
max symbol latency: 7&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 718&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 152&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl find -d -r&lt;br /&gt;
700 AdaptHeatCurve = no&lt;br /&gt;
700 DisplayedOutsideTemp = 6.375&lt;br /&gt;
700 Hc1ActualFlowTempDesired = 45.6435&lt;br /&gt;
700 Hc1AutoOffMode = night&lt;br /&gt;
700 Hc1ExcessTemp = 0.0&lt;br /&gt;
700 Hc1FlowTemp = 50&lt;br /&gt;
700 Hc1HeatCurve = 1.5&lt;br /&gt;
700 Hc1HeatCurveAdaption = 0.0&lt;br /&gt;
700 Hc1MaxFlowTempDesired = 90&lt;br /&gt;
700 Hc1MinFlowTempDesired = 15&lt;br /&gt;
700 Hc1PumpStatus = 1&lt;br /&gt;
700 Hc1RoomTempSwitchOn = thermostat&lt;br /&gt;
700 Hc1Status = 1&lt;br /&gt;
700 Hc1SummerTempLimit = 21&lt;br /&gt;
700 HcStorageTempBottom =  (empty for 3115b5240602000000a000 / 080000a000ffffff7f)&lt;br /&gt;
700 HcStorageTempTop =  (empty for 3115b52406020000009f00 / 0800009f00ffffff7f)&lt;br /&gt;
700 HolidayTemp = 10&lt;br /&gt;
700 HwcFlowTemp = 0.0&lt;br /&gt;
700 HwcMaxFlowTempDesired = 80&lt;br /&gt;
700 HwcOpMode = auto&lt;br /&gt;
700 HwcSFMode = auto&lt;br /&gt;
700 HwcStorageTemp = 23&lt;br /&gt;
700 HwcStorageTempBottom =  (empty for 3115b52406020000009e00 / 0800009e00ffffff7f)&lt;br /&gt;
700 HwcStorageTempTop =  (empty for 3115b52406020000009d00 / 0800009d00ffffff7f)&lt;br /&gt;
700 HwcTempDesired = 55&lt;br /&gt;
700 HwcTimer_Friday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Monday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Saturday = 07:00;07:50;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Sunday = 07:20;08:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Thursday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Tuesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 HwcTimer_Wednesday = 06:00;06:40;17:50;18:30;-:-;-:-&lt;br /&gt;
700 MaxRoomHumidity = 40&lt;br /&gt;
700 OpMode = auto&lt;br /&gt;
700 OpModeCooling = auto&lt;br /&gt;
700 OpModeEffect = alle&lt;br /&gt;
700 OpModeVentilation = auto&lt;br /&gt;
700 OutsideTempAvg = 7.60156&lt;br /&gt;
700 PrEnergySum = 27&lt;br /&gt;
700 PrEnergySumHc = 27&lt;br /&gt;
700 PrEnergySumHcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHcThisMonth = 0&lt;br /&gt;
700 PrEnergySumHwc = 0&lt;br /&gt;
700 PrEnergySumHwcLastMonth = 0&lt;br /&gt;
700 PrEnergySumHwcThisMonth = 0&lt;br /&gt;
700 RoomHumidity = 49&lt;br /&gt;
700 SFMode = auto&lt;br /&gt;
700 SolarYieldTotal = 0&lt;br /&gt;
700 SystemFlowTemp =  (empty for 3115b52406020000004b00 / 0800004b00ffffff7f)&lt;br /&gt;
700 WaterPressure = 2.1&lt;br /&gt;
700 YieldTotal = 0&lt;br /&gt;
700 Z1ActualRoomTempDesired = 19.5&lt;br /&gt;
700 Z1DayTemp = 19.5&lt;br /&gt;
700 Z1HolidayTemp = 10&lt;br /&gt;
700 Z1NightTemp = 15&lt;br /&gt;
700 Z1OpMode = auto&lt;br /&gt;
700 Z1OpModeCooling = auto&lt;br /&gt;
700 Z1QuickVetoTemp = 21&lt;br /&gt;
700 Z1RoomTemp = 19.5&lt;br /&gt;
700 Z1SFMode = auto&lt;br /&gt;
700 Z1Timer_Friday = 06:40;17:30;17:30;22:30;-:-;-:-&lt;br /&gt;
700 Z1Timer_Monday = 06:40;07:40;16:40;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Saturday = 07:30;22:30;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Sunday = 08:00;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Thursday = 06:40;07:40;15:10;22:00;-:-;-:-&lt;br /&gt;
700 Z1Timer_Tuesday = 06:40;22:00;-:-;-:-;-:-;-:-&lt;br /&gt;
700 Z1Timer_Wednesday = 06:40;22:00;22:00;22:00;-:-;-:-&lt;br /&gt;
700 Z1ValveStatus = 1&lt;br /&gt;
bai AATemp = 197.25;62379;cutoff&lt;br /&gt;
bai AITemp =  (ERR: invalid position for 3108b509030d3300 / 00)&lt;br /&gt;
bai CounterStartattempts1 = 7&lt;br /&gt;
bai CounterStartattempts2 = 1&lt;br /&gt;
bai CounterStartAttempts3 = 1&lt;br /&gt;
bai DateTime = valid;21:50:35;28.03.2026;8.375&lt;br /&gt;
bai DeactivationsTemplimiter = 0&lt;br /&gt;
bai DisplayMode = 129&lt;br /&gt;
bai ExhaustCurve = 0&lt;br /&gt;
bai ExhaustWayBlockCounter = 0&lt;br /&gt;
bai Expertlevel_ReturnTemp = -1.81;cutoff&lt;br /&gt;
bai ExternalFlowTempDesired = 90.00&lt;br /&gt;
bai ExtFlowTempDesiredMin = 45.50&lt;br /&gt;
bai FanHours = 32&lt;br /&gt;
bai FanStarts = 267&lt;br /&gt;
bai FlowTemp = 44.31;ok&lt;br /&gt;
bai FlowTempDesired = 45.50&lt;br /&gt;
bai HcHours = 26&lt;br /&gt;
bai HcPumpMode = permanent&lt;br /&gt;
bai HcPumpStarts = 211&lt;br /&gt;
bai HcStarts = 100&lt;br /&gt;
bai HcUnderHundredStarts = 94&lt;br /&gt;
bai HoursTillService = 3010&lt;br /&gt;
bai HwcHours = 5&lt;br /&gt;
bai HwcPostrunTime = 300&lt;br /&gt;
bai HwcStarts = 0&lt;br /&gt;
bai HwcTemp = -14.94;cutoff&lt;br /&gt;
bai HwcTempDesired = 0.00&lt;br /&gt;
bai HwcTempMax = 65.00&lt;br /&gt;
bai HwcUnderHundredStarts = 74&lt;br /&gt;
bai HwcWaterflow =  (ERR: invalid position for 3108b509030d5500 / 00)&lt;br /&gt;
bai HwcWaterflowMax =  (ERR: invalid position for 3108b509030d5600 / 00)&lt;br /&gt;
bai Maintenancedata_HwcTempMax = 0.00&lt;br /&gt;
bai OutdoorstempSensor = 8.19;ok&lt;br /&gt;
bai OverflowCounter = no&lt;br /&gt;
bai PowerValue =  (ERR: invalid position for 3108b509030daa00 / 00)&lt;br /&gt;
bai PrAPSCounter = 0&lt;br /&gt;
bai PredCombustionPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMPredCounter = 0;0;0&lt;br /&gt;
bai PredFanPWMRefPWMcounter = 0&lt;br /&gt;
bai PredIgnitionPredCounter = 0;0;0&lt;br /&gt;
bai PredSourcePressurePredCounter =  (ERR: invalid position for 3108b509030d4301 / 00)&lt;br /&gt;
bai PredWaterflowDevThreshold =  (ERR: invalid position for 3108b509030d4401 / 00)&lt;br /&gt;
bai PredWaterflowSwitchingPoint =  (ERR: invalid position for 3108b509030d4501 / 00)&lt;br /&gt;
bai PredWaterpressureMaxPressure = 4000&lt;br /&gt;
bai PredWaterpressureMinPressure = 0&lt;br /&gt;
bai PredWaterpressureSwitchingPoint = 0&lt;br /&gt;
bai PrEnergyCountHc1 = 9469&lt;br /&gt;
bai PrEnergyCountHwc1 = 1922&lt;br /&gt;
bai PrEnergyCountHwc2 = 0&lt;br /&gt;
bai PrEnergyCountHwc3 = 0&lt;br /&gt;
bai PrEnergySumHc1 = 18134146&lt;br /&gt;
bai PrEnergySumHwc1 = 6876091&lt;br /&gt;
bai PrEnergySumHwc2 = 0&lt;br /&gt;
bai PrEnergySumHwc3 = 0&lt;br /&gt;
bai PumpHours = 93&lt;br /&gt;
bai ReturnTemp = -13.50;215;cutoff&lt;br /&gt;
bai ReturnTempMax = 0.00&lt;br /&gt;
bai SecondPumpMode = 2&lt;br /&gt;
bai SHEMaxFlowTemp =  (ERR: invalid position for 3108b509030dc300 / 00)&lt;br /&gt;
bai Status01 = 47.0;-;8.375;0.0;23.0;off&lt;br /&gt;
bai Status02 = auto;60;75.0;80;55.0&lt;br /&gt;
bai Status16 =  (ERR: invalid position for 3108b5040116 / 00)&lt;br /&gt;
bai Status =  (ERR: invalid position for 3108b5110103 / 00)&lt;br /&gt;
bai StorageLoadPumpHours = 10&lt;br /&gt;
bai StorageloadPumpStarts = 16&lt;br /&gt;
bai StorageTemp = 23.00;ok&lt;br /&gt;
bai StorageTempDesired = 55.00&lt;br /&gt;
bai StorageTempMax = 58.38&lt;br /&gt;
bai TempDiffBlock = 0&lt;br /&gt;
bai TempDiffFailure = 0&lt;br /&gt;
bai TempGradientFailure = 0&lt;br /&gt;
bai Templimiter = on&lt;br /&gt;
bai TemplimiterWithNTC = yes&lt;br /&gt;
bai TempMaxDiffExtTFT = 0.00&lt;br /&gt;
bai TimerInputHc = on&lt;br /&gt;
bai ValveMode = 0&lt;br /&gt;
bai ValveStarts =  (ERR: invalid position for 3108b509030d1a00 / 00)&lt;br /&gt;
bai WaterHcFlowMax =  (ERR: invalid position for 3108b509030dd000 / 00)&lt;br /&gt;
bai WaterPressure = 2.160;ok&lt;br /&gt;
bai WaterpressureBranchControlOff = off&lt;br /&gt;
bai WaterpressureMeasureCounter = 0&lt;br /&gt;
bai WaterpressureVariantSum = 0&lt;br /&gt;
bai WPPostrunTime = 5&lt;br /&gt;
bai WPPWMPower = 30&lt;br /&gt;
bai WPPWMPowerDia = 101&lt;br /&gt;
scan.08  = Vaillant;BAI00;0703;7401&lt;br /&gt;
Scan.08 Id = ;;;;;;&lt;br /&gt;
scan.15  = Vaillant;70000;0510;6403&lt;br /&gt;
Scan.15 Id = 21;17;52;0020171315;0082;026621;N7&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl read RoomHumidity&lt;br /&gt;
49&lt;br /&gt;
&lt;br /&gt;
root@b4d7ad18-ebusd:/# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1002</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1002"/>
		<updated>2026-03-28T20:50:22Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* First and second start-up of the app */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1001</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1001"/>
		<updated>2026-03-28T20:50:01Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* MQTT */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this entity should be created automatically when it will be published on the bus.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1000</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=1000"/>
		<updated>2026-03-27T22:45:02Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|Water&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=999</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=999"/>
		<updated>2026-03-27T22:43:33Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|WaterPressure&lt;br /&gt;
filter-non-name = Z1Cooling|VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=998</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=998"/>
		<updated>2026-03-27T21:14:26Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* MQTT */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|WaterPressure&lt;br /&gt;
filter-non-name = VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
To obtain the missing entity WaterPressure, publish this on the bus (valid for VRC700 only):&lt;br /&gt;
Topic:&lt;br /&gt;
homeassistant/sensor/ebusd_700_water_pressure/config&lt;br /&gt;
Json:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Water Pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_topic&amp;quot;: &amp;quot;ebusd/700/WaterPressure&amp;quot;,&lt;br /&gt;
  &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.value.value }}&amp;quot;,&lt;br /&gt;
  &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;bar&amp;quot;,&lt;br /&gt;
  &amp;quot;device_class&amp;quot;: &amp;quot;pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;,&lt;br /&gt;
  &amp;quot;unique_id&amp;quot;: &amp;quot;ebusd_700_water_pressure&amp;quot;,&lt;br /&gt;
  &amp;quot;device&amp;quot;: {&lt;br /&gt;
    &amp;quot;identifiers&amp;quot;: [&amp;quot;ebusd_700&amp;quot;],&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;ebusd 700&amp;quot;,&lt;br /&gt;
    &amp;quot;manufacturer&amp;quot;: &amp;quot;Vaillant&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=997</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=997"/>
		<updated>2026-03-27T21:09:45Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
Some filters for unneeded entities + WaterPressure which is not added by default:&lt;br /&gt;
&amp;lt;pre&amp;gt;# pwd&lt;br /&gt;
/mnt/data/supervisor/addon_configs/b4d7ad18_ebusd&lt;br /&gt;
# grep filter mqtt-hassio.cfg | grep &amp;quot;=&amp;quot; | grep -v &amp;quot;^#&amp;quot;&lt;br /&gt;
filter-seen = 5&lt;br /&gt;
filter-name = status|temp|humidity|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$|sensor|timer|WaterPressure&lt;br /&gt;
filter-non-name = VentilationTimer|NoiseReductionTimer|TariffTimer|Hc2|Hc3|Z2|Z3|CcTimer&lt;br /&gt;
filter-level = ^$&lt;br /&gt;
filter-direction = r|u&lt;br /&gt;
filter-non-field = ^sensor$&lt;br /&gt;
# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=996</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=996"/>
		<updated>2026-03-22T21:16:11Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* MQTT */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Hundreds of ephemeral MQTT topics are created on the fly and used to the needed entities.&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=995</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=995"/>
		<updated>2026-03-22T21:14:20Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUS Adapter Stick C6 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi. As stated above, I don&#039;t use WiFi for reliability reasons.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; connect to the WiFi (Opened SSID &amp;quot;EBUS&amp;quot;) then browse to the IP 192.168.4.1 and finally change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=994</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=994"/>
		<updated>2026-03-22T21:11:51Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Disclaimer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;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.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=993</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=993"/>
		<updated>2026-03-22T21:11:34Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Disclaimer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;t intend to structure it better nor being more verbose ;-) Should you have questions, contact me by email on ha2026@pnzone.net.&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=992</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=992"/>
		<updated>2026-03-22T21:09:40Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Disclaimer =&lt;br /&gt;
I use this page as a very drafty &amp;quot;personal&amp;quot; notepad / memo. It&#039;s a bit messy but straight to the point and I don&#039;t intend to structure it better ;-)&lt;br /&gt;
&lt;br /&gt;
= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=991</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=991"/>
		<updated>2026-03-22T21:06:10Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Climate card */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits &amp;amp; sources ==&lt;br /&gt;
* eBUSd HA integation: https://www.home-assistant.io/integrations/ebusd&lt;br /&gt;
* eBUSd USB stick: https://adapter.ebusd.eu/v5-c6/stick.en.html&lt;br /&gt;
* Global how-to (HA, Vaillant, eBUS, thermostat &amp;amp; climate): https://fromeijn.nl/connected-vaillant-to-home-assistant/&lt;br /&gt;
* Thermostat &amp;amp; climate integration: https://github.com/john30/ebusd/discussions/764&lt;br /&gt;
* Vaillant heat curves explained : https://protonsforbreakfast.wordpress.com/2024/10/16/vaillant-heat-pump-controls-part-1-the-heat-curves/&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=990</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=990"/>
		<updated>2026-03-22T20:57:43Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Climate card */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;br /&gt;
&lt;br /&gt;
In order to see the Mode current status &amp;amp; buttons (auto, day, night, off), then edit the yaml code of the card added on the dashboard and add the features section :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type: thermostat&lt;br /&gt;
entity: climate.vrc700&lt;br /&gt;
features:&lt;br /&gt;
  - type: climate-hvac-modes&lt;br /&gt;
    hvac_modes:&lt;br /&gt;
      - auto&lt;br /&gt;
      - heat&lt;br /&gt;
      - cool&lt;br /&gt;
      - &amp;quot;off&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=989</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=989"/>
		<updated>2026-03-22T18:48:41Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Climate card */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      - name: VRC700                                                                       &lt;br /&gt;
        unique_id: vaillant_vrc700_zone1_gv34&lt;br /&gt;
&lt;br /&gt;
        max_temp: 23                                                                       &lt;br /&gt;
        min_temp: 15                                                                       &lt;br /&gt;
        precision: 0.1                                                                     &lt;br /&gt;
        temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
        modes:                                                                             &lt;br /&gt;
         - &#039;auto&#039;                                                                            &lt;br /&gt;
         - &#039;heat&#039;                                                                            &lt;br /&gt;
         - &#039;cool&#039;                                                                         &lt;br /&gt;
         - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
        mode_state_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {% set state = value_json.value.value %}&lt;br /&gt;
          {{ values[state] if state in values.keys() else &#039;off&#039; }}&lt;br /&gt;
        mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        mode_command_template: &amp;gt;-&lt;br /&gt;
          {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
          {{ values[value] if value in values.keys() else &#039;auto&#039; }}&lt;br /&gt;
        mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
        temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
        temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
        temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
        current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=988</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=988"/>
		<updated>2026-03-22T17:42:34Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Climate card */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      name: VRC700                                                                       &lt;br /&gt;
      max_temp: 23                                                                       &lt;br /&gt;
      min_temp: 15                                                                       &lt;br /&gt;
      precision: 0.1                                                                     &lt;br /&gt;
      temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
      modes:                                                                             &lt;br /&gt;
       - &#039;auto&#039;                                                                            &lt;br /&gt;
       - &#039;heat&#039;                                                                            &lt;br /&gt;
       - &#039;cool&#039;                                                                         &lt;br /&gt;
       - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
      mode_state_template: &amp;gt;-&lt;br /&gt;
        {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
        {% set state = value_json[&amp;quot;value&amp;quot;].value %}&lt;br /&gt;
        {{ values[state] if state in values.keys() }}&lt;br /&gt;
      mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      mode_command_template: &amp;gt;-&lt;br /&gt;
        {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
        {{ values[value] if value in values.keys() }}&lt;br /&gt;
      mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
      temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;&lt;br /&gt;
      temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
      temperature_command_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired/set&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
      current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=987</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=987"/>
		<updated>2026-03-22T10:33:15Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Heating system control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Climate card ==&lt;br /&gt;
In configuration.yaml, add this configuration (specific to the Vaillant VRC700):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mqtt:                                                                                    &lt;br /&gt;
  climate:                                                                               &lt;br /&gt;
      name: VRC700                                                                       &lt;br /&gt;
      max_temp: 25                                                                       &lt;br /&gt;
      min_temp: 10                                                                       &lt;br /&gt;
      precision: 0.1                                                                     &lt;br /&gt;
      temp_step: 0.5                                                                     &lt;br /&gt;
                                                                                         &lt;br /&gt;
      modes:                                                                             &lt;br /&gt;
       - &#039;auto&#039;                                                                            &lt;br /&gt;
       - &#039;heat&#039;                                                                            &lt;br /&gt;
       - &#039;cool&#039;                                                                         &lt;br /&gt;
       - &#039;off&#039;                                                                           &lt;br /&gt;
 &lt;br /&gt;
      mode_state_template: &amp;gt;-&lt;br /&gt;
        {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;day&#039;:&#039;heat&#039;, &#039;night&#039;:&#039;cool&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
        {% set state = value_json[&amp;quot;value&amp;quot;].value %}&lt;br /&gt;
        {{ values[state] if state in values.keys() }}&lt;br /&gt;
      mode_state_topic: &amp;quot;ebusd/700/Z1OpMode&amp;quot;&lt;br /&gt;
&lt;br /&gt;
      mode_command_template: &amp;gt;-&lt;br /&gt;
        {% set values = { &#039;auto&#039;:&#039;auto&#039;, &#039;heat&#039;:&#039;day&#039;, &#039;cool&#039;:&#039;night&#039;, &#039;off&#039;:&#039;off&#039;} %}&lt;br /&gt;
        {{ values[value] if value in values.keys() }}&lt;br /&gt;
      mode_command_topic: &amp;quot;ebusd/700/Z1OpMode/set&amp;quot;&lt;br /&gt;
                                                                          &lt;br /&gt;
      temperature_state_topic: &amp;quot;ebusd/700/Z1ActualRoomTempDesired&amp;quot;   &lt;br /&gt;
      temperature_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;     &lt;br /&gt;
                                                                     &lt;br /&gt;
      temperature_low_state_topic: &amp;quot;ebusd/700/Z1NightTemp&amp;quot;           &lt;br /&gt;
      temperature_low_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot; &lt;br /&gt;
                                                                     &lt;br /&gt;
      temperature_high_state_topic: &amp;quot;ebusd/700/Z1DayTemp&amp;quot;            &lt;br /&gt;
      temperature_high_state_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
                                                                  &lt;br /&gt;
      temperature_low_command_topic: &amp;quot;ebusd/700/Z1NightTemp/set&amp;quot;  &lt;br /&gt;
      temperature_high_command_topic: &amp;quot;ebusd/700/Z1DayTemp/set&amp;quot;   &lt;br /&gt;
                                                                  &lt;br /&gt;
      current_temperature_topic: &amp;quot;ebusd/700/Z1RoomTemp&amp;quot;           &lt;br /&gt;
      current_temperature_template: &amp;quot;{{ value_json.value.value }}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:VRC700 HA.png]]&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:VRC700_HA.png&amp;diff=986</id>
		<title>Fichier:VRC700 HA.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:VRC700_HA.png&amp;diff=986"/>
		<updated>2026-03-22T10:32:32Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=985</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=985"/>
		<updated>2026-03-21T20:38:33Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* WebUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=984</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=984"/>
		<updated>2026-03-21T20:38:21Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* WebUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
root@b4d7ad18-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial high speed, enhanced, firmware 1.1[6112].1[6112]&lt;br /&gt;
signal: acquired&lt;br /&gt;
symbol rate: 23&lt;br /&gt;
max symbol rate: 118&lt;br /&gt;
min arbitration micros: 2&lt;br /&gt;
max arbitration micros: 4326&lt;br /&gt;
min symbol latency: 3&lt;br /&gt;
max symbol latency: 10&lt;br /&gt;
scan: finished&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 3&lt;br /&gt;
messages: 717&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 253&lt;br /&gt;
update: 16&lt;br /&gt;
address 03: master #11&lt;br /&gt;
address 08: slave #11, scanned &amp;quot;MF=Vaillant;ID=BAI00;SW=0703;HW=7401&amp;quot;, loaded &amp;quot;vaillant/bai.0010006101.inc&amp;quot; ([Scan_id_product=&#039;&#039;]), &amp;quot;vaillant/08.bai.csv&amp;quot;&lt;br /&gt;
address 10: master #2&lt;br /&gt;
address 15: slave #2, scanned &amp;quot;MF=Vaillant;ID=70000;SW=0510;HW=6403&amp;quot;, loaded &amp;quot;vaillant/15.700.csv&amp;quot;&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=983</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=983"/>
		<updated>2026-03-21T20:36:09Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUS Adapter Stick C6 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
[[Fichier:EBUS C6.png]]&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:EBUS_C6.png&amp;diff=982</id>
		<title>Fichier:EBUS C6.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:EBUS_C6.png&amp;diff=982"/>
		<updated>2026-03-21T20:35:38Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=981</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=981"/>
		<updated>2026-03-21T20:34:05Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUS Adapter Stick C6 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stick is configured by default on WiFi.&lt;br /&gt;
We need to connect to the WiFi, via the Opened SSID EBUS, then IP 192.168.4.1 and then change its connection type from TCP to USB Serial:&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=980</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=980"/>
		<updated>2026-03-21T20:33:30Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUSd app */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=979</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=979"/>
		<updated>2026-03-21T09:07:39Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* WebUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Signal should be acquired at this stage. Indeed the USB stick green&#039;s led is flashing quickly meaning it sees frames on the eBus.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; I opened a case:&lt;br /&gt;
* https://github.com/john30/ebusd/discussions/1718&lt;br /&gt;
* https://github.com/john30/ebusd-esp32/issues/161&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=978</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=978"/>
		<updated>2026-03-21T08:58:09Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUSd app */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Signal should be acquired at this stage. Indeed the USB stick green&#039;s led is flashing quickly meaning it sees frames on the eBus.&lt;br /&gt;
&lt;br /&gt;
=&amp;gt; I opened a case: https://github.com/john30/ebusd/discussions/1718&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=977</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=977"/>
		<updated>2026-03-20T15:16:59Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* WebUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=976</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=976"/>
		<updated>2026-03-18T10:28:42Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* eBUSd app */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;br /&gt;
&lt;br /&gt;
=== WebUI ===&lt;br /&gt;
&amp;lt;pre&amp;gt;oot@2ad9b828-ebusd:/# ebusctl info&lt;br /&gt;
version: ebusd 26.1.26.1&lt;br /&gt;
device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
signal: no signal&lt;br /&gt;
reconnects: 0&lt;br /&gt;
masters: 1&lt;br /&gt;
messages: 17&lt;br /&gt;
conditional: 0&lt;br /&gt;
poll: 0&lt;br /&gt;
update: 10&lt;br /&gt;
address 31: master #8, ebusd&lt;br /&gt;
address 36: slave #8, ebusd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=975</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=975"/>
		<updated>2026-03-18T10:18:46Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
=== First and second start-up of the app ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MQTT ===&lt;br /&gt;
Two topics are created automatically under core-mosquitto\ebusd\global :&lt;br /&gt;
- running&lt;br /&gt;
- uptime&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=974</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=974"/>
		<updated>2026-03-18T10:15:31Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Heating system control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
== Configuration ==&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;br /&gt;
&lt;br /&gt;
== First and second start-up of the app ==&lt;br /&gt;
&amp;lt;pre&amp;gt;[11:12:55] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:12:56] INFO: Seeding default mqtt-hassio.cfg into addon config folder.&lt;br /&gt;
[11:12:56] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:12:57.257 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:12:57.263 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:12:57.505 [bus notice] signal acquired&lt;br /&gt;
2026-03-18 11:12:57.505 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:12:58.135 [mqtt notice] connection established&lt;br /&gt;
2026-03-18 11:12:59.045 [bus error] signal lost&lt;br /&gt;
s6-rc: info: service legacy-services: stopping&lt;br /&gt;
s6-rc: info: service legacy-services successfully stopped&lt;br /&gt;
s6-rc: info: service legacy-cont-init: stopping&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully stopped&lt;br /&gt;
s6-rc: info: service fix-attrs: stopping&lt;br /&gt;
s6-rc: info: service fix-attrs successfully stopped&lt;br /&gt;
s6-rc: warning: service s6rc-oneshot-runner is marked as essential, not stopping it&lt;br /&gt;
2026-03-18 11:14:01.404 [main notice] SIGTERM received&lt;br /&gt;
2026-03-18 11:14:01.531 [device error] transport closed&lt;br /&gt;
2026-03-18 11:14:01.531 [main notice] ebusd stopped&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner: starting&lt;br /&gt;
s6-rc: info: service s6rc-oneshot-runner successfully started&lt;br /&gt;
s6-rc: info: service fix-attrs: starting&lt;br /&gt;
s6-rc: info: service fix-attrs successfully started&lt;br /&gt;
s6-rc: info: service legacy-cont-init: starting&lt;br /&gt;
s6-rc: info: service legacy-cont-init successfully started&lt;br /&gt;
s6-rc: info: service legacy-services: starting&lt;br /&gt;
s6-rc: info: service legacy-services successfully started&lt;br /&gt;
[11:14:06] INFO: eBUSd addon version 26.1.6&lt;br /&gt;
[11:14:07] INFO: ebusd --foreground --updatecheck=off --mqtthost=core-mosquitto --mqttport=1883 --mqttuser=&amp;lt;redacted&amp;gt; --mqttpass=&amp;lt;redacted&amp;gt; --mqttjson --mqttint=/config/mqtt-hassio.cfg --device=enh:/dev/ttyACM0 --mqttjson &lt;br /&gt;
2026-03-18 11:14:07.723 [device notice] transport opened&lt;br /&gt;
2026-03-18 11:14:07.727 [main notice] ebusd 26.1.26.1 started with broadcast scan on device: /dev/ttyACM0, serial speed, enhanced&lt;br /&gt;
2026-03-18 11:14:07.944 [bus notice] bus started with own address 31/36&lt;br /&gt;
2026-03-18 11:14:07.944 [device notice] reset, supports info&lt;br /&gt;
2026-03-18 11:14:07.948 [mqtt notice] connection established&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=973</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=973"/>
		<updated>2026-03-18T10:10:59Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Heating system control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBUSd app ==&lt;br /&gt;
USB eBUS adapter (--device): enh:/dev/ttyACM0&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=972</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=972"/>
		<updated>2026-03-18T10:07:19Z</updated>

		<summary type="html">&lt;p&gt;Apn : +eBUS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;br /&gt;
&lt;br /&gt;
= Heating system control =&lt;br /&gt;
== eBUS Adapter Stick C6 ==&lt;br /&gt;
How is it recognized by HAOS:&lt;br /&gt;
&amp;lt;pre&amp;gt;[402858.821291] usb 1-1.3: new full-speed USB device number 3 using xhci_hcd&lt;br /&gt;
[402858.916632] usb 1-1.3: New USB device found, idVendor=303a, idProduct=1001, bcdDevice= 1.02&lt;br /&gt;
[402858.916664] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3&lt;br /&gt;
[402858.916676] usb 1-1.3: Product: USB JTAG/serial debug unit&lt;br /&gt;
[402858.916687] usb 1-1.3: Manufacturer: Espressif&lt;br /&gt;
[402858.916695] usb 1-1.3: SerialNumber: 58:E6:C5:F6:A1:8C&lt;br /&gt;
[402858.964414] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device&lt;br /&gt;
[402858.964666] usbcore: registered new interface driver cdc_acm&lt;br /&gt;
[402858.964679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=971</id>
		<title>FreeBSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=971"/>
		<updated>2026-02-09T10:33:01Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* ZFS snapshots */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Named =&lt;br /&gt;
== Manually updating a Dynamic controlled zone ==&lt;br /&gt;
&#039;&#039;&amp;quot;If you have to edit the zone files of dynamic zones manually while the DNS server is running, you&#039;ll have to freeze the zones with &#039;&#039;&#039;# rndc freeze &amp;lt;myzone&amp;gt;&#039;&#039;&#039; before editing and unfreeze them with &#039;&#039;&#039;# rndc thaw &amp;lt;myzone&amp;gt;&#039;&#039;&#039; after editing. This is because named(8) has internal state information and external journal files attached to dynamic zones that have to be kept in sync with the zone files&amp;lt;ref&amp;gt;https://forums.freebsd.org/threads/dynamic-dns-with-bind-and-isc-dhcp-server.33849/&amp;lt;/ref&amp;gt;&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Rsync = &lt;br /&gt;
&lt;br /&gt;
To delete files in the target if they disappeared from the source, then add the --delete option to your command. For example:&lt;br /&gt;
&lt;br /&gt;
rsync -avh source/ dest/ --delete&amp;lt;br&amp;gt;&lt;br /&gt;
NB: -avh is for --archive --verbose --human-readable&amp;lt;ref&amp;gt;https://askubuntu.com/a/665918&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Migration of folders to a new server ==&lt;br /&gt;
&lt;br /&gt;
=== One shot ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av /var/db/ports/ root@newice3:/var/db/ports/&lt;br /&gt;
rsync -av /etc/ root@newice3:/etc/oldice3/&lt;br /&gt;
rsync -av /usr/local/etc/ root@newice3:/usr/local/etc/oldice3/&lt;br /&gt;
rsync -av /etc/ssh/ssh_config /etc/ssh/sshd_config newice3:/etc/ssh/&lt;br /&gt;
rsync -av /etc/banner /etc/motd.template /etc/pki/ newice3:/etc/&lt;br /&gt;
rsync -av /etc/pki/ newice3:/etc/pki/&lt;br /&gt;
rsync -av /usr/local/lib/sasl2/smtpd.conf root@newice3:/usr/local/lib/sasl2/&lt;br /&gt;
rsync -av /var/ftp/ newice3:/var/ftp/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1 full + diff at the migration time === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av --exclude={&#039;rc.d&#039;,&#039;oldice3&#039;,&#039;newice3&#039;,&#039;namedb&#039;,&#039;openvpn&#039;,&#039;pkg.conf&#039;,&#039;portsnap.conf&#039;} /usr/local/etc/ root@newice3:/usr/local/etc/ --delete --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.ip.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam_awstats.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /root/ root@newice3:/root/ --delete --dry-run&lt;br /&gt;
rsync -av /home/ root@newice3:/home/ --delete --dry-run&lt;br /&gt;
rsync -av /var/www/ root@newice3:/var/www/ --delete --dry-run&lt;br /&gt;
rsync -av /usr/local/www/ root@newice3:/usr/local/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/ root@newice3:/var/log/oldice3/ --delete --dry-run&lt;br /&gt;
rsync -av /var/awstats/ root@newice3:/var/awstats/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/www/ root@newice3:/var/log/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/fail2ban/ root@newice3:/var/db/fail2ban/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/mysql/ root@newice3:/var/db/mysql/ --delete --dry-run (to do when mysql server is off)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Nginx =&lt;br /&gt;
== Maxmind ==&lt;br /&gt;
Country based filtering can be performed in nginx thanks to the free Maxmind databases.&lt;br /&gt;
&lt;br /&gt;
A cron job shall be used to update these databases on a daily basis&amp;lt;ref&amp;gt;https://herrbischoff.com/2021/05/nginx-how-to-restrict-access-by-geographical-location-on-freebsd/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ZFS snapshots = &lt;br /&gt;
FreeBSD creates a snapshot at each update (freebsd-update fetch &amp;amp;&amp;amp; freebsd-update install). These snapshots are not needed anymore should your system restarts &amp;amp; runs correctly. Moreover they take loads of space on your hardrive.&lt;br /&gt;
&lt;br /&gt;
== Procedure to delete ==&lt;br /&gt;
&lt;br /&gt;
=== List &amp;amp; check ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE                                Active Mountpoint Space Created&lt;br /&gt;
14.3-RELEASE-p6_2025-12-19_121434 -      -          927M  2025-12-19 12:14&lt;br /&gt;
default                           NR     /          814G  2023-12-01 23:34&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Check that the active Boot Envionment is the default (NR set on default).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
NAME                                       USED  AVAIL  REFER  MOUNTPOINT&lt;br /&gt;
zroot/ROOT/default@2025-12-19-12:14:34-0   927M      -   812G  -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Delete ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl destroy 14.3-RELEASE-p6_2025-12-19_121434&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Results ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE      Active Mountpoint Space Created&lt;br /&gt;
default NR     /          813G  2023-12-01 23:34&lt;br /&gt;
root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
no datasets available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reboot or no reboot after a minor system upgrade ? =&lt;br /&gt;
&lt;br /&gt;
After a system upgrade performed thanks to :&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-update fetch&lt;br /&gt;
root@icecube BSD:~ # freebsd-update install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the output of these two commands differs, then reboot your system:&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-version -k&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
root@icecube BSD:~ # uname -r&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= PF =&lt;br /&gt;
After a reboot of FreeBSD, PF may fail to start due to tables being too big (i.e. &amp;gt; 100k entries).&amp;lt;br&amp;gt;&lt;br /&gt;
This is explained here with a quick &amp;amp; dirty non-permanent fix :&amp;lt;br&amp;gt;&lt;br /&gt;
https://forums.freebsd.org/threads/table-loading-in-pf-issues.86101/#post-577832&lt;br /&gt;
# First load the PF Options only (specific to big tables handling): pfctl -Of /etc/pf.conf&lt;br /&gt;
# Then restart PF the usual way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf/etc/pf.conf:98: cannot define table firehol4: Cannot allocate memory&lt;br /&gt;
pfctl: Syntax error in config file: pf rules not loaded&lt;br /&gt;
/etc/rc.d/pf: WARNING: Unable to load /etc/pf.conf.&lt;br /&gt;
.&lt;br /&gt;
root@icecube BSD:~ # sed -n &#039;98p&#039; /etc/pf.conf&lt;br /&gt;
table &amp;lt;firehol4&amp;gt; persist file &amp;quot;/etc/pf_table_firehol4&amp;quot;&lt;br /&gt;
root@icecube BSD:~ # wc -l /etc/pf_table_firehol4&lt;br /&gt;
   99856 /etc/pf_table_firehol4&lt;br /&gt;
root@icecube BSD:~ # pfctl -Of /etc/pf.conf&lt;br /&gt;
root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf.&lt;br /&gt;
root@icecube BSD:~ # &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{references}}&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=970</id>
		<title>FreeBSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=970"/>
		<updated>2026-02-06T09:27:32Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* PF */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Named =&lt;br /&gt;
== Manually updating a Dynamic controlled zone ==&lt;br /&gt;
&#039;&#039;&amp;quot;If you have to edit the zone files of dynamic zones manually while the DNS server is running, you&#039;ll have to freeze the zones with &#039;&#039;&#039;# rndc freeze &amp;lt;myzone&amp;gt;&#039;&#039;&#039; before editing and unfreeze them with &#039;&#039;&#039;# rndc thaw &amp;lt;myzone&amp;gt;&#039;&#039;&#039; after editing. This is because named(8) has internal state information and external journal files attached to dynamic zones that have to be kept in sync with the zone files&amp;lt;ref&amp;gt;https://forums.freebsd.org/threads/dynamic-dns-with-bind-and-isc-dhcp-server.33849/&amp;lt;/ref&amp;gt;&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Rsync = &lt;br /&gt;
&lt;br /&gt;
To delete files in the target if they disappeared from the source, then add the --delete option to your command. For example:&lt;br /&gt;
&lt;br /&gt;
rsync -avh source/ dest/ --delete&amp;lt;br&amp;gt;&lt;br /&gt;
NB: -avh is for --archive --verbose --human-readable&amp;lt;ref&amp;gt;https://askubuntu.com/a/665918&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Migration of folders to a new server ==&lt;br /&gt;
&lt;br /&gt;
=== One shot ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av /var/db/ports/ root@newice3:/var/db/ports/&lt;br /&gt;
rsync -av /etc/ root@newice3:/etc/oldice3/&lt;br /&gt;
rsync -av /usr/local/etc/ root@newice3:/usr/local/etc/oldice3/&lt;br /&gt;
rsync -av /etc/ssh/ssh_config /etc/ssh/sshd_config newice3:/etc/ssh/&lt;br /&gt;
rsync -av /etc/banner /etc/motd.template /etc/pki/ newice3:/etc/&lt;br /&gt;
rsync -av /etc/pki/ newice3:/etc/pki/&lt;br /&gt;
rsync -av /usr/local/lib/sasl2/smtpd.conf root@newice3:/usr/local/lib/sasl2/&lt;br /&gt;
rsync -av /var/ftp/ newice3:/var/ftp/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1 full + diff at the migration time === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av --exclude={&#039;rc.d&#039;,&#039;oldice3&#039;,&#039;newice3&#039;,&#039;namedb&#039;,&#039;openvpn&#039;,&#039;pkg.conf&#039;,&#039;portsnap.conf&#039;} /usr/local/etc/ root@newice3:/usr/local/etc/ --delete --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.ip.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam_awstats.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /root/ root@newice3:/root/ --delete --dry-run&lt;br /&gt;
rsync -av /home/ root@newice3:/home/ --delete --dry-run&lt;br /&gt;
rsync -av /var/www/ root@newice3:/var/www/ --delete --dry-run&lt;br /&gt;
rsync -av /usr/local/www/ root@newice3:/usr/local/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/ root@newice3:/var/log/oldice3/ --delete --dry-run&lt;br /&gt;
rsync -av /var/awstats/ root@newice3:/var/awstats/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/www/ root@newice3:/var/log/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/fail2ban/ root@newice3:/var/db/fail2ban/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/mysql/ root@newice3:/var/db/mysql/ --delete --dry-run (to do when mysql server is off)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Nginx =&lt;br /&gt;
== Maxmind ==&lt;br /&gt;
Country based filtering can be performed in nginx thanks to the free Maxmind databases.&lt;br /&gt;
&lt;br /&gt;
A cron job shall be used to update these databases on a daily basis&amp;lt;ref&amp;gt;https://herrbischoff.com/2021/05/nginx-how-to-restrict-access-by-geographical-location-on-freebsd/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ZFS snapshots = &lt;br /&gt;
FreeBSD creates a snapshot at each FreeBSD update (freebsd-update fetch &amp;amp;&amp;amp; freebsd-update install). These snapshots are not needed anymore should your system restarts &amp;amp; runs correctly. Moreover they take loads of space on your hardrive.&lt;br /&gt;
&lt;br /&gt;
== Procedure to delete ==&lt;br /&gt;
&lt;br /&gt;
=== List &amp;amp; check ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE                                Active Mountpoint Space Created&lt;br /&gt;
14.3-RELEASE-p6_2025-12-19_121434 -      -          927M  2025-12-19 12:14&lt;br /&gt;
default                           NR     /          814G  2023-12-01 23:34&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Check that the active Boot Envionment is the default (NR set on default).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
NAME                                       USED  AVAIL  REFER  MOUNTPOINT&lt;br /&gt;
zroot/ROOT/default@2025-12-19-12:14:34-0   927M      -   812G  -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Delete ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl destroy 14.3-RELEASE-p6_2025-12-19_121434&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Results ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE      Active Mountpoint Space Created&lt;br /&gt;
default NR     /          813G  2023-12-01 23:34&lt;br /&gt;
root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
no datasets available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reboot or no reboot after a minor system upgrade ? =&lt;br /&gt;
&lt;br /&gt;
After a system upgrade performed thanks to :&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-update fetch&lt;br /&gt;
root@icecube BSD:~ # freebsd-update install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the output of these two commands differs, then reboot your system:&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-version -k&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
root@icecube BSD:~ # uname -r&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= PF =&lt;br /&gt;
After a reboot of FreeBSD, PF may fail to start due to tables being too big (i.e. &amp;gt; 100k entries).&amp;lt;br&amp;gt;&lt;br /&gt;
This is explained here with a quick &amp;amp; dirty non-permanent fix :&amp;lt;br&amp;gt;&lt;br /&gt;
https://forums.freebsd.org/threads/table-loading-in-pf-issues.86101/#post-577832&lt;br /&gt;
# First load the PF Options only (specific to big tables handling): pfctl -Of /etc/pf.conf&lt;br /&gt;
# Then restart PF the usual way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf/etc/pf.conf:98: cannot define table firehol4: Cannot allocate memory&lt;br /&gt;
pfctl: Syntax error in config file: pf rules not loaded&lt;br /&gt;
/etc/rc.d/pf: WARNING: Unable to load /etc/pf.conf.&lt;br /&gt;
.&lt;br /&gt;
root@icecube BSD:~ # sed -n &#039;98p&#039; /etc/pf.conf&lt;br /&gt;
table &amp;lt;firehol4&amp;gt; persist file &amp;quot;/etc/pf_table_firehol4&amp;quot;&lt;br /&gt;
root@icecube BSD:~ # wc -l /etc/pf_table_firehol4&lt;br /&gt;
   99856 /etc/pf_table_firehol4&lt;br /&gt;
root@icecube BSD:~ # pfctl -Of /etc/pf.conf&lt;br /&gt;
root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf.&lt;br /&gt;
root@icecube BSD:~ # &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{references}}&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=969</id>
		<title>FreeBSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=969"/>
		<updated>2026-02-06T09:26:12Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* PF */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Named =&lt;br /&gt;
== Manually updating a Dynamic controlled zone ==&lt;br /&gt;
&#039;&#039;&amp;quot;If you have to edit the zone files of dynamic zones manually while the DNS server is running, you&#039;ll have to freeze the zones with &#039;&#039;&#039;# rndc freeze &amp;lt;myzone&amp;gt;&#039;&#039;&#039; before editing and unfreeze them with &#039;&#039;&#039;# rndc thaw &amp;lt;myzone&amp;gt;&#039;&#039;&#039; after editing. This is because named(8) has internal state information and external journal files attached to dynamic zones that have to be kept in sync with the zone files&amp;lt;ref&amp;gt;https://forums.freebsd.org/threads/dynamic-dns-with-bind-and-isc-dhcp-server.33849/&amp;lt;/ref&amp;gt;&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Rsync = &lt;br /&gt;
&lt;br /&gt;
To delete files in the target if they disappeared from the source, then add the --delete option to your command. For example:&lt;br /&gt;
&lt;br /&gt;
rsync -avh source/ dest/ --delete&amp;lt;br&amp;gt;&lt;br /&gt;
NB: -avh is for --archive --verbose --human-readable&amp;lt;ref&amp;gt;https://askubuntu.com/a/665918&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Migration of folders to a new server ==&lt;br /&gt;
&lt;br /&gt;
=== One shot ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av /var/db/ports/ root@newice3:/var/db/ports/&lt;br /&gt;
rsync -av /etc/ root@newice3:/etc/oldice3/&lt;br /&gt;
rsync -av /usr/local/etc/ root@newice3:/usr/local/etc/oldice3/&lt;br /&gt;
rsync -av /etc/ssh/ssh_config /etc/ssh/sshd_config newice3:/etc/ssh/&lt;br /&gt;
rsync -av /etc/banner /etc/motd.template /etc/pki/ newice3:/etc/&lt;br /&gt;
rsync -av /etc/pki/ newice3:/etc/pki/&lt;br /&gt;
rsync -av /usr/local/lib/sasl2/smtpd.conf root@newice3:/usr/local/lib/sasl2/&lt;br /&gt;
rsync -av /var/ftp/ newice3:/var/ftp/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1 full + diff at the migration time === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av --exclude={&#039;rc.d&#039;,&#039;oldice3&#039;,&#039;newice3&#039;,&#039;namedb&#039;,&#039;openvpn&#039;,&#039;pkg.conf&#039;,&#039;portsnap.conf&#039;} /usr/local/etc/ root@newice3:/usr/local/etc/ --delete --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.ip.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam_awstats.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /root/ root@newice3:/root/ --delete --dry-run&lt;br /&gt;
rsync -av /home/ root@newice3:/home/ --delete --dry-run&lt;br /&gt;
rsync -av /var/www/ root@newice3:/var/www/ --delete --dry-run&lt;br /&gt;
rsync -av /usr/local/www/ root@newice3:/usr/local/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/ root@newice3:/var/log/oldice3/ --delete --dry-run&lt;br /&gt;
rsync -av /var/awstats/ root@newice3:/var/awstats/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/www/ root@newice3:/var/log/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/fail2ban/ root@newice3:/var/db/fail2ban/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/mysql/ root@newice3:/var/db/mysql/ --delete --dry-run (to do when mysql server is off)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Nginx =&lt;br /&gt;
== Maxmind ==&lt;br /&gt;
Country based filtering can be performed in nginx thanks to the free Maxmind databases.&lt;br /&gt;
&lt;br /&gt;
A cron job shall be used to update these databases on a daily basis&amp;lt;ref&amp;gt;https://herrbischoff.com/2021/05/nginx-how-to-restrict-access-by-geographical-location-on-freebsd/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ZFS snapshots = &lt;br /&gt;
FreeBSD creates a snapshot at each FreeBSD update (freebsd-update fetch &amp;amp;&amp;amp; freebsd-update install). These snapshots are not needed anymore should your system restarts &amp;amp; runs correctly. Moreover they take loads of space on your hardrive.&lt;br /&gt;
&lt;br /&gt;
== Procedure to delete ==&lt;br /&gt;
&lt;br /&gt;
=== List &amp;amp; check ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE                                Active Mountpoint Space Created&lt;br /&gt;
14.3-RELEASE-p6_2025-12-19_121434 -      -          927M  2025-12-19 12:14&lt;br /&gt;
default                           NR     /          814G  2023-12-01 23:34&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Check that the active Boot Envionment is the default (NR set on default).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
NAME                                       USED  AVAIL  REFER  MOUNTPOINT&lt;br /&gt;
zroot/ROOT/default@2025-12-19-12:14:34-0   927M      -   812G  -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Delete ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl destroy 14.3-RELEASE-p6_2025-12-19_121434&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Results ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE      Active Mountpoint Space Created&lt;br /&gt;
default NR     /          813G  2023-12-01 23:34&lt;br /&gt;
root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
no datasets available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reboot or no reboot after a minor system upgrade ? =&lt;br /&gt;
&lt;br /&gt;
After a system upgrade performed thanks to :&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-update fetch&lt;br /&gt;
root@icecube BSD:~ # freebsd-update install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the output of these two commands differs, then reboot your system:&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-version -k&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
root@icecube BSD:~ # uname -r&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= PF =&lt;br /&gt;
After a reboot of FreeBSD, PF may fail to start due to tables being too big (i.e. &amp;gt; 100k entries).&amp;lt;br&amp;gt;&lt;br /&gt;
This is explained here with a quick &amp;amp; dirty non-permanent fix :&amp;lt;br&amp;gt;&lt;br /&gt;
https://forums.freebsd.org/threads/table-loading-in-pf-issues.86101/#post-577832&lt;br /&gt;
# First load the PF Options only (specific to big tables handling): pfctl -Of /etc/pf.conf&lt;br /&gt;
# Then restart PF the usual way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf/etc/pf.conf:98: cannot define table firehol4: Cannot allocate memory&lt;br /&gt;
pfctl: Syntax error in config file: pf rules not loaded&lt;br /&gt;
/etc/rc.d/pf: WARNING: Unable to load /etc/pf.conf.&lt;br /&gt;
.&lt;br /&gt;
root@icecube BSD:~ # sed -n &#039;98p&#039; /etc/pf.conf&lt;br /&gt;
table &amp;lt;firehol4&amp;gt; persist file &amp;quot;/etc/pf_table_firehol4&amp;quot;&lt;br /&gt;
root@icecube BSD:~ # wc -l /etc/pf_table_firehol4&lt;br /&gt;
   99856 /etc/pf_table_firehol4&lt;br /&gt;
root@icecube BSD:~ # pfctl -Of /etc/pf.conf&lt;br /&gt;
root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{references}}&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=968</id>
		<title>FreeBSD</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=FreeBSD&amp;diff=968"/>
		<updated>2026-02-06T09:23:52Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* PF */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Named =&lt;br /&gt;
== Manually updating a Dynamic controlled zone ==&lt;br /&gt;
&#039;&#039;&amp;quot;If you have to edit the zone files of dynamic zones manually while the DNS server is running, you&#039;ll have to freeze the zones with &#039;&#039;&#039;# rndc freeze &amp;lt;myzone&amp;gt;&#039;&#039;&#039; before editing and unfreeze them with &#039;&#039;&#039;# rndc thaw &amp;lt;myzone&amp;gt;&#039;&#039;&#039; after editing. This is because named(8) has internal state information and external journal files attached to dynamic zones that have to be kept in sync with the zone files&amp;lt;ref&amp;gt;https://forums.freebsd.org/threads/dynamic-dns-with-bind-and-isc-dhcp-server.33849/&amp;lt;/ref&amp;gt;&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Rsync = &lt;br /&gt;
&lt;br /&gt;
To delete files in the target if they disappeared from the source, then add the --delete option to your command. For example:&lt;br /&gt;
&lt;br /&gt;
rsync -avh source/ dest/ --delete&amp;lt;br&amp;gt;&lt;br /&gt;
NB: -avh is for --archive --verbose --human-readable&amp;lt;ref&amp;gt;https://askubuntu.com/a/665918&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Migration of folders to a new server ==&lt;br /&gt;
&lt;br /&gt;
=== One shot ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av /var/db/ports/ root@newice3:/var/db/ports/&lt;br /&gt;
rsync -av /etc/ root@newice3:/etc/oldice3/&lt;br /&gt;
rsync -av /usr/local/etc/ root@newice3:/usr/local/etc/oldice3/&lt;br /&gt;
rsync -av /etc/ssh/ssh_config /etc/ssh/sshd_config newice3:/etc/ssh/&lt;br /&gt;
rsync -av /etc/banner /etc/motd.template /etc/pki/ newice3:/etc/&lt;br /&gt;
rsync -av /etc/pki/ newice3:/etc/pki/&lt;br /&gt;
rsync -av /usr/local/lib/sasl2/smtpd.conf root@newice3:/usr/local/lib/sasl2/&lt;br /&gt;
rsync -av /var/ftp/ newice3:/var/ftp/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1 full + diff at the migration time === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rsync -av --exclude={&#039;rc.d&#039;,&#039;oldice3&#039;,&#039;newice3&#039;,&#039;namedb&#039;,&#039;openvpn&#039;,&#039;pkg.conf&#039;,&#039;portsnap.conf&#039;} /usr/local/etc/ root@newice3:/usr/local/etc/ --delete --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.ip.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /etc/pf.blocked.webspam_awstats.conf root@newice3:/etc/ --dry-run&lt;br /&gt;
rsync -av /root/ root@newice3:/root/ --delete --dry-run&lt;br /&gt;
rsync -av /home/ root@newice3:/home/ --delete --dry-run&lt;br /&gt;
rsync -av /var/www/ root@newice3:/var/www/ --delete --dry-run&lt;br /&gt;
rsync -av /usr/local/www/ root@newice3:/usr/local/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/ root@newice3:/var/log/oldice3/ --delete --dry-run&lt;br /&gt;
rsync -av /var/awstats/ root@newice3:/var/awstats/ --delete --dry-run&lt;br /&gt;
rsync -av /var/log/www/ root@newice3:/var/log/www/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/fail2ban/ root@newice3:/var/db/fail2ban/ --delete --dry-run&lt;br /&gt;
rsync -av /var/db/mysql/ root@newice3:/var/db/mysql/ --delete --dry-run (to do when mysql server is off)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Nginx =&lt;br /&gt;
== Maxmind ==&lt;br /&gt;
Country based filtering can be performed in nginx thanks to the free Maxmind databases.&lt;br /&gt;
&lt;br /&gt;
A cron job shall be used to update these databases on a daily basis&amp;lt;ref&amp;gt;https://herrbischoff.com/2021/05/nginx-how-to-restrict-access-by-geographical-location-on-freebsd/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ZFS snapshots = &lt;br /&gt;
FreeBSD creates a snapshot at each FreeBSD update (freebsd-update fetch &amp;amp;&amp;amp; freebsd-update install). These snapshots are not needed anymore should your system restarts &amp;amp; runs correctly. Moreover they take loads of space on your hardrive.&lt;br /&gt;
&lt;br /&gt;
== Procedure to delete ==&lt;br /&gt;
&lt;br /&gt;
=== List &amp;amp; check ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE                                Active Mountpoint Space Created&lt;br /&gt;
14.3-RELEASE-p6_2025-12-19_121434 -      -          927M  2025-12-19 12:14&lt;br /&gt;
default                           NR     /          814G  2023-12-01 23:34&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Check that the active Boot Envionment is the default (NR set on default).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
NAME                                       USED  AVAIL  REFER  MOUNTPOINT&lt;br /&gt;
zroot/ROOT/default@2025-12-19-12:14:34-0   927M      -   812G  -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Delete ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl destroy 14.3-RELEASE-p6_2025-12-19_121434&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Results ===&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # bectl list&lt;br /&gt;
BE      Active Mountpoint Space Created&lt;br /&gt;
default NR     /          813G  2023-12-01 23:34&lt;br /&gt;
root@icecube BSD:~ # zfs list -t snapshot&lt;br /&gt;
no datasets available&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reboot or no reboot after a minor system upgrade ? =&lt;br /&gt;
&lt;br /&gt;
After a system upgrade performed thanks to :&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-update fetch&lt;br /&gt;
root@icecube BSD:~ # freebsd-update install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the output of these two commands differs, then reboot your system:&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # freebsd-version -k&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
root@icecube BSD:~ # uname -r&lt;br /&gt;
14.3-RELEASE-p7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= PF =&lt;br /&gt;
After a reboot of FreeBSD, PF may fail to start due to tables being too big (i.e. &amp;gt; 100k entries).&amp;lt;br&amp;gt;&lt;br /&gt;
This is explained here with a quick &amp;amp; dirty non-permanent fix :&amp;lt;br&amp;gt;&lt;br /&gt;
https://forums.freebsd.org/threads/table-loading-in-pf-issues.86101/#post-577832&lt;br /&gt;
# First load the PF Options only (specific to big tables handling): pfctl -Of /etc/pf.conf&lt;br /&gt;
# Then restart PF the usual way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf/etc/pf.conf:98: cannot define table firehol4: Cannot allocate memory&lt;br /&gt;
pfctl: Syntax error in config file: pf rules not loaded&lt;br /&gt;
/etc/rc.d/pf: WARNING: Unable to load /etc/pf.conf.&lt;br /&gt;
.&lt;br /&gt;
root@icecube BSD:~ # pfctl -Of /etc/pf.conf&lt;br /&gt;
root@icecube BSD:~ # service pf restart&lt;br /&gt;
Disabling pf.&lt;br /&gt;
Enabling pf.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{references}}&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=967</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=967"/>
		<updated>2026-01-30T22:48:54Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Cabling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[Fichier:Gpio.jpg|300px|]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:Gpio.jpg&amp;diff=966</id>
		<title>Fichier:Gpio.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:Gpio.jpg&amp;diff=966"/>
		<updated>2026-01-30T22:46:00Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=965</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=965"/>
		<updated>2026-01-30T22:44:57Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Garage door control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security are required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[File:gpio.jpg]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=964</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=964"/>
		<updated>2026-01-30T22:44:36Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;br /&gt;
&lt;br /&gt;
== Garage door control ==&lt;br /&gt;
I finally replaced my ZigBee relay &amp;amp; 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.&lt;br /&gt;
I&#039;m indeed usually against Wireless technology when high reliability &amp;amp; security is required.&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
* Dry contact relay: [https://www.amazon.com.be/dp/B0F59PPVZB 5 Pack 5V Channel Relay Module, 1 Channel Relay Module with Optocoupler High or Low Level Trigger Expansion Board for Raspberry Pi Arduino Board]&lt;br /&gt;
* Breakout board: [https://www.amazon.com.be/dp/B0DM4YKVCX Geekworm G469 GPIO Terminal Block Breakout Board for Raspberry Pi 4B/3B+/3B/ Zero 2W]&lt;br /&gt;
* Jumper wire cables: [https://www.amazon.com.be/dp/B074P726ZR AZDelivery Jumper Wire Cable 3 x 40 pcs. each 20 cm M2M/ F2M/F2F, 40 Pin Male to Male, 40 Pin Female to Female, Compatible with Arduino and Raspberry Pi Breadboard including an E-Book]&lt;br /&gt;
&lt;br /&gt;
=== Cabling ===&lt;br /&gt;
[[File:gpio.jpg]]&lt;br /&gt;
* Garage door magnetic sensor: GPIO_17 (pin #11) + GND (pin #9)&lt;br /&gt;
* Relay:&lt;br /&gt;
** DCC+ =&amp;gt; 5V (pin #4)&lt;br /&gt;
** DCC- =&amp;gt; GND (pin #6)&lt;br /&gt;
** Signal (relay trigger) =&amp;gt; GPIO_4 (pin #7)&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&amp;lt;pre&amp;gt;[core-ssh config]$ tail -n 12 configuration.yaml &lt;br /&gt;
switch:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    switches:&lt;br /&gt;
      - port: 4&lt;br /&gt;
        name: &amp;quot;Garage door button - GPIO_4&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_switch_port_4&amp;quot;&lt;br /&gt;
binary_sensor:&lt;br /&gt;
  - platform: rpi_gpio&lt;br /&gt;
    sensors:&lt;br /&gt;
      - port: 17&lt;br /&gt;
        name: &amp;quot;Garage door sensor - GPIO_17&amp;quot;&lt;br /&gt;
        unique_id: &amp;quot;garage_door_sensor_port_17&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/andrewshilliday/garage-door-controller#hardware-setup&lt;br /&gt;
* https://pinout.xyz/pinout/ground&lt;br /&gt;
* https://forum.hacf.fr/t/gpio-sur-rpi-4/73908&lt;br /&gt;
* https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-door-sensor-relay&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=963</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=963"/>
		<updated>2026-01-26T23:11:15Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* ZHAQuirks for TS0601 by _TZE204_nklqjk62 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=962</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=962"/>
		<updated>2026-01-26T23:08:25Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* ZHAQuirks for TS0601 by _TZE204_nklqjk62 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 by _TZE204_nklqjk62 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
=== Signature of the device ===&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How-to make it work ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
=== Result ===&lt;br /&gt;
[[Fichier:TS0601.png]]&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:TS0601.png&amp;diff=961</id>
		<title>Fichier:TS0601.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Fichier:TS0601.png&amp;diff=961"/>
		<updated>2026-01-26T23:07:04Z</updated>

		<summary type="html">&lt;p&gt;Apn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=960</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=960"/>
		<updated>2026-01-26T23:05:32Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* ZHAQuirks for TS0601 by _TZE204_nklqjk62 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 by _TZE204_nklqjk62 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not recognized by HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
Signature of the device:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Way to make it work:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
Credits:&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=959</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=959"/>
		<updated>2026-01-26T23:04:24Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* ZHAQuirks for TS0601 by _TZE204_nklqjk62 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 by _TZE204_nklqjk62 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not known from HomeAssistant ZHA.&lt;br /&gt;
&lt;br /&gt;
Here is the signature of such device:&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;node_descriptor&amp;quot;: {&lt;br /&gt;
    &amp;quot;logical_type&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;complex_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;user_descriptor_available&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;reserved&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;aps_flags&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;frequency_band&amp;quot;: 8,&lt;br /&gt;
    &amp;quot;mac_capability_flags&amp;quot;: 142,&lt;br /&gt;
    &amp;quot;manufacturer_code&amp;quot;: 4417,&lt;br /&gt;
    &amp;quot;maximum_buffer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;maximum_incoming_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;server_mask&amp;quot;: 10752,&lt;br /&gt;
    &amp;quot;maximum_outgoing_transfer_size&amp;quot;: 66,&lt;br /&gt;
    &amp;quot;descriptor_capability_field&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;endpoints&amp;quot;: {&lt;br /&gt;
    &amp;quot;1&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0100&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0000&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0004&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0005&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0006&amp;quot;,&lt;br /&gt;
        &amp;quot;0xef00&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x000a&amp;quot;,&lt;br /&gt;
        &amp;quot;0x0019&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;2&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0x0104&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0402&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0500&amp;quot;&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: []&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;242&amp;quot;: {&lt;br /&gt;
      &amp;quot;profile_id&amp;quot;: &amp;quot;0xa1e0&amp;quot;,&lt;br /&gt;
      &amp;quot;device_type&amp;quot;: &amp;quot;0x0061&amp;quot;,&lt;br /&gt;
      &amp;quot;input_clusters&amp;quot;: [],&lt;br /&gt;
      &amp;quot;output_clusters&amp;quot;: [&lt;br /&gt;
        &amp;quot;0x0021&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;manufacturer&amp;quot;: &amp;quot;_TZE204_nklqjk62&amp;quot;,&lt;br /&gt;
  &amp;quot;model&amp;quot;: &amp;quot;TS0601&amp;quot;,&lt;br /&gt;
  &amp;quot;class&amp;quot;: &amp;quot;ts0601_garage.TuyaGarageSwitchTO&amp;quot;&lt;br /&gt;
}&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the way to make it work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;br /&gt;
&lt;br /&gt;
Credits:&lt;br /&gt;
* https://github.com/zigpy/zha-device-handlers/issues/2533&lt;br /&gt;
* https://community.home-assistant.io/t/tuya-ts0601-zigbee-garage-door-opener/466400/5&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
	<entry>
		<id>https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=958</id>
		<title>Home Assistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.deprelledelanieppe.be/mediawiki/index.php?title=Home_Assistant&amp;diff=958"/>
		<updated>2026-01-26T23:02:35Z</updated>

		<summary type="html">&lt;p&gt;Apn : /* Garage Remote control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Raspberry PI &amp;amp; Home Assistant OS =&lt;br /&gt;
== Custom routes issue ==&lt;br /&gt;
When installing HA natively on a RPI if static routing is needed, then the best solution is this one:&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.reddit.com/r/homeassistant/comments/1mav1j6/run_nmcli_and_any_other_root_level_commands_step/&lt;br /&gt;
&lt;br /&gt;
Step-by-Step: Access Full Root Shell on HAOS via Port 22222&lt;br /&gt;
# Install the Add-on Add HassOS SSH port 22222 Configurator via the Home Assistant Add-on Store (manual repository add required).&lt;br /&gt;
# Generate SSH Keys On your hassOS terminal :ssh-keygen cat ~/.ssh/id_rsa.pub&lt;br /&gt;
# Paste Public Key into Configurator Add-on Open the add-on config panel and paste your public key (id_rsa.pub) into the configuration.&lt;br /&gt;
# Hard Reboot HAOS After saving config, power off or hard reboot the Home Assistant OS host to activate the root SSH access.&lt;br /&gt;
# SSH into HAOS Root (Port 22222) On your terminal:ssh -p 22222 root@127.0.0.1&lt;br /&gt;
# 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 &amp;lt;name&amp;gt;&lt;br /&gt;
# (Optional) Delete or Reset Network Configurations You can also:cd /etc/NetworkManager/system-connections/ rm &amp;lt;stale-profile&amp;gt;.nmconnection reboot&lt;br /&gt;
# Cleanup Once fixed: Uninstall the 22222 Configurator &amp;amp; Remove your public key if desired&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Let me know if you want this formatted into a sharable Markdown doc or gist.&lt;br /&gt;
Sources:&lt;br /&gt;
* https://community.home-assistant.io/t/add-on-hassos-ssh-port-22222-configurator/264109&lt;br /&gt;
* https://community.home-assistant.io/t/command-not-found-nmcli/902180&lt;br /&gt;
* https://github.com/home-assistant/operating-system/blob/0724608f/Documentation/network.md#L151-L189 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the route ===&lt;br /&gt;
Then specifically for my case:&lt;br /&gt;
&amp;lt;pre&amp;gt;apn@macbook-pro-apn ~ % ssh -p 22222 root@192.168.1.111&lt;br /&gt;
Enter passphrase for key &#039;/Users/apn/.ssh/id_ed25519&#039;: &lt;br /&gt;
Welcome to Home Assistant OS.&lt;br /&gt;
&lt;br /&gt;
Use `ha` to access the Home Assistant CLI.&lt;br /&gt;
# nmcli connection show&lt;br /&gt;
NAME             UUID                                  TYPE      DEVICE &lt;br /&gt;
Supervisor end0  b41646fb-ab0f-3c2b-955c-fe19a392b46b  ethernet  end0   &lt;br /&gt;
lo               c70e4258-1a90-4aab-b9d6-c4218edaf965  loopback  lo     &lt;br /&gt;
# nmcli connection modify &amp;quot;Supervisor end0&amp;quot; +ipv4.routes &amp;quot;192.168.2.0/24 192.168.1.101&amp;quot;&lt;br /&gt;
# nmcli connection up &amp;quot;Supervisor end0&amp;quot;&lt;br /&gt;
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)&lt;br /&gt;
# &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Garage Remote control =&lt;br /&gt;
&lt;br /&gt;
Sometimes a remote control can send multiple button/click triggers even when a button is pushed once.&lt;br /&gt;
&lt;br /&gt;
That&#039;s the case with the [https://fr.aliexpress.com/item/4001062612446.html &#039;&#039;Tuya Zigbee3.0 Remote Control With 4 Key&#039;&#039;]] that I just bought to trigger a Zigbee dry relay MHCOZY TYZG-001-RF (only used in Zigbee mode &amp;amp; cabled in NO - Normally opened). This dry relay simulates a push button to open a Garage door.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;mutex&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Here are the scripts to make this work properly:&lt;br /&gt;
&lt;br /&gt;
== MHCOZY ZG-001 ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:MHCOZY TYZG-001-RF.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Scripts&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Pulse TUZG Relay (0.5s)&lt;br /&gt;
mode: single&lt;br /&gt;
sequence:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_on&lt;br /&gt;
  - delay:&lt;br /&gt;
      milliseconds: 500&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: light.mhcozy_tyzg_001_rf&lt;br /&gt;
    action: light.turn_off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tuya Zigbee3.0 Remote Control ==&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tuya Remote Control.png]]&lt;br /&gt;
&lt;br /&gt;
Go to &#039;&#039;&#039;Settings &amp;gt; Devices &amp;amp; services &amp;gt; Helpers&#039;&#039;&#039; and create the following Boolean &#039;&#039;&#039;Toggle&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Name: garage_remote_control_lock&lt;br /&gt;
Entity ID: input_boolean.garage_remote_control_lock&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure it&#039;s set to Off (click on it when created to set its state).&lt;br /&gt;
&lt;br /&gt;
Then go to &#039;&#039;&#039;Settings &amp;gt; Automations &amp;amp; scenes &amp;gt; Automations&#039;&#039;&#039; and create the following script:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control&lt;br /&gt;
description: Trigger the garage door opening/closing via the remote control with lock to prevent duplicates&lt;br /&gt;
triggers:&lt;br /&gt;
  - event_type: zha_event&lt;br /&gt;
    event_data:&lt;br /&gt;
      device_ieee: $your_device_ieee_identifier&lt;br /&gt;
      command: arm&lt;br /&gt;
    trigger: event&lt;br /&gt;
conditions:&lt;br /&gt;
  - condition: state&lt;br /&gt;
    entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    state: &amp;quot;off&amp;quot;&lt;br /&gt;
actions:&lt;br /&gt;
  - action: input_boolean.turn_on&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
  - action: script.pulse_relay_0_5s&lt;br /&gt;
    data: {}&lt;br /&gt;
  - delay:&lt;br /&gt;
      seconds: 10&lt;br /&gt;
  - action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
    target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;pre&amp;gt;alias: Garage remote control lock reset on startup&lt;br /&gt;
triggers:&lt;br /&gt;
  - event: start&lt;br /&gt;
    trigger: homeassistant&lt;br /&gt;
actions:&lt;br /&gt;
  - target:&lt;br /&gt;
      entity_id: input_boolean.garage_remote_control_lock&lt;br /&gt;
    action: input_boolean.turn_off&lt;br /&gt;
    data: {}&lt;br /&gt;
mode: single&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ZHAQuirks for TS0601 by _TZE204_nklqjk62 ==&lt;br /&gt;
&lt;br /&gt;
The TS0601 by _TZE204_nklqjk62 is not known from HomeAssistant ZHA. Here is the way to make it work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[core-ssh zhaquirks]$ pwd&lt;br /&gt;
/config/zhaquirks&lt;br /&gt;
[core-ssh zhaquirks]$ cat ts0601_garage.py&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Tuya based cover and blinds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
from typing import Dict&lt;br /&gt;
&lt;br /&gt;
from zigpy.profiles import zgp, zha&lt;br /&gt;
from zigpy.quirks import CustomDevice&lt;br /&gt;
import zigpy.types as t&lt;br /&gt;
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time&lt;br /&gt;
from zigpy.zcl.clusters.security import IasZone&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.const import (&lt;br /&gt;
    DEVICE_TYPE,&lt;br /&gt;
    ENDPOINTS,&lt;br /&gt;
    INPUT_CLUSTERS,&lt;br /&gt;
    MODELS_INFO,&lt;br /&gt;
    OUTPUT_CLUSTERS,&lt;br /&gt;
    PROFILE_ID,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster&lt;br /&gt;
from zhaquirks.tuya.mcu import (&lt;br /&gt;
    DPToAttributeMapping,&lt;br /&gt;
    TuyaMCUCluster,&lt;br /&gt;
    TuyaOnOff,&lt;br /&gt;
)&lt;br /&gt;
from zhaquirks.tuya.ts0601_dimmer import TuyaOnOffNM&lt;br /&gt;
&lt;br /&gt;
ZONE_TYPE = 0x0001&lt;br /&gt;
&lt;br /&gt;
class ContactSwitchCluster(TuyaLocalCluster, IasZone):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya ContactSwitch Sensor.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    _CONSTANT_ATTRIBUTES = {ZONE_TYPE: IasZone.ZoneType.Contact_Switch}&lt;br /&gt;
&lt;br /&gt;
    def _update_attribute(self, attrid, value):&lt;br /&gt;
        self.debug(&amp;quot;_update_attribute &#039;%s&#039;: %s&amp;quot;, attrid, value)&lt;br /&gt;
        super()._update_attribute(attrid, value)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageManufCluster(NoManufacturerCluster, TuyaMCUCluster):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya garage door opener.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    attributes = TuyaMCUCluster.attributes.copy()&lt;br /&gt;
    attributes.update(&lt;br /&gt;
        {&lt;br /&gt;
            # ramdom attribute IDs&lt;br /&gt;
            0xEF02: (&amp;quot;dp_2&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF04: (&amp;quot;dp_4&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF05: (&amp;quot;dp_5&amp;quot;, t.uint32_t, True),&lt;br /&gt;
            0xEF0B: (&amp;quot;dp_11&amp;quot;, t.Bool, True),&lt;br /&gt;
            0xEF0C: (&amp;quot;dp_12&amp;quot;, t.enum8, True),&lt;br /&gt;
        }&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    dp_to_attribute: Dict[int, DPToAttributeMapping] = {&lt;br /&gt;
        # garage door trigger ¿on movement, on open, on closed?&lt;br /&gt;
        1: DPToAttributeMapping(&lt;br /&gt;
            TuyaOnOffNM.ep_attribute,&lt;br /&gt;
            &amp;quot;on_off&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        2: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_2&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        3: DPToAttributeMapping(&lt;br /&gt;
            ContactSwitchCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;zone_status&amp;quot;,&lt;br /&gt;
            lambda x: IasZone.ZoneStatus.Alarm_1 if x else 0,&lt;br /&gt;
            endpoint_id=2,&lt;br /&gt;
        ),&lt;br /&gt;
        4: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_4&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        5: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_5&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        11: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_11&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
        # garage door status (open, closed, ...)&lt;br /&gt;
        12: DPToAttributeMapping(&lt;br /&gt;
            TuyaMCUCluster.ep_attribute,&lt;br /&gt;
            &amp;quot;dp_12&amp;quot;,&lt;br /&gt;
        ),&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    data_point_handlers = {&lt;br /&gt;
        1: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        2: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        3: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        4: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        5: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        11: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
        12: &amp;quot;_dp_2_attr_update&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TuyaGarageSwitchTO(CustomDevice):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Tuya Garage switch.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    signature = {&lt;br /&gt;
        MODELS_INFO: [&lt;br /&gt;
            (&amp;quot;_TZE200_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE200_wfxuhoea&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
            (&amp;quot;_TZE204_nklqjk62&amp;quot;, &amp;quot;TS0601&amp;quot;),&lt;br /&gt;
        ],&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=1 profile=260 device_type=0x0051&lt;br /&gt;
            # input_clusters=[0, 4, 5, 61184]&lt;br /&gt;
            # output_clusters=[10, 25]&amp;gt;&lt;br /&gt;
            1: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster.cluster_id,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            # &amp;lt;SimpleDescriptor endpoint=242 profile=41440 device_type=97&lt;br /&gt;
            # input_clusters=[]&lt;br /&gt;
            # output_clusters=[33]&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    replacement = {&lt;br /&gt;
        ENDPOINTS: {&lt;br /&gt;
            1: {&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    Basic.cluster_id,&lt;br /&gt;
                    Groups.cluster_id,&lt;br /&gt;
                    Scenes.cluster_id,&lt;br /&gt;
                    TuyaGarageManufCluster,&lt;br /&gt;
                    TuyaOnOffNM,&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
            2: {&lt;br /&gt;
                PROFILE_ID: zha.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zha.DeviceType.IAS_ZONE,&lt;br /&gt;
                INPUT_CLUSTERS: [&lt;br /&gt;
                    ContactSwitchCluster&lt;br /&gt;
                ],&lt;br /&gt;
                OUTPUT_CLUSTERS: [],&lt;br /&gt;
            },&lt;br /&gt;
            242: {&lt;br /&gt;
                PROFILE_ID: zgp.PROFILE_ID,&lt;br /&gt;
                DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,&lt;br /&gt;
                INPUT_CLUSTERS: [],&lt;br /&gt;
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],&lt;br /&gt;
            },&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
[core-ssh zhaquirks]$ cd ..&lt;br /&gt;
[core-ssh config]$ tail -n 2 configuration.yaml &lt;br /&gt;
zha:&lt;br /&gt;
  custom_quirks_path: /config/zhaquirks&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then restart Home Assistant and discover the device. If the device was previously wrongly discovered, just delete it and discover it again.&lt;/div&gt;</summary>
		<author><name>Apn</name></author>
	</entry>
</feed>