Firmware Changelog¶
Every firmware version that has been released to regulators in the field, newest first. Each entry summarizes what changed since the previous release; open Full detail for the specifics.
Your regulator updates itself over WiFi — new versions appear in the app under Setup → System → Software Updates. If you would rather update over a USB cable, or need to recover a unit, see Reset Firmware over USB.
0.0.4¶
Released September 5, 2026. Changes since 0.0.3.
The regulator can now work from a real battery temperature instead of judging the battery by how warm its own circuit board is. That reading comes either from a second temperature probe wired alongside the alternator one, or from a battery monitor already on the boat's network, and it drives both the cold-weather charging cutoff and a new hot-battery cutoff. Overvoltage protection adds two timed cuts for voltage that stays high rather than merely spiking, and field drive can now be limited in volts taken straight from the alternator's data sheet instead of only as a percentage. On the dashboard, tapping any of the main readings tells you what is holding charging back and where that limit is set; the solar forecast now checks itself each day against what the panels actually produced; and the phone app runs on Android as well as iPhone.
Full detail
Charging and control¶
- Field drive can be capped in volts as well as percent: a new Max Field Volts setting (
MaxFieldVolts) is solved against the measured bus every control tick, and whichever of it and Max Field % binds first is enforced. - A read-only Field Ceiling readout shows the ceiling actually in force (
ccDutyCeiling()), which now flows through the governor, the per-speed floors, the field-curve sweep and the raw duty writer instead of each reading Max Field % on its own. - A per-speed keep-alive floor that would sit above the field ceiling is conceded down to it, so the duty the regulator believes it applied matches what the hardware applies.
- The voltage-loop gain derate for battery temperature now follows the selected battery-temperature source rather than the board sensor, and holds itself inert (
cvTempDerateInert) if the source class changed since the gains were fitted. - Voltage Control Autotuning gained a return-to-base step (REBASE) so the two field levels it replays are learned one settle apart; it also reports engine-speed drift during setup and during the pulse train, replacing the old fixed 8% RPM abort.
- The autotune probe step and its overvoltage cushions are now scaled by system voltage class, which previously left a 48 V bank with a quarter of the warning margin per cell.
- The oscillation damper's detection bar is now a setting (
HuntTrigPct) instead of a fixed 0.5% duty swing; the relaxed bar for voltage-damper-driven wobble tracks it proportionally. - A live edit of the PID tracking gain now takes effect immediately instead of waiting for the next entry into automatic mode.
- "Min% floor" is renamed tachometer keep-alive throughout the interface, console messages and the commissioning stage name ("Keep-Alive Floor & Field Decay").
- Commissioning's hold on the limiter toggles, the wind-down governor and the maintenance-reboot ladder is now keyed on the wizard dialog actually being open, not on the stored in-progress byte, so a run stopped for days no longer freezes them.
Protection¶
- Two timed overvoltage cuts (low and mid tier) cut the field when the filtered bus stays continuously above target by a set margin for a set dwell; any dip below the line resets that tier's timer. Each tier has its own margin and dwell, and a dwell of 0 disables it.
- The timed tiers share the adaptive fast-overvoltage lockout ladder, so a persistent cause escalates whichever rung catches it. They add session and lifetime counters, new field-off reasons and new entries in the overvoltage telemetry.
- The overvoltage ladder is now explicit:
VoltageHardwareLimit(the shunt monitor's alert comparator) is a persisted user setting rather than a derived value, and the software instant cut (AlternatorHardShutdownV) is clamped to sit strictly below it — on write, on import and at boot, which repairs the inverted pair an upgrading device would otherwise boot with. - A system-voltage class change now rescales both absolute rungs and both timed-tier margins by the same ratio instead of re-deriving a conservative fallback.
- New hot-charge lockout (
hotChargeLockoutEnable,MaxChargeTempF): charging ramps to zero and cuts above a battery-temperature ceiling, with its own hysteresis and alarm. It acts only on a measured battery temperature, never on the board stand-in. - The cold-charge lockout now reads the battery-temperature source chain rather than the board sensor, and its console message names the source in use.
- Load-dump detection tiers gained user-set consecutive-sample counts (
LoadDumpN1/N2/N3), clamped at boot so an imported zero cannot latch the detector permanently. - Hard over-current debounce default raised from 20 ms to 40 ms; devices already provisioned keep their stored value.
- A BMS on/off signal withholding permission now reports its own off reason instead of the generic "charging disabled".
- The Protections page is regrouped by subject, with a single Over-Voltage Ladder card holding both timed tiers and both absolute rungs in the order they engage.
Sensors and inputs¶
- The temperature bus is now multi-drop: up to six probes are enumerated and bound to roles (alternator, battery, extra) by their stored serial number, never by bus position. Roles are assigned in a new Setup > Temperature page with a Scan button and live per-probe readings.
- A battery-temperature source chain (
batteryTempF()) picks, in order, the battery probe, a NMEA 2000 battery status message, VE.Direct, RV-C, and — only if you opt in — the regulator board temperature. The source can also be pinned manually or set to none. - New extra temperature probe with its own high and low alarms, a live readout, and optional publication on the boat network.
- VE.Direct battery temperature (the "T" field on a shunt fitted with a sensor) is now decoded and staleness-tracked.
- The temperature task issues one bus-wide conversion per cycle and reads every probe from it, forces an immediate read when the engine starts, and re-searches the bus after three consecutive misses on a bound role.
- The BMS on/off opto input is read on GPIO42, every tick regardless of whether the feature is enabled, and its raw state is published so wiring can be verified before the wire is given any authority.
- Motion-sensor freshness is stamped when a sample actually lands rather than when a poll is attempted; a live attitude readout was added and "Level Zero" is now "Zero Now".
- WiFi rejoin scans are now active with hidden networks shown, so a hidden network can actually be matched and rejoined.
- Average engine speed in uploaded sensor windows was being divided by 100 while the window minimum and maximum were not; it is now reported on the same scale.
NMEA 2000 and other networks¶
- RV-C transmit: the regulator can publish itself as an RV-C charging source — Charger Status 1/2/3, Charger Configuration Status, DC Source Status 1/2/3 and the DM_RV diagnostic message — with settable charger instance, DC source instance and device priority. It shares the claimed address with the existing NMEA 2000 node.
- The RV-C fault message maps the regulator's own cut reasons onto RV-C service points, red for a cut that stopped charging and yellow for an advisory.
- NMEA 2000 charger configuration (PGN 127510) is now transmitted, which is where field drive percentage reaches the bus, and charger mode (Standalone, Primary, Secondary) is selectable and published by both charger messages.
- Battery temperature is published in the battery status message when the battery probe is live, and the extra probe can be published as its own temperature instance.
- Charge-limit follow builds a passive roster of bus nodes from address claims and product information, so a capture records who published the limits. That identity also rides the live telemetry.
- Charge-limit decoding corrections: the register a Victron gateway actually broadcasts for voltage control is confirmed, its "not available" value is now treated as a withdrawal of the limit rather than an unrecognised frame, and the allowed-to-charge bits in the BMS I/O register are decoded per Victron's own published decoder.
- A header banner appears when charge-limit follow is switched on but nothing is arriving, the sender has gone silent, or the limits were rejected as implausible — with a grace period so a gateway rebooting does not raise it.
- The charge-limit capture download now begins with a header: firmware version, dialect, follow state, the authority's address, the node roster, and the battery recorded in Vessel Info.
- RV-C battery temperature from DC Source Status 2 is decoded and feeds the battery-temperature chain.
Cloud and updates¶
- An update now asks the background temperature and cloud tasks to retire themselves and waits, instead of deleting a task that may be inside a network call; the update is abandoned if the cloud task will not leave.
- A supervisor recreates those tasks after an attempt, retries every two seconds, and raises a console alarm plus a maintenance reboot if memory will not allow it.
- A wedge timer releases a stuck update flag after 40 minutes, which was previously silencing the console, the temperature-task health alarm and the reboot ladder all at once.
- The alternate firmware slot is promoted at a fallback boot only when it holds exactly the image a completed, signature-verified install recorded. A failed install erases the slot header and drops the record.
- The web file partition is wiped before the first asset of an update is written, so a renamed asset cannot leave its predecessor behind.
- The signature fetch is bounded: 12-second connect, handshake and read budgets, a length check, and a stall guard on the body read.
- Internet time sync now waits for a real time packet rather than accepting the restored clock as proof, which previously stamped uploads with a days-old time and blocked the phone from correcting it.
- Long-term history pulled from the cloud no longer stops at one year; it steps over up to six empty months before concluding there is nothing older.
- After the last commissioning step, a device that can reach the cloud and is not yet registered is offered registration, with what registration provides spelled out.
- The USB port answers the browser installer's handshake with the running firmware name, version and serial, and accepts WiFi credentials from it.
Dashboard and app¶
- New limit panel: tapping any header reading, the field percentage, or the PROTECTION / BATT > TARGET / BMS LIMIT words opens a box naming the one thing holding charging back, the number it is held against, and where that number is set.
- Battery temperature appears in the header and on Live Data > Battery, with the source it came from and its own staleness greying.
- New Setup > Temperature page for probe identification and role assignment; a new Setup > Battery > Battery Temperature card holds the source chain and both charge-temperature lockouts.
- New solar ledger on Live Data > Weather: today's predicted and actual harvest and consumption, the learned performance ratio, complete days on record, and a predicted-versus-actual chart over 30 or 90 days.
- Defer to Solar now closes the loop — each complete day's actual-versus-forecast harvest nudges the performance ratio (
solarLearnEnable), and the bar a day must clear can be sized from predicted consumption plus a margin instead of a fixed threshold (solarUseConsEnable). - The phone app runs on Android: hardware and gesture Back is handled through the open dialogs, app traffic is pinned to the joined WiFi network so a network with no internet still reaches the regulator, and the regulator's name is resolved natively.
- The iOS app can join the regulator's own hotspot from inside the app rather than sending you to system settings.
- Position source and time source are now separate settings, so the phone can set the clock without sharing where the boat is. Location permission is requested in context, only when a feature that needs it is switched on.
- A dialog now explains the blank gauges and dead settings that follow an interface/firmware version mismatch, and offers to reload or re-sync.
- The alternator session percentage plot is recovered from the device after a page reload or a WiFi drop, instead of starting empty.
- The app opens on Live Data > Diag so Charging System Health is the first thing seen.
- Settings whose feature is switched off or whose hardware is absent are now greyed with a note naming the switch that enables them, instead of being hidden; readouts that could only show a dash are still hidden, with one explanatory note per panel.
- Commissioning: a new "Stop for now" keeps every finished step and discards only the step in progress; Abort now restores the exact pre-run state, so a device that was commissioned before a targeted redo ends up commissioned again.
- Commissioning also gained a "Before You Start" screen, a wait box between the setup screens that would otherwise look finished, and an advisory on phone-sized screens suggesting a laptop for first-time setup.
- Fuel volume units (US gallons or litres) are selectable and applied to the fuel table, live burn, economy and totals. Dark mode, dashboard update rate and fast-channel plot sampling moved into Display Preferences.
- Access-point mode answers each operating system's connectivity probe in the form it expects, so no captive sign-in sheet pops up, and the access point can be raised again after engine-off standby instead of staying down until a reboot.
- The interface is titled Xregulator.
Internal¶
- Every telemetry channel now carries a boot identifier and the time it was built, so a cached block left over from a previous boot or a rejected channel can be detected. The diagnostics snapshot carries a per-channel freshness verdict.
- New gate-tuning capture for alternator-health work: a 10 Hz session logger into 192 KB of PSRAM downloaded as a binary and decoded in the browser, plus a field sweeper that ramps duty up and back down under the same override path the field curve uses, with settable rate, span and turnaround margins.
- Config import: a system-voltage class in the payload is applied before the rest, so a class-only push converts the charge profile and trips instead of leaving them at the old class; renamed parameters are matched through an alias table; an import that starts while the field is driving is noted on the console.
- The accelerometer driver was replaced with a fork whose I2C transport reports bus failures — the stock one always returned success, making every error check vacuous.
- Alternator-health gate blame counters no longer split idle from cruise, and the steady-state engine-speed band was tightened from 30 to 20 RPM on open-loop sensitivity measurements.
- Charge cycles are now uploaded with fractional precision.
- New device endpoints:
/tempSensors,/altsess.csv,/solarledger.csv,/altlog.bin.
0.0.3¶
Released August 21, 2026. Changes since 0.0.2.
This release connects the regulator to the rest of the boat's electronics. It can now broadcast its own battery, alternator, charger and temperature readings onto the NMEA 2000 network so a chartplotter or instrument display can show them and alarm on them, read a second instrument feed through the separate NMEA 0183 input, and — where a managed battery or its management system publishes charge limits on that network — hold its charge voltage and current below what the battery is asking for, with every built-in protection still in charge.
Automatic maintenance restarts are no longer on a fixed twelve-hour clock. The regulator now waits for a genuinely quiet moment with the engine off and nobody connected, gives a ten-minute warning if someone is watching, and only forces a restart after three days of continuous running.
Also here: 36-volt banks are supported, the Celsius preference now covers every temperature the regulator shows or asks for, and the settings pages have been reorganized so everything the regulator talks to lives on one Integrations page.
Full detail
Charging and control¶
- 36-volt banks are now a supported system voltage class alongside 12, 24 and 48 V (
SYSTEM_VOLTAGE_CLASS, renamed fromBATTERY_VOLTAGE). Every class-scaled quantity — charge profile, protection margins, control-loop gains, field-duty ceiling, resting-voltage table, plausibility windows — scales for it. - The critical voltage-disagreement threshold is now derived from the system voltage class instead of banding on bulk voltage, which mis-bucketed a 36 V bank into the 48 V band.
- The oscillation damper (hunt governor) was rebuilt around a persistent engine-speed map. It makes one test cut to
HuntCutPctof your integral gain, keeps it only if measured ripple drops by at leastHuntVerifyPct, and then applies that reduction proactively whenever the engine returns to that speed, tapering back to full gain acrossHuntWingPctof speed either side. - The damper gained a second lever: a wobble that keeps the voltage loop's derivative term (D-term) alternating direction is tested by pausing the D-term instead of cutting gain. A verified result switches the D-term off at that speed only; it is never reduced partway.
- The damper is now opt-in (
HuntGovEnabledefaults off on new units; units with a stored value keep it). New settings:HuntCutPct,HuntVerifyPct,HuntWingPct,HuntCooldownMin,HuntSteadyPct,HuntQualifyScans. The learned map clears on a voltage-class change, an engine-speed recalibration, an alternator health reset, or from the dashboard. - Discharge counting was inverted in the Peukert correction: heavier-than-rated discharge was counting slower instead of faster. Now
dischargeCurrent_A / PeukertRatedCurrent_A. - Automatic shunt gain correction now reads an unsaturated shadow coulomb count (
shadowCoulombX100), so over-reading is visible as well as under-reading — the live counter's clamp at full capacity hid one direction of drift entirely. - Alternator statistics and voltage averaging in
UpdateBatterySOCnow run without a battery shunt; only the battery-side sections (coulomb count, state of charge, capacity tracker, full-charge detection) are gated on one. - Field duty is hard-capped at 99% in
setDutyPercent, so the high-side gate driver's bootstrap always gets a refresh slice. Switching frequency is clamped to 100–19455 Hz and the timer clock source is forced to APB, so the top of that range actually attaches at boot. The 400 Hz default is unchanged. - Commissioning's between-step rest hold now re-asserts the field enable line, so the tachometer pickup keeps its keep-alive load through a rest resumed after a cut.
- Manual field mode is exempt from the engine-stopped immediate cut, which previously fought the manual path at loop rate.
- Post-protection recovery hands off bumplessly: integrator state is capped to the flared ceiling at release, so a banked reserve no longer steps the setpoint on exit. The stress test's pinned target gets the same bumpless seed and keeps the down-glide pacing floor.
- The learned minimum-field floor table forces its top bin to zero when the ceiling anchor lands at or above the last speed breakpoint — the table holds its last bin flat forever above that point, so a non-zero floor would have ridden to unlimited overspeed.
- Knee learning no longer trains during a CV plant fit, and the plant fit's setup phases bypass the learned floor so all three phases can reach distinct currents.
- "Defer to Solar" (weather mode) now reports itself as its own field-off reason instead of reading as a plain disable, and the flag is set last so the banner never blames the forecast when the key, the on/off switch, the battery management input or a full battery is the real cause.
- A forecast that can no longer be refreshed releases the solar pause after the refresh interval plus a 30-minute grace, and the analysis runs in every mode — previously an access-point boot or a run of failed fetches could latch the alternator off with nothing left to re-evaluate it. The fetch also honors
WeatherUpdateIntervalinstead of a hardcoded hour, and the on-demand "Update Weather Now" button no longer requires the field to be off.
Protection¶
- Every flash write on the control task is now gated on the hardware field-cut signal (
fieldCutSettled) rather than commanded duty. The old duty-based gate read "off" during a live zero-duty voltage hold, letting flash commits land on live control passes. The two staggered field-off flushes moved to +20 s and +28 s, twice the fast-overvoltage lockout ceiling, so cut-and-retry churn can never reach a flash write. - A staged firmware install now waits for the field to be de-energized before it starts. The install blocks the control task for the whole download and flash, which would freeze the field at its last commanded duty with software protections dead.
- A protection cut during the closed-loop sine sweep now latches an abort, stops the sweep and discards the results, and reports the real cause. Points spanning the cut and lockout measured the outage, not the plant, and were being graded as field saturation.
- The low-temperature alarm no longer fires on the thermistor's disconnected sentinel value, and that sentinel is no longer converted from Celsius into a plausible-looking Fahrenheit reading that passed every downstream check.
- The garbage-reject ceilings on both voltage inputs now scale with the system voltage class instead of a fixed 70 V, which rejected legitimate readings on 48 V banks.
- "Time since last overheat" stays pinned at zero until an overheat has actually been recorded.
- The engine-dynamic warning bits sent on the network cover a hard over-temperature cut and protective field cuts, deliberately never a normal thermal derate.
Dashboard and app¶
- New Integrations settings page, with one collapsible card per external system: NMEA 2000, NMEA 0183, Victron VE.Direct, Victron CAN (DVCC), RV-C, and the shared Charge-Limit Follow card. A matching Live Data → Integrations tab shows what each one is actually receiving.
- New Engine settings page holding tachometer scaling (
RPMScalingFactor) and pulley ratio. - Commissioning is now the first Alternator tab rather than a sub-tab of Tuning.
- The Celsius/Fahrenheit preference now covers console and alarm messages, settings input fields and their limits, and plot axes — not just readouts.
- New ESP32-tab rows: free data storage, age of the last acknowledged cloud upload, and a device clock converted into the viewing device's time zone with a skew note when the two disagree by more than half a minute. The tab is now split into collapsible sections (System Overview, Sensor Health, Timing & Diagnostics, App Usage, About).
- New Oscillation Damper panel under Live Data → Diag: live state, current-loop gain as a share of your setting, D-term state, a plot of the learned speed map, the episode record, and a Clear System button.
- Charging system health is now graded on the same sustained multi-second average the record book stores, on both sides of the comparison, so a momentary dip can no longer read as lost health. The trend's lower line is each hour's low-10% mark rather than that hour's single worst sample.
- A "BMS LIMIT" chip appears in the stage banner when a followed charge limit is the binding constraint (limiter codes 8 and 9).
- A one-time explainer describes the maintenance-restart tiers during first setup, and the ten-minute restart warning popup was rewritten to say what actually happens.
- The WiFi setup page gained a "Forget saved ship's WiFi" checkbox, and a blank SSID field no longer silently wipes working credentials.
- The Solar page was rewritten in plain English: where the position comes from, where the forecast comes from and what leaves the boat, when it refreshes, a forecast-age line under the table, and an access-point-mode note explaining that only the forecast needs internet.
- Selecting phone GPS as the speed source now shows what it costs before it applies: battery drain, foreground-only behavior without the native background plugin, and exclusion from the cloud speed leaderboard.
- The battery-defaults proposal gained tiered notices — a warning about charging lithium below freezing, and plain statements of where the regulator does not yet compensate for temperature.
- Settings search moved from a tab to a bare icon in the tab-row gutter. Card grids now pack like masonry instead of stretching every card to the tallest in its row, and tooltip boxes are repositioned to stay on screen.
- All five static assets now revalidate as a matched set, so a browser can no longer pair a cached hour-old stylesheet with just-updated markup.
- iOS focus-zoom handling was reworked: label taps, keyboard next-field arrows and programmatic focus no longer leave the page stuck zoomed.
Sensors and inputs¶
- NMEA 0183 receive on its own protected serial input, independent of VE.Direct. Selectable speed (4800/9600/19200/38400) and signal polarity, checksum-validated sentence and error counters, and heading decoding from HDT/THS/HDG/HDM. The drain is held to a hard 500 µs per pass by four independent limits and reports itself to the console if it ever exceeds that.
- Victron VE.Direct is more robust: a larger receive buffer, a per-tick drain budget raised from 256 to 2048 bytes, and — importantly — values are only read when a new checksum-valid frame actually lands. Previously any arriving bytes marked the data fresh, which kept stale values alive and integrated phantom solar power.
- A missing or failed BMP388 barometer no longer hangs the boot in an infinite loop; it retries once, warns, and marks itself disconnected (
BMP388Disconnected). Its sample cycle dropped from 8 s to 4 s so a single missed read stays inside the 10 s staleness window. - The DS18B20 temperature sensor's address is now filled in before its resolution is set (previously a no-op on a zeroed address), and a failed read is retried in place before it counts as a miss.
- Maximum speed, session and lifetime, is now the best 60-second average (
sogSust1m) rather than a single-sample peak, integrated time-weighted with a gap rule so a dropout cannot manufacture a record. The reset button is relabeled "Sustained Speed". - Phone GPS is selectable as the speed and course source (
speedSourceMode) — a deliberate choice, never an automatic fallback. In that mode the app posts fixes every ~2 s, and records set that way are flagged in cloud uploads. - True wind angle now converts heading into the wind reading's reference frame using the variation the heading message carries, instead of subtracting a magnetic heading from a true-north wind direction.
- Fuel economy and the fuel-economy curve now check speed-over-ground freshness; a frozen speed after GPS loss was keeping economy looking live and freezing curve bins with it.
- With no battery shunt fitted, battery current, its rate of change, state of charge and the battery-current watermark now report as unavailable everywhere — dashboard, downloadable logs and cloud uploads — instead of publishing the current input's noise as a measurement.
NMEA 2000 and other networks¶
- Transmit (producer) mode, off by default (
n2kTxEnable). The regulator claims an address and publishes, with per-message switches and instance numbers: battery status and DC detailed status (127508 + 127506), the alternator as its own DC instance, alternator temperature (130312), charger status with charge stage (127507), engine speed (127488), engine dynamic parameters with warning bits (127489), and battery configuration (127513). One message per loop pass, on a rotating scan, so transmit cost never stacks inside a control tick. - Missing sources publish the standard not-available encoding rather than a stale or invented number; alternator temperature is skipped entirely while the sensor is dead, so the display's own data-lost alarm owns that case. A charge-stage change transmits promptly instead of waiting out its interval.
- Receive of battery status and DC detailed status from a chosen instance (
n2kRxBattInstance) — voltage, current, temperature, state of charge and state of health from a shunt, battery monitor or a managed battery's gateway. Display and telemetry only; charge control always runs on the regulator's own sensors. - Charge-limit follow (DVCC-style), off by default (
dvccEn), reading charge voltage and current limits from either Victron VE.Can proprietary registers or RV-C DC source messages. A decoded limit is a clamp-only request: it can lower the regulator's voltage target or current ceiling, never raise anything, and every local protection outranks it. - The follower vets its authority before obeying it: values must stay inside a plausibility window (
dvccCvlMin/dvccCvlMax), arrive steadily fordvccSettleS, and not flap. An implausible or flapping value latches UNTRUSTED and hands control back to local targets until manually reset. Silence fordvccSilenceSreverts the clamps. - A current limit of zero is obeyed as "stop charging". While a followed voltage limit is holding the bus below the absorption target, the absorption stage's overall time ceiling pauses with it, so a long clamp cannot force the bank out of absorption half-charged.
- A raw frame capture (paused-and-snapshotted so lines can never tear) exposes the candidate CAN frames as hex text, for validating the decode against real equipment before enabling follow.
- The NMEA 2000 driver is now a fork whose transmit never blocks; the stock driver waited up to 100 ms per frame on a full queue with no bus attached. Transmit accepted and dropped counts, the claimed address, and timing for parse, transmit and the follow tick are all published.
- Console output from the receive handlers is now gated behind the verbose switch — battery configuration, attitude, boat speed and DC status were printing unconditionally at bus rate.
Cloud and updates¶
- Registration, profile update and account deletion moved off the web-server task onto the background worker, with the dashboard polling for the result. A dead uplink used to starve every other endpoint for up to ~45 seconds.
- A periodic six-hour re-check re-reports the firmware version and re-reads the forced-update flag. With uptimes now reaching 24–72 hours, a staged update sat dormant until the next reboot and a cancelled one left the notice stuck on screen.
- Remote configuration pushes are now visible to the owner: a notice when one is queued (with the administrator's description and a restart-now option), and a receipt after one lands listing exactly which settings it changed.
- Update robustness: a web-file open, write or size mismatch now fails the whole update rather than shipping a corrupt bundle behind a valid signature; an oversize firmware image is rejected before the stream starts; the running application remounts the factory filesystem after a failed update instead of losing it until the next power cycle; and the recovery jumper now clears staged-update flags from the namespace they actually live in.
- Learned-surface sync-back responses are de-chunked and checked for completeness. A truncated body parses cleanly and would otherwise have wholesale-replaced the learned reference surface.
- Uploads gained sustained-speed maximum and a phone-source flag; battery current and state of charge upload as null when no shunt was present for the window, rather than as zero.
- App usage counting: page opens, visible dwell time and button presses are counted on the regulator and uploaded once per local calendar day when it is registered and online. Counts survive a maintenance restart and are shown under Live Data → ESP32 → App Usage.
Internal¶
- Maintenance restarts run a three-tier ladder in
checkAndRestart: at 24 hours only in a fully quiet window held five minutes (engine and field off, no connected client, cloud queue drained, state of charge and battery voltage above their floors); at 48 hours without the client and state-of-charge preferences, with a ten-minute countdown if someone is watching; at 72 hours regardless of engine state, with brown-out voltage the only remaining hold. A restart is also requested early if the largest contiguous internal RAM block sits below 20 KB for 30 minutes straight. - Worst-pass blame capture: when a field-on loop pass sets a new session worst, the top three timed consumers of that pass are recorded and published to the diagnostics panel. Field-on-only splits were added for the loop worst, the current-sense read interval and both slow ADC read gaps, so field-off background work no longer inflates the control-relevant numbers.
- Battery health history moved from NVS strings to filesystem blobs. The NVS string cap silently truncated the capacity ring at roughly 120 points; a legacy string migrates once and is removed only after the blob write succeeds. Integer fields in the legacy format now parse as integers — routing epochs through a float was shifting every timestamp by up to a minute per reboot.
- Free data storage is refreshed event-driven: writers set a dirty flag and the roughly 100 ms filesystem traversal runs at the next heap walk with the field cut, never on a live control pass.
- Settings loaded from storage are now range-clamped on the load path, not just in the web handler — configuration import and remote pushes write storage directly and only take effect through a reboot.
- Commissioning start and cancel are serialized under a mutex; the previous lock-free double-check left an instruction-wide window where a mid-sequence cancel could be overwritten and the torn-down start marched to completion.
- Configuration export now includes runtime, lifecycle and debug state as export-only entries, and publishes the list of names import refuses so the dashboard's diff can separate device state from importable changes.
- Alternator-health emit windowing was reworked: a 2-second trailing average with a trimmed-range cleanliness test replaced a continuous-steadiness clock that one 100 ms blip could reset, which was starving the record book. Temperature dwell dropped from 80 s to 40 s, the excitation and temperature cell sizes were retuned from a sensitivity study, a case-temperature slope tag rides every record, and simulator-generated points are no longer queued for upload.
- Boat-performance pending points gained an admission policy: best-ever points always get a slot and evict ordinary ones, and ordinary points are rate-limited per conditions cell, so weeks offline cannot drop the records that matter.
- The CPU load sampler discards and re-baselines on the 71-minute microsecond counter wrap instead of latching a phantom 100% into telemetry.
- Assorted fixes: the filesystem mutex is only released by its actual holder; the background HTTPS task self-deletes instead of returning into a panic; live event payloads are truncation-guarded rather than overrunning their stack buffer; the thermal log download no longer drops its newest row; imported alternator-health files are rejected unless the header declares the right system and axis count; and
FieldAdjustmentInterval, which gated nothing, was retired along with several obsolete storage-key migrations.
0.0.2¶
Released July 30, 2026.
Pre tracking system.