Repository navigation
Conversation
Return borrowed listener references on early callback failure and cancellation. Offer an explicit capture retry for disconnected collectors while preserving live endpoint checks and redirect consent. Add real-socket and flow regression coverage, translations and user documentation. Refs #43, #45. No callback retry policy changes or new inverter driver.
|
Thanks, Mike — both the code and the evidence pack are genuinely useful. I compared your capture with the Maxinn capture from #26: the core MP/Q1/MD exchanges match, including the reply lengths. That gives us a good starting point for a shared short-ASCII family. I reproduced the listener-reference leak and fixed the cleanup in main, with real-socket regression tests. I kept that separate from changes to callback retries. There are a few things to resolve before merging the driver:
The evidence is enough to work on these points without asking you to repeat the capture. I'll keep the review here so we can bring the useful parts in without changing existing collectors' behavior unexpectedly. |
|
Hey - first of all just glad this appears to be a useful starting point. Reading through your list of findings there's some stuff that looks like obvious errors to pass back into my agentic loop but this in particular:
I'd like to think through this with you if you have the time. Fundamentally, for unknown reasons, this inverter just doesn't report useful load information while on DC power and the load is under ~1000W. I'm fortunate enough to have a 30kWh battery but even with that, I could consume nearly 50% of available battery backup overnight while the inverter load was reporting 0W ! This is...not very helpful. So I'm very interested in the computed load from the BMS - it's a key feature for me. But I do understand that having the same signal be labeled "inverter load" but also quietly be "...and also sometimes this estimated thing..." is kind of crappy. Would you be open to having more and more clearly labeled load information come from the driver? For example:
I have also seen a couple garbage readings come through over the last 24 hours and I'm trying to work through them. Do you have any thoughts on the best way to handle garbage readings? So far I have two classes which I think deserve separate solutions (though I am open to literally any thoughts here): 1- Filter readings which are known impossible - either out of bounds for the equipment or so obviously absurd they can be filtered out completely - for example I got a 2400kW reading once last night, on a 12kW inverter. That's just silly. Is there already a filtering strategy, or is there a known-good filtering strategy for things like this? It appears that from the wire protocol we can determine a VA ceiling, so the driver with no configuration should be able to compute an upper limit. I'm thinking of deriving known min/max V I and P for various data values given information we can fetch from the protocol, and just filtering obviously junk data. Is that okay? 2- Hold-for-confirmation readings which are possible but implausible - readings in bound for equipment but highly unlikely and transient. Example: BMS returned 84% one reading, 67% the next, and 84% again the third reading. I'm guessing 5kWh weren't consumed and magically stored in the BMS in the span of 20 seconds, and I think the driver may actually be able to filter that based on max charging amperage and discharge rate, but the "plausibility" case can still be constructed. What if it was within parameters but represented a fairly wild swing still. I'm thinking maybe a small state machine works against the same model and for really large swings or values that suddenly de-correlate holding the suspect values for a X readings (3? something like that) until confirmed then sending them through In concert with that I'd like to start emitting counters of BMS disconnects, filtered/rejected data values, and held-pending data values This is feature design via a textarea on github - I feel like it's a possible start but it's obviously just draft / thoughts. If this is all a terrible idea, I'm open to any other strategy or information Thanks again for the project - this PR merged or not, it's already personally useful in it's local test integration form |
Preserve the existing runtime header contract and add an internal checksum-validating binary codec with fixed deadlines, explicit grammar and terminal ambiguity handling. Cover fragmentation, late-frame overlap, suffix preservation and cancellation. No AABB session admission or new inverter driver is enabled. Refs #45. Transport foundation only; no release or deployment.
|
Thanks, Mike. Yes — separating those readings makes sense. I'd keep the reported load percentage, battery-side DC power, and an explicitly labelled AC-load estimate separate. Even watts calculated from a load percentage and a VA rating should not be presented as measured active power. The low-load limitation you describe is a good reason to offer an estimate, not to silently replace the original reading. For the spikes, I'd check the raw reply, checksum and scaling before adding smoothing. Hard checks such as SOC outside 0–100% are useful; equipment-based limits need confirmed ratings and allowance for overload. I wouldn't automatically reject every sudden SOC change, since a BMS can revise its estimate. Rejection/availability counters would be useful diagnostics, but held values shouldn't look like fresh measurements. There is now a smaller read-only family profile in main, based on the shared Anern/Maxinn exchanges: basic telemetry plus optional BMS/rated readings with expiry. It deliberately does not include live PV, BMS current, battery power, estimated load or controls yet, so it won't replace every feature of your branch. The PR remains open. If you're happy to try that baseline, please keep a copy of your current build, install main and send a fresh Support Archive with what matches or looks wrong. No remote access is needed at this stage. The archive now preserves the binary reply bytes correctly; if a spike recurs, include the sensor and time too, since an archive takes a fresh snapshot rather than recording past samples. |
|
Oh cool - re the short family implementation on main already - I'll continue working on my branch but reconcile it with what is on main so I keep tracking the active progress here in the primary clone / upstream and keep this merge-able at any point as we continue to collaborate I think the corrupt RB decode is the main thing to solve then any filtering / smoothing concerns I have become secondary My inverter is an interesting case, as a very specific example of local equipment, in that it has some active faults right now. So I'm working locally on mapping all the error codes and faults etc today. To be honest, the fact it is not working correctly is one of the reasons I am so motivated to use this project - I need deep insight to coordinate with my vendor ! At any rate, your original feedback items, and now your new ones are all queued for ingestion here as I work on my local system and I'll take my turn now to actual handle all your feedback then collect more data, then re-propose a re-worked PR plus supporting evidence based on current state Cheers |
|
I performed an analysis of my tip implementation vs your new mainline short-ascii implementation in order to generate more useful work and less slop, and I think the rules it came up with might be useful as a separate item, something you might consider adding to AGENTS.md for future contributors perhaps? The prompt was essentially "compare the common parts of both implementations and where you can discern that tip implementation is different from main because of bloat instead of extra features, analyze why so that we may provide guidance to future agents on generating features without bloat" Lean implementation (Maksym-shaped) — repo rules Verified 2026-09-16 by comparing pristine tip short-ASCII (~825 LOC driver + fat schema) against origin/main family (~149 LOC driver + thin parsers). Tip was both more feature-rich and bloated in the shared parse/detect path. Treat the following as standing repo rules for all agentic work on this fork.
|
2d918e5 to
181386f
Compare
|
Hey Maksym 👋 Thanks again for the time and the feedback — especially for landing the short-ASCII family on main and for the clear notes on measurement vs estimate and junk-handling order. That saved me from doubling down on the tip-shaped path. TL;DR: I force-updated this PR’s branch to a rebuild from current Against your first review list
Against the follow-up (load split + junk)
Aux pathway / live PV (following your lead)You left an unfinished admission: socket
Night-time live PV after cutover looked plausible (~10–12 V / 0 W) vs SmartValue in the same window. Support Archive askPost-additive archive on the family deploy is attached below (binaries preserved, includes Evidence guideRelease: https://github.com/mikehardy/ha-eybond-local/releases/tag/short-ascii-family-q9a-evidence
What we do not have a clean receipt for yet (so: not everything):
Happy to iterate. Let me know what you’d like next on this branch. Cheers |
|
Oh - the first 2 commits are small test deflakes for my macOS environment - I find agentic loops get hung up on test flakes if you try to insist on testing and coverage as evidence but there are flaky tests. It just slows everything down. So I asked it to deflake the ones that were failing in my environment prior to starting real work. If those are unwanted obviously we can drop them. But it made the queue processing fairly smooth here once I'd ingested all your feedback and reshaped everything to match the repo better |
|
Thanks Mike — the rebuild is much easier to review. Keeping the family identity, separating the AC estimate, and using the existing auxiliary path are all good changes. I've reviewed There are still a few things to address before these additions can go into the shared driver:
For the two macOS commits: normalizing both sides of the metadata path comparison is worth reviewing separately, with symlink containment tests. The DESSMonitor test change isn't just a deflake: it explicitly accepts fetching callbacks after the building stage. Let's keep the ordering guarantee and make callback delivery deterministic instead of allowing progress to move backward. I'd split the next revision into independently testable changes: current/scaling evidence, filter/availability behavior, then opt-in PV admission. No need to induce bad data on the live inverter — synthetic regression cases are appropriate for the rejection and expiry rules. |
|
copy that - will work on the structure and the other points you raise - also, I'm still working on mapping all the error codes. I've got the schema, the manual for cross-reference and actual fault conditions locally ( 😭 ) so I can expose the decoded errors as diagnostic sensors. It needs work still (based on your feedback) but I can assert that it's still working - even it's "needs work" state quite well locally so I'm sure we'll get there |
|
Just a note that this is definitely not "stale" for me - I'm refining the work locally through iterations on the code versus the direct observations of behavior on-site with this inverter combined with the perspective from your previous reviews and your adding drivers .md guidance. I should have something that is correct (vs actual device behavior) soon, and ...hopefully at least good enough to deserve review and perhaps an eventual merge shortly. My current code iteration has survived a full day/night cycle without collector hangs or strange behavior so it's looking promising. |
|
Thanks for the update, Mike! A full day/night run on the actual inverter is useful evidence. No worries — I'll keep the PR open while you finish the next revision. Once you've pushed it, I can review the new code alongside your observations. Thanks for taking the earlier feedback into account. |

Hey Maksym 👋
First — sincere thanks for creating and maintaining EyeBond Local. I just got my first solar kit, I've never really done Python or Home Assistant before, and somehow I still landed in your repo. I've been doing software for about 30 years and public GitHub maintenance for nearly 10, with heavy agent use all this year, so I'm pretty motivated to make this inverter work — and I'm always happy to help a fellow maintainer.
This PR was built agentically (Cursor agents did a lot of the digging, coding, and adversarial review loops), but I'm a human on the other end listening, and I'm ready to iterate until it works for you if that's possible.
Summary
Adds a read-only EyeBond short-ASCII path for OFFG / URTU1920-style collectors (proven live on an Anern SPI-12000W), plus two small shared fixes the driver needs on the callback transport / admission side.
Commits (reviewable one at a time):
fix: stop callback identity from leaking shared listeners— admission/callback lifecyclefix: discriminate callback AABB MPPT frames from FC4— bareaabbside-channel on the callback socketfeat: add read-only EyeBond short-ASCII driver for Anern SPI-12000W— driver, schema, catalog, testsDriver direction and implemented scope
The required driver is not
eybond_g_ascii; it is the FC4/short-ASCII family matching APKDevUrtu1920_01(SmartValue /19B4.xml).Implemented here as
eybond_short_ascii(read-only):MD/Q1/F/RB5AA5…02→aabb0200for MPPT PV (same elicit path SmartValue/cloud uses)0x02FF, collector0xFF, payloadCMD+device_addr+CRLive PV proof (example): SmartValue Historical 07:47:17 showed 1.67 kW / 118.5 V / Track; HA after the
5AA5solicit path showed about 1.59–1.65 kW and 118.7–120.2 V / Track. Re-verified after deploying this rewritten branch to my HA.Known gaps (documented in the evidence pack):
RBwith pack-voltage raw 0 and SoC 0 = BMS link lost (omit SoC/V/I zeros; trailing fields may be nonzero)Testing / iteration loop
How this was developed against live hardware:
adb) as the cloud ground truth5AA5→aabb0200exchange independently of the app UIha core restartfor a fast edit → deploy → correlate loopmainuntil findings (including nits) were cleared, then history rewritten into the three commits abovecompileall+ quality-gate static checksEvidence pack
I uploaded a maintainer evidence pack (proxy capture, ValueCloud summaries, APK/
19B4notes, live HA↔SmartValue correlation write-up, sanitized session exports; credentials redacted) here, hoping it helps you and your agents work the PR:Please treat it as site-local evidence even though emails/passwords were scrubbed.
Pull Request Checklist
From CONTRIBUTING.md:
unittestshort-ASCII / AABB / admission / transport suites; full suite has known macOS loopback-alias infra gaps on my machine)python3 tools/quality_gate.pyunit stage depends on that same loopback infra locally)INVERTER_MODEL_CATALOG.generated.md)manifest.jsonrequirements.local/artifacts committedHappy to adjust structure, naming, tests, or scope — just say the word.
Cheers,
Mike