[BUG] - Telemetry parsing fails in Service Mode — bow is required, but the controller intentionally omits <BodyOfWater> during the safety lockout
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 1/5
- Thời gian dự kiến
- Dưới một giờ
- Mức phù hợp với người mới
- 88/100
Hướng nghiên cứu
Bắt đầu tại models/telemetry.py, khoảng dòng 503, nơi trường bắt buộc BodyOfWater được định nghĩa, và xem xét các quy ước về collection tùy chọn của model Telemetry. Sử dụng Service Mode XML tối thiểu trong issue hoặc test suite hiện có để xác minh rằng tài liệu được phân tích, backyard.state vẫn là Service Mode và bow là một danh sách rỗng thay vì phát sinh OmniParsingError.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Disclosure / Notes
Claude did all the heavy lifting for me from a claude code session running on my Home Assistant docker host to review logs, code and HA history. Filing the bug here and not in haomnilogic-local since the issue is part of python-omnilogic-local. I've reviewed what claude did and the information provided. Also, of note, my controller is connected via ethernet, not wifi.
Summary
Telemetry.bow is declared as a required field. When the OmniLogic controller is placed in
Service Mode from the front panel, it stops emitting <BodyOfWater> elements entirely — the
telemetry document reduces to just <Backyard>. Telemetry.model_validate then raises
OmniParsingError, and the library returns nothing at all for the whole duration of the lockout.
This is not a malformed or corrupted response. Service Mode is a safety interlock: it locks out
every remote client so that equipment cannot be started while someone is physically working on it.
The Hayward mobile app is equally locked out during Service Mode, which suggests the controller is
deliberately withholding body-of-water state from all clients rather than glitching. The library is
modelling an intentional, documented operating state as a parse failure.
Related but distinct from #155 (that one is an enum range issue on valveActuatorState; this is a
required-field issue on a structurally different response shape). Same downstream symptom.
Environment
python-omnilogic-local |
5.0.0 |
| pydantic | 2.13.4 |
Controller firmware (mspVersion) |
R0502000, build revision 28706 |
Telemetry STATUS version |
1.12 (statusVersion="12") |
| Downstream | haomnilogic-local 2.0.1 on Home Assistant 2026.8.3 |
Evidence
Entering Service Mode from the front panel, per the controller's own USB log export:
[2026/08/25 18:53:23][Warn][UI][Current Link: node://UIFlow/shutdown.node, PreviousScreen: 2, Current Screen: 38, Running Mode: 3]
[2026/08/25 18:53:29][Notify][PoolLogic][[ 115] UI_SET_SYSTEM_STATE]
[2026/08/25 18:53:29][Warn][UI][[UI_ServiceMode_RemoveTimedServiceEvent:613]ServiceModeTimerFindAndRemoveByEvent]
[2026/08/25 18:53:29][Warn][UI][Current Link: node://UIFlow/serviceMode/serviceModeTop.node, PreviousScreen: 38, Current Screen: 41]
[2026/08/25 18:53:29][Warn][Term-Handler][HPN_SystemStateSet():194, Set System State: "Enter Service Mode", NodeId: 65021]
Thirteen seconds later, the next telemetry poll failed, and kept failing until Service Mode was
exited:
2026-08-25 18:53:42 OmniParsingError: Failed to parse Telemetry: 1 validation error for Telemetry
BodyOfWater
Field required [type=missing, input_value={'@version': '1.12', 'Bac...spVersion': 'R0502000'}}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.13/v/missing
Note the truncated input_value: the document that arrived contained the Backyard element and
nothing else. Exactly one validation error is reported, because every other equipment
collection is already optional — bow is the only required one, so it is the only thing that
fails.
Timeline, cross-referencing the panel log against the client:
| Time | Event |
|---|---|
| 18:53:29 | "Enter Service Mode" set on the front panel |
| 18:53:42 | First OmniParsingError — BodyOfWater missing |
| 18:53:42 → 18:55:26 | Every poll fails; 12 consecutive OmniParsingError in total |
| 18:55:26 | Service Mode exited → BodyOfWater returns → parsing resumes immediately |
Nothing else was wrong: the controller was healthy throughout, the pool equipment kept running,
and the network path was unaffected.
Minimal reproduction
The XML below is a constructed minimal case, not a captured document — but it reproduces the exact
error above. state="2" is BackyardState.SERVICE_MODE.
from pyomnilogic_local.models.telemetry import Telemetry
from pyomnilogic_local.models.exceptions import OmniParsingError
SERVICE_MODE = """<?xml version="1.0" encoding="UTF-8" ?>
<STATUS version="1.12">
<Backyard systemId="0" statusVersion="12" airTemp="101" state="2" ConfigChksum="2759708" mspVersion="R0502000" />
</STATUS>"""
try:
t = Telemetry.load_xml(SERVICE_MODE)
print("parsed OK, backyard state =", t.backyard.state)
except OmniParsingError as e:
print(f"{type(e).__name__}: {e}")
Output:
OmniParsingError: Failed to parse Telemetry: 1 validation error for Telemetry
BodyOfWater
Field required [type=missing, input_value={'@version': '1.12', 'Backyard': {'@systemId': '0', ...}}, input_type=dict]
Root cause
models/telemetry.py L503:
bow: list[TelemetryBoW] = Field(alias="BodyOfWater")
No default, so pydantic treats it as required. The class docstring 24 lines above states the
intent explicitly:
All equipment collections except backyard and bow are optional and will be None
So bow being required is deliberate — it just doesn't account for Service Mode, where the
controller legitimately reports no bodies of water.
Proposed fix
Give bow a default so a Service Mode document parses:
bow: list[TelemetryBoW] = Field(alias="BodyOfWater", default_factory=list)
I've suggested default_factory=list rather than | None = None because existing consumers
iterate telemetry.bow directly and an empty list keeps them working unchanged. That said,
None would match the convention already used for the other optional collections and would let
callers distinguish "Service Mode" from "no bodies of water configured."
Callers that want to detect the lockout explicitly can then read
telemetry.backyard.state == BackyardState.SERVICE_MODE, which already parses correctly
(BackyardState defines SERVICE_MODE = 2 and TIMED_SERVICE_MODE = 4).
I verified this by applying the change in-memory against 5.0.0 and re-validating the same
Service Mode document:
parsed OK -> backyard.state = Service Mode | is SERVICE_MODE: True | bow = []
So the one-line change is sufficient: nothing else in the Service Mode document fails to
validate, and the resulting object carries exactly the signal a caller needs to report the
lockout rather than an error.
Downstream impact
In haomnilogic-local, OmniLogicEntity.available is:
return super().available and self.equipment._omni.backyard.is_ready
and the integration ships a dedicated binary_sensor for backyard Service Mode. So there is
already purpose-built handling for exactly this state — and none of it can execute, because
telemetry parsing fails before any of it is reached.
The practical result is that the one operating mode the safety interlock exists to make visible is
the mode Home Assistant cannot report. Instead of entities cleanly showing unavailable because the
system is in Service Mode, the coordinator raises UpdateFailed and every entity for the config
entry drops out with a generic fetch error. Measured on my system: 90 seconds of full blackout
across all 73 entities for a ~2 minute Service Mode session.
Identifiers (device ID, MSP ID, local IP) redacted from the log excerpts above; happy to supply a
full unredacted log privately if useful.
- Ngôn ngữ chính
- Python
- Star
- 10
- Fork
- 13
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Không có mẫu pull request
- Không có hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của cryptk/python-omnilogic-local
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
cryptk/python-omnilogic-local#150 ·
-
feat(cli): Add control commands (set temperature, on/off, speed)Có thể đã có người làm @tonyfruzza đã nhận 148 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
cryptk/python-omnilogic-local#145 · 1 bình luận ·
-
Pumps can be VSPs as well as featuresCó thể đã có người làm @tonyfruzza đã nhận 147 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 52/100
cryptk/python-omnilogic-local#99 · 8 bình luận ·
Tất cả issue của cryptk/python-omnilogic-local
Issue tương tự
-
[Bug]: LangGraph Store sync put bypasses namespace validationCó thể đã có người làm @ktz03 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
volcengine/OpenViking#6050 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: Streamed /v1/chat/completions sends unredacted agent error text (keys) in the final chunkCó thể đã có người làm @rodricksz4h5 đã nhận hôm nay. Đang mởarea/streaming comp/gateway P2 type/security
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
NousResearch/hermes-agent#138245 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[oblt-aw][autodoc] Update user onboarding guide for mandatory trigger CODEOWNERS stepCó thể đã có người làm @github-actions đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Maintainer thường phản hồi trong vòng 1 ngày
-
correction metadata
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 68/100
acl-org/acl-anthology#10378 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
cloudtrail_multi_region_enabled_logging_management_events fails when the advanced event selector has a custom nameCó thể đã có người làm @12YYCCYY16 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
prowler-cloud/prowler#13033 ·
Maintainer thường phản hồi trong vòng 1 ngày