AN-301 LoRaWAN Emergency Button User Guide

Device Information: Model AN-301, devEui ffffff100004bccc, gateway IP 192.168.31.205, Modbus Slave ID 6, BACnet Device ID 110

1 Protocol Overview

The AN-301 reports battery voltage, tamper status/event, SOS event/time, and signal quality on Fport 210.

Payload format (Fport 210):

Byte Field Description
0 Reserved Always 0x00 (protocol version)
1 … N TLV pairs [Type(1 B)][Value(N B)] … repeating until end

Each Type byte determines the field name and the number of following value bytes:

Type Value Bytes Field Name Encoding Scale Unit Notes
0x01 1 model uint8 Model code = 0x01
0x14 1 sosEvent uint8 0=normal 1=SOS danger
0x77 1 tamperState uint8 0=normal 1=tampered (status)
0x7D 1 batteryVoltageState uint8 0=normal 1=low voltage
0x04 2 batteryVoltage uint16 BE ÷1000 V e.g. 0x0DFC=3580 → 3.580 V
0x05 1 batteryLowEvent uint8 0=normal 1=low-voltage event triggered
0x03 1 tamperEvent uint8 0=normal 1=tamper event triggered

JavaScript Decoder Example:

// AN-301 Emergency Button — Fport 210 uplink decoder
function decodeUplink(bytes) {
  // bytes[0] is reserved (0x00); Type-Value pairs start at index 1
  var i = 1, r = {};
  function u16(b,o){ return (b[o]<<8)|b[o+1]; }
  while (i < bytes.length) {
    var t = bytes[i++];
    switch (t) {
      case 0x01: r.model            = bytes[i++]; break;           // model code
      case 0x03: r.tamperEvent      = bytes[i++]; break;           // 0=normal  1=event
      case 0x04: r.batteryVoltage   = u16(bytes,i)/1000; i+=2; break; // V
      case 0x05: r.batteryLowEvent  = bytes[i++]; break;
      case 0x14: r.sosEvent         = bytes[i++]; break;           // 0=normal  1=SOS
      case 0x77: r.tamperState      = bytes[i++]; break;
      case 0x7D: r.batteryVoltageState = bytes[i++]; break;
      default:   i++; break; // skip unknown type
    }
  }
  return r;
}
// Example payload (hex): 00 01 01 14 00 77 00 7D 00 04 0D FC 05 00
// → { model:1, sosEvent:0, tamperState:0, batteryVoltageState:0, batteryVoltage:3.58, batteryLowEvent:0 }

Script download: LPP.zip

Compatibility note: LPP.js is developed and tested against ChirpStack v4.17.0. The ChirpStack JavaScript codec API may differ across versions — if you are running a different ChirpStack version, review and adjust the script as needed before deployment.
⚠️ The IP addresses (192.168.31.205 / 192.168.31.193), ChirpStack API token, Slave ID, BACnet Device ID, and devEui in the examples below are for demonstration only. Replace them with your actual gateway IP, ChirpStack API token, and device parameters.

2.1 ChirpStack MQTT Subscription

Subscribe to the MQTT topic to receive real-time uplink frames:

Application ID3ef9e6b9-ec54-4eda-86b8-a5fb46899f39 is the factory-default ChirpStack
application built into the gateway. Replace it with your actual application
ID if you have created a different one.

Gateway IP192.168.31.205 is the gateway WAN port IP shown as an
example. Replace it with your actual gateway IP address.

Device EUIffffff100004bccc is the EUI of the example device.
Replace it with the EUI shown in the gateway device list, or use +
as a wildcard to subscribe to all devices at once.
# Subscribe to one specific device
mosquitto_sub -h 192.168.31.205 -p 1883 \
  -u gateway -P mqtt88888888 \
  -t "application/3ef9e6b9-ec54-4eda-86b8-a5fb46899f39/device/ffffff100004bccc/event/up"

# Subscribe to ALL devices on ALL applications (wildcard)
mosquitto_sub -h 192.168.31.205 -p 1883 \
  -u gateway -P mqtt88888888 \
  -t "application/+/device/+/event/up"

Example uplink payload (JSON):

{
  "devEui": "ffffff100004bccc",
  "fPort": 210,
  "object": {
    ...  (decoded LPP fields)
  }
}

2.2 IoT Hub HTTP API

Send a GET request to retrieve the latest device state:

curl -s "http://192.168.31.205:8070/api/getStatus?devEui=ffffff100004bccc"
{
  "success": true,
  "result": {
    "batteryVoltage": 3.57,
    "tamperStatus": false,
    "sosEvent": false,
    "model": "AN-301"
  }
}

2.3 IoT Hub Modbus TCP — Python Script

Script download: modbus_tcp_read.py

Use modbus_tcp_read.py to poll all registers at once:

python3 modbus_tcp_read.py --ip 192.168.31.205 --port 502 \
    --slaveId 6 --sensorType AN-301
Target: 192.168.31.205:502 | Slave ID: 6 | Sensor: AN-301
================================================================================================================================================================
Attribute                | Addr   | FC  | Format     | Order        | Cnt | Scale    | Raw(Hex)            | Value              | Unit
----------------------------------------------------------------------------------------------------------------------------------------------------------------
online                   | 6      | 03  | Bit/Bool   | Big(ABCD)    | 1   | x1       | 0001                | true               | none
lastOnlineTime           | 7      | 03  | UnixTime   | Big(ABCD)    | 2   | x1       | 69CC C78F           | 1775028111         | second
batteryVoltage           | 9      | 03  | Int16(S)   | Big(ABCD)    | 1   | /100     | 0165                | 3.57               | volt
tamperStatus             | 10     | 03  | Bit/Bool   | Big(ABCD)    | 1   | x1       | 0000                | false              | none
tamperEvent              | 11     | 03  | Int16      | Big(ABCD)    | 1   | x1       | 0000                | 0.0                | none
sosEvent                 | 12     | 03  | Bit/Bool   | Big(ABCD)    | 1   | x1       | 0000                | false              | none
sosEventTime             | 13     | 03  | UnixTime   | Big(ABCD)    | 2   | x1       | 0000 0000           | 0                  | second
model                    | 39     | 03  | String(24B) | ASCII        | 12  | x1       | 414E 2D33 3031 0000 ... | AN-301             | none
rssi                     | 51     | 03  | Int16      | Big(ABCD)    | 1   | x1       | FFD1                | -47.0              | none
snr                      | 52     | 03  | Int16      | Big(ABCD)    | 1   | x1       | 000C                | 12.0               | none

2.4 IoT Hub Modbus TCP — Modbus Poll

Tool download: Modbus Poll 9.5.0.1507.zip

  1. Open Modbus Poll, connect to 192.168.31.205:502, Slave ID 6
  2. Menu Setup → Read/Write Definition, set Function Code = FC03, Start Address = 6, Length = 47
  3. Click OK — values update in real-time

2.5 IoT Hub BACnet BIP — Python Script

Script download: bacnet_read.py

Use bacnet_read.py to read all BACnet objects:

python3 bacnet_read.py --ip 192.168.31.205 --port 47808 --id 110
Target: 192.168.31.205:47808 | BACnet ID: 110 | Scan: 11000-11099
------------------------------------------------------------
Type | Instance | Offset | Value                    | Object Name
------------------------------------------------------------
BI   | 11002    | 2      | active                   | ffffff100004bccc.online
AI   | 11003    | 3      | 1775028096.00            | ffffff100004bccc.lastOnlineTime
AI   | 11004    | 4      | 3.57                     | ffffff100004bccc.batteryVoltage
BI   | 11005    | 5      | inactive                 | ffffff100004bccc.tamperStatus
AI   | 11006    | 6      | 0.00                     | ffffff100004bccc.tamperEvent
BI   | 11007    | 7      | inactive                 | ffffff100004bccc.sosEvent
AI   | 11008    | 8      | 0.00                     | ffffff100004bccc.sosEventTime
CV   | 11012    | 12     | AN-301                   | ffffff100004bccc.model
AI   | 11013    | 13     | -47.00                   | ffffff100004bccc.rssi
AI   | 11014    | 14     | 12.00                    | ffffff100004bccc.snr

2.6 IoT Hub BACnet BIP — YABE

Tool download: SetupYabe_v2.1.0.exe

  1. Open YABE, connect to 192.168.31.205:47808
  2. Expand Device 110 in the device tree
  3. Browse AI/BI/AV/BV/CV objects to view real-time values