Solution to read electrical measurements sent by Schneider PowerTag sensors. These devices communicate with ZigBee Green Power and require precise control of the timings to work reliably.
A Sonoff ZigBee Dongle-E
device (not the -P model!) with custom firmware is
used as a gateway. The firmware is based on the NCP-UART firmware provided by
Silicon Labs, modified to automatically send a special ACK reply which is specific to PowerTags.
Currently the firmware is tailored for Sonoff ZigBee Dongle-E
devices, but can
work on any devices using a Silicon Labs EFR32MGxx chip by adapting the pinout
and rebuilding.
The powertagd
command runs on the host and communicates with the dongle via
USB/UART using Silicon Labs EZSP
protocol. It processes the readings received
from PowerTags. By default, each received measurement is simply printed to stdout
in
InfluxDB Line Protocol
format. This output is intended to be piped to another app to process the data as needed.
The powertagctl
command is used to create the ZigBee network, commission
and configure the PowerTags.
Flash the firmware to the dongle. You can either use the built-in bootloader
and upload the ncp-uart-hw-gp-multi-rail.gbl
file, or flash the
ncp-uart-hw-gp-multi-rail.s37
file directly with a JTAG debugger.
Warning: Be prepared to hook a JTAG debugger to recover the dongle if anything goes wrong.
Check out Sonoff firmware flashing
to use the bootloader method, just replace the firmware with the one in this repo.
Build powertagd
and powertagctl
by running make
in the src
directory.
Connect the USB dongle and determine where it was mapped in /dev
.
On Linux it should be something like /dev/ttyACM0
On macOS it should be something like /dev/cu.usbmodemXXXXXXXX
(Optional) Run a network scan and choose a channel. The closer the dBm value is to 0, the stronger the signal. In the following example the best picks would be channel 12 or 13.
$ powertagctl -d /dev/xxx scan
...
Starting energy scan...
Energy scan result: channel 11: -64 dBm
Energy scan result: channel 12: -43 dBm
Energy scan result: channel 13: -45 dBm
Energy scan result: channel 14: -78 dBm
Energy scan result: channel 15: -87 dBm
Energy scan result: channel 16: -87 dBm
Energy scan result: channel 17: -87 dBm
Energy scan result: channel 18: -88 dBm
Energy scan result: channel 19: -87 dBm
Energy scan result: channel 20: -88 dBm
Energy scan result: channel 21: -83 dBm
Energy scan result: channel 22: -59 dBm
Energy scan result: channel 23: -58 dBm
Energy scan result: channel 24: -78 dBm
Energy scan result: channel 25: -89 dBm
Energy scan result: channel 26: -88 dBm
Create a ZigBee network on your preferred channel:
powertagctl -d /dev/xxx create <channel>
Commission PowerTags:
powertagctl -d /dev/xxx pair
Finally run powertagd -d /dev/xxx
to start processing the PowerTags readings.
powertagd
has built-in support to send metrics directly to InfluxDB:
powertagd -d /dev/xxx -o influxdb \
--url http://127.0.0.1:8086 \
--org <OrgName> \
--bucket <BucketName> \
--token <XXX>
Below some sample Flux queries for InfluxDB/Grafana.
from(bucket: "powertag")
|> range(start: v.timeRangeStart, stop:v.timeRangeStop)
|> filter(fn: (r) => r.id == "0x12345678" and r._field == "total_power_active")
|> aggregateWindow(every: v.windowPeriod, fn: mean)
Where "powertag" is the bucket name and 0x12345678 is the PowerTag id.
import "date"
import "timezone"
option location = timezone.location(name: "Europe/Paris")
start = date.truncate(t: -30d, unit: 1d)
stop = date.truncate(t: 1d, unit: 1d)
from(bucket: "powertag")
|> range(start: start, stop: stop)
|> filter(fn: (r) => r.id == "0x12345678" and r._field == "total_energy_rx")
|> aggregateWindow(every: 1d, fn: spread, createEmpty: true)
|> timeShift(duration: -1s)