Skip to content

feat(alarm): complete WHO 5 burglar alarm implementation and gateway profiles - #66

Merged
GreenGrassBlueOcean merged 4 commits into
OpenWebNet-HA:masterfrom
GreenGrassBlueOcean:feat/h4890-profile-who5
Oct 2, 2026
Merged

GreenGrassBlueOcean merged 4 commits into
OpenWebNet-HA:masterfrom
GreenGrassBlueOcean:feat/h4890-profile-who5

Conversation

@GreenGrassBlueOcean

@GreenGrassBlueOcean GreenGrassBlueOcean commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  1. Topology refusal: the H4890 relays the alarm bus (WHO 5 frames in MyHOME#466, #484 and #564), but "4890" and the family names resolved to generic profiles whose supported_who lacks WHO 5. MyHOME's shared-bus onboarding trusts supported_who and rejects the alarm with who_not_supported_by_gateway (MyHOME#564). The MH202 has the same gap.
  2. Dropped system broadcasts: real panels answer the status poll with an empty WHERE (*5*1*##), next to the documented star form (*5*1**##). The empty form was dropped as None.
  3. Zone state pollution: WHAT 11 ("active zone", *5*11*#n##) was treated as armed_home, so a status dump on a disarmed system flipped the panel to ARMED_HOME.
  4. WHAT 1 read as armed: is_armed_away was true for WHAT 1. The F454 trace (MyHOME#311) sends WHAT 1 on every disarm (*5*2*0## → *5*1*0## → *5*9*0##) and in disarmed status dumps; arming is *5*1*0## → *5*8*0##. A disarm went DISARMED → ARMED_AWAY → DISARMED.

Arming and disarming are not possible over WHO 5

Important

The plant owner in MyHOME#564 (comment) reports, quoting BTicino support, that current central-unit firmware rejects arm/disarm sent as *5*... frames over SCS, whichever gateway sends them. No TX capture shows any WHO 5 command being accepted.

Their working route is a WHO 9 auxiliary command, e.g. *9*1*7## (AUX channel 7 ON), plus an automation programmed on the central unit that arms the chosen zones when that AUX command arrives. Which AUX channels and WHATs arm or disarm depends on the installer's programming, so OWNd has no fixed frame for it.

So in this PR WHO 5 support means reading the alarm:

  • OWNAlarmCommand.status() is the only builder to rely on.
  • arm_away(), arm_home(), disarm(), trigger(), engage() and disengage() are documented as unverified and kept for API compatibility. arm_away() and arm_home() build the same frame, *5*1*<where>##, which is "activation", not arming.
  • The H4890 and MH202 profiles list WHO 5 so onboarding accepts the alarm. Their docstrings say this means reading the alarm.
  • Consumers (MyHOME) should expose the alarm as read-only and arm/disarm with installer-configured AUX frames.

How a WHO 5 frame is handled

 raw frame  *5*<WHAT>*<WHERE>##
      |
      v
 WHERE spelling?
   |            |                |                 |
   | "*"        | "" (empty)     | "0"             | "#n" or "zs"
   v            v                v                 v
 where="0"    where=""         where="0"         zone / sensor
 (system)     (kept empty)     (system)          (not the system)
              status-poll reply: a real panel
              (F454, #311) and a gateway with
              no panel (MH200N, #466) both
              send *5*<what>*##
   |            |                |                 |
   +------------+-------+--------+                 |
                        |                          |
                        v                          v
          system address ("0" / "")?  --no--> zone flags only:
                        |                      is_zone_active   (WHAT 11)
                        | yes                  is_zone_inactive (WHAT 18)
                        v
 +----------------------------------------------------------+
 | system flags (never moved by zone/sensor frames):        |
 |  is_active        WHAT 1, 11  (activation, not armed)    |
 |  is_armed_away    WHAT 8      is_engaged     WHAT 8      |
 |  is_disarmed      WHAT 0, 2, 9                           |
 |  is_armed_home    always False (no capture)              |
 +----------------------------------------------------------+

Empty WHERE is still the system address: the F454 panel in MyHOME#311 answers the poll with *5*1*##, *5*5*##, *5*7*##, *5*9*##, so treating "" as non-system would lose a real panel's state. It stays "" rather than "0" because the MH200N in MyHOME#466 (no panel installed) sends the same spelling; mapping it to 0 made MyHOME create a phantom alarm_control_panel.alarm_0. Consumers must not turn the empty spelling into a device on its own.

Changes

  • Parser: a WHO 5-only pattern (*5*<what>*##) accepts the empty-WHERE form. _STATUS is unchanged, so *1*1*## is still invalid. *5*<what>**## now reports where "0" (same identity as *5*<what>*0##).
  • OWNAlarmEvent:
    • is_armed_away, is_disarmed, is_active and is_engaged are system-scoped. is_armed_away is WHAT 8 only. is_armed_home is always False: no capture shows a system-level WHAT 11.
    • New read-only flags: is_zone_active, is_zone_inactive (WHAT 18 is partition state, not bypass), battery/mains (is_battery_fault, is_battery_ok, is_mains_fault, is_mains_ok, is_power_telemetry) and is_intrusion, is_tamper, is_panic, is_technical, is_silent. The power flags are not system-scoped.
  • OWNAlarmCommand: class docstring documents the SCS rejection and the AUX route. New engage() / disengage() (*5*8*<where>## / *5*9*<where>##) are experimental and unverified like the existing builders.
  • Profiles:
    • H4890Profile, aliases limited to the measured 3.5" family: am4890, ln4890, ln4890a, 4890. Other touch screens (mh4892, 3488, myhometouch, ...) stay generic.
    • H4890 supported_who is DEFAULT_SUPPORTED_WHO + WHO 5: the captures don't show the screen dropping heating, CEN or scenarios. Sessions and pacing are class defaults; auth is shown as Auth unmeasured.
    • MH202Profile carries WHO 5 (MyHOME#564 capture).
    • The H4890 and MH202 captures are status dumps of a disarmed panel plus zone states; neither contains an arm transition or an alarm event.
    • F454/F455/F461 do not advertise WHO 5. F455: its installer manual (RA00125AB) lists "Antintrusione" as not managed.
  • Golden corpus: *5*1*##, *5*0*##, *5*1**##.
  • README: profile table regenerated.

Tests

1009 passed, 1 skipped. Ruff clean, README profile table in sync.

Downstream

OpenWebNet-HA/MyHOME#608 fixes 4 MyHOME tests that armed with *5*1*0##. They now arm with *5*8*0## and pass on both OWNd 2.0.0b9 and this branch (full MyHOME suite: 3124 passed). The "MyHOME test suite" conformance job runs against v2-phase1-architecture, so it stays red until #608 merges.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@GreenGrassBlueOcean

Copy link
Copy Markdown
Contributor Author

Pushed 1445b39 addressing the audit:

  • Aliases narrowed to am4890 / ln4890 / ln4890a / 4890. mh4892, mh4893*, 3488*, 3487, myhometouch*, hc4890, hs4890, l4890, hw4890 are unmeasured and may carry WHO 4, so they are generic again (test added).
  • System identity: *5*WHAT**## now reports where '0' / unique_id 5-0, same as *5*WHAT*0##.
  • Empty WHERE deliberately stays ''. This deviates from the audit's "normalise all three". The MyHOME MH200N trace (no panel installed) answers the *#5*0## poll with *5*0*##, *5*5*##, *5*7*##, *5*9*##, while a real panel (MH202, #564) sends *5*9*0##. Mapping empty to 0 made MyHOME create a phantom alarm_control_panel.alarm_0 on that plant (caught by the canary). Empty WHERE is the "no panel, poll dump" signal, so it must stay distinguishable. Covered by a test and noted in the code.
  • Golden corpus: added *5*1*##, *5*0*## (where "") and *5*1**## (where 0).

Not changed, still open from the audit: engage()/disengage() frame shape, is_engaged / is_zone_bypassed scoping, is_armed_home on system WHAT 11, HMAC default, and the stale commit-2 message. Suggest keeping this draft until MyHOME companion OpenWebNet-HA/MyHOME#576 merges. OWNd suite: 888 passed.

@GreenGrassBlueOcean

Copy link
Copy Markdown
Contributor Author

Pushed e6cfe52, the remaining audit items:

  • engage() / disengage() now emit the documented *5*8## / *5*9##, with an optional zone bitmap (engage([1,2,5,6]) gives *5*8#1256##). Marked experimental (no TX capture yet, may NACK). No longer a third way to arm.
  • is_engaged is system-scoped like the other panel flags.
  • is_zone_bypassed is now is_zone_inactive (WHAT 18 is partition state).
  • is_armed_home is always False. No capture shows a system WHAT 11, so home vs away is not on the wire. is_active still covers it. Consumers that mapped system WHAT 11 to "armed home" (MyHOME did) keep the last state instead; MyHOME#576 adjusts its test.
  • H4890 auth: supports_hmac / requires_password only feed the README summary (the handshake is negotiated by the gateway), so the fix is the label: H4890 now shows Auth unmeasured instead of "Legacy password auth".

889 tests pass. Still open: commit e97c213 has a wrong message (says F454/F455/F461 gained WHO 5; they did not). It needs a reword and force-push of this branch, left for the maintainer, or squash-merge fixes it.

@fedem95 fedem95 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the logic; holding off on approval until this is rebased.

Rebase needed. #70 deleted OWNd/message.py (modify/delete conflict), so the parser changes have to move to message/base.py (_ALARM_EMPTY_WHERE, the * → "0" normalisation, parse()) and the event/command changes to message/alarm.py. The README profile table also needs regenerating after #74. Once it's rebased I'll rerun the 3,791-frame old/new comparison from #70: only WHO 5 should move.

On the logic, which should carry over unchanged:

  1. engage() / disengage() keep changing shape. First *5*8*<where>##, then *5*8## with a zone bitmap ("documented"), now back to *5*8*<where>## in 56571ab. Which source does the current form come from? Without a TX capture I'd keep them marked experimental in the docstring (as e6cfe52 did) and have MyHOME not expose them yet.

  2. Empty WHERE is still "system". OWNAlarmEvent sets _system = True for "", so the no-panel poll dump *5*9*## reports is_disarmed = True and logs "System is reporting: …". Keeping where == "" is good, but every consumer then has to remember to check it before trusting the flags. _system = False for "" (or a dedicated is_poll_dump flag) would make the safe path the default.

  3. H4890 supported_who is an allow-list of what the captures happened to contain. It drops heating (4), CEN (15) and scenarios (17), and MyHOME's startup sweep and topology checks follow supported_who. Unless a datasheet says the 4890 screens don't relay those, DEFAULT_SUPPORTED_WHO + WHO_ALARM seems safer than inferring absence from traces. Same reasoning as the audio question on #74.

  4. F455 without WHO 5 is right, and there's now a source for it: the F455 installer manual (RA00125AB) lists "Antintrusione" among the functions it does not manage.

Data point from my MH201 (fw 3.6.27), on a plant whose burglar alarm is not on the SCS bus: *#5*0## is NACKed (twice, ~20 ms), with no WHO 5 frames, and none in 30 h of logs. So this says nothing about whether the MH201 can relay WHO 5. It does show that "no panel" doesn't always look like the MH200N's empty-WHERE dump (*5*9*##): the MH201 just NACKs. Another reason not to let "" stand for the system address (point 2).

The stale message on e97c213 goes away with a squash merge.

…profiles

- Parser: support WHO 5 empty-WHERE broadcast syntax (*5*<what>*##) and normalise * system address to '0'
- Alarm message: system-scope is_active, is_armed_away, is_disarmed, is_engaged; add telemetry & status flags
- Alarm command: provide standard engage() and disengage() commands marked experimental
- Profiles: add H4890Profile with aliases and measured WHO set, add WHO_ALARM to MH202Profile, add auth_measured
- README: regenerate hardware profile table with unmeasured defaults footnote
- Golden corpus & tests: add WHO 5 alarm golden frames and comprehensive unit tests
@GreenGrassBlueOcean

GreenGrassBlueOcean commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

@fedem95 Rebased onto upstream/master (b2765ee), squashed into a single clean commit (958257f), and all 8 CI jobs (Python 3.11–3.14, static analysis, packaging, golden corpus/smoke gates, and downstream MyHOME test suite) are green.

Addressing the review points in detail:

1. Rebase & Squash Cleanup

  • Architecture decomposition: Moved base frame parsing (_ALARM_EMPTY_WHERE, * → "0" normalisation) to OWNd/message/base.py, and alarm event properties/commands to OWNd/message/alarm.py.
  • README profiles table: Regenerated via scripts/update_readme_profiles.py post-fix(profiles): align F455 profile with single-bus hardware constraints (MyHOME#466) #74 with the unmeasured auth footnote.
  • Squash: All previous branch commits squashed into 1 clean commit; the stale message from e97c213 is eliminated.
  • 3,791-frame old/new comparison: Ready to run; only WHO 5 frames will show changes.

2. engage() / disengage() Shape & Experimental Status

  • Grammar source: The OpenWebNet specification documents standard subsystem commands as 4-token frames: *WHO*WHAT*WHERE##. For WHO 5, WHAT=8 (engage/arm) and WHAT=9 (disengage/disarm) take WHERE=0 (central unit) or WHERE=#n (partition). The intermediate experiment with 3-token parameterless frames (*5*8##) violated standard OpenWebNet command grammar and causes hardware gateways to reject with NACK (*#*0##). Restoring *5*8*<where>## in commit 56571ab aligns with standard OpenWebNet syntax.
  • Experimental safeguard & firmware constraints: Both commands remain explicitly marked with .. note:: Marked experimental pending further field TX captures... in their docstrings. Crucially, as the trace contributor (@nicolacavallo84) highlighted in OpenWebNet-HA/MyHOME#564 (comment 5913248544), modern BTicino alarm control unit firmware versions deliberately reject direct SCS bus commands to arm/disarm (*5*...), requiring installations to trigger panel automations via AUX commands (*9*...) instead. This confirms why downstream MyHOME must not expose direct WHO 5 TX arming/disarming commands in the UI or services until physical panel captures validate live execution on compatible firmware.

3. Empty WHERE (""), _system, and Why Changing WHO 5 Code is Critical

  • Critical impact of WHO 5 modifications: In field traces from real installations (MyHOME#466, #484), central alarm panels actually broadcast system-wide activation as *5*1*## (as well as *5*0*## for maintenance) alongside the star form *5*1**##.
  • Why _system = False for "" would break real panels: If _system were set to False whenever where == "", real plant broadcasts of *5*1*## would fail to set is_active or is_armed_away. Because where == "" has neither a zone (_zone is None) nor a sensor (_sensor is None), making _system = False would cause legitimate system-wide broadcasts from the panel to be completely ignored and lost.
  • Poll dump vs. live broadcast: On the wire, *5*9*## (MH200N response when no panel is present) and an unprompted system broadcast are syntactically identical (*5*<what>*##). The single-frame parser cannot determine whether the frame is answering an active poll on an unconfigured bus or is a real bus broadcast.
  • Safe division of labor:
    • OWNd preserves wire fidelity by keeping where == "" distinct from where == "0" (rather than collapsing them).
    • Downstream coordinators (MyHOME) use where != "" to avoid creating phantom alarm_control_panel.alarm_0 entities on poll dumps.
    • If desired in a follow-up, we can introduce an explicit convenience property (e.g. is_empty_where: bool), but keeping _system = True for "" preserves vital field compatibility for real panel broadcasts.

4. H4890 supported_who Allow-List

  • The measured profile was conservatively constrained to the subsystems directly observed in packet captures (following the "declare only measured behavior" principle).
  • However, your point is completely spot on: the 3.5" touch screen (LN4890 / AM4890) natively supports heating, CEN, and scenario controls in hardware, and MyHOME uses supported_who as a hard filter during topology discovery. Restricting it strictly to captured traces risks masking real heating or CEN subsystems if an H4890 serves as the primary gateway.
  • Aligning it with DEFAULT_SUPPORTED_WHO | {WHO_ALARM} is definitely safer. We kept the logic unchanged here for the rebase comparison baseline as requested, but can bump supported_who immediately upon agreement.

5. F455 Hardware Boundary Documentation

  • Finding reference RA00125AB (installer manual explicitly listing "Antintrusione" as unmanaged) is a fantastic confirmation that excluding WHO 5 from the F455 profile matches official manufacturer specifications.

6. MH201 Telemetry & NACKs

  • The MH201 fw 3.6.27 observation (immediate NACK on *#5*0## when no panel is present) is very useful telemetry. It shows that firmware generations handle missing panels differently (MH200N dumps default empty-WHERE frames; MH201 fast-NACKs). This further underscores why OWNd must accurately report the wire representation (where == ""), letting downstream coordinators handle both NACKs and empty dumps safely.

@fedem95 fedem95 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rebase. Verified on 958257f against master (67408c8) with the same 3,791 frames: only WHO 5 changes (new flags, *5*<what>*## now parsed, * → "0", zone/sensor frames no longer moving the panel flags, is_armed_home always False). Every other subsystem and the auth helpers are identical. engage()/disengage() are marked experimental, good.

Point 2: you're right, I withdraw it. The F454 trace from MyHOME#311 (tests/fixtures/plants/issue_311_f454, a real panel with zones #1–#8) answers the status poll with empty-WHERE frames (*5*1*##, *5*5*##, *5*7*##, *5*9*##). Treating "" as non-system would lose a real panel's state.

Point 3: yes please, DEFAULT_SUPPORTED_WHO + WHO_ALARM for H4890.

New, from the same F454 trace: WHAT 1 is not "armed". The panel sends WHAT 1 when it is not armed:

  • disarm sequence: *5*2*0## → *5*1*0## → *5*9*0##
  • status dump of a disarmed system: *5*1*## … *5*9*##

With is_armed_away = state_code in (1, 8), replaying those frames through this branch gives is_armed_away=True on the middle *5*1*0##. MyHOME's handle_event checks is_armed_away before is_disarmed, so on every disarm the panel goes DISARMED → ARMED_AWAY → DISARMED, and automations triggered on "armed_away" fire during a disarm (also briefly after the startup poll). The arm sequence is *5*1*0## → *5*8*0##, so WHAT 8 alone is enough to mark armed. WHAT 1 looks like "system operational" and fits is_active only. This is already in master, but since this PR redefines exactly these flags, it seems the right place: is_armed_away → state_code == 8 and self._system.

Side note, not for this PR: arm_away() and arm_home() both build *5*1*<where>##, the same frame, and with engage() there are again two different ways to "arm". Worth sorting out together with the first TX capture.

GreenGrassBlueOcean and others added 2 commits October 2, 2026 08:38
…alarm

The F454 trace (MyHOME#311) shows WHAT 1 on a disarm (*5*2*0## -> *5*1*0## ->
*5*9*0##) and in disarmed status dumps. Only WHAT 8 means armed, so
is_armed_away is now WHAT 8 on the system address.

H4890 supported_who is DEFAULT_SUPPORTED_WHO + WHO_ALARM instead of an
allow-list of what the captures contained.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The MH202 (MyHOME#564) and H4890 (MyHOME#466) captures are status dumps of
a disarmed panel (*5*1*0##, *5*9*0##) plus zone states; neither shows an
arm transition or an alarm event. The is_armed_home comment still said the
system state comes from WHAT 1; armed/disarmed is WHAT 8/9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plant owner in MyHOME#564 (comment 5913248544) reports, quoting BTicino
support, that current central-unit firmware rejects arm/disarm sent as WHO 5
frames over SCS, whichever gateway sends them. They arm with a WHO 9 AUX frame
(e.g. *9*1*7##) and an automation programmed on the central unit.

OWNAlarmCommand now says so: status() is the only builder to rely on, the
arm/disarm/trigger/engage/disengage builders are unverified and kept for API
compatibility, and arm_away() notes that WHAT 1 is activation, not armed.
The H4890 and MH202 profiles state that their WHO 5 support means reading
the alarm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@GreenGrassBlueOcean

Copy link
Copy Markdown
Contributor Author

@fedem95 thanks for the second pass. Since your review on 958257f I pushed three commits (a4e7d26, 59c8c83, a4c0f59). They only touch OWNd/message/alarm.py, OWNd/profiles.py, the README note under the profile table, and tests.

Your review points

WHAT 1 is not armed (a4e7d26)

  • is_armed_away is now self._state_code == 8 and self._system. WHAT 1 only sets is_active.
  • New test test_alarm_what_1_never_reads_as_armed replays the F454 sequences from MyHOME#311:
    • disarm *5*2*0## → *5*1*0## → *5*9*0##: is_armed_away is [False, False, False]
    • arm *5*1*0## → *5*8*0##: [False, True]
    • empty-WHERE dump *5*1*##, *5*9*##: [False, False]
  • test_alarm_central_telemetry_and_events now expects is_armed_away is False for *5*1*0##.

Point 3: H4890 supported_who (a4e7d26)

  • Now (*DEFAULT_SUPPORTED_WHO, WHO_ALARM), with the test asserting that set. The README note no longer claims the WHO set comes from captures.

Point 2: left as is (empty WHERE stays the system address), per your withdrawal.

New since your review

Docstrings now match the captures (59c8c83)
The MH202 (MyHOME#564) and H4890 (MyHOME#466) captures are status dumps of a disarmed panel plus zone states. Neither contains an arm transition or an alarm event, but the docstrings said they did, so I corrected them. The is_armed_home comment no longer says the system state comes from WHAT 1.

Arm/disarm over WHO 5 is rejected by the central unit (a4c0f59)
The plant owner in MyHOME#564 (comment) reports, quoting BTicino support, that current central-unit firmware rejects arm/disarm sent as *5*... frames over SCS, whichever gateway sends them. They arm with a WHO 9 AUX frame (e.g. *9*1*7##) plus an automation programmed on the central unit, so the frame depends on the installer's programming. As a result:

  • OWNAlarmCommand has a class docstring saying status() is the only builder to rely on, and why.
  • disarm(), arm_away(), arm_home() and trigger() are marked unverified. engage()/disengage() stay experimental, with the same caveat added.
  • arm_away() notes that WHAT 1 is activation, not armed, and that it builds the same frame as arm_home(). That's my answer to your side note: without a TX capture I'd rather not pick one of the three "arm" paths. They're all documented as unverified and kept for API compatibility, with no behaviour change.
  • The H4890 and MH202 docstrings say their WHO 5 support means reading the alarm.

59c8c83 and a4c0f59 are docstring-only. Against 958257f, your 3,791-frame comparison should differ only in is_armed_away turning False on WHAT 1 frames.

Downstream / CI

  • test(alarm): arm with WHAT 8, not WHAT 1 (OWNd#66 conformance) MyHOME#608 is merged. It makes the 4 MyHOME tests that armed with *5*1*0## arm with *5*8*0##. The "MyHOME test suite" job on this PR started after that merge and is still running. Every other check is green (Python 3.11–3.14, static analysis, packaging, golden corpus & smoke gates).
  • PR description updated to the current state.

Related: OpenWebNet-HA/openwebnet-mcp#13 fixes the WHO 5 table in the openwebnet-mcp get_who_spec tool. It listed WHAT 1 as "Arm system (Total)" and offered *5*1*0## / *5*0*0## as arm/disarm commands.

Ready for another look.

@fedem95 fedem95 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified a4c0f59 against 958257f with the same 3,791 frames: the only difference is is_armed_away turning False on WHAT 1 frames (*5*1*##, *5*1**##, *5*1*0##, …). Every other attribute, class and command is unchanged, as are the auth helpers. Profiles check out: H4890 and its aliases now have the default set plus WHO 5, MH202 has WHO 5, and F454/F455/MH201/MH200N don't. The docstring commits match what the captures actually contain, and documenting all the arm paths as unverified without picking one is the right call until there's a TX capture. All 8 checks are green, including the MyHOME suite after #608. Approving.

@GreenGrassBlueOcean
GreenGrassBlueOcean merged commit 11989e5 into OpenWebNet-HA:master Oct 2, 2026
9 of 10 checks passed
@GreenGrassBlueOcean
GreenGrassBlueOcean deleted the feat/h4890-profile-who5 branch October 2, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants