Wrapper
This commit is contained in:
@@ -10,38 +10,69 @@ PyAware seems to already decode Serial Data. Look at porting that to portable C
|
||||
* Parse Serial Data
|
||||
* A simple C parser, portable to allow parsing
|
||||
|
||||
This repo now contains a **portable C parser** for the SP PRO serial protocol, ported
|
||||
from [neerolyte/selpi](https://github.com/neerolyte/selpi) (PyAware itself is not open
|
||||
source). Full protocol notes are in [docs/PROTOCOL.md](docs/PROTOCOL.md) and the ESP32
|
||||
This repo is a **portable C parser** for the SP PRO serial protocol (ported from
|
||||
[neerolyte/selpi](https://github.com/neerolyte/selpi) — PyAware itself is not open
|
||||
source), packaged as a **PlatformIO / Arduino library** with an optional thin C++
|
||||
wrapper. Full protocol notes are in [docs/PROTOCOL.md](docs/PROTOCOL.md) and the ESP32
|
||||
wiring in [docs/HARDWARE.md](docs/HARDWARE.md).
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
src/ sppro.h / sppro.c portable core: CRC, frame build/parse,
|
||||
src/ sppro.h / sppro.c portable C core: CRC, frame build/parse,
|
||||
md5.h / md5.c register map + scaling, MD5 login, session layer
|
||||
host/ main.c Linux serial-console dashboard (termios)
|
||||
esp32/ sppro_esp32.ino ESP32 (Arduino) example, reuses the core unchanged
|
||||
tests/ test_sppro.c host known-answer tests (no hardware)
|
||||
Sppro.h optional header-only C++/Arduino wrapper (any Stream)
|
||||
examples/ Esp32SerialMonitor/ ESP32 example (.ino + platformio.ini)
|
||||
docs/ PROTOCOL.md wire protocol, CRC, login, register map + scaling
|
||||
HARDWARE.md RS-232 pinout and MAX3232 -> ESP32 wiring
|
||||
extras/ host/main.c Linux serial-console dashboard (termios)
|
||||
tests/test_sppro.c host known-answer tests (no hardware)
|
||||
Makefile host build (test / console)
|
||||
library.json, library.properties, keywords.txt PlatformIO + Arduino manifests
|
||||
```
|
||||
|
||||
The core (`src/`) is C99, **no dynamic allocation and no I/O** — it builds/parses byte
|
||||
buffers and converts raw words to units. I/O is supplied by the caller through a small
|
||||
`sppro_transport_t` read/write callback, so the same code runs on a host or an MCU.
|
||||
The core (`src/sppro.*`) is C99, **no dynamic allocation and no I/O** — it builds/parses
|
||||
byte buffers and converts raw words to units. I/O is supplied by the caller through a
|
||||
small `sppro_transport_t` read/write callback, so the same code runs on a host, an MCU,
|
||||
or anything with a serial port. Only `src/` and `examples/` are part of the published
|
||||
library; `extras/` is development tooling (Arduino ignores it).
|
||||
|
||||
## Build & test
|
||||
## Use on Arduino / ESP32 (PlatformIO or Arduino IDE)
|
||||
|
||||
Add the library (`lib_deps = SPPro` in PlatformIO once published, or *Sketch → Include
|
||||
Library* in the Arduino IDE), then use the `Sppro` wrapper, which works over **any**
|
||||
Arduino `Stream` (HardwareSerial, SoftwareSerial, WiFiClient, …):
|
||||
|
||||
```cpp
|
||||
#include <Sppro.h>
|
||||
Sppro sp(Serial2); // wraps any Stream
|
||||
|
||||
void setup() {
|
||||
Serial2.begin(57600, SERIAL_8N1, 16, 17); // via a MAX3232 level shifter
|
||||
sp.login(""); // "" = no serial password
|
||||
sp.readScales();
|
||||
}
|
||||
void loop() {
|
||||
Serial.println(sp.value("BatteryVolts")); // scaled value, or NAN on error
|
||||
delay(5000);
|
||||
}
|
||||
```
|
||||
|
||||
A complete ESP32 example is in
|
||||
[`examples/Esp32SerialMonitor/`](examples/Esp32SerialMonitor); build it standalone with
|
||||
`cd examples/Esp32SerialMonitor && pio run` (it links the parent library via
|
||||
`lib_deps = symlink://../..`). See [docs/HARDWARE.md](docs/HARDWARE.md) — the SP PRO port
|
||||
is RS-232 (±12 V) and **needs a MAX3232 level shifter**; never wire it straight to a GPIO.
|
||||
|
||||
## Build & test on a host (no hardware)
|
||||
|
||||
```sh
|
||||
make test # build and run the host unit tests (no hardware needed)
|
||||
cd extras
|
||||
make test # build and run the host unit tests
|
||||
make host # build ./build/sppro-console
|
||||
```
|
||||
|
||||
## Run against a real SP PRO
|
||||
|
||||
Wire it up per [docs/HARDWARE.md](docs/HARDWARE.md) (RS-232, **needs a MAX3232 level
|
||||
shifter**, 57600 8N1), then:
|
||||
Then, with a real SP PRO + USB-RS232 adapter:
|
||||
|
||||
```sh
|
||||
./build/sppro-console /dev/ttyUSB0 [serial_password] [interval_seconds]
|
||||
@@ -52,7 +83,7 @@ voltage, state of charge, load/solar/generator power, and energy totals. The ser
|
||||
password is set on the inverter (front panel → Settings → Communications); pass `""` if
|
||||
none is configured, or set `SPPRO_PASSWORD`.
|
||||
|
||||
## Using the core in another project
|
||||
## Use the pure C core (non-Arduino: ESP-IDF, STM32, Linux, Zephyr …)
|
||||
|
||||
```c
|
||||
#include "sppro.h"
|
||||
@@ -68,15 +99,21 @@ sppro_session_read(&t, sppro_reg_by_name("BattSocPercent"), &scales, &soc);
|
||||
sppro_session_read(&t, sppro_reg_by_name("BatteryVolts"), &scales, &vbat);
|
||||
```
|
||||
|
||||
For environments with their own protocol loop, the pure helpers (`sppro_build_query`,
|
||||
`extras/host/main.c` is a full worked example of the two callbacks (termios). For
|
||||
environments with their own protocol loop, the pure helpers (`sppro_build_query`,
|
||||
`sppro_parse_query_response`, `sppro_decode`, `sppro_crc16`, `sppro_login_response`) can
|
||||
be used without the session/transport layer.
|
||||
|
||||
## Status & caveats
|
||||
|
||||
- Verified by host unit tests: CRC against selpi's documented `0xa000` frame, MD5
|
||||
known-answers, frame round-trips, and the scaling formulas. **Not yet verified against
|
||||
physical hardware** — confirm decoded values against the inverter's own display.
|
||||
- Verified by host unit tests (`cd extras && make test`): CRC against selpi's documented
|
||||
`0xa000` frame, MD5 known-answers, frame round-trips, and the scaling formulas. The
|
||||
ESP32 example + C++ wrapper are verified to compile/link via PlatformIO. **Not yet
|
||||
verified against physical hardware** — confirm decoded values against the inverter's own
|
||||
display.
|
||||
- On 8-bit AVR, `double` is 32-bit float, so very large `Wh` accumulators lose some
|
||||
precision (fine for display). Use the 32-bit-int register types directly if you need
|
||||
exact counts.
|
||||
- Read-only monitoring is the focus. Write framing (`sppro_build_write` /
|
||||
`sppro_session_write`) exists because login needs it, but no inverter-setting writes
|
||||
are wired into the demos.
|
||||
|
||||
Reference in New Issue
Block a user