Network provisioning
Getting Wi-Fi credentials onto the device. RainMaker Neo uses ESP-IDF's network provisioning component through the app_network example helper, so the transport and protocol are the standard Espressif ones — which means the standard ESP RainMaker phone apps and provisioning SDKs work unchanged.
This is one of the three things a node needs before it can do useful work — the other two, the node's permanent identity and its link to a user account, are covered under Device credentials and User-node association below.
The firmware side
app_network collapses the whole sequence into one call:
app_network_init();
app_network_provision(NEO_MFG_DATA_DEVICE_TYPE_LIGHT,
NEO_MFG_DATA_DEVICE_SUBTYPE_LIGHT);
Internally that is esp_rmaker_pre_prov_init() → set manufacturer data → start provisioning → esp_rmaker_pre_prov_deinit(). The device type and subtype go into the BLE advertisement's manufacturer data so a phone app can filter for your product; pass NEO_MFG_DATA_DEVICE_TYPE_NONE to skip that.
It must run before esp_rmaker_node_init() — provisioning is memory-hungry and the split exists so the SDK can free provisioning resources before the rest of it comes up. See Code basics.
If the device already has credentials, the call returns immediately and the node connects. On POSIX it is a no-op — the host is already on a network.
To hook UI feedback around it, register lifecycle callbacks:
app_network_prov_hooks_t hooks = {
.on_begin = led_start_slow_blink,
.on_session_start = led_start_fast_blink,
.on_end = led_stop_blink,
};
app_network_set_prov_hooks(&hooks);
Transports
| Transport | Kconfig | Notes |
|---|---|---|
| BLE | CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE | The default and the better UX — the phone keeps its internet connection throughout. Selects BT_ENABLED. |
| SoftAP | CONFIG_APP_NETWORK_PROV_TRANSPORT_SOFTAP | The node hosts an AP the phone joins. Broadest compatibility, worse UX — the phone loses internet mid-flow. |
The examples default to BLE with CONFIG_BT_ENABLED=y and CONFIG_BT_NIMBLE_ENABLED=y in sdkconfig.defaults.
Provisioning security and PoP
The provisioning session is secured by protocomm. Security version 2 (SRP6a) is the default and recommended; version 1 is available for compatibility.
| Option | Default | Notes |
|---|---|---|
CONFIG_APP_PROV_SECURITY_VERSION_2 | selected | SRP6a. Use this. |
CONFIG_APP_NETWORK_POP_TYPE_RANDOM | selected | Random PoP. |
CONFIG_APP_NETWORK_POP_TYPE_MAC | — | Derive the PoP from the MAC address. Convenient, and weaker — the MAC is discoverable. |
CONFIG_APP_NETWORK_POP_TYPE_NONE | — | No PoP. Development only. |
CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH | 5 | Wrong-PoP attempts before provisioning stops. Range 0–20; 0 disables the guard. |
CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD | 30 | Minutes before provisioning auto-stops. 0 disables the timeout. |
CONFIG_APP_NETWORK_PROV_NAME_PREFIX | "PROV" | Advertised name prefix, e.g. PROV_a1b2c3. |
CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT | 3 | Failed connection attempts before the credentials are erased and provisioning restarts. |
Leave CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD non-zero — especially if you use no PoP. A device that advertises a provisioning service forever is a device anyone can claim. A reboot restarts provisioning, so a timeout costs the legitimate user very little.
The QR code
CONFIG_APP_NETWORK_PROV_SHOW_QR (default y) prints a provisioning QR code to the serial console. Scanning it in the phone app fills in the name, PoP, and transport automatically.
CONFIG_APP_NETWORK_PROV_COMPACT_QR switches to a compact format (NP:<name>|<pop>|<transport>) instead of the default JSON — smaller and easier to scan. The examples enable it.
In production the QR code must be generated off-device and printed on the label or packaging; the serial console is a development convenience. The batch registration flows generate QR images for you: see the qrcode/ directory in the dashboard ZIP.
User-node association
Provisioning gets the node onto a network. Association tells the cloud which user account owns it. Both normally happen in one phone-app flow, but they are separate mechanisms.
RainMaker Neo uses challenge-response, which proves possession of the node's private key rather than trusting a self-reported node ID:
The node exposes this as a ch_resp protocomm endpoint. There are two places it can live:
| Where | Available | Enable with |
|---|---|---|
| During provisioning | Only while a provisioning session is active | Nothing — always present |
| On the local endpoints service | Any time, on an already-networked node | esp_rmaker_chal_resp_service_enable() — the examples call it when CONFIG_ESP_RMAKER_LOCAL_CTRL_CHAL_RESP_ENABLE (alongside local control) or CONFIG_ESP_RMAKER_ON_NETWORK_CHAL_RESP_ENABLE (challenge-response only) is set |
The provisioning-time endpoint covers the normal case. The on-network endpoint exists for nodes that join a network without a provisioning session — a factory-configured installation, an Ethernet device, or a POSIX host. It rides on the same protocomm service as local control (advertised over mDNS as _esp_rmaker_ctrl._tcp), and the two endpoint sets can be enabled in any combination. See Local control.
For the protobuf message definitions, see Firmware specifications → Provisioning.
Development shortcut: skip provisioning
For bench work, you can write network credentials straight into NVS and never provision:
python tools/esp_network_prov_nvs/esp_network_prov_nvs.py \
--port /dev/cu.usbserial-0001 --offset 0x9000 --size 0x6000
It reads ESP_WIFI_SSID / ESP_WIFI_PASSWORD from .env and flashes the NVS partition directly. See Tools reference.
Related
- Device credentials — how identity, network credentials, and user association differ
- Firmware specifications → Provisioning
- Product overview → User-node association
- Cloud specifications → Node association