Holman WiFi Tap timers intergration?

I have it mostly working with 3 tap timers and a moisture sensor. You’re a bloody legend, Darek!

However, I’m getting heartbeat timeout errors, typically on one device of the three. This is not a particular device getting the error consistently, but there is always one or two that get it. Each time I reboot HASS or reload localtuya, device 032 might timeout and 033 might be back online or vice versa. Device 031 (the first one I installed) seems to be the most consistent at connecting, but this could be a fluke.

2021-11-20 18:26:26 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Heartbeat failed due to timeout, disconnecting
' THE ABOVE ERROR MESSAGE IS FROM LINE 387 OF ./pytuya/__init__.py
2021-11-20 18:26:26 ERROR (MainThread) [custom_components.localtuya.common] [033...033] Connect to 192.168.1.191 failed
Traceback (most recent call last):
  File "/home/homeassistant/.homeassistant/custom_components/localtuya/common.py", line 149, in _make_connection
    status = await self._interface.status()
  File "/home/homeassistant/.homeassistant/custom_components/localtuya/pytuya/__init__.py", line 472, in status
    status = await self.exchange(STATUS)
  File "/home/homeassistant/.homeassistant/custom_components/localtuya/pytuya/__init__.py", line 451, in exchange
    msg = await self.dispatcher.wait_for(seqno)
  File "/home/homeassistant/.homeassistant/custom_components/localtuya/pytuya/__init__.py", line 240, in wait_for
    await asyncio.wait_for(self.listeners[seqno].acquire(), timeout=timeout)
  File "/usr/lib/python3.8/asyncio/tasks.py", line 501, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

I’ve tried increasing HEARTBEAT_INTERVAL as high as 120 in ./pytuya/__init__.py (line 77) but I still get the error. (in fact, 120 seems to make it less stable, where they all lose connection sporadically)

If I open the Smart Life app on my phone, they all disconnect from HA, but come back when I close it.

It looks like the _make_connection function is asynchronous. I wonder if it would work better if the holman devices were polled sequentially (synchronously)? e.g. maybe the holman hub is choking on asynchronous requests for multiple devices.

Any ideas?

Thanks,
Joe

Tuya is known to accept single API connection. I don’t know what it depends on but, say, Genio plugs were strict while DETA double socket responded to multiple requests.
As an example - when I had Genio added to localtuya I was unable to query it using tuya-cli. Guess what - timeout :slight_smile:
I think it is possible you run something, say, tuya app in your phone what takes single connection available and then everything else fails. Make sure you kill app in all phones. Kill, not just put off screen.

Yes, I have noticed that - I can’t connect using tuya-cli while HA is running. However, I can connect with tuya-cli and query the DPS info etc. after I stop HA. The only other tuya app is smart life on my phone, and I’ve tried killing that, with no effect. tuya-cli works for all devices as long as I’m not running HA.

I think the disconnect is happening at the “Errno 104”:

2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Started heartbeat loop
2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Sending command heartbeat (device type: type_0a)
2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Send payload: b'{}'
2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Waiting for sequence number -100
2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.pytuya] [033...033] Connection lost: [Errno 104] Connection reset by peer
2021-11-25 22:40:00 DEBUG (MainThread) [custom_components.localtuya.common] [033...033] Disconnected - waiting for discovery broadcast

After that, I get the timeout messages per my previous post.

033 is the most common culprit, but sometimes 033 is the only tuya device discovered and all others (including lights, sockets) are unavailable! In this case, I can see valid dps payloads returned from 031 and 032, however some of the payloads from these devices show "cid":"033" which seems weird:

2021-11-25 22:40:01 DEBUG (MainThread) [custom_components.localtuya.pytuya] [031...031] Decrypted payload: {}

2021-11-25 22:40:01 DEBUG (MainThread) [custom_components.localtuya.pytuya] [032...032] Decrypted payload: {}

2021-11-25 22:40:01 DEBUG (MainThread) [custom_components.localtuya.pytuya] [031...031] Decrypted payload: {"dps":{"101":21,"102":47,"103":121,"105":"2","106":"0","107":5,"108":true,"113":"0","115":true,"116":false,"117":true,"120":0,"125":false,"127":"HOL9-018-023-005-000"},"cid":"031"}

2021-11-25 22:40:01 DEBUG (MainThread) [custom_components.localtuya.pytuya] [032...032] Decrypted payload: {"dps":{"101":21,"102":47,"103":117,"105":"2","106":"0","107":5,"108":true,"113":"0","115":true,"116":false,"117":true,"120":0,"125":false,"127":"HOL9-018-023-005-000"},"cid":"032"}
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [03B...03B] Dispatching message TuyaMessage(seqno=0, cmd=8, retcode=0, payload=b'3.3\x00\x00\x00\x00\x00\x00=\x0b\x00\x00\x00\x01\xda\xfcM\xff\x9d\xbe\x82E\x1avh\x89\x7fv:\xfbfu~mV\xc0\x92\xb3\x00\xcb\x04\xffw>\xcf\xe5z\n\xa9\xe7\x0b"\x9cW&\x85JL\x99\xf6dmJ $\xe1\x17\x06Z[\xdc\x046\xf8\x9a\x87\xbd\x83', crc=4259542800)
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [03B...03B] Got status update
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [03B...03B] Decrypted payload: {"dps":{"128":"AAAAAAA="},"cid":"033","t":1637842203}
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [031...031] Dispatching message TuyaMessage(seqno=0, cmd=8, retcode=0, payload=b'3.3\x00\x00\x00\x00\x00\x00=\x0b\x00\x00\x00\x01\xda\xfcM\xff\x9d\xbe\x82E\x1avh\x89\x7fv:\xfbfu~mV\xc0\x92\xb3\x00\xcb\x04\xffw>\xcf\xe5z\n\xa9\xe7\x0b"\x9cW&\x85JL\x99\xf6dmJ $\xe1\x17\x06Z[\xdc\x046\xf8\x9a\x87\xbd\x83', crc=4259542800)
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [031...031] Got status update
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [031...031] Decrypted payload: {"dps":{"128":"AAAAAAA="},"cid":"033","t":1637842203}
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [032...032] Dispatching message TuyaMessage(seqno=0, cmd=8, retcode=0, payload=b'3.3\x00\x00\x00\x00\x00\x00=\x0b\x00\x00\x00\x01\xda\xfcM\xff\x9d\xbe\x82E\x1avh\x89\x7fv:\xfbfu~mV\xc0\x92\xb3\x00\xcb\x04\xffw>\xcf\xe5z\n\xa9\xe7\x0b"\x9cW&\x85JL\x99\xf6dmJ $\xe1\x17\x06Z[\xdc\x046\xf8\x9a\x87\xbd\x83', crc=4259542800)
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [032...032] Got status update
2021-11-25 22:40:04 DEBUG (MainThread) [custom_components.localtuya.pytuya] [032...032] Decrypted payload: {"dps":{"128":"AAAAAAA="},"cid":"033","t":1637842203}

I’ve found some other cases where the payload cid’s dont match the reporting device, although these don’t always cause errors.

I have the HA startup log files from each of these scenarios which I could send if you think they would help.

I should also mention, when I turn on one of the tap timers, sometimes the entities on the other timers report whatever the running timer is showing - e.g. if 031 is running, 031 and 032 will both show as running, with all of the same values for timer, flow, etc. I think this resolves itself after the tap timer stops running.

I haven’t dug into this issue yet, but I wonder if it’s related to incorrect CID’s being reported per my previous post.

[EDIT 2021-11-29]
I think I have resolved this particular issue by checking the CID in the payload against the device CID before updating the listener status. Here’s my edited TuyaProtocol._setup_dispatcher() (with gratuitous debug dumps):

    def _setup_dispatcher(self):
        def _status_update(msg):
            decoded_message = self._decode_payload(msg.payload)
            if "cid" in decoded_message:
                self.debug("%s _status_update cid %s", self.id, decoded_message["cid"])
                self.debug(decoded_message["cid"]!=self.id)
                if (decoded_message["cid"]!=self.id):
                    self.debug("_status_update cid mismatch %s", decoded_message["cid"])
                    return

            self.debug("_status_update cid match %s", decoded_message["cid"])

            if "dps" in decoded_message:
                self.dps_cache.update(decoded_message["dps"])

            listener = self.listener and self.listener()
            if listener is not None:
                listener.status_updated(self.dps_cache)

        return MessageDispatcher(self.id, _status_update)

Some timers (including the one running) will intermittently become unavailable while one timer is running. However, they seem to reconnect OK.

I suspect that heartbeats, like status messages, are also being broadcast to all devices, not just the one they were requested from. Since the heartbeat payload has no data (i.e. no CID), my filter hack above won’t work for that.

This still didn’t resolve my connection issue. I tried factory resets of all devices and re-configured it, but the same device always failed to connect.

However, I found that by swapping the order of devices in configuration.yaml (and deleting each device integration to force HA to rediscover them), the order of devices determines which ones connect and which don’t! The first one in the list connects consistently, the second one usually connects but can intermittently become unavailable, and the third one almost always fails to connect.

Since I suspected some sort of “traffic jam” was happening at the holman hub, I tried deleting the hub socket device integration, to remove one source of noise. And suddenly, all 3 tap timers were online!

I then tried putting the hub socket after the timers in the config file, but it connected before the timers anyways, and I was back to the original problem. I don’t need this socket to be automated, so I’m just going to leave it deleted.

I don’t know if a 4th timer would cause the same issue, or if it’s something that the socket is specifically doing that’s causing problems.

I still get disconnections when a timer is running, however these usually reconnect OK.

I still think this might be resolved by polling each device on the holman hub sequentially rather than asynchronously, since otherwise it seems to broadcast some messages to all listening CID’s. But now that I understand the localtuya code better, I can see that this isn’t easy to do! This would probably require a dedicated Holman integration as a fork of localtuya.

I think the issue is in the MessageDispatcher.wait_for function - it’s listening for the sequence number, but needs to filter for CID as well before returning the message to TuyaProtocol.exchange. I’ll play around with it and see if I can get it working.

I noticed today that Tuya Scenes are appearing in Home Assistant (I’m connected via Tuya Cloud).
These are created under ‘tap to run’ under ‘smart’ and appear to trigger correctly via HA.

To avoid the risk of the ‘start’ firing correctly and the ‘stop’ not firing - and the fact I generally only need to water for 3 minutes at a time - I’ve created a tuya scene with a manual watering on, 3 minute delay, manual watering off which I’ll trigger from HA moving forward, using weather-based rules etc.

1 Like

@darecki I had issues getting it working due to the following error:

2021-12-11 19:42:42 ERROR (SyncWorker_2) [homeassistant.loader] The custom integration 'localtuya' does not have a valid version key (3.2.1.1-beta) in the manifest file and was blocked from loading. See https://developers.home-assistant.io/blog/2021/01/29/custom-integration-changes#versions for more details

I worked around it by editing the manifest.json and removing the -beta suffix.

After fixing that, I had success controlling my two Holman WX1s with your integration! Thank you for this.

struggled a lot with getting the local key due to needing to re-pairing to Tuya Smart, but once that was sorted it works great.

My CIDs are: 0C1, 0C2 for my taps, and 0CB for the socket.

Has anyone figured out how to trigger the manual timed watering? I’m a little bit worried about starting an irrigation cycle but then unable to stop the watering due to WiFi/HASS issues.

For manual watering you need to flick tap switch (from on to off) and that will start counting down timer. It is clever - there is no on-off for tap, just start timer so it will stop when desired even if hub is offline at that time.

I have made automation which looks at moisture and rain forecast for next 24h and if decides to water, it sets timer value and flick the switch.

1 Like

I thought there is a chance to have it better if gateway id and cid will be used together instead of simply cid instead of gateway. That, however, requires introducing cid everywhere starting as config option. Lots of changes.

I think I’ve found a bug where both of my tap entities are reporting the states of the other.

For example, when my Garden tap is turned on, the Lawn tap status and switch also reflects the Garden tap status, but the Lawn tap itself isn’t on. Other entities are affected include the liters spent. This doesn’t appear to happen all the time though, there is a spot on the graph just before 12pm where the states are different.

image

I’m not sure if my manual watering countdown timer works as expected either but I can’t tell if the state mixup is related.

Can you try to run query from tuya-cli at the same time? That will reveal if this is HA side or hub responds with wrong data.

There is a fix in local tuya for some race condition, I merged it yesterday.

Hey Mate

I’ve got Local Tuya working, how did you find the IP address for the hub / tap timer?

I can’t get mine to work … Not as tech savvy as you lot :slight_smile:

  1. Do I add this through the Local Tuya integration, or can it only be done through YAML?
  2. Do I need to add the u hub first, or only the tap’s themselves?
  3. I only really care about on / off.
  4. I can see all the info in the Tuya IOT when searching by DeviceID but I don’t get an IP for the tap timers, I get one for the hub but it’s different to the rest of my network and I get an error when I try to add.

I feel that I am very closeo so any help would be excellent.

This is my output from the gateway ID

{
“result”: {
“active_time”: 1637923685,
“category”: “wg2”,
“category_name”: “Gateway”,
“create_time”: 1637923685,
“gateway_id”: “”,
“icon”: “smart/icon/ay1556838860681oKmdO/e47c08d07b3801b3ea8890b3f548bc7f.png”,
“id”: “I am an ID”,
“ip”: “”,
“lat”: “-”,
“local_key”: I am a key",
“lon”: “”,
“model”: “EMateGateWay”,
“name”: “Wi-Fi Hub stable”,
“online”: true,
“owner_id”: “42797758”,
“product_id”: “lzjw7vgzngzrzy74”,
“product_name”: “Wi-Fi Hub”,
“sub”: false,
“time_zone”: “+10:30”,
“update_time”: 1639959418,
“uuid”: “a09d1b253abc5b07”
},
“success”: true,
“t”: 1640576587750

This is from my Tap

{
“result”: {
“active_time”: 1637923838,
“category”: “kg”,
“category_name”: “Switch”,
“create_time”: 1637923838,
“gateway_id”: “bf9e36c6ebc2cfa4b5cvud”,
“icon”: “smart/icon/ay1556838860681oKmdO/ab17f6e4e677bba7d3868a7a57cfe5b7.png”,
“id”: “iamatapid”,
“ip”: “”,
“lat”: “-”,
“local_key”: “Iamatapkey”,
“lon”: “”,
“model”: “EMateWTT”,
“name”: "Roof Sprinklers ",
“node_id”: “051”,
“online”: true,
“owner_id”: “42797758”,
“product_id”: “zrsgzc8jktsricjj”,
“product_name”: “WX1 Tap Timer”,
“sub”: true,
“time_zone”: “+10:30”,
“update_time”: 1640024161,
“uuid”: “bfa76055c6d6058fedx3ds”
},
“success”: true,
“t”: 1640577670707

You can use either the config flow or do it using your configuration yaml… I ended up using the config flow, but I think using yaml would probably be more flexible to work with later on.

The tap will list as a unique entity, it is not subordinate to the gateway (if that makes sense?)… So you don’t need to add the gateway first.

There is two things I’d highlight here to think about here: (1) the negated switch and (2) the countdown.

  1. Negated switch. The valve presents as a negated switch so it will appear as ‘on’ while the tap is ‘off’. Because this annoyed me, I created a separate switch that keeps itself in the opposite state to the valve switch and updates the valve switch if it is clicked by a user on a lovelace view.
  2. Countdown. Remember that when you turn the tap on, it starts to countdown and switches itself off when the countdown reaches 0. It appears the maximum might be 59 min (but I could be wrong here). So depending on your use case it may end up being simpler to use the countdown to turn off the tap. To do this you could have an automation that sets the countdown, then turns the tap on.

Use the IP address for your gateway device. It’s probably easiest to get this IP from your home router… if you’re looking at the Tuya IoT Platform it’s probably listing your public IP address. I used tuacli to get the details (in particular the CID) for the tap, I cannot see the CID listed in what you’ve posted from the Tuya IoT Platform (I assume that’s where you’ve got that from?)… so you may need to get tuyacli to get that final bit of detail.

HTH, goodluck.

Thanks for the full and complete answer :slight_smile: I’ll give it a go now.

I am thinking UID and CCID are the same?
Trying the TuyaCLI thing, but another uphill curve.
If I install ubuntu to a VM, hopefully that will work.

The CID should be a 3 letter/number identifier for the device. They only exist for items that are ‘sub devices’ of something else (this is probably somewhat backwards to what I explained earlier), so for me the WX1 Tap Timer has a CID of 061 and the socket has a CID of 06B.

Looking at what you posted earlier perhaps you could try the node_id… it’s the only identifier that fits from what’s listed, but I’m taking a guess here.

Hello Nathan,

I’ve successfully run TuyaCLI

I get

[ { name: ‘Wi-Fi Hub 2’,
id: ‘IAMANID1’,
key: ‘IAMAKEY’,
subDevices:
[ { name: ‘small tank’, id: ‘IAMANID2’, cid: ‘051’ },
{ name: ‘Wi-Fi Socket 2’,
id: ‘IAMANID3’,
cid: ‘05B’ } ] },

I have the IP address which is detected from using auto detect in Local Tuya, but no combination of these keys / names / ID lets me add anything.

I will reboot everything (router, HA etc) and try again later.

Should I put my names in inverted coma’s or will it cope with the spaces? So far I have not used ‘name name’

So if I recall you use the key of the parent entity, the CID of the entity you’re attempting to add. Also, make sure you’ve closed the Tuya app/any other device connections like the Tuyacli as it can only handle one connection at a time.

I had trouble trying to get it setup early on too and I never figured out why… I honestly just kept trying and it eventually worked, ever since then it’s been reliable, but I never figured out what the setup issue was.