Bluetooth
Every SolarAssistant device advertises a BLE GATT peripheral that a mobile app can use for local provisioning — configuring Wi-Fi, authenticating, and reading live metrics — without requiring a network connection.
Discovery
Scan for BLE devices and look for one whose advertised name starts with SolarAssistant- (or the organisation's custom app name if white-labelled). A # in the suffix marks a site ID, meaning the device is registered. Without one, the suffix is the last 6 characters of the device's machine ID and the device has not been registered yet:
SolarAssistant-#12345 ← registered
SolarAssistant-a3f8c2 ← not yet registeredKey off the # — never off whether the suffix parses as a number. The machine ID is hexadecimal, so for roughly one device in sixteen it happens to contain only digits, and SolarAssistant-483920 is an unregistered device rather than site 483920.
The name is a human-readable hint only — use site_id from the Service Data (see below) as the authoritative source. A non-zero value means the device is registered.
Once found, connect to the device and discover its GATT services. All SolarAssistant characteristics live under a single service UUID:
45a2b616-7083-41e9-851f-23f3ed252300Advertisement data
The advertisement includes Service Data under UUID 0x5341. This lets a scanning app read basic device state without connecting. The payload is 6 bytes. Note: the status byte refreshes approximately once per minute — use the Network status characteristic for real-time connection state.
| Bytes 0–2 | uint24 LE | site_id — numeric site ID. 0 if the device has not yet been registered. |
| Bytes 3–4 | uint16 LE | org_id — organisation ID. 0 for the default SolarAssistant organisation. |
| Byte 5 | bitmask | status — bit 0: Wi-Fi connected, bit 1: Ethernet connected, bit 3: internet reachable, bit 4: monitoring running — the device is polling its inverter and battery. Bits are independent and combinable, and bit 2 is unused. |
Characteristics
A connected client also discovers ...304, ...305 and ...306, which are reserved for authenticated API access and live metrics. These are not implemented yet — the Bluetooth stack accepts a write but nothing acts on it, so use only the characteristics documented below.
READNOTIFY45a2b616-7083-41e9-851f-23f3ed252302Network status
Returns the connection state of every network adapter on the device (Ethernet, Wi-Fi, and Internet). Adapter entries cover eth* and wlan* interfaces, sorted by name, followed by an Internet entry that reports whether the device has a working route to the internet. The value is a UTF-8 JSON string.
Subscribe to notifications to receive an update whenever the network state changes (e.g. after writing Wi-Fi credentials). Expect the status to reach Up within ~15–30 seconds if the credentials are correct.
Response
[
{ "adapter": "eth0", "status": "Down", "ip": null },
{ "adapter": "wlan0", "status": "Up", "ip": "192.168.1.101" },
{ "adapter": "Internet", "status": "Up", "ip": "1.2.3.4" }
]| adapter | string | Interface name, e.g. eth0, wlan0, or Internet. |
| status | string | Interface status — Up, Down, Dormant, or other values as reported by the operating system. |
| ip | string | IP address when connected. null otherwise. |
READWRITE45a2b616-7083-41e9-851f-23f3ed252303Wi-Fi config
Read: returns the currently saved Wi-Fi configuration as a UTF-8 JSON string. The password is never included in the response.
Read response
{
"ssid": "MyNetwork",
"country_code": "US"
}| ssid | string | Saved network SSID. null if not configured. |
| country_code | string | Saved ISO 3166-1 alpha-2 country code. null if not configured. |
Write: stores new Wi-Fi credentials and initiates a connection attempt. The value is a UTF-8 JSON string.
Use write with response so the device can confirm the payload was accepted before attempting to connect. After a successful response, watch for Network status notifications (characteristic ...302) — the device pushes an update as the connection state changes.
Write payload
{
"ssid": "MyNetwork",
"password": "secret",
"country_code": "US"
}| ssid | string | Network SSID. |
| password | string | WPA2 passphrase. Pass an empty string for open networks. |
| country_code | string | ISO 3166-1 alpha-2 country code (e.g. US, GB). Optional — defaults to the previously stored value on the device. |
READ45a2b616-7083-41e9-851f-23f3ed252308Site URL
Returns the device's remote access URL as a UTF-8 string, e.g. https://solar-dev-rpi5.us.solar-assistant.io. An empty string means the device has not been registered yet.
Response
https://solar-dev-rpi5.us.solar-assistant.ioREAD45a2b616-7083-41e9-851f-23f3ed252307Build date
Returns the firmware build date as a UTF-8 string in YYYY-MM-DD format. This is the same value published in the mDNS TXT record (build_date).
Response
2026-07-06READ45a2b616-7083-41e9-851f-23f3ed252301Wi-Fi networks
Returns a list of nearby Wi-Fi networks seen by the device. The list is deduplicated by SSID — only the strongest signal for each SSID is included — and sorted by signal strength descending. The value is a UTF-8 JSON string.
Response
[
{ "ssid": "MyNetwork", "signal": 96, "country": "US" },
{ "ssid": "OtherNetwork", "signal": 14, "country": "US" }
]| ssid | string | SSID. |
| signal | integer | Signal quality, 0–100. |
| country | string | ISO 3166-1 alpha-2 country code reported by the access point. |