Skip to content

MarkS0485/OpenMPPT

OpenMPPT

CI CodeQL Dependabot Updates Publish package License: GPL-3.0-or-later

A generic, vendor-extensible .NET library for solar charge controllers and battery devices. It owns everything between "raw bytes on a wire" and "decoded telemetry your app can render" — Modbus and Victron codecs, frame reassembly, register decode, and a clean driver interface — with no UI and no platform BLE dependency.

Build the device-talking once; consume it everywhere: desktop and mobile apps, web dashboards, chart renderers, loggers, database ingesters, headless services.

┌── your consumer (app / website / logger / service) ──┐
│   subscribes to IDeviceDriver events, renders models │
└───────────────────────┬──────────────────────────────┘
                        │  OpenMPPT (this library, net8.0)
        ┌───────────────┴───────────────┐
        │  Drivers      orchestrate      │   Modbus · Victron · Renogy · EPEver
        │  Codecs       pure bytes↔model │   · Demo. Pure, fully unit-tested.
        │  Model        MpptLive, etc.   │
        │  Abstractions IDeviceDriver,   │
        │               IFrameTransport  │
        └───────────────┬───────────────┘
                        │  IFrameTransport / IAdvertisementSource  (you implement)
┌───────────────────────┴──────────────────────────────┐
│  the radio: BLE GATT, serial / RS-485, or Modbus-TCP  │
└───────────────────────────────────────────────────────┘

The one idea

The library never touches a radio. A driver only sees a byte pipe, so the same driver works over BLE, a USB serial dongle, or a TCP socket. The host implements one tiny interface — IFrameTransport ("connect, send these bytes, here are the bytes I got") — and OpenMPPT does all the framing, CRC, reassembly, decode and poll/transaction logic. That keeps each host's transport shim small and the protocol logic in one tested place.

Hook a consumer in two lines

No-hardware demo source (works today):

await using IDeviceDriver driver = new DemoDriver();
driver.LiveChanged += live =>
    Console.WriteLine($"{live.BatteryVoltage:0.0} V  {live.ChargeCurrent:0.0} A  {live.SocEstimate:0}%");
await driver.StartAsync("demo");

A real device is identical from the consumer's side — pick a vendor from the registry, give it your IFrameTransport (or IAdvertisementSource) shim, and the same events flow:

var registry = DeviceRegistry.CreateDefault();
await using IDeviceDriver driver = registry.Create(
    "generic.modbus-mppt", new DriverContext { FrameTransport = myBleTransport });
driver.LiveChanged     += vm.OnLive;
driver.SettingsChanged += vm.OnSettings;
await driver.StartAsync(mac);

Generic consumers read driver.Capabilities to decide what to show — a read-only advertisement device simply omits WriteSettings and the UI hides its editors. No vendor-specific code.

Layout

Folder What
Abstractions/ IDeviceDriver, IFrameTransport, IAdvertisementSource, ConnectionState, DeviceCapabilities, DeviceType, RawFrame
Model/ MpptLive, MpptSettings, ChargerState, BatteryProfile, BatteryChemistry — serialization-friendly records
Codecs/Modbus/ ModbusCrc, ModbusFrame, ModbusReassembler, MpptProtocol, MpptRegisters
Codecs/Victron/ VictronDecoder (Instant Readout AES-CTR)
Drivers/ ModbusMpptDriver, ModbusProfileDriver (Renogy/EPEver), VictronDriver, DemoDriver
Devices/ DeviceRegistry, VendorDescriptor, DriverContext — the vendor catalogue

Build & test

dotnet build OpenMppt.slnx -c Debug
dotnet test  OpenMppt.slnx -c Debug      # headless, no hardware
dotnet pack  src/OpenMppt -c Release -o artifacts   # → OpenMPPT.<ver>.nupkg

Targets net8.0 so both net8 and net10 consumers can reference it; the test project runs on net10.

What's built

  • Vendor registryDeviceRegistry + VendorDescriptor + transport-aware identification; adding a vendor is one descriptor.
  • Drivers — generic Chinese Modbus MPPT (live + settings + write), Victron Instant Readout (passive), Renogy/SRNE + EPEver (profile-driven), plus the hardware-free DemoDriver.
  • 83 headless tests, CI, GitHub Packages publish, aggressive Dependabot.

Roadmap

  • More host transport examples (BLE GATT, serial/RS-485, Modbus-TCP) — transports ship with the hosts, not here (this stays platform-neutral).
  • More device categories over time (battery monitors, inverters).

License

OpenMPPT is licensed under the GNU General Public License v3.0 or later — see LICENSE.


OpenMPPT · GPL-3.0-or-later · contributions welcome — see CONTRIBUTING

About

Generic, vendor-extensible .NET library for solar charge controllers and battery devices (BLE / serial / Modbus-TCP) behind a clean, transport-agnostic device-driver interface.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages