Parcourir la source

docs: confirm Grid Feed-in Power's exporting case with a direct capture (#28)

hidemichixt-creator's follow-up capture (issue #7) has a full battery and PV
surplus flowing out, and aPhaseMainsPower reads +495 W -- positive really
does mean feeding into the grid, matching what v2.6.1 shipped on physical
symmetry alone. Adds a regression test pinning this exact payload and
updates the const.py comment; no functional code change.
Bob Ehlers il y a 1 mois
Parent
commit
db7d95a51c

+ 11 - 0
CHANGELOG.md

@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ---
 
+## [2.7.1] - 2026-09-16
+
+### Notes
+- **Grid Feed-in Power's exporting case is now directly confirmed**, not just
+  inferred by symmetry. v2.6.1 shipped it without a capture of a device
+  actually exporting; hidemichixt-creator's follow-up capture (#7) has a full
+  battery and PV surplus flowing out (897 W PV, 0 W battery, 351 W load),
+  and `aPhaseMainsPower` reads +495 W — positive really does mean feeding
+  into the grid. No code change; this closes out the caveat from the
+  previous release.
+
 ## [2.7.0] - 2026-09-15
 
 ### Fixed

+ 7 - 3
custom_components/solar_of_things/const.py

@@ -119,9 +119,13 @@ SENSOR_KEYS = [
 #                              batteryPower − pv1Power reproduces
 #                              |aPhaseMainsPower| to within rounding in both
 #                              AC-connected samples (e.g. 614+720−234=1100 W).
-#                              Negative = importing from mains; positive would
-#                              be feed-in by the same physical symmetry (not
-#                              yet directly observed — no sample went positive).
+#                              Negative = importing from mains, positive =
+#                              feeding in — confirmed directly (not just by
+#                              symmetry) by a follow-up capture with the
+#                              battery full and PV surplus flowing out
+#                              (897 W PV, 0 W battery, 351 W load ->
+#                              +495 W on aPhaseMainsPower, the ~50 W gap
+#                              being ordinary inverter conversion loss).
 #     positiveTerminalBatteryCurrent   Sign flips consistently across all four
 #                              states: negative while charging (-17.6, -27 A),
 #                              positive while discharging (+25.5, +17.6 A).

+ 1 - 1
custom_components/solar_of_things/manifest.json

@@ -11,5 +11,5 @@
   "requirements": [
     "pycryptodome>=3.9.0"
   ],
-  "version": "2.7.0"
+  "version": "2.7.1"
 }

+ 31 - 0
tests/test_energy_flow.py

@@ -71,6 +71,23 @@ ISSUE_7_NOAC_PV_DISCHARGING = {
     "bmsSOC": 54,
 }
 
+# Trimmed from UPS_AC_PV_GridFeeding.txt (issue #7, 2026-09-16): the capture
+# hidemichixt-creator took specifically to settle the positive/exporting case
+# left unconfirmed in v2.6.1 — PV surplus after a full battery is being fed
+# back to the grid.
+ISSUE_7_GRID_FEEDING = {
+    "pv1Power": 897,
+    "pv2Power": 0,
+    "load_power": 0.351,
+    "aPhaseMainsPower": 495,
+    "bPhaseMainsPower": 0,
+    "cPhaseMainsPower": 0,
+    "positiveTerminalBatteryCurrent": 0,
+    "negativeTerminalBatteryCurrent": 0,
+    "batteryPower": 0,  # battery full (96% SOC), neither charging nor discharging
+    "bmsSOC": 96,
+}
+
 
 # ─── Pure mapping ──────────────────────────────────────────────────────────────
 
@@ -117,6 +134,20 @@ def test_grid_import_and_feed_in_split_from_signed_mains_power() -> None:
     assert mapped_no_ac["feedInPower"] == 0.0
 
 
+def test_feed_in_power_positive_case_confirmed_by_direct_export_capture() -> None:
+    """v2.6.1 shipped Grid Feed-in Power's positive/exporting case inferred
+    only by symmetry — no capture had shown a device actually exporting.
+    hidemichixt-creator's follow-up capture (issue #7, 2026-09-16) settles it:
+    PV surplus (897 W) after a full battery (0 W charge/discharge) with a
+    351 W load leaves ~546 W to go somewhere, and aPhaseMainsPower reads
+    +495 W (the ~50 W gap is ordinary inverter conversion loss) — positive
+    really does mean exporting, matching the prediction exactly.
+    """
+    mapped = map_energy_flow_fields(ISSUE_7_GRID_FEEDING)
+    assert mapped["feedInPower"] == 495.0
+    assert mapped["gridPower"] == 0.0  # not importing while exporting
+
+
 def test_battery_charging_and_discharge_current_split_by_sign() -> None:
     """positiveTerminalBatteryCurrent flips sign with charge direction.