diff --git a/CHANGELOG.md b/CHANGELOG.md index d2d69af..5f48ea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,9 @@ Driver versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html targeting both must use. ### Fixed -- **`foxess_h3_smart` 0.9.4 — grid charging at night finally works.** It never had: the BMS-ceiling guard read `Pwr_limit_Bat_up` milliseconds after writing the session enable, but the inverter sleeps in standby at night and its master samples the RC block slowly (the same fact behind the 60 s timeout floor), so the register still reported the sleeping value, the guard refused, the host reverted the driver, and the release put the inverter straight back to sleep — every retry slot, all night (observed 2026-09-08: five hours of refusals at 10% SoC with a 20 °C pack; the unguarded v0.2.0 had night-imported happily, and the reference implementation drives the session continuously rather than gate on a first read). A night charge that meets a floor-level limit is now **accepted as pending**: the driver holds AC = 0 — no import, no discharge, session keeping the inverter awake — re-reads the limit every poll, applies the true setpoint the moment the BMS wakes, and gives up only after a 3-minute patience window (a genuine cold/fault hold). Daylight behaviour unchanged: an awake inverter reporting a floor-level limit is a real refusal. The v2 entrypoint returns `accepted` / `charge_pending_bms_wake` for the pending state — the contract's word for "heard you, not done yet". New metric `foxess_bms_charge_limit_w` every poll, so the next BMS mood swing is a time series instead of a mystery +- **`foxess_h3_smart` 0.9.5 — the pending-charge wait is now universal, because the BMS limit follows activity, not capability.** 0.9.4 fixed the night refusal loop but kept the instant refusal in daylight — and the same loop promptly reappeared with the sun up: a battery idle at the SoC floor under weak PV dozes off and reports no charge headroom even in daylight (two incidents on the 1K5, 2026-08-19/20, SoC 11–14%, battery 0 W, limit below the floor, sun up; the host re-commanded every 5 minutes and the fault flapped indefinitely). A floor-level limit now always accepts the charge as pending — and the pending state PROBES with a gentle 200 W charge (night: AC = −200; daylight: AC = pv − 200) rather than holding at zero, because live metric data showed the limit register follows power FLOW, not capability: 12+ minutes of flat-0 limit across politely-held sessions, while the unguarded v0.2.0 had charged 4.5 kW from the same idle state just by asking. And because the same metric showed the register staying flat 0 even while the pack demonstrably charged at the probe level, capability is read from **measured uptake** when the register is dead: the request ramps 500 W per poll while the battery follows (decaying a step on stalls, never exceeding the commanded target), the register path takes over the moment `Pwr_limit_Bat_up` actually rises, and the patience window only counts time without uptake — a pack that is charging is success in progress, while a genuinely full or cold pack sees at most 3 minutes of a 200 W request it is free to ignore. Also corrects the incident dates the 0.9.4 notes carried (August, not September) + +- **`foxess_h3_smart` 0.9.4 — grid charging at night finally works.** It never had: the BMS-ceiling guard read `Pwr_limit_Bat_up` milliseconds after writing the session enable, but the inverter sleeps in standby at night and its master samples the RC block slowly (the same fact behind the 60 s timeout floor), so the register still reported the sleeping value, the guard refused, the host reverted the driver, and the release put the inverter straight back to sleep — every retry slot, all night (observed 2026-08-18/19: five hours of refusals at 10% SoC with a 20 °C pack; the unguarded v0.2.0 had night-imported happily, and the reference implementation drives the session continuously rather than gate on a first read). A night charge that meets a floor-level limit is now **accepted as pending**: the driver holds AC = 0 — no import, no discharge, session keeping the inverter awake — re-reads the limit every poll, applies the true setpoint the moment the BMS wakes, and gives up only after a 3-minute patience window (a genuine cold/fault hold). Daylight behaviour unchanged: an awake inverter reporting a floor-level limit is a real refusal. The v2 entrypoint returns `accepted` / `charge_pending_bms_wake` for the pending state — the contract's word for "heard you, not done yet". New metric `foxess_bms_charge_limit_w` every poll, so the next BMS mood swing is a time series instead of a mystery ### Changed - **`huawei` 2.1.2 and `ferroamp_modbus` 2.1.2 are now telemetry-only.** Both drivers exposed battery control without a hardware-verified way to hold 0 W: Huawei's stop command returned the inverter to self-consumption, and Ferroamp Modbus selected auto mode. FTW uses 0 W as an enforced battery hold, so either path could let native charging continue during an idle plan slot. The Lua boundary now refuses every command and performs no writes during command, default or cleanup. Huawei control can return after a SUN2000/LUNA2000 test proves held charge, discharge and zero plus a safe release. Ferroamp control remains available through the hardware-verified MQTT driver; its Modbus path needs the same proof before it can write again. diff --git a/SUPPORT_STATUS.md b/SUPPORT_STATUS.md index a426fc8..fd1e2af 100644 --- a/SUPPORT_STATUS.md +++ b/SUPPORT_STATUS.md @@ -60,8 +60,8 @@ Catalog source is not proof that a target can install or run a driver. | ferroamp_dc2_v2x | 2.1.0 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | | ferroamp_modbus | 2.1.2 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | | ferroamp_modbus | 2.1.2 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | -| foxess_h3_smart | 0.9.4 | ftw-core | not_assessed | 0.9.4 | — | not_recorded | — | not_assessed | yes | -| foxess_h3_smart | 0.9.4 | blixt-l1 | not_assessed | 0.9.4 | — | not_recorded | — | not_assessed | yes | +| foxess_h3_smart | 0.9.5 | ftw-core | not_assessed | 0.9.5 | — | not_recorded | — | not_assessed | yes | +| foxess_h3_smart | 0.9.5 | blixt-l1 | not_assessed | 0.9.5 | — | not_recorded | — | not_assessed | yes | | fronius | 2.1.1 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | | fronius | 2.1.1 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | | fronius_api | 1.0.2 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | diff --git a/devices.yaml b/devices.yaml index b6802a1..07c3710 100644 --- a/devices.yaml +++ b/devices.yaml @@ -417,7 +417,7 @@ manufacturers: protocols: - protocol: modbus driver: "foxess_h3_smart" - version: "0.9.4" + version: "0.9.5" ders: [pv, battery, meter] control: true firmware_versions: "" @@ -428,7 +428,7 @@ manufacturers: protocols: - protocol: modbus driver: "foxess_h3_smart" - version: "0.9.4" + version: "0.9.5" ders: [pv, battery, meter] control: true firmware_versions: "" diff --git a/drivers/lua/foxess_h3_smart.lua b/drivers/lua/foxess_h3_smart.lua index 6804e05..a8d0114 100644 --- a/drivers/lua/foxess_h3_smart.lua +++ b/drivers/lua/foxess_h3_smart.lua @@ -67,25 +67,26 @@ -- implementation's finding: command right at the limit and the -- inverter clips PV while the battery takes ~50 W less than it -- could -- the gap is what lets PV fill in. Below a 250 W floor --- the response depends on whether the inverter can be believed: --- daylight: the inverter is awake, the refusal is real (full, --- cold, BMS hold) -- release and report why; native --- self-use surplus-charges better than a fight. --- night: the inverter sleeps in standby and its master --- samples the RC block slowly, so the limit register --- still shows the sleeping value right after session --- enable. Refusing here re-releases the session and --- the inverter never wakes -- the loop that made --- grid charging never work at night (found --- 2026-09-08: 5 h of refusals, 10% SoC, 20 C pack, --- while the unguarded v0.2.0 had night-imported --- happily, and the reference drives the session --- continuously rather than gate on first read). --- Instead: accept the command, hold AC = 0 (no --- import, session keeps the inverter awake), re-read --- the limit every poll, apply the true setpoint when --- it wakes, give up only after a 3 min patience --- window (a genuine cold/fault hold). +-- the charge is accepted as PENDING, day or night: command a +-- gentle CHARGE_PROBE_W charge (night: AC = -probe; daylight: +-- AC = pv - probe), keep the session alive, re-read the limit +-- every poll, apply the true setpoint the moment it rises, give +-- up after a 3 min patience window (a genuine full / cold / +-- fault hold; native self-use then serves better than a fight). +-- Why a probe instead of refusing or waiting: the limit register +-- follows power FLOW, not capability. A pack that has sat idle +-- dozes off and reports no headroom until current actually +-- moves. Refusing re-releases the session so nothing ever asks +-- (the loop behind grid charging never working at night, +-- 2026-08-18/19: 5 h of refusals at 10% SoC, 20 C pack), a +-- night-only fix left the identical loop in daylight with the +-- battery idle at the SoC floor (2026-08-19/20, SoC 11-14%, +-- sun up), and a polite held-at-zero session proved insufficient +-- on hardware (metric: 12+ min of flat-0 limit across held +-- sessions). The unguarded v0.2.0 charged 4.5 kW from this +-- exact idle state just by asking -- asking is the wake-up call. +-- The reference avoids the entire class by never gating on a +-- first read; the probe keeps its spirit and our ceiling guard. -- 2. Daylight split (PV string VOLTAGE >= 70 V -- voltage says the -- panels are awake even when power is ~0 at dawn; power says -- nothing at night): @@ -147,7 +148,7 @@ DRIVER = { id = "foxess_h3_smart", name = "FoxESS H3-Smart / 1K5", manufacturer = "Fox ESS", - version = "0.9.4", + version = "0.9.5", host_api_min = 1, host_api_max = 2, protocols = { "modbus" }, @@ -172,7 +173,7 @@ PROTOCOL = "modbus" -- other field here. DRIVER_MANIFEST = { name = "foxess_h3_smart", - version = "0.9.4", + version = "0.9.5", role = "inverter", requires = {}, options = {}, @@ -248,6 +249,24 @@ local CHARGE_BMS_FLOOR_W = 250 -- The RC block is sampled slowly by the inverter master (the same -- fact behind the 60 s timeout floor), so seconds are not enough. local CHARGE_WAKE_PATIENCE_MS = 180000 +-- The wake stimulus, and the uptake ramp behind it. Hardware findings +-- on the discovering 1K5 (2026-08-20 morning, via the limit metric): +-- a session that asks for nothing never wakes the pack (12+ min of +-- flat-0 limit across held-at-zero sessions), and the register stays +-- flat 0 EVEN WHILE the pack demonstrably charges at the probe level +-- -- in the idle-at-floor state the register is simply dead, while +-- the pack itself takes whatever is asked (the unguarded v0.2.0 +-- imported 4.5 kW from this exact state). So: probe with a gentle +-- charge, and when the pack provably follows, ramp the request on +-- MEASURED UPTAKE -- the guard the header's charge section always +-- named as the next step. The register path still takes over the +-- moment Pwr_limit_Bat_up actually rises. +local CHARGE_PROBE_W = 200 +-- Ramp step per poll while escalating on uptake, and the fraction of +-- the current request the pack must be following for the ramp (or the +-- request itself) to be trusted. +local CHARGE_RAMP_STEP_W = 500 +local CHARGE_FOLLOW_FRACTION = 0.5 local PV_VOLTS_DAYLIGHT = 70 -- The PV reading is DC-side; the AC terminals see less after -- conversion, and feeding raw DC PV into the AC setpoint makes the @@ -278,9 +297,15 @@ local fault_active = nil local rc_enabled = false local rc_target_w = nil -- site convention: positive = charge local rc_command_ms = 0 --- millis when a charge first found the BMS limit below the floor at --- night; nil when no charge is waiting. See CHARGE_WAKE_PATIENCE_MS. +-- millis when a charge first found the BMS limit below the floor; +-- nil when no charge is waiting. See CHARGE_WAKE_PATIENCE_MS. local charge_wake_since = nil +-- The uptake ramp's current request (W) while the limit register is +-- dead; nil when not ramping. Grows by CHARGE_RAMP_STEP_W per poll +-- while the measured battery charge keeps following. +local charge_ramp_w = nil +-- Battery power from the last poll, site convention (+ = charging). +local last_bat_w = nil -- PV curtail cap (AC-output ceiling, W). nil = none. Armed by the -- `curtail` action; only honoured when the operator opted in via -- supports_pv_curtail (the host injects _supports_pv_curtail). @@ -411,24 +436,39 @@ local function compute_vendor(battery_target_w) return nil, "battery charge limit unreadable" end if limit < CHARGE_BMS_FLOOR_W then - -- Daylight: the inverter is awake, so a floor-level limit is a - -- real refusal (full, cold, BMS hold) -- release and let native - -- self-use surplus-charge instead. + -- PENDING, day or night: the limit register follows the battery's + -- ACTIVITY, not its capability -- an idle battery dozes off and + -- reports no headroom until a session asks and waits. Refusing + -- releases the session so nothing ever asks: that loop made grid + -- charging never work at night (2026-08-18/19), and the night-only + -- 0.9.4 fix left the identical loop in daylight with the battery + -- idle at the SoC floor under weak PV (2026-08-19/20, SoC 11-14%, + -- battery 0 W, sun up). Hold the battery at zero instead -- night: + -- AC = 0; daylight: AC = pv, so PV passes to house + grid -- keep + -- the session alive, re-read every poll, and let the refresh + -- path's patience window bound a genuine full/cold/fault hold. + -- Uptake ramp: the pack following the current request is the + -- capability signal the dead register cannot give. Grow the + -- request one step per poll while it follows; fall back to the + -- probe when it stops. + local request = CHARGE_PROBE_W + local following = (last_bat_w or 0) >= (charge_ramp_w or CHARGE_PROBE_W) * CHARGE_FOLLOW_FRACTION + if following then + request = math.min(battery_target_w, (charge_ramp_w or CHARGE_PROBE_W) + CHARGE_RAMP_STEP_W) + else + -- Decay one step rather than reset: the inverter can lag a poll + -- behind a raised request, and a full reset would saw-tooth. + request = math.max(CHARGE_PROBE_W, (charge_ramp_w or CHARGE_PROBE_W) - CHARGE_RAMP_STEP_W) + end + charge_ramp_w = request + local why = "probing " .. request .. " W while the BMS charge limit sleeps" if (last_pv_volts or 0) >= PV_VOLTS_DAYLIGHT then - return nil, "battery is not accepting charge now" + if last_pv_w == nil then + return nil, "no PV reading yet" + end + return last_pv_w * PV_AC_EFF - request, why, true end - -- Night: the inverter has been in standby and its master samples - -- the RC block slowly, so Pwr_limit_Bat_up still reports the - -- sleeping value right after the session enable. Failing here - -- releases the session and puts the inverter straight back to - -- sleep -- the loop that made grid charging never work at night - -- (discovered 2026-09-08: five hours of refusals at 10% SoC with - -- a 20 C battery, while the unguarded build had night-imported - -- happily). Hold AC = 0 instead: no import, no discharge, session - -- alive; every poll re-reads the limit and the real setpoint - -- follows the moment the BMS wakes. The patience window in the - -- refresh path bounds how long a genuine refusal can hold this. - return 0, "waiting for the BMS charge limit to wake", true + return -request, why, true end local p_eff = math.min(battery_target_w, limit - CHARGE_BMS_MARGIN_W) -- Guard 2: daylight by string voltage, not power. @@ -517,6 +557,7 @@ local function release_remote_control() rc_target_w = nil prev_vendor_w = nil charge_wake_since = nil + charge_ramp_w = nil if rc_enabled then rc_enabled = false checked_write(RC_ENABLE_ADDR, 0) @@ -604,6 +645,7 @@ function driver_poll() if power then local bat_out = {} bat_out.W = -i32(power, POWER_ADDR, 39237) + last_bat_w = bat_out.W bat_out.V = reg(power, POWER_ADDR, 39227) * 0.1 bat_out.A = -i32(power, POWER_ADDR, 39228) * 0.001 local soc = read(SOC_ADDR, 1) @@ -682,7 +724,7 @@ function driver_poll() if prev_vendor_w ~= nil then host.emit_metric("foxess_rc_setpoint_w", prev_vendor_w) end - -- The BMS charge ceiling as a time series: the 2026-09-08 night of + -- The BMS charge ceiling as a time series: the 2026-08-18/19 night of -- refused charging was undiagnosable precisely because this value -- was only ever read inside command paths. One extra register pair -- per poll buys the ability to see the BMS's mood remotely. @@ -709,6 +751,11 @@ function driver_poll() host.log("warn", "foxess_h3_smart: releasing remote control: " .. why) release_all() elseif pending then + if (last_bat_w or 0) >= CHARGE_PROBE_W * CHARGE_FOLLOW_FRACTION then + -- The pack is charging: pending-with-uptake is success in + -- progress, not a refusal to time out. + charge_wake_since = host.millis() + end if charge_wake_since == nil then charge_wake_since = host.millis() elseif host.millis() - charge_wake_since > CHARGE_WAKE_PATIENCE_MS then @@ -721,6 +768,7 @@ function driver_poll() end else charge_wake_since = nil + charge_ramp_w = nil end end elseif rc_enabled then @@ -795,7 +843,7 @@ function driver_command(action, value, context) if pending then if charge_wake_since == nil then charge_wake_since = host.millis() - host.log("info", "foxess_h3_smart: charge accepted; holding 0 W while the BMS charge limit wakes") + host.log("info", "foxess_h3_smart: charge accepted as pending; " .. tostring(why)) end else charge_wake_since = nil @@ -883,7 +931,7 @@ function driver_command_v2(cmd) end return { status = "accepted", code = "charge_pending_bms_wake", - message = "holding 0 W while the BMS charge limit wakes; charge follows on refresh", + message = "probing " .. CHARGE_PROBE_W .. " W while the BMS charge limit wakes; full charge follows on refresh", device_state = "controlled", evidence = { "write_ack", "readback" }, } diff --git a/drivers/tests/test_foxess_h3_smart_control.py b/drivers/tests/test_foxess_h3_smart_control.py index 3474e35..8b6753c 100644 --- a/drivers/tests/test_foxess_h3_smart_control.py +++ b/drivers/tests/test_foxess_h3_smart_control.py @@ -161,6 +161,14 @@ def test_v1_entrypoints_still_serve_local_builds(): NIGHT = """ host._modbus_registers.holding[39070] = 550 host._modbus_registers.holding[39072] = 480 +host._modbus_registers.holding[39237] = 0 +host._modbus_registers.holding[39238] = 0 +pcall(driver_poll) +""" + +IDLE_BAT = """ +host._modbus_registers.holding[39237] = 0 +host._modbus_registers.holding[39238] = 0 pcall(driver_poll) """ @@ -168,7 +176,7 @@ def test_v1_entrypoints_still_serve_local_builds(): def test_night_charge_with_sleeping_bms_holds_and_waits(): """A sleeping BMS limit must not fail the command — that released the session and put the inverter back to sleep, the loop that made - grid charging never work at night (2026-09-08).""" + grid charging never work at night (2026-08-18/19).""" out = drive(NIGHT + """ host._modbus_registers.holding[46018] = {0, 0} local r = driver_command("battery", 2000) @@ -176,7 +184,7 @@ def test_night_charge_with_sleeping_bms_holds_and_waits(): """) assert out["V1_RESULT"] == "true" # accepted, not refused assert out["RC_ENABLE"] == "1" # session stays up - assert setpoint(out) == 0 # holding, not importing + assert setpoint(out) == -200 # probe import, not full charge def test_night_charge_applies_when_bms_wakes(): @@ -192,25 +200,57 @@ def test_night_charge_applies_when_bms_wakes(): assert out["RC_ENABLE"] == "1" +PATIENCE_CYCLES = """ +for _ = 1, 3 do + host._millis_counter = host._millis_counter + 70000 + driver_command("battery", 2000) + pcall(driver_poll) +end +print("MARK done") +""" + + def test_night_charge_gives_up_after_patience_window(): out = drive(NIGHT + """ host._modbus_registers.holding[46018] = {0, 0} driver_command("battery", 2000) -host._millis_step = 200000 -pcall(driver_poll) -pcall(driver_poll) -print("MARK done") -""") +""" + PATIENCE_CYCLES) assert out["RC_ENABLE"] == "0" # released: genuine refusal -def test_daylight_low_limit_still_refuses(): - out = drive(""" +def test_daylight_low_limit_holds_and_waits(): + """0.9.5: the limit register follows battery ACTIVITY, not + capability — an idle battery dozes off in daylight too (observed + at 11-14% SoC with the sun up). Pending is universal: hold the + probe gently (AC = pv - 200) and wait.""" + out = drive(IDLE_BAT + """ host._modbus_registers.holding[46018] = {0, 0} local r = driver_command("battery", 2000) print("V1_RESULT " .. tostring(r)) """) - assert "not accepting charge" in out["V1_RESULT"] + assert out["V1_RESULT"] == "true" + assert out["RC_ENABLE"] == "1" + assert setpoint(out) == round(PV_W * EFF) - 200 # probe under PV pass-through + + +def test_daylight_charge_applies_when_bms_wakes(): + out = drive(IDLE_BAT + """ +host._modbus_registers.holding[46018] = {0, 0} +driver_command("battery", 2000) +host._modbus_registers.holding[46018] = {0, 6000} +pcall(driver_poll) +print("MARK done") +""") + # limit awake: daylight vendor = pv * eff - target + assert setpoint(out) == round(PV_W * EFF) - 2000 + + +def test_daylight_pending_gives_up_after_patience_window(): + out = drive(IDLE_BAT + """ +host._modbus_registers.holding[46018] = {0, 0} +driver_command("battery", 2000) +""" + PATIENCE_CYCLES) + assert out["RC_ENABLE"] == "0" # released: genuine refusal def test_v2_night_charge_pending_is_accepted_not_applied(): @@ -223,4 +263,56 @@ def test_v2_night_charge_pending_is_accepted_not_applied(): assert out["CODE"] == "charge_pending_bms_wake" assert out["STATE"] == "controlled" assert out["EVIDENCE"] == "write_ack,readback" - assert setpoint(out) == 0 + assert setpoint(out) == -200 # the probe, not the full charge + + +def _bat_charging(w): + """Registers for a battery charging at `w` (vendor: negative).""" + raw = (-w) & 0xFFFFFFFF + return (f"host._modbus_registers.holding[39237] = {raw >> 16}\n" + f"host._modbus_registers.holding[39238] = {raw & 0xFFFF}\n") + + +def test_pending_ramps_on_measured_uptake_with_dead_register(): + """2026-08-20 hardware finding: the pack charges at the probe level + while the limit register stays flat 0 — capability must be read + from measured uptake, one step per poll.""" + out = drive(NIGHT + """ +host._modbus_registers.holding[46018] = {0, 0} +driver_command("battery", 2000) +""" + _bat_charging(210) + """ +pcall(driver_poll) +print("SP1_HI " .. tostring(host._modbus_registers.holding[46003])) +print("SP1_LO " .. tostring(host._modbus_registers.holding[46004])) +""" + _bat_charging(650) + """ +pcall(driver_poll) +print("MARK done") +""") + sp1 = (int(out["SP1_HI"]) << 16) | int(out["SP1_LO"]) + sp1 = sp1 - (1 << 32) if sp1 >= (1 << 31) else sp1 + assert sp1 == -700 # probe followed -> one step up + assert setpoint(out) == -1200 # still following -> next step + assert out["RC_ENABLE"] == "1" + + +def test_pending_ramp_decays_when_uptake_stalls(): + out = drive(NIGHT + """ +host._modbus_registers.holding[46018] = {0, 0} +driver_command("battery", 2000) +""" + _bat_charging(210) + """ +pcall(driver_poll) +""" + _bat_charging(650) + """ +pcall(driver_poll) +""" + _bat_charging(100) + """ +pcall(driver_poll) +print("MARK done") +""") + assert setpoint(out) == -700 # 1200 decays one step, no reset + + +def test_pending_with_uptake_never_times_out(): + out = drive(NIGHT + """ +host._modbus_registers.holding[46018] = {0, 0} +driver_command("battery", 2000) +""" + _bat_charging(210) + PATIENCE_CYCLES) + assert out["RC_ENABLE"] == "1" # charging = success in progress diff --git a/index.yaml b/index.yaml index f75147a..e187a9f 100644 --- a/index.yaml +++ b/index.yaml @@ -259,14 +259,14 @@ drivers: size_bytes: 11190 sha256: "c5b0ed1bb867b93861406740832a329454195f90f580d8f032b7777b54959996" - name: "foxess_h3_smart" - version: "0.9.4" + version: "0.9.5" tier: community protocol: modbus connectivity: local ders: [pv, battery, meter] control: true - size_bytes: 38826 - sha256: "a5bb5ef96b09bd85847aadf38be1914119819ba01ebe2dcfd79441bdbba59855" + size_bytes: 41341 + sha256: "8d2775354a1716dee9b03aedef0b8415bafa94e60271e2eced24cecde03964aa" - name: "fronius" version: "2.1.1" tier: core diff --git a/manifests/foxess_h3_smart.yaml b/manifests/foxess_h3_smart.yaml index 0f6b7cd..b3aa4ff 100644 --- a/manifests/foxess_h3_smart.yaml +++ b/manifests/foxess_h3_smart.yaml @@ -1,5 +1,5 @@ name: "foxess_h3_smart" -version: "0.9.4" +version: "0.9.5" tier: community author: "Sourceful Labs AB" protocol: modbus @@ -27,9 +27,9 @@ upstream_docs: kind: register_map url_stability: stable min_host_version: "1.5.0" -size_bytes: 38826 +size_bytes: 41341 dkb_id: "" -sha256: "a5bb5ef96b09bd85847aadf38be1914119819ba01ebe2dcfd79441bdbba59855" +sha256: "8d2775354a1716dee9b03aedef0b8415bafa94e60271e2eced24cecde03964aa" signature: "" bytecode_sha256: "" bytecode_signature: "" diff --git a/packages/v1/foxess_h3_smart/package-source.json b/packages/v1/foxess_h3_smart/package-source.json index cecfa06..848354e 100644 --- a/packages/v1/foxess_h3_smart/package-source.json +++ b/packages/v1/foxess_h3_smart/package-source.json @@ -1,7 +1,7 @@ { "schema_version": "sourceful.driver-package-source/v1", "package_id": "com.sourceful.driver.foxess-h3-smart", - "version": "0.9.4", + "version": "0.9.5", "channel": "beta", "display_name": "FoxESS H3-Smart / 1K5", "identity": { diff --git a/support-status.json b/support-status.json index 7806824..39e8c21 100644 --- a/support-status.json +++ b/support-status.json @@ -786,12 +786,12 @@ }, { "catalog_source": true, - "catalog_version": "0.9.4", + "catalog_version": "0.9.5", "driver_id": "foxess_h3_smart", "package_id": "com.sourceful.driver.foxess-h3-smart", "targets": { "blixt-l1": { - "candidate_package_version": "0.9.4", + "candidate_package_version": "0.9.5", "control_enabled": true, "hil": "not_recorded", "historical_signed_beta_version": null, @@ -801,7 +801,7 @@ "target_conformance": "not_assessed" }, "ftw-core": { - "candidate_package_version": "0.9.4", + "candidate_package_version": "0.9.5", "control_enabled": true, "hil": "not_recorded", "historical_signed_beta_version": null,