Download:
- solveforce_phone_one.py — Download
- SHA‑256:
2a3c1913de43ed678ada29e44df29e33fdeb6dc82efd9ef86efe056017117fd1
What changed (precisely)
- New flags
--export
Enables JSONL export (ClickHouse‑ready JSONEachRow).--export-dir <path>
Directory to write JSONL files. Defaults toexports.
Tip (Termux): use your SD card for easy access, e.g./sdcard/solveforce/exports.
- When it writes
- On every plugin read—whether triggered by the poller or by a manual
/readrequest. - File per plugin:
<export-dir>/<plugin>.jsonl. - Row shape (one JSON object per line):
{"plugin":"battery","_ts":"2025-08-19T05:55:00.123Z","data":{...}}
- Safety
- Exports are best-effort and never crash the server.
- If the path is invalid, runtime continues; you’ll see the status in
/health.
Quick start on Android
Termux
# Optional: storage + Termux:API for battery reads
termux-setup-storage
pkg install -y python termux-api
# Run (local only)
python solveforce_phone_one.py --host 127.0.0.1 --port 8080 --poll 0
# Run with exports to SD card + poll every 5s, visible on LAN
python solveforce_phone_one.py --host 0.0.0.0 --port 8080 --poll 5 --export --export-dir /sdcard/solveforce/exports
Open on the phone: http://127.0.0.1:8080/ui
From another device on Wi‑Fi: http://PHONE_IP:8080/ui
Verify it’s exporting
- Hit
/health— you’ll see:
{
"status":"ok",
"export":{"enabled": true, "dir": "/sdcard/solveforce/exports"},
...
}
- Trigger some reads:
/read?plugin=all(exports rows forbatteryandnet)- Or let the poller run (
--poll 5) and check the folder:/sdcard/solveforce/exports/battery.jsonl/sdcard/solveforce/exports/net.jsonl
- Tail a file (Termux):
tail -f /sdcard/solveforce/exports/battery.jsonl
ClickHouse ingestion (when you’re ready)
Example tables:
CREATE TABLE gw_battery
(
plugin String,
_ts DateTime64(3, 'UTC'),
data JSON
)
ENGINE = MergeTree
ORDER BY _ts;
CREATE TABLE gw_net
(
plugin String,
_ts DateTime64(3, 'UTC'),
data JSON
)
ENGINE = MergeTree
ORDER BY _ts;
Load:
INSERT INTO gw_battery FORMAT JSONEachRow
-- paste the contents of battery.jsonl here;
INSERT INTO gw_net FORMAT JSONEachRow
-- paste the contents of net.jsonl here;
Notes & next toggles (coming steps if you want them)
- Step 2 — plugin scaffolder & auto‑loader:
plugins/directory on the phone;/admin/refreshto discover new plugins. - Step 3 — richer metrics: per‑plugin read counters, last_ok timestamps, and
/events(SSE) for a live dashboard. - Step 4 — network/grid readers: SNMP/NETCONF/gNMI/OpenADR/IEC‑61850/DNP3; still read‑only.
Say “Step two” and I’ll add the plugin scaffolder and dynamic loader immediately.