UWB Data Exchange
APP Data Encapsulation
Over-the-air payload is encapsulated in compact binary TLV encoding. The payload structure is displayed below.
Data encapsulation is designed as follows:
msgType (1B) | APP1 TLV structure | APP2 TLV structure | ||
---|---|---|---|---|
APP_ID (2B) | length [B] (1B) | data (up to 100B)* | …… | |
0x64 | id of the application | length of data for the application in bytes | application data | ……. |
All multi bytes data types within the app protocol are in Little-endian if not mentioned explicitly different.
msgType: 0x64 is dedicated to user applications.
APP_ID: The range for custom APP ID is <4096;16565>. APP ID is used in all OTA messages.
Data: The maximal data length that can be sent from the application to the server (and vice versa) in one blink period is limited to 100B of payload. Moreover, the application should assume that other applications and the system also need to send some content. So if the sum of data sent from all applications is greater than 100B per period over a long period of time, buffer congestion may occur.
Send Data from Server to Tag (Backchannel)
The server user interface is based on REST API in the RTLS Manager.
The documentation of those APIs can be found here:
RTLS Manager API: http://[RTLS Studio IP]/documentation/api-rtlsmanager
Interactive API via available at http://[RTLS STUDIO IP]/documentation/api-rtlsmanager
Requests listed above can take from milliseconds to minutes, depending on Tag settings. Therefore there is a JOB approach used to handle HTTP requests with a long response time. So, firstly user gets an immediate answer about the job acceptance (HTTP 202 JOB_ID) and later he can poll for job status via HTTP GET JOB_ID request.
Send Data from Server
HTTP POST method /tags/{id or mac}/backchannel, that allows sending arbitrary data to the selected tag.
Required fields in the HTTP request: X-Apikey, id, body
Required field in the request body
Payload REQUIRED
Timeout OPTIONAL
Maximal time to trying to deliver the backchannel request from anchor to the tag. If the anchor is not able to do it in a defined time the job will be canceled with status failed (message: timeout occurred). The timeout value is set in seconds. If it will be set to null, the timeout will be set automatically by the server, based on the tag settings.
- Anchor OPTIONAL
- Define which anchor should be used to send backchannel requests. Anchors MAC address in the hexadecimal form must be used (without 0x prefix). If null, the anchor will be chosen automatically by the server.
Request (via Swagger):
Request (via CURL):
curl -X POST "http://172.16.18.20/rtlsmanager/api/tags/0x24025e4e8949/backchannel" -H "accept: application/json" -H "X-ApiKey: 17254faec6a60f58458308763" -H "Content-Type: application/json" -d "{ \"payload\": \"6400040301F401\", \"timeout\": 10}"
The job is received and it returns an immediate response 202 with JOB ID, in our case 896215.
If the job responds to code 202, the data was successfully received by the server.
Response:
Response body { "id": 896215 } Response headers access-control-allow-origin: * cache-control: no-cache, private connection: Keep-Alive content-length: 13 content-type: application/json date: Tue, 25 Jan 2022 16:19:22 GMT keep-alive: timeout=5, max=52 location: /rtlsmanager/api/jobs/896215 server: Apache/2.4.29 (Ubuntu) strict-transport-security: max-age=63072000; includeSubdomains x-content-type-options: nosniff
Check Data Request State
HTTP GET /jobs/{id}
The user then receives if the data was delivered to the tag via job id GET /jobs/{id}.
Request (via Swagger):
Request (via CURL):
curl -X GET "http://172.16.18.20/rtlsmanager/api/jobs/896215" -H "accept: application/json" -H "X-ApiKey: 17254faec6a60f58458308763"
Response:
If the data was successfully delivered to the tag the job status returns completed. There are just two other states that can happen: in-progress or failed. The reason is provided in the message field i.e Timeout occurred, Transaction was canceled, or successfully completed.
Timeout occurred:
The tag is in the Sleep Mode and it has disabled Refresh Interval in Sleep Mode. In this case, the tag does not send the blink pool messages, thus it is also not able to receive any backchannel requests. Solution: Disable the Sleep Mode, or set some non-zero Refresh Interval in sleep mode, see more Tag Settings Backchannel Considerations.
The tag got out of range of the selected anchor before the request was sent to it.
Response body { "id": "896215", "at": "2022-01-25T16:19:22Z", "request": "rtlsmanager/api/tags/0x24025e4e8949/backchannel", "job": { "status": "completed", "details": { "end": "2022-01-25T16:19:23.064Z", "durationMs": 39 }, "message": "successfully completed", "parameters": { "tag": "24025e4e8949", "jobId": "896215", "start": "2022-01-25T16:19:23.025Z", "action": "reqStart", "anchor": "6827198f5eef", "payload": "6400040301F401", "numOfAcks": 3, "timeoutMs": 10000, "syncEnabled": true, "immediateAck": true, "transactionId": "61f0230b06" } } } Response headers access-control-allow-origin: * cache-control: no-cache, private connection: Keep-Alive content-length: 487 content-type: application/json date: Tue, 25 Jan 2022 16:21:08 GMT keep-alive: timeout=5, max=87 server: Apache/2.4.29 (Ubuntu) strict-transport-security: max-age=63072000; includeSubdomains x-content-type-options: nosniff
Receive Data from Server on Tag
Tag polls for the data from the server each blink period
The data for the application that was received from the server is passed to the APP's callback function in the following structure:
If len is non zero, there is a new payload within the data buffer
typedef struct { uint16_t app_id; uint8_t len; uint8_t data[100]; }app_data_t;
Send Data from Tag to Server
Data_Req()
The payload is stored to transmit buffer via function prepare_response declared in app_data_handlig.h
bool Data_Req(uint16_t app_id, uint8_t len, uint8_t* data, uint8_t priority, data_confirm_cb_t confirm_cb)
app_id - ID of given application
len - payload size in bytes
data - pointer to buffer to be sent via UWB
app_priority - The priority value can have the following values: 0, 1, 2, 3, 4, 5, 6. The lower number has a higher priority. Priorities 0, 1, 3, and 5 are reserved for applications that have been implemented by Sewio, other priorities can be freely used.
data_confirm - optionally there is the possibility to pass a callback function
data_confirm_cb_t
to get a confirmation once the data are sent. If this feature is not used the NULL must be passed instead of a callback function.
IF there is a payload with a higher priority the payload will be copied into the internal buffer, but it will not be sent in the next blink because of other applications with higher priority. In this case, our payload will be sent in the next blink after a higher priority payload is served.
IF return true
The payload was successfully received and it is ready for asynchronous transmission via the UWB channel
IF return false
Buffer is full, the APP must wait until the next period and try it again.
Data_Conf()
This confirmation callback is called just after sending the UWB frame.
Throughput limitations
The amount of data that can be sent by applications is limited by throughput. The maximal length of payload that can be sent in one blink is limited to 100B. So the average sum of data length from all apps should not exceed this value.
We do not recommend a data payload longer than 50B. The longer payload the higher the packet error rate.
Be careful, if some application will generate too much data, it can fill the entire buffer and prevent other applications from sending their data. It can cause congestion or malfunctions of the system. The Sewio core positioning metadata information like tag info, battery level, or sensors data is sent in the same way as user APPS data.
Receive Data from Tag on Server
Application is represented in REST API as datastream named: bc_datastream_APP_ID
Whenever the server receives any UWB frame from the anchor which contains the APP payload it immediately exposes the given payload to the corresponding bc_datastream_APP_ID.
In order to get a payload for a given application and given tag, we need to know the unique FeedID of the given tag.
Get Payload from APP
REST API: GET/tags/{id}/datastreams/{datastreams_id}
FeedID: required unique ID of Tag feed
DatastreamID: required unique ID of APP
Request (via Swagger):
Request (via CURL):
curl -X GET "http://172.16.18.20/sensmapserver/api/feeds/32/datastreams/bc_payload_1024" -H "accept: application/json" -H "X-ApiKey: 17254faec6a60f58458308763"
REST API response contains payloads with timestamps that were received for the given application ID.
Response:
Response headers access-control-allow-origin: * cache-control: no-cache, private connection: Keep-Alive content-length: 346 content-type: application/json date: Tue, 25 Jan 2022 16:14:24 GMT keep-alive: timeout=5, max=88 server: Apache/2.4.29 (Ubuntu) strict-transport-security: max-age=63072000; includeSubdomains x-content-type-options: nosniff Response body Download { "id": "bc_payload_1024", "current_value": "00", "at": "2022-01-25 15:54:29.870000", "unit": { "symbol": "", "label": "" }, "datapoints": [ { "value": "026f170f0010", "at": "2022-01-25T15:50:41.341000Z" }, { "value": "00", "at": "2022-01-25T15:50:42.447000Z" }, ...
On this page: