Status and diagnostics¶
Who the device is, what it is doing right now, and what happened before the last reboot.
| Route | Method | What it does |
|---|---|---|
/api/info |
GET | Identity: device type, model, hardware and firmware version, device id, MAC, API level. Cheap and dependency-free: the first thing an integration asks. |
/api/status |
GET | The live picture: status bits, uptime, memory, die temperature, the health counters. Built for polling. |
/api/status?deep=1 |
GET | The same plus the largest free PSRAM block. Walks the whole heap, so it is for one look, never a poll. |
/api/status/tasks |
GET | The task monitor: every task with its state, core, priority, never-used stack bytes and run time. |
/api/faults |
GET | Latched fault codes: structural problems the firmware recorded (boot errors, registry headroom, flash budget). They survive reboots and power cycles until cleared. |
/api/faults/clear |
POST | Clears the latched faults: {"cleared":true}. |
/api/restart/history |
GET | The reboot history with reasons, planned or not, and a crash note for a boot that followed a crash. |
/api/restart/report |
GET | The stored crash report as plain text, the lines a user sends to support. 404 when none is stored. |
/api/restart/report |
DELETE | Forgets the stored crash report: {"cleared":true}. |
/api/restart |
POST | Reboots the device: answers {"ok":true}, waits about a second, restarts. |
/api/info¶
{
"device_type": "wican_pro",
"model": "WiCAN Pro",
"hw_version": "WiCAN-PRO",
"fw_version": "v6.00p_alfa-02-dirty",
"device_id": "68ee8f5a653d",
"mac": "68:EE:8F:5A:65:3C",
"api_level": 6
}
device_type and model tell a WiCAN PRO from a WiCAN OBD or USB. api_level is the number an app checks before it relies on a route that appeared in a later firmware.
/api/status¶
{
"bits": {
"awake": true,
"sleep": false,
"sta_connected": true,
"mqtt_connected": true,
"ble_connected": false,
"sdcard_mounted": true,
"ble_enabled": false,
"sta_enabled": true,
"ap_enabled": false,
"autopid_enabled": true,
"home_mode": false,
"drive_mode": false,
"smartconnect": false,
"sta_ap_overlap": false,
"time_synced": true,
"vpn_enabled": false,
"wake_voltage_ok": true,
"eth_connected": false,
"autopid_idle": true,
"motion": false,
"sta_suspended": false,
"ap_suspended": false,
"ble_suspended": false
},
"network_connected": true,
"uptime": "01:14:28",
"version": "v6.00p_alfa-02-dirty",
"partition": "ota_0",
"boot_count": 1,
"unexpected_resets": 0,
"memory": {
"internal": {
"total": 203827,
"free": 66815,
"min_free": 60619,
"largest_block": 31744
},
"psram": {
"total": 4388152,
"free": 3990056,
"min_free": 3828296
}
},
"temp_c": 44.6,
"health": {
"log_errors": 55,
"log_warnings": 5,
"flash": {
"writes": 0,
"write_bytes": 0,
"erases": 0,
"erase_bytes": 0
},
"caps": {
"settings": {
"used": 41,
"cap": 48
},
"cmdline": {
"used": 38,
"cap": 48
},
"bridge_ep": {
"used": 15,
"cap": 24
},
"events_src": {
"used": 25,
"cap": 32
},
"events_act": {
"used": 14,
"cap": 24
},
"ble_ch": {
"used": 1,
"cap": 4
},
"http_routes": {
"used": 118,
"cap": 144
}
},
"faults": 0
}
}
bits are the live flags, each owned by the part of the firmware that knows:
| Bit | Meaning |
|---|---|
awake, sleep, wake_voltage_ok |
the sleep state; wake_voltage_ok false = the battery is below the sleep voltage and a countdown may be running |
sta_connected, sta_enabled, ap_enabled, sta_ap_overlap |
WiFi: joined to your network, station on, access point on, both on the same channel |
sta_suspended, ap_suspended, ble_suspended |
why an interface is down although it is configured on: the device handed the radio to another interface (a phone on BLE suspends WiFi, a station on the access point suspends BLE) |
mqtt_connected |
the MQTT broker connection is up |
ble_connected, ble_enabled |
a phone is connected over Bluetooth LE; BLE is on |
sdcard_mounted |
an SD card is mounted |
autopid_enabled, autopid_idle |
the vehicle data loop is on; it is not talking to the vehicle right now |
time_synced |
the clock is trusted (set from the network, the RTC chip or by hand) |
vpn_enabled |
a VPN is configured and up |
eth_connected |
a USB Ethernet adapter has a link |
motion |
the motion sensor sees the car moving |
home_mode, drive_mode, smartconnect |
reserved, always false on this firmware |
network_connected is true when either WiFi or the USB Ethernet link is up. memory reports internal RAM and PSRAM separately; largest_block is the fragmentation signal. health carries the counters the firmware watches itself with: logged errors and warnings, flash writes and erases, registry headroom (caps), and the number of latched faults.
/api/status/tasks¶
{
"cores": 2,
"total_us": 4468223812,
"tasks": [
{
"name": "IDLE1",
"state": "X",
"core": 1,
"prio": 0,
"stack_hw": 780,
"runtime_us": 4464255033
},
{
"name": "IDLE0",
"state": "R",
"core": 0,
"prio": 0,
"stack_hw": 772,
"runtime_us": 4407565504
},
{
"name": "socket_net",
"state": "B",
"core": -1,
Tasks come busiest first. stack_hw is the number of stack bytes a task has never used: a small number means it runs close to an overflow. CPU load is a client-side difference between two polls: (runtime_us now - runtime_us before) / (total_us difference x cores); the IDLE tasks' share is the idle time.
/api/faults¶
A fault is the firmware's own trouble code: raised when something structural went wrong, kept in flash until someone clears it with POST /api/faults/clear (the console command is faults -c). The web interface shows the count in its header.
/api/restart/history¶
{
"boot_count": 1,
"unexpected_resets": 0,
"elf_sha": "3b63cddd0199a1e8",
"brake": {
"verdict": "normal",
"streak": 0,
"limit": 3,
"parks": 0,
"settled": true,
"settle_s": 600,
"report_budget": 4
},
"records": [
{
"seq": 1,
"reason": "poweron",
"planned": false,
"planned_reason": "none",
"source": "unknown",
"flags": 0,
"boot_time": 0,
"time_valid": false,
"request_time": 0,
"request_uptime_ms": 0,
"mode": "normal",
"settled": true
}
]
}
Newest record first. Each record says why that boot happened: reason is the hardware reset cause, planned whether the firmware asked for it, planned_reason and source who asked (a settings submit, a firmware update, the web interface, a crash park). boot_count and unexpected_resets are the totals; elf_sha identifies the running image.
A record whose boot followed a crash carries crash: summary (one line, as the boot log prints it), kind (exception, abort, int_wdt, task_wdt, debug), the program counter and address, the task, the uptime at the crash, the abort message and up to 16 backtrace addresses. python tools/crash_decode.py --url http://<device> in the firmware repository turns the addresses into function names when the matching image is at hand.
mode on a record says how that boot ran (normal, park, park_bare, safe) and settled whether it stayed up for 600 seconds. The top-level brake block is the crash-loop brake: three runs in a row that crash before they settle park the device asleep with the LED breathing red; a power cycle starts the count again. report, present only while a crash report is stored, mirrors GET /api/restart/report.
/api/restart/report¶
Plain text, at most 1024 bytes, the same lines as the console's restart_tracker --report and the safe-mode page:
The bench device had no stored report when this page was captured, hence the 404 body above. A device that crashed shows WiCAN crash report, Device:, Firmware:, Image:, Stored:, Loop: when it was a loop, Crash:, Backtrace: and Core N: lines.
/api/restart¶
Answers {"ok":true} first, then restarts about a second later. The reboot is recorded in the history as planned, reason user_request, source web_ui.