Repository navigation
fix(services): reject half-hour time zones in sync_time with a translated error - #764
Merged
GreenGrassBlueOcean merged 2 commits intoOct 21, 2026
Conversation
…ated error OWNd 2.0.0b11 raises ValueError from set_datetime_to_now() and set_time_to_now() when the UTC offset is not a whole number of hours, because the WHO 13 time-zone field only carries a sign and an hour offset. myhome.sync_time called the builders unguarded, so Home Assistant instances in Asia/Kolkata, Australia/Adelaide or America/St_Johns got a raw traceback. Build both frames up front in _build_time_sync_commands() so a failure never sends only half of the datetime/time pair, and raise a ServiceValidationError with the sync_time_unsupported_offset translation key instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…est the whole-hour path The ServiceValidationError fallback message now equals the sync_time_unsupported_offset translation, and test_services checks that Europe/Brussels still sends both WHO 13 frames with a sign + whole-hour T field after the half-hour rejection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 task done
Merged
1 task done
GreenGrassBlueOcean
added a commit
that referenced
this pull request
Oct 21, 2026
- Count and summarize every pull request merged since 2.0.0b15, grouped by subsystem, with the expose engine (#750), slat tilt (#508) and impulse covers (#667) as the headline features. - Covers: the start-up floor is the per-cover min_motor_pulse (#708), timed runs end at the stop status (#707) and full-travel keypad runs report the end (#760); drop the "lift only" and open follow-up lines, both shipped. - New behaviour-change section: sync_time refuses half-hour time zones (#764) and advanced: true on an F411 now warns (#762). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 21, 2026
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.
Follow-up to OWNd 2.0.0b11 (OpenWebNet-HA/OWNd#129), which
manifest.jsononv2-phase1-architecturealready pins.1. What is the problem?
myhome.sync_timeraises an uncaughtValueErrorin half-hour time zones (custom_components/myhome/services.py):The WHO 13 time-zone field
Tis three digits: a sign digit plus a two-digit hour offset (001= GMT+1,102= GMT-2). It cannot carry+05:30,+10:30or-02:30.Up to OWNd 2.0.0b10,
OWNGatewayCommand.set_datetime_to_now()/set_time_to_now()truncated such offsets, so the gateway clock was set with the wrong offset and nothing was reported. Since 2.0.0b11 (feat(message,profiles): add declarative expose frame builders, query helpers, and profile flags OWNd#129) the builders raiseValueError: UTC offset +05:30 is not a whole number of hoursinstead.handle_sync_time()called the builders without handling that error. A Home Assistant instance configured forAsia/Kolkata,Australia/Adelaide,America/St_Johns, and so on got a raw traceback from the service call instead of a readable error.Reproduced against the PyPI wheel:
OWNGatewayCommand.set_datetime_to_now(tz)on 2.0.0b11Europe/Brussels*#13**#22*09*57*37*002*03*21*10*2026##Asia/KolkataValueError: UTC offset +05:30 is not a whole number of hoursAustralia/AdelaideValueError: UTC offset +10:30 is not a whole number of hoursAmerica/St_JohnsValueError: UTC offset -02:30 is not a whole number of hours2. How is it solved?
_build_time_sync_commands(timezone)(custom_components/myhome/services.py):DIMENSION 22datetime frame and theDIMENSION 0time frame together, before anything is sent, so a failure can never leave the gateway with only one of the two frames.ValueErrorinto aServiceValidationErrorwithtranslation_key="sync_time_unsupported_offset"and thetimezoneanderrorplaceholders.gateway: <mac>) and the all-gateways call (one sync per bus, skipping followers).strings.json,translations/en.json):sync_time_unsupported_offset: Cannot synchronise the gateway clock for time zone "{timezone}": {error}. OpenWebNet only carries whole-hour UTC offsets.tests/test_init.py::test_services):hass.configtoAsia/Kolkataand checks that both the per-gateway and all-gateways calls raiseServiceValidationErrorwith the right translation key andtimezoneplaceholder, and thatgateway.sendis never called.Europe/Brusselsand checks that the call still sends exactly two frames, each with a sign + whole-hourTfield (001/002).The expose engine in #750 calls the same WHO 13 builders and already catches the
ValueErrorthere; this PR does not touch that branch.3. State Diagram
flowchart TD Call["myhome.sync_time\n(gateway: mac | all)"] --> TZ["timezone = hass.config time_zone"] TZ --> Build["_build_time_sync_commands(timezone)\nset_datetime_to_now + set_time_to_now"] Build -->|whole-hour offset| Send["send *#13**#22*H*M*S*T*W*D*M*Y##\nthen *#13**#0*H*M*S*T##"] Build -->|"ValueError (+05:30, +10:30, -02:30 …)"| Err["ServiceValidationError\nsync_time_unsupported_offset\n(nothing sent)"]4. Where are the traces (real ones)?
Tfieldtests/fixtures/traces/issue_624/myhome_trace_MH200N_all_2026-10-05T20-50-47.json*#13**22*22*50*32*001*01*05*10*2026##:T = 001, GMT+1 as a sign plus whole hours.2.0.11)tests/fixtures/traces/f461_live_2026-10-18/myhome_trace_F461_live_2026-10-18.json*#13**0*22*51*00*999##and*#13**22*22*51*02*999*00*18*10*2026##:T = 999(offset not set). There are no minute digits in any capturedTfield.No capture from a gateway configured for a half-hour zone exists. The failure is on the HA side, before any frame is built.
5. What does the Firmware Oracle / Encyclopedia say?
functional/who-13-integration-gateway/dimensions.md,capabilities.md):DIMENSION 0payloadH*M*S*T: "T| Time zone | three digits, sign + hour offset". The first digit is0for positive and1for negative, and the other two are the hour offset (001= GMT+1,102= GMT-2).DIMENSION 22payloadH*M*S*T*W*D*M*Ycarries the sameTfield.capabilities.mddescribes the time-zone encoding as an hour-offset representation, not a named time-zone identifier.openwebnet-mcp—parse_and_validate_frame,lookup_firmware_verdict):*#13**#22*09*57*37*002*03*21*10*2026##is grammar-valid (DIMENSION_WRITING, WHO 13, DIMENSION 22). Neither it nor*#13**0##has been replayed against the 12 emulated gateways yet, so there are no firmware verdicts for WHO 13 writes either way.Verification
Full suite against the released
OWNd==2.0.0b11wheel (PYTHONPATH= scratch install, not the editable../OWNd) with--cov=custom_components/myhome:4358 passed, 5 snapshots passed,TOTAL 14468 statements, 0 missed, 100.0%tests/test_init.py::test_servicescovers both directions:Asia/Kolkataraisessync_time_unsupported_offsetand sends nothing, andEurope/Brusselsstill sends both frames withT = 001|002.scripts/typing_ratchet.py:0 error(s); baseline 0as CI runs it (without OWNd installed). With the b11 wheel visible to mypy it reports 14 errors in 7 modules. None are in lines this PR changes; they are the MyHOME/OWNd boundary errors that fix(config_flow): inject the HA websession into OWNd discovery and correct the OWNd licence #757 resolves.ruff check custom_components tests scripts(All checks passed!)scripts/verify_ha_standards.py&scripts/sync_documentation.py --check(both pass)V2 Architecture: New entities implement
handle_event()and do not manually subscribe viaasync_dispatcher_connect. (No entities are added or changed.)🤖 Generated with Claude Code