BLE_PROTOCOL.md: - ESP32 BLE provisioning protocol spec - Characteristics UUIDs and data formats - WiFi credential exchange flow - Security considerations - Error handling SENSORS_IMPLEMENTATION_PLAN.md: - Complete implementation roadmap - Phase 1: BLE scanning and connection - Phase 2: WiFi provisioning - Phase 3: Device management - Phase 4: Status monitoring - API endpoints and data models - Testing checklist Technical reference for: - Backend developers - Mobile developers - QA team
14 KiB
WellPlug BLE Protocol Documentation
Overview
WellPlug devices (WP_XXX) use Bluetooth Low Energy (BLE) for configuration. This document describes the communication protocol.
Device Information
| Parameter | Value |
|---|---|
| Service UUID | 4fafc201-1fb5-459e-8fcc-c5c9c331914b |
| Characteristic UUID | beb5483e-36e1-4688-b7f5-ea07361b26a8 |
| Properties | read, write, notify |
| Platform | ESP32 |
Connection Flow
- Scan for devices with name starting with
WP_ - Connect to the device
- Subscribe to notifications on the characteristic
- Unlock device with PIN command
- Send commands and receive responses
Commands
1. Unlock Device (Required First!)
Must be sent before any other command.
| Command | pin|7856 |
| Response | pin|ok |
| Note | PIN 7856 is universal for all devices |
Example:
Send: pin|7856
Recv: pin|ok
2. Get WiFi Networks List
Scans and returns available WiFi networks.
| Command | w |
| Response | mac,XXXXXX|w|COUNT|SSID1,RSSI1|SSID2,RSSI2|... |
Response Format:
mac,XXXXXX- Device MAC addressw- Command echoCOUNT- Number of networks found (-1 = scanning, -2 = no networks, 0+ = count)SSID,RSSI- Network name and signal strength (dBm)
Example:
Send: w
Recv: mac,142b2f81a14c|w|19|FrontierTower,-55|MyNetwork,-67|...
3. Set WiFi Credentials
Configures the device to connect to a WiFi network.
| Command | W|SSID,PASSWORD |
| Response | mac,XXXXXX|W|ok or mac,XXXXXX|W|fail |
Example:
Send: W|FrontierTower,mypassword123
Recv: mac,142b2f81a14c|W|ok
For devices with long MAC (>12 chars): Use JSON format instead:
{"FUNC":"W","SSID":"NetworkName","PSW":"password123"}
4. Get WiFi Connection Status
Returns current WiFi connection status.
| Command | a |
| Response | mac,XXXXXX|a|SSID,STATUS |
Status Values:
0- Not connected- Other - Connected
Example:
Send: a
Recv: mac,142b2f81a14c|a|FrontierTower,1
5. Reboot Device
Restarts the device. BLE connection will be lost.
| Command | s |
| Response | (device disconnects) |
Example:
Send: s
(device reboots and disconnects)
6. Disconnect BLE
Disconnects BLE connection (device side).
| Command | D |
| Response | (connection closed) |
Response Format
All responses follow this format:
mac,XXXXXX|COMMAND|DATA
Where:
mac,XXXXXX- Device MAC address (last 12 hex chars)COMMAND- Echo of the command sentDATA- Response data (varies by command)
Error Response:
error
Python Example
import asyncio
from bleak import BleakClient, BleakScanner
SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
CHAR_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8"
async def configure_wellplug(device_name, wifi_ssid, wifi_password):
# Find device
device = await BleakScanner.find_device_by_name(device_name, timeout=10)
if not device:
print("Device not found")
return
def on_notify(sender, data):
print(f"Response: {data.decode('utf-8')}")
async with BleakClient(device) as client:
# Subscribe to notifications
await client.start_notify(CHAR_UUID, on_notify)
# 1. Unlock device
await client.write_gatt_char(CHAR_UUID, b"pin|7856", response=True)
await asyncio.sleep(1)
# 2. Get WiFi list
await client.write_gatt_char(CHAR_UUID, b"w", response=True)
await asyncio.sleep(2)
# 3. Set WiFi credentials
cmd = f"W|{wifi_ssid},{wifi_password}".encode()
await client.write_gatt_char(CHAR_UUID, cmd, response=True)
await asyncio.sleep(2)
# 4. Check status
await client.write_gatt_char(CHAR_UUID, b"a", response=True)
await asyncio.sleep(1)
# Usage
asyncio.run(configure_wellplug("WP_497_81a14c", "MyWiFi", "password123"))
Important Notes
- Always unlock first - Device won't respond to commands without PIN
- Use
response=True- When writing with bleak, useresponse=Truefor reliable communication - Subscribe before writing - Subscribe to notifications before sending commands
- Wait for responses - Allow 1-2 seconds between commands for device to respond
- Reboot disconnects - Command
swill disconnect BLE, need to reconnect after
Known Devices
| Device Name | MAC Address | Notes |
|---|---|---|
| WP_497_81a14c | 142b2f81a14c | Test device 1 |
| WP_523_81aad4 | 142b2f81aad4 | Test device 2 |
WellNuo Legacy API Documentation
Overview
The WellNuo Legacy API (eluxnetworks.net) is used for device management, deployments, and sensor data. This is a REST-like API using POST requests with form-urlencoded parameters.
Base URL
https://eluxnetworks.net/function/well-api/api
Authentication
Login (Get Token)
| Function | credentials |
| Method | POST |
Parameters:
| Parameter | Value |
|---|---|
function |
credentials |
user_name |
username |
ps |
password |
clientId |
001 |
nonce |
any value |
Response:
{
"access_token": "eyJhbGci...",
"privileges": "-1",
"user_id": 32,
"max_role": -1,
"status": "200 OK"
}
Example:
curl -X POST "https://eluxnetworks.net/function/well-api/api" \
-d "function=credentials&user_name=USERNAME&ps=PASSWORD&clientId=001&nonce=111"
Deployments
List Deployments
| Function | deployments_list |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | deployments_list |
user_name |
Yes | Username |
token |
Yes | Access token |
first |
Yes | Start index (0) |
last |
Yes | End index (50) |
Response:
{
"result_list": [
{"deployment_id": 21, "email": "user@example.com", "first_name": "John", "last_name": "Doe"},
...
],
"status": "200 OK"
}
Devices
List All Devices
| Function | device_list |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | device_list |
user_name |
Yes | Username |
token |
Yes | Access token |
first |
Yes | Start index |
last |
Yes | End index |
Response:
{
"result_list": [
[device_id, well_id, "MAC_ADDRESS", timestamp, "location", "description", deployment_id],
...
],
"status": "200 OK"
}
Device Array Format:
[0]device_id - Internal device ID[1]well_id - Device well ID (from device name WP_XXX)[2]MAC address (uppercase, no colons)[3]Last seen timestamp (Unix)[4]Location name[5]Description[6]deployment_id (0 = not assigned)
List Devices by Deployment
| Function | device_list_by_deployment |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | device_list_by_deployment |
user_name |
Yes | Username |
token |
Yes | Access token |
deployment_id |
Yes | Target deployment ID |
first |
Yes | Start index |
last |
Yes | End index |
Assign Device to Deployment
| Function | device_set_well_id |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | device_set_well_id |
user_name |
Yes | Username |
token |
Yes | Access token |
device_id |
Yes | Internal device ID |
well_id |
Yes | New well_id to assign |
mac |
Yes | Device MAC address |
Example - Reassign device:
curl -X POST "https://eluxnetworks.net/function/well-api/api" \
-d "function=device_set_well_id&user_name=USER&token=TOKEN&device_id=743&well_id=500&mac=142B2F81A14C"
Update Device Settings
| Function | device_form |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | device_form |
user_name |
Yes | Username |
token |
Yes | Access token |
well_id |
Yes | Device well_id |
device_mac |
Yes | MAC address |
description |
No | Description text |
location |
No | Location code |
close_to |
No | Position description |
radar_threshold |
No | Radar sensitivity (0-100) |
group |
No | Group ID |
Reboot Device
| Function | device_reboot |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | device_reboot |
user_name |
Yes | Username |
token |
Yes | Access token |
device_id |
Yes | Device ID to reboot |
Device Online Status Checking
Method 1: device_list API (Individual Check)
Use device_list to check last seen timestamp for specific devices.
How to determine online/offline:
- Field
[3]contains Unix timestamp of last update - Calculate hours since last update
- If < 1 hour → ONLINE
- If > 1 hour → OFFLINE
Example:
curl -X POST "https://eluxnetworks.net/function/well-api/api" \
-d "function=device_list&user_name=USER&token=TOKEN&first=0&last=100"
Response:
{
"result_list": [
[743, 497, "142B2F81A14C", 1736859744, "Location", "Description", 70],
[769, 523, "142B2F81AAD4", 1736859630, "Location", "Description", 70]
],
"status": "200 OK"
}
Status calculation:
Device 743 (WP_497):
Last seen: 1736859744 → 2026-01-14 10:02:24
Hours ago: 0.0 → ONLINE
Device 769 (WP_523):
Last seen: 1736859630 → 2026-01-14 10:00:30
Hours ago: 0.03 → ONLINE
Method 2: request_devices API (Batch Check by Deployment) ⭐
IMPORTANT: This is the endpoint Robert uses to show "green" (online) devices in the app!
Quote from Robert: "there is API call to find out if set of devices are recently seen by server"
This endpoint returns only devices that are recently active (sent data to server in the last ~1 hour).
| Function | request_devices |
Parameters:
| Parameter | Required | Description |
|---|---|---|
function |
Yes | request_devices |
user_name |
Yes | Username |
token |
Yes | Access token |
deployment_id |
Yes | Deployment to check |
group_id |
Yes | Group filter ("All" for all groups) |
location |
Yes | Location filter ("All" for all locations) |
fresh |
Yes | true ← KEY PARAMETER! Filters only recently seen devices |
Example:
curl -X POST "https://eluxnetworks.net/function/well-api/api" \
-d "function=request_devices" \
-d "user_name=USER" \
-d "token=TOKEN" \
-d "deployment_id=38" \
-d "group_id=All" \
-d "location=All" \
-d "fresh=true"
How it works (Robert's app logic):
- Call
request_deviceswithfresh=true - Response contains ONLY online devices (recently seen by server)
- If device is in response → Show GREEN (online) ✅
- If device is NOT in response → Show GRAY (offline) ❌
Response example:
{
"result_list": [
[device_id_1, well_id_1, "MAC1", timestamp_1, ...],
[device_id_2, well_id_2, "MAC2", timestamp_2, ...]
],
"status": "200 OK"
}
Only devices that sent data recently appear in the list!
Alternative without fresh=true:
- Returns ALL devices in deployment (regardless of status)
- You need to manually check timestamp field [3] to determine online/offline
Note: This endpoint requires devices to be properly linked to the deployment in the Legacy API system. Use Method 1 (device_list) if deployment linkage is not set up.
Creating and Activating Deployments
Create/Update Deployment with Devices
Function: set_deployment
This endpoint is used to create a new deployment or update existing one with devices, beneficiary info, and WiFi credentials.
Key Parameters:
| Parameter | Description |
|---|---|
function |
set_deployment |
user_name |
Installer username |
token |
Access token |
deployment |
Deployment name or "NEW" for new deployment |
beneficiary_name |
Beneficiary full name |
beneficiary_email |
Beneficiary email |
beneficiary_user_name |
Beneficiary login username |
beneficiary_password |
Beneficiary password |
beneficiary_address |
Beneficiary address |
caretaker_username |
Caretaker username (can be same as installer) |
caretaker_email |
Caretaker email |
persons |
Number of persons in household |
pets |
Number of pets |
gender |
Gender |
race |
Race index |
born |
Year born |
lat |
GPS latitude |
lng |
GPS longitude |
wifis |
JSON array of WiFi credentials: ["SSID1|password1", "SSID2|password2"] |
devices |
JSON array of device well_ids: [497, 523] |
beneficiary_photo |
Photo filename |
beneficiary_photo_data |
Base64 encoded JPEG photo |
reuse_existing_devices |
1 to reuse, 0 to create new |
Example WiFi credentials format:
["FrontierTower|frontiertower995", "HomeNetwork|password123"]
Example devices list:
[497, 523]
After creating deployment:
- Devices are linked to the deployment
- WiFi credentials are stored
- Beneficiary account is created
- Devices will start reporting data to server
- Devices become "live" and visible in
request_deviceswithfresh=true
Known Test Devices
| Device Name | device_id | well_id | MAC Address | Status |
|---|---|---|---|---|
| WP_497_81a14c | 743 | 497 | 142B2F81A14C | Configured |
| WP_523_81aad4 | 769 | 523 | 142B2F81AAD4 | Configured |
Both devices are assigned to:
- Deployment ID: 70
- Beneficiary: Sergei Terekhov (ID: 76)
- Owner: serter2069@gmail.com (User ID: 63)
- WiFi Network: FrontierTower
Changelog
- 2026-01-14 - Added Legacy API documentation (deployments, devices)
- 2026-01-13 - Initial BLE protocol documentation created