Skip to content
Snowbird Power Systems

Documentation

Bluetooth

BTHome broadcast, the standard Battery Service, the Snowbird GATT service, and how writes are locked down.

What the radio does

The Snowbird Feather 1S, Snowbird Core 1S, Snowbird 18650 and Snowbird Pack carry a pre-certified nRF52 module that is also the board's supervisor. One processor, one register map, and three ways to read it over the air. The Snowbird Lite 1S has no radio.

Mode For Connection
BTHome v2 broadcast Home Assistant, gateways, anything that listens none
Battery Service (0x180F) Phones and OS battery widgets standard GATT
Snowbird service Full telemetry and configuration custom GATT

Telemetry is readable by anything. Writes are off until you turn them on.

BTHome broadcast

Every 2 s by default the board sends a BTHome v2 advertisement with:

Field BTHome object Unit
Battery 0x01 %
Voltage 0x0C V, 0.001 resolution
Current 0x43 A, signed, 0.001 resolution
Temperature 0x02 °C, 0.01 resolution
Power (solar) 0x0B W, 0.01 resolution
Energy (harvested today) 0x0A kWh, 0.001 resolution
Charging 0x16, binary on / off
Problem 0x1A, binary set while any fault is active
Packet id 0x00 wraps at 255

The device name is Snowbird- followed by the last four hex digits of the module's address. setName() changes it.

Home Assistant

  1. Make sure a Bluetooth adapter or an ESPHome Bluetooth proxy is set up in Home Assistant.
  2. Open Settings, then Devices and Services. The board appears under Discovered as a BTHome device within a minute.
  3. Click Configure. No key is needed; the broadcast is unencrypted by default.
  4. The entities above appear on the device. Add the battery and the solar power to a dashboard.

To encrypt the broadcast, set a 16-byte key with setBTHomeKey() and enter the same key when Home Assistant asks for it. Encrypted packets are also replay-protected by the packet counter.

Battery Service

The standard Bluetooth SIG Battery Service exposes Battery Level (0x2A19) as a percentage with notifications, and Battery Level Status (0x2BED) carrying the charging state, the external power flag and the fault flag. A phone's Bluetooth settings page shows the level next to the device name without any app.

The Snowbird service

Service UUID base: 5B1E0000-7A2C-4C6D-9E2F-5A3B0A1D0001. The service UUID has 0000 at bytes 2 and 3; each characteristic replaces them.

Characteristic UUID (bytes 2 and 3) Access Contents
Telemetry 0x0010 read, notify SOC, voltage, current, temperature, time-to-empty, input source, charge state; 16 bytes
Solar 0x0011 read, notify panel power, harvested today, MPPT voltage
Cells 0x0012 read, notify per-cell voltages and imbalance; Pack only
Faults 0x0020 read, notify the same bitmask as faults()
Events 0x0021 notify the same edge events as the INT pin
Event log 0x0022 read the last 32 events with timestamps
Capabilities 0x0001 read board id, cells, BMS, BLE, balance, firmware and register map versions
Configuration 0x0030 read, write (locked) chemistry, capacity, charge current, temperature limits, 5 V enable
Control 0x0031 write (locked) unlock, confirm, ship mode, sleep
Name 0x0032 read, write (locked) up to 20 bytes

Characteristic layouts are the register map's layouts, byte for byte, so the register map is the reference for both.

Writes are off by default

Configuration and Control are read-only until writes are enabled, and the hardware chemistry and voltage ceilings apply to BLE writes exactly as to I2C writes. A paired phone cannot do anything the jumper forbids.

Enable writes in one of two ways:

  • Close the BLE-WRITE solder jumper on the underside, or
  • Call pmic.enableBLEWrites(true) over I2C from the host.

Once enabled, a write requires a bonded connection using LE Secure Connections with a six-digit passkey. The passkey is printed on the pinout card and in the BLE_PASSKEY register; setBLEPasskey() changes it. Up to four bonds are stored. clearBonds() forgets them all.

Legacy pairing and Just Works are not offered. A central that cannot do LE Secure Connections can read everything and write nothing.

Advertising and power

Interval Average current
1 s 60 µA
2 s (default) 42 µA
5 s 32 µA
Off 28 µA

setAdvertisingInterval_ms() takes 1000 to 5000. Below the SOC threshold set by setSocLowThreshold(), default 15 %, the interval stretches to 10 s. In ship mode the radio is off.

Transmit power is 0 dBm by default and setTxPower_dBm() takes −20 to +4. Range in the open is about 60 m at 0 dBm with a phone.

Tools

  • nRF Connect (Android and iOS) reads everything, including the custom service, and does the bond for writes.
  • The Snowbird dashboard at /dashboard is a Web Bluetooth page: live telemetry, the event log, a harvest chart, and configuration once bonded. It works in Chrome on Android, Windows, macOS, Linux and ChromeOS. iOS Safari has no Web Bluetooth, so iPhone users use nRF Connect or Home Assistant.
  • Home Assistant through BTHome needs no app at all.

The no-radio build

Some sites forbid radios. The no-radio firmware build compiles advertising and GATT out entirely; the module stays, the board stays the same SKU, and the I2C interface is unchanged. Flash it over I2C with snowbird-flash --image no-radio; see Firmware updates. hasBLE() returns false on a board running it, and the Capabilities register says why.

The regulatory labels on the board do not change with the build, because the transmitter is still present.