Download the file:
- solveforce_phone_zero.py — Download
- SHA‑256:
85f09d30ab48d2d7989de5a8439f8dc1b9b1fa78773b73f0dff0a743135cc94a
1) The Philosophy (Zero → One → Many)
- Zero (this file): a single HTTP server with a simple, mobile‑friendly /ui page, a tiny plugin registry, and no background magic. Pure signal.
- One (read‑only senses): add minimal plugins (battery, IP) only if available on the phone—no failures if not.
- Many (build out): enable polling, metrics, JSON exports, then fold in network/energy adapters as separate, explicit modules. Safety by spelling.
2) Run on Android (Termux or Pydroid)
A) Termux (recommended)
# Install Python
pkg update -y && pkg upgrade -y
pkg install -y python
# Optional: Termux:API for battery (play store/FDroid app + pkg):
pkg install -y termux-api
# Put the file somewhere, then:
python solveforce_phone_zero.py --host 127.0.0.1 --port 8080 --poll 0
# Open on the phone: http://127.0.0.1:8080/ui
- To expose on your LAN:
python solveforce_phone_zero.py --host 0.0.0.0 --port 8080 --poll 5
# From a laptop on same Wi‑Fi: http://PHONE_IP:8080/ui
B) Pydroid 3 (GUI)
- Open Pydroid → new file → paste the script → run.
- Open http://127.0.0.1:8080/ui in your phone’s browser.
No Termux:API? The battery plugin simply reports
available: false—no crashes, no drama.
3) What “Zero” includes (and nothing more)
- /ui – minimal mobile page with buttons for:
/health(uptime),/state(plugins + latest),/read?plugin=battery,/read?plugin=net,/metrics- A Translate input that normalizes math operators and currencies into canonical tokens.
- Plugins (built‑in, read‑only):
battery– uses Termux:API if present (termux-battery-status)net– IPv4 viaip -o -4if present, else Androidgetpropfallback
- No background polling by default. Add
--poll 5to start a safe background read loop.
4) The Root UI (your phone is the console)
After launch, open:
- Root page:
http://127.0.0.1:8080/ui- Tap /state to see loaded plugins.
- Tap battery to read battery (if Termux:API exists).
- Tap net to read basic IP info.
- Try Translate with:
$199.99+VAT=€210≈
Everything is spelled as JSON, so meaning travels with the signal. That’s the Logos discipline applied to a phone server.
5) Where we grow next (in small, explicit steps)
Step 1 — JSONL export toggle
- Add a file-backed export option (ClickHouse‑ready
JSONEachRow) with an--exportflag. - Store reads from
batteryandnetwhen polling is enabled.
Step 2 — Modular “/plugins” directory
- Introduce a
plugins/folder. Each.pyfile defines aPluginsubclass with aNAMEandread()—auto‑loaded at boot. - Include
scaffoldsubcommand to generate a plugin stub from the phone.
Step 3 — Observability
- Expand
/metricswith counters per plugin: reads, successes, last_ok. - Add
/events(server‑sent events) to stream JSON to the UI for a live dashboard.
Step 4 — Network & Grid (still read‑only)
- Add
snmpadapter (pure polling reads),netconf(GET only),gnmisubscribe,openadrevent polling,iec61850path‑reads—each as a separate plugin, opt‑in only.
Step 5 — Security & Remote Access
- Keep local or LAN‑only unless using Tailscale. No public exposure without an auth layer.
We will explicitly add any mutating (write) operations in their own adapters with a clear, documented boundary—no surprises.
6) Sanity checks & fixes
- Port busy? Pick another
--port. - Battery unavailable? Install Termux:API app and
pkg install termux-api. - LAN unreachable? Use
--host 0.0.0.0and read the phone’s Wi‑Fi IP in Android Settings or runip -o -4 addr.
7) Why this is “SolveForce‑correct”
- Root‑first: the phone is the console; the UI is source‑of‑truth.
- Language‑first: operators and currencies normalize to canonical tokens—no silent ambiguity.
- Safety‑first: zero writes; reads are explicit; polling is off until you ask for it.
- Composable: plugins are tiny, auditable dictionaries of reality.
If you want, I’ll immediately add Step 1 (JSONL export) and Step 2 (plugins/ scaffold) and re-issue a fresh file. Or we stay at Zero until you say “grow.”
Step One added—JSONL export toggle is now in your phone-first gateway.
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.