📺

AirLink Devices

Preface: A note on Bluetooth® SIG requirements

Our understanding is that the Bluetooth® Special Interest Group requires that any entity branding and selling devices enabled with Bluetooth® must register as a member with the SIG at bluetooth.com, as well as declare the product and the Bluetooth® component being used. This is true for resellers, distributors, and all commercial sales. The final selling brand and product name must be separately declared by the seller, even if the component containing Bluetooth® has been declared by the manufacturer.

Although membership has a free tier, each declaration as of this writing costs $8,000, set to rise to $9,600 in 2022. Multiple products using the same Bluetooth® component (one with an approved QDID) can be added to a new or existing declaration, however if the underlying Bluetooth® component is changed even within the same product, a new declaration must be filed with the full fee. Repercussions of not filing declarations may include shipments of the product being held by customs agents, from a global reference list maintained at bluetooth.com.

This requirement as we understand only applies for sold products, not prototypes.

Please note that this note is not official Bluetooth® SIG communication, but rather it is our understanding of the requirements set by the Bluetooth® SIG as of this writing.


Background

The Simusolar team tested how far we could find an AirLink device from in presence of walls and with clear line of sight.

AirLink Devices adopt the Open Connectivity Foundation's Resource Model bridging guidelines for Bluetooth LE devices. A key feature of this bridge is that several OCF Resources are wrapped into one Bluetooth Service to make GET/POST requests efficient. We leverage CBOR for this encapsulation.


Design

Resource model design

The OCF bridging recommendation covers GATT properties well, however it does not cover Advertising nor does it cover a resource enumerator explicitly.

We used the following additional assumptions to design our resource models:

  1. Bluetooth gateways from any vendor adopting AirLink should be able to detect other AirLink devices, to ensure interoperability as well as crowd-sourced stolen asset detection. Hence the advertising packet needs to be open format with sufficient information to identify the device and it's basic state
  1. Extended advertising should not be required to transmit the required data, limiting the overall size to 26 bytes
  1. The advertisement data packet as well as other GATT service characteristics must be CBOR encoded lists of Resource Model properties. This is designed for compatibility with the Nexus Channel effort. The GATT characteristics should be in 2-D array format, whereas the Advertisement packet will be a single dimensional byte array with positionally separated properties to conserve data packet length. The gateway device then converts this into a 2-D CBOR array and includes location information before transmitting to the server.
  1. Location is to be appended by the gateway device before transmission to the server, as non-gateway devices are unlikely to have GSM/GPS to locate themselves. However, devices can store locations provided to them by gateway devices to enable a location history within the device if required
  1. Pay-as-you-go credits are sent as OpenPAYGO Tokens - this is to ensure interoperability with existing keypad/remote enabled devices as well as independence from time-stamp synchronization between server/gateway/end device.
  1. We cover the following general use cases here:
    1. Required: Asset locatability by any gateway via advertisement
    1. Required: Resource enumerator service
    1. Required: Pay-as-you-go credits - we postulate that this does not require manufacturer specific authorization because OpenPAYG Tokens are already securely encrypted between a server and device
    1. Optional: Power use and Productive Output data logging
    1. Optional: Self-provisioning as supported by Thingsboard.io servers

Device Discovery Services

  1. The advertisement packet is a compressed resource always readable from the device. Hence we designate it as an 'Implicit PUT'. The advertising device can be considered to be constantly PUTing the packet to gateway devices ready to receive it. A gateway device would read this resource and decompress it to create a standard-format Resource Model with Properties! It would add items such as resource type, interface type etc as required by OCF but also timezone, location lat-lon where the device was discovered and the manufacturer ID which is in the bluetooth header
  1. The resources enumerator is a standard resource telling a gateway device what other resources the polled device has. This is not considered a regular registered resource property but rather a GET endpoint, hence it doesn't have an RTR

'AirLink Advertisement' as Implicit PUT Resource /advt

Resource PropertyOctetsQualifiersNx ResourceDescription
Array Cbor header1CBOR HeaderArray declaration header of 8 elements
BLE Advt resource version "rv"3Float (uint16_t)Read-OnlyAirLink Advt Resource 1.010 (major/minor digits), 2 Bytes = 2^(8*2) = 65536 i.e from 0-65535 (0xFFFF) The format of the data version according to the protocol used. First integer is major number, second minor
Device Fault Status "ft", cbor encoded1Integer (uint8_t)Read-OnlyAirLink Advt Resource 1.0From 0-23. Any Universal error that should be executed with priority. Error 0 = Unprovisioned, Error 1 = Lost track of PAYG credit (battery off), Error 2 = Battery Fault Error 3 = Output Overcurrent/Overtemp - details in ftd field in timeseries data Error 23 = Lost device (e.g. when device doesn't find other Bluetooth devices from it's 'pack'. Errors 4-22 are manufacturer specific
Device ID "did" + Cbor header 2 bytes5Read-OnlyAirLink Advt Resource 1.02^(8*4) = 4,294,967,296 numeric device ids. The ID of the device that resides in manufacturer registry
Timestamp last pulled from gateway or network "gts"5Byte ArrayRead-OnlyAirLink Advt Resource 1.0Linux epoch format, expires in Y2035
Device provisioning status "pst"1Integer (uint8_t)Read-OnlyAirLink Advt Resource 1.02^8 = 256 i.e from 0-255 (0xFF) The status of the device according to manufacturer definition. It can be unprovisioned, disabled, recall, stolen, Cash, Loan. The range is from 1-9. If not supported then 0
Device FW Ver "fv"2Integer (uint8_t)Read-OnlyAirLink Advt Resource 1.02^8 = 256 i.e from 0-255 (0xFF). Shows the version of the hardware firmware. It ranges from 01-99. If not supported then 0
Device PayG Credit Remaining "cr"5Read-OnlyAirLink Advt Resource 1.02^(8*2) = 65536 i.e from 0-65535 (0xFFFF). The value remaining for the device to OFF. Range is from 01-9999 If non payg device then 0
PayG Unit "pu"2Read-OnlyStringAirLink Advt Resource 1.02^8 = 256 i.e from 0-255 (0xFF). The unit of the PayG update, it can be minutes, hours, days, months and years. [m-minutes, h-hours, d- days, M-months, Y-years]. For non-PAYG device, 'x'
Spare1AirLink Advt Resource 1.0
Device Manufacturer ID "mid" added by gateway deviceInteger (uint16_t)MandatoryRead-OnlyAirLink Advt Resource 1.0From Device advertisement - all manufacturers and end brands of BLE products need to be registered with Bluetooth SIG, as well as EnAccess as tenants to use this service

Location Resource, appended to Advt /loc

Resource PropertyOctetsQualifiersNx ResourceDescription
Array Cbor header1CBOR HeaderArray declaration header of 8 elements
Timestamp last pulled from gateway or network "gts"5Byte ArrayRead-OnlyLocation Resource 1.0Linux epoch format, expires in Y2035
Gateway Manufacturer ID "gmid" added by gateway device2Integer (uint16_t)MandatoryRead-OnlyLocation Resource 1.0How can we prevent one manufacturer from messing up the other's IDs?
Gateway Device ID "gid" added by gateway device5Integer (uint32_t)Location Resource 1.0
Longitude "ln" added by gateway deviceStringLocation Resource 1.0Added by gateway device reporting location of non-gateway device, 10 octets
Latitude "lt" added by gatway deviceStringLocation Resource 1.0Added by gateway device reporting location of non-gateway device, 10 octets
Location accuracy "la" added by gateway deviceStringLocation Resource 1.0Added by gateway device reporting location of non-gateway device, 6 octets
Device Signal strength "dss" added by gateway deviceStringLocation Resource 1.0Added by gateway device reporting the exactly location of the device from a gateway expressed in dBm

Resources Enumerator (nx/res endpoint, known UUID)

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1CBOR HeaderRead-OnlyHeader indicating JSON-like structure
Resources mapCBOR StructRead-Onlynx/resList of resources in this device, composed as JSON packet format described here: https://angaza.github.io/nexus-channel-models/resource_type_spec.html Added characteristic and service UUIDs per rtr

Device Config Service

  1. We presume and recommend self-provisioning, although this resource can also be written to if the device firmware permits.
  1. Gateways can be updated with a list of these configurations for downstream devices
  1. The command resource is a passthrough for building a custom encrypted application links e.g. Nexus Channel

'Device Provisioning' Resource /dcfg

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
Device Provisioning resource version "rv"3Read-OnlyAirLink Device Provisioning 1.010 (major/minor digits)
Device ID "did" + Cbor header 2 bytes6MandatoryRead-WriteAirLink Device Provisioning 1.02^(8*4) = 4,294,967,296 numeric device ids. The ID of the device that resides in manufacturer registry
PayG Units accepted "pul"10MandatoryRead-OnlyStringUnencryptedAirLink Device Provisioning 1.0CSV list of acceptable Units e.g. "l" for liters, "h,d" for hours and days
Payg Token starting code "psc"5Write-OnlyAirLink Device Provisioning 1.01-day token, https://github.com/EnAccess/OpenPAYGO-HW https://github.com/angaza/nexus-embedded
PayG Unit "pu"1EncryptedMandatoryRead-WriteStringAirLink Device Provisioning 1.036^1 The unit of the PayG update, it can be minutes, hours, days, months and years. [m-minutes, h-hours, d- days, M-months, Y-years]
Productive Output Set Limit "opmax"4IntegerRead-WriteAirLink Device Provisioning 1.0Max brightness, max water flow etc set for safety / environmental reasons / other reasons
BLE TimeSeries Data Format "tdf"2IntegerOptionalRead-WriteUnencryptedAirLink Device Provisioning 1.0Might be removed
Provisioning Status "pst"1IntegerMandatoryRead-WriteUnencryptedAirLink Device Provisioning 1.0Reflected in Advt packet also. It can be unprovisioned, disabled, recall, stolen, Cash, Loan. The range is from 1-9. If not supported then 0
Server access Token "sat"21EncryptedMandatoryStringWrite-OnlyAirLink Device Provisioning 1.0Thinsboard.io has a 20-char device authentication token unique to each device. During device provisioning, this token is written to the device, permanently attaching the device to the server. The token is never transmitted again.

'Client Provisioning' Resource /ccfg

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
Client Provisioning resource version "rv"3Read-Only10 (major/minor digits)
Customer Name "cn"16OptionalRead-WriteStringUnencryptedAirLink Client Provisioning 1.0Requested by customers for lost device reporting. This writes the customer name to a device with the maximum of 16 characters with space and special characters inclusive.
Customer's Phone "cp" 16OptionalRead-WriteStringUnencryptedAirLink Client Provisioning 1.0Requested by customers for stolen device reporting (needs a workflow to collect this number explicitly from client in addition to regular lead number). Assign the mobile number of the customer to a device. With maximum of 16 character including + and country code number. This is for security purpose
Readable ID "rid" + Cbor header 2 bytes6MandatoryRead-WriteAirLink Client Provisioning 1.02^(8*4) = 4,294,967,296 numeric device ids or payment reference or any number that device should display
Provisioning Status "pst"1IntegerMandatoryRead-WriteUnencryptedAirLink Client Provisioning 1.0Reflected in Advt packet also. It can be unprovisioned, disabled, recall, stolen, Cash, Loan. The range is from 1-9. If not supported then 0
Server Auth Token "sat" encryption overhead20EncryptedMandatoryStringWrite-OnlyAirLink Client Provisioning 1.0Thinsboard.io has a 20-char device authentication token unique to each device

'Command' Resource /nxc

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
COSE command "cmd"120EncryptedWrite-OnlyAirLink Nexus Command 1.0Upto 120 bytes for Nexus Channel Passthrough commands

PUE Use Service

We envision 2 primary usages of a productive use asset:

  1. PAYG control: This is a generic PAYG packet intended to cover all known PAYG use cases for BLE assets
  1. Use data (time-series): This is a generic IoT Data packet designed to cover both battery-less and battery-based devices
  1. Gateways can accumulate data for/from several devices

'AirLink PAYG' Resource /pc

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor map header1Read-Writeencapsulating the rest of the properties
AirLink PAYG resource version "rv"3Read-Only10 (major/minor digits)
Device PayG Credit Remaining "re"5IntegerMandatoryRead-WritePAYG Credit 1.0should be The value remaining for the device to OFF. For Write, a Nexus Channel Link must be established otherwise read-only, updated via token
Mode "mo"1Read-WritePAYG Credit 1.0mode of device i.e. leading/following etc For Write, a Nexus Channel Link must be established otherwise read-only, updated via token
PayG Token "tkn"5EncryptedIntegerWrite-OnlyPAYG Credit 1.0https://github.com/EnAccess/OpenPAYGO-HW. Accepted by device only if valid. No read token to ensure unsecured gateways cannot act maliciously.
Last Added PayG Credit "lcr"2IntegerOptionalRead-OnlyPAYG Credit 1.0Historical last PayG credit update duration. Range is from 01-9999
Timestamp at which PayG remaining was calculated "ts"6DateTimeOptionalRead-OnlyPAYG Credit 1.0Linux epoch format, expires in Y2035. The Last date and time when the PayG update was fetched from the Server to client [Mobile phone or other communication device]
Timestamp of last PAYG Update to device "lts"6DateTimeOptionalRead-OnlyPAYG Credit 1.0Linux epoch format, expires in Y2035, readonly - Historical last PayG update Timestamp
Current Local Time "lt"6DateTimeOptionalRead-WritePAYG Credit 1.0Linux epoch format, expires in Y2035. The current time when updating the device with PayG update. We do not recommend using this to calculate PAYG use, because it could be used to trick the device into more tokens. This is for non-PAYG purposes

'AirLink PUE' Resource /pu

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
AirLink TimeSeries resource version "rv"4Read-OnlyAirLink PUE Timeseries 1.01.0
Time Series Data Format "df"1IntegerMandatoryRead-OnlyAirLink PUE Timeseries 1.0following DF in OpenPAYGO Metrics (in case device has GSM). 0 if not used
Productive Equipment Type "pue"2IntegerMandatoryRead-OnlyAirLink PUE Timeseries 1.0e.g. "Surface Pump", "Borehole Pump", "Fishing Light" etc preregistered types
BatteryDevice "bat"1IntegerMandatoryRead-OnlyAirLink PUE Timeseries 1.0Yes/No internal or system level battery? or is this covered by energy gen/consumption sub-resources?
Device Fault "ft"1EnumIntegerMandatoryRead-OnlyAirLink PUE Timeseries 1.0Same as Advertisement packet
Device Fault Data "ftd"2ByteArrayIntegerOptionalAirLink PUE Timeseries 1.0Can contain details of error e.g. over-pressure error could contain max pressure measured
seconds since data measured "ss"6MandatoryRead-OnlyAirLink PUE Timeseries 1.0Gateway to add seconds to meet latest time when dispatching to server - means sync timestamp will need saving internally on the gateway
Productive Output Primary Metric "op"4IntegerOptional Grp 1Read-OnlyAirLink PUE Timeseries 1.0e.g. Water output for pumps in Litres/hour, ? for FL
Productive Output Set Limit4IntegerOptional Grp 1Read-Write
Productive Output Secondary Metric "os"4IntegerOptional Grp 1Read-OnlyAirLink PUE Timeseries 1.0e.g. Pressure for pumps in kPa (1kPa = 10cm water or 0.1 bar) ? for FL

'Energy Generation' Resource /ein

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
Voltage (milliVolts) "vi"4IntegerOptionalRead-Onlyenergy generation 1.0Input voltage depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL
Current (centiAmps) "ai"4IntegerOptionalRead-Writeenergy generation 1.0Input current depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL - If a value is written, it can be considered as a current limit setting
Power (deciWatts) "pi"4IntegerOptionalRead-Onlyenergy generation 1.0Input power depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL
Type of source "st"1EnumIntegerMandatoryRead-Writeenergy generation 1.0Type of power generator. Known types - 0 = Disconnected/None - autodetected 1 = DC Solar - autodetected 2 = AC Grid/microgrid (as a source) - autodetected 3 = DC Grid/microgrid (as a source) - from gateway 4 = AC Wind power - from gateway 5 = DC Wind power - from gateway 6 = AC Hydro power - from gateway 7 = DC Hydro power - from gateway 8 = AC Petrol/Diesel Generator - from gateway 100 = Unknown - from gateway
eg4IntegerOptionalRead-Onlyenergy generation 1.0'Energy generated' in deciwatt-hours(Wh / 10). Computed over a time window defined by egs and egp.
egs4IntegerOptionalRead-Onlyenergy generation 1.0'Energy generation start'. Minutes in the past (minutes ago) when the reported eg value began accumulation.
egp4IntegerOptionalRead-Onlyenergy generation 1.0'Energy generation period'. Minutes since egs over which the value of eg was accumulated. For example, if egs is 60, and egp is 60, the value of eg represents the watt-hours generated during the past hour.

'Energy Consumption' Resource /eout

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
Voltage (milliVolts) "vo"4IntegerOptionalRead-Onlyenergy consumption 1.0Output voltage depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL
Current (centiAmps) "ao"4IntegerOptionalRead-Onlyenergy consumption 1.0Output current depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL - If a value is written, it can be considered as a current limit setting
Power (deciWatts) "po"4IntegerOptionalRead-Onlyenergy consumption 1.0Output power depending on data format registered by manufacturer. We will start with PV in controllers and Output in FL
eo4IntegerOptionalRead-Onlyenergy consumption 1.0'Energy consumed' in deciwatt-hours(Wh / 10). Computed over a time window defined by egs and egp.
eos4IntegerOptionalRead-Onlyenergy consumption 1.0'Energy consumed start'. Minutes in the past (minutes ago) when the reported eg value began accumulation.
eop4IntegerOptionalRead-Onlyenergy consumption 1.0'Energy consumed period'. Minutes since egs over which the value of eg was accumulated. For example, if egs is 60, and egp is 60, the value of eg represents the watt-hours generated during the past hour.

'Battery Device' Resource /batt

Resource PropertyOctetsQualifiersNx ResourceDescription
cbor header1Read-Writeencapsulating the rest of the properties
Bat Voltage mV "vb"4IntegerOptional Grp 3Read-OnlyBattery 1.0Only for Battery Device
Bat Pct "cp"3IntegerOptional Grp 3Read-OnlyBattery 1.0Only for Battery Device, charge percentage
Charging Status "cs"1EnumOptional Grp 3Battery 1.00 = No Data 1 = Charging - fast 2 = Charging - slow / trickle 3 = Discharging
Alert Threshold (%) "th"3IntegerOptional Grp 3Read-WriteBattery 1.0
Low battery "lb"1BoolOptional Grp 3Battery 1.00: cp>th 1: cp<th
LastChargeCycle BatPctMin "cmin"2IntegerOptionalRead-OnlyBattery 1.0Only for Battery Device, Could be Infrequently reported
LastChargeCycle BatPctMax "cmax"2IntegerOptionalRead-OnlyBattery 1.0Only for Battery Device, Could be Infrequently reported
LastChargeCycle ChgTime "tc"2IntegerOptionalRead-OnlyBattery 1.0in minutes, Only for Battery Device, Could be Infrequently reported
LastChargeCycle ChgUnits (mAh) "qc"2IntegerOptionalRead-OnlyBattery 1.0in milliamp-hours, Only for Battery Device, Could be Infrequently reported
Bat Health "bh"1IntegerOptionalRead-OnlyBattery 1.0Only for Battery Device, Could be Infrequently reported