Repository navigation
Pure-Python local control, replacing the bundled Go binaries (3.0.0) - #23
Merged
Merged
Conversation
Commands were previously sent by shelling out to a bundled Go CLI, shipped as five compiled binaries (34.4 MB) whose source lived in a separate private repo. Those are removed. crypto.py produces the same XXTEA auth token in pure Python using only the standard library. Output is byte-identical to the retired tinxy-cli, verified across 319 cases covering key lengths either side of the 16-byte boundary and timestamps either side of the 4-byte block boundary. The wire format was captured from the real binary and matched exactly: POST /toggle with password, action, relayNumber and optional brightness, brightness omitted when action is 0. Added: - mDNS discovery (async_step_zeroconf), including DHCP address tracking - RSSI, SSID and IP diagnostic sensors; RSSI disabled by default because it changes on nearly every poll and fills the recorder database - optimistic entity state, so a toggle shows immediately instead of after the queue delay plus a poll - command spacing as a configurable option Fixed: - unreachable devices now go unavailable instead of serving their last known state forever; the coordinator raises UpdateFailed rather than swallowing - the coordinator built a second set of hubs without the configured timeout, so request_timeout never applied to polling. Hubs are now built once and shared. DEFAULT_REQUEST_TIMEOUT is 5 to match the value polling has actually been running at, since 3 was only ever applied to commands - failed commands raise HomeAssistantError instead of logging silently - a race in the command queue: dedup replaced the deque while the worker held a reference across its rate-limit sleep, so operating a second switch on the same device mid-sleep popped from an orphaned queue and dropped the command - superseded commands no longer surface as user-facing errors - device registry rejected firmware as an int; coerced to str at the source, which HA 2026.12 will require - _register_devices ran on every poll instead of once - the API token was logged at info level during device lookup Command spacing is 1 second and cannot be set lower. The auth token encrypts a whole-second timestamp and the device rejects any timestamp it has already seen, so two commands in the same second cannot both be authenticated. This is per device, not per relay. Dating the timestamp forward appears to work but sets the device's high-water mark, locking out honestly-dated commands until real time catches up: sending now+30 made a device reject normal commands for 30 seconds. Reads are unauthenticated and unaffected, so polling stays fast. Entries created before 3.0.0 adopt their chip id as unique_id so discovery recognises them instead of offering duplicates. Entity unique_ids are unchanged, so existing entities, history and automations survive the upgrade. Verified on Home Assistant 2026.9.2 against WIFI_2SWITCH_V1 firmware 82: discovery, entity creation, relay control and diagnostics, with no errors.
manifest.json was missing `requirements` entirely, which hassfest treats as a required key. It is empty on purpose: nothing outside the standard library and Home Assistant's own dependencies is needed. Also dropped the empty homekit and ssdp discovery blocks, which matched nothing, and corrected hacs.json, which still advertised switch alone while the integration now provides fan, lock and sensor as well.
Three schema violations, none of which surfaced until CI ran the real validators for the first time. manifest.json carried a `description` key, which is not part of the manifest schema. strings.json carried a `config.options` block holding two token-choice labels, which is not part of the translation schema either; those strings were never rendered, since the choose_token step supplies its own labels through vol.In. Both predate this branch. hacs.json declared `domains`, which HACS no longer accepts at all. This branch had widened it from switch alone to the four platforms the integration now provides, which is what drew the validator's attention to a key that should not have been there in the first place.
`homeassistant` is not part of the manifest schema, so hassfest rejects it. The minimum version belongs in hacs.json, which already declared 2025.4.0, and that is the copy HACS actually enforces. Nothing reads the manifest key, so this changes no behaviour. Pre-existing.
domain and name first, then alphabetical. iot_class sorted after issue_tracker and version after zeroconf.
Matches the pre-release tag, so HACS and the version Home Assistant reports agree. Bumped to 3.0.0 when the beta is done.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Commands used to be sent by shelling out to a bundled Go CLI, shipped as five
compiled binaries totalling 34.4 MB whose source lived in a separate private
repo. HACS users were installing and executing code they had no way to audit.
That is now about 70 lines of pure Python using nothing outside the standard
library, with output verified identical to the binary it replaces.
Added
changes on nearly every poll and would fill the recorder database
queue delay plus a poll
Fixed
state indefinitely
request_timeoutnever applied to polling at all. Hubs are built once andshared, and the default is now 5s to match what polling has actually been using
held a reference across its spacing sleep, so operating a second switch on the
same device moments later dropped the command
Home Assistant 2026.12
_register_devicesran on every poll rather than onceCommand spacing
A device accepts at most one command per second, and that limit is per device
rather than per relay, so commands are queued and spaced. Reads are unrestricted
and are not queued.
Upgrading
In place. Entity unique IDs are unchanged, so existing entities, history and
automations survive. Entries created before 3.0.0 adopt their chip id as
unique_id, without which discovery would offer them again and duplicate them.Two changes are visible: unreachable devices now show as unavailable rather than
stale, and failed commands report an error. Both surface problems that were
previously hidden.
Verification
73 tests against Home Assistant 2026.9.2, with full coverage of the config flow.
Verified end to end on a WIFI_2SWITCH_V1 running firmware 82, and on a live
upgrade from 2.6.0 with three existing devices.