Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Building indoor location applications using the Red Point Positioning RTLS system
Contents
1 About This Guide
2 Introduction
3.1 Locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1 Get all the locations
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Sub-locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
17
19
20
7 References
21
Page 1
This document is intended to be used by third-party developers who will be building location-based applications or
integrating existing software with Red Point Positionings RTLS system. It describes the application programming
interfaces (API) for configuring the indoor positing system, retrieving node information, including location, reading
sensor values, and controlling actuators.
Page 2
Introduction
The basic interface for communicating with the RPP system is the REST API. This allows third-party code to get and set
various parameters within the RTLS system. For example, it is a simple matter to query the system for radio nodes
seen within a given time-interval. This interface is flexible, but inherently inefficient for continuous operation because
of its polling nature.
The RBS also provides a publication/subscription mechanism that allows for push notifications to third-party clients
whenever there is an update to position or sensor data.
Details for each of these interfaces are provided in their respective sections below.
Page 3
Describe the model for interacting with the system. How is data stored? How do we retrieve it?
3.1 Locations
3.1.1 Get all the locations
GET /locations.json
[
{
"id": 1,
"name": "Default Building",
"description": "Default City",
"latitude": 39.9173,
"longitude": 116.441,
"elevation": 0.0,
"street_address": "123 Main St",
"street_address2": null,
"city": "Default City",
"state": "Earth",
"zip": 123456,
Page 4
"zip4": null,
"model_name": "",
"rpl_prefix": 1,
"rpl_version": 0,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
}
]
GET /locations/:id.json
{
"id": 1,
"name": "Default Building",
"description": "Default City",
"latitude": 39.9173,
"longitude": 116.441,
"elevation": 0.0,
"street_address": "123 Main St",
"street_address2": null,
"city": "Default City",
"state": "Earth",
"zip": 123456,
"zip4": null,
"model_name": "",
"rpl_prefix": 1,
"rpl_version": 0,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
}
Parameters:
3.2 Sub-locations
3.2.1 Get all the sub-locations
GET /sublocations.json
[
{
"id": 1,
"name": "Floor #1",
"description": "Office park, floor #1",
"location_id": 1,
"created_at": "2014-06-20T07:41:01.000Z",
Page 5
"updated_at": "2014-06-20T07:41:01.000Z"
},
{
"id": 2,
"name": "Floor #2",
"description": "Office park, floor #2",
"location_id": 1,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
}
]
GET /sublocations/:id.json
{
"id": 1,
"name": "Floor #1",
"description": "Office park, floor #1",
"location_id": 1,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
}
Parameters:
GET /locations/:id/sublocations.json
[
{
"id": 1,
"name": "Floor #1",
"description": "Office park, floor #1",
"location_id": 1,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
},
{
"id": 2,
"name": "Floor #2",
"description": "Office park, floor #2",
"location_id": 1,
"created_at": "2014-06-20T07:41:01.000Z",
"updated_at": "2014-06-20T07:41:01.000Z"
}
]
Page 6
Parameters:
3.3 Nodes
3.3.1 Get all the nodes
GET /nodes.json
[
{
"announce_timestamp": "2013-10-24T02:58:13Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:52:47Z",
"id": 22,
"last_heard": "2013-10-24T02:58:23Z",
"mac_address": "00cd00fffe000229",
"name": "M #229",
"node_type_id": 2,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "2013-10-24T02:58:23Z",
"position_x": 239,
"position_y": 359,
"position_z": 120,
"ranging_frequency": 4,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
"sequence_number": 0,
"sublocation_id": 1,
"updated_at": "2013-10-24T02:58:23Z",
"current_system_timestamp": "2013-10-24T02:58:23+00:00"
},
{
"announce_timestamp": "2013-10-24T02:59:35Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:51:15Z",
"id": 20,
"last_heard": "2013-10-24T02:59:35Z",
"mac_address": "00cd00fffe000273",
"name": "F #273",
"node_type_id": 1,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 128,
"position_y": 942,
"position_z": 30,
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
Page 7
"sequence_number": 0,
"sublocation_id": 1,
"updated_at": "2013-10-24T02:59:35Z",
"current_system_timestamp": "2013-10-24T02:59:36+00:00"
},
{
"announce_timestamp": "2013-10-24T02:59:27Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:51:15Z",
"id": 21,
"last_heard": "2013-10-24T02:59:27Z",
"mac_address": "00cd00fffe000280",
"name": "F #280",
"node_type_id": 1,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 66,
"position_y": 0,
"position_z": 30,
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
"sequence_number": 0,
"sublocation_id": 1,
"updated_at": "2013-10-24T02:59:27Z",
"current_system_timestamp": "2013-10-24T02:59:36+00:00"
},
...
]
Returns a list of nodes which have sent a heartbeat message within a specific interval regardless of location and
sub-location.
GET /nodes/recent.json?interval=:timespec
[
{
"announce_timestamp": "2013-10-24T03:14:20Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-09-25T04:34:39Z",
"id": 18,
"last_heard": "2013-10-24T03:14:20Z",
"mac_address": "00cd00fffe000248",
"name": "B #248",
"node_type_id": 4,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 315,
"position_y": 444,
"position_z": 30,
"ranging_frequency": 0,
Page 8
"reporting_frequency": 10,
"root_formed": true ,
"root_formed_timestamp": "2013-10-23T02:03:08Z",
"sequence_number": 0,
"sublocation_id": 1,
"updated_at": "2013-10-24T03:14:20Z",
"current_system_timestamp": "2013-10-24T03:14:24+00:00"
},
{
"announce_timestamp": "2013-10-24T03:14:18Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:52:47Z",
"id": 22,
"last_heard": "2013-10-24T03:14:24Z",
"mac_address": "00cd00fffe000229",
"name": "M #229",
"node_type_id": 2,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "2013-10-24T03:14:24Z",
"position_x": 237,
"position_y": 360,
"position_z": 120,
"ranging_frequency": 4,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
"sequence_number": 0,
"sublocation_id": "1",
"updated_at": "2013-10-24T03:14:24Z",
"current_system_timestamp": "2013-10-24T03:14:24+00:00"
}
]
Parameters:
timespec (optional) - The time specification in seconds (s), minutes (m), hours (h), or days (d), e.g. 5s stands
5 seconds, 5m stands for 5 minutes, 5h stands for 5 hours, 5d stands for 5 days. The parameter is optional, with
the default specified by the
dr2.yml
15m.
default_node_time_interval.
GET /nodes/mobile.json
[
{
"announce_timestamp": "2013-10-24T03:24:30Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:52:47Z",
"id": 22,
"last_heard": "2013-10-24T03:24:34Z",
"mac_address": "00cd00fffe000229",
Page 9
timespec (optional) - ?interval=:timespec The time specification in seconds (s), minutes (m), hours
(h), or days (d), e.g. 5s stands 5 seconds, 5m stands for 5 minutes, 5h stands for 5 hours, 5d stands for 5
days. If the interval is not specified, all mobiles nodes will be listed, regardless of recent activity.
GET /nodes/fixed.json
[
{
"announce_timestamp": "2013-10-24T03:35:48Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-09-19T08:27:38Z",
"id": 13,
"last_heard": "2013-10-24T03:35:48Z",
"mac_address": "00cd00fffe000226",
"name": "F #226",
"node_type_id": 1,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": -5,
"position_y": 278,
"position_z": 30,
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
"sequence_number": 0,
"sublocation_id": 1,
"sw_version": "0",
"updated_at": "2013-10-24T03:35:48Z",
"current_system_timestamp": "2013-10-24T03:35:49+00:00"
Page 10
},
{
"announce_timestamp": "2013-10-24T03:35:49Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-10-11T05:51:15Z",
"id": 20,
"last_heard": "2013-10-24T03:35:49Z",
"mac_address": "00cd00fffe000273",
"name": "F #273",
"node_type_id": 1,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 128,
"position_y": 942,
"position_z": 30,
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": false ,
"root_formed_timestamp": "1970-01-01T00:00:00Z",
"sequence_number": 0,
"sublocation_id": 1,
"sw_version": "0",
"updated_at": "2013-10-24T03:35:49Z",
"current_system_timestamp": "2013-10-24T03:35:49+00:00"
}
]
Parameters:
timespec (optional) - ?interval=:timespec The time specification in seconds (s), minutes (m), hours
(h), or days (d), e.g. 5s stands 5 seconds, 5m stands for 5 minutes, 5h stands for 5 hours, 5d stands for 5
days. If the interval is not specified, all mobiles nodes will be listed, regardless of recent activity.
GET /nodes/bridge.json
[
{
"announce_timestamp": "2013-10-24T03:38:15Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-09-25T04:34:39Z",
"id": 18,
"last_heard": "2013-10-24T03:38:15Z",
"mac_address": "00cd00fffe000248",
"name": "B #248",
"node_type_id": 4,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 315,
"position_y": 444,
"position_z": 30,
Page 11
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": true ,
"root_formed_timestamp": "2013-10-23T02:03:08Z",
"sequence_number": 0,
"sublocation_id": 1,
"sw_version": "0",
"updated_at": "2013-10-24T03:38:15Z",
"current_system_timestamp": "2013-10-24T03:38:16+00:00"
}
]
Parameters:
timespec (optional) - ?interval=:timespec the time specification in seconds (s), minutes (m), hours
(h), or days (d), e.g. 5s stands 5 seconds, 5m stands for 5 minutes, 5h stands for 5 hours, 5d stands for 5
days. If the interval is not specified, all mobiles nodes will be listed, regardless of recent activity.
GET /sublocation/:sublocation_id/bridge.json
[
{
"announce_timestamp": "2013-10-24T03:46:38Z",
"bridge_mac_address": "00cd00fffe000248",
"created_at": "2013-09-25T04:34:39Z",
"id": 18,
"last_heard": "2013-10-24T03:46:38Z",
"mac_address": "00cd00fffe000248",
"name": "B #248",
"node_type_id": 4,
"parent_mac_address": "00cd00fffe000248",
"position_update_timestamp": "1970-01-01T00:00:00Z",
"position_x": 315,
"position_y": 444,
"position_z": 30,
"ranging_frequency": 0,
"reporting_frequency": 10,
"root_formed": true ,
"root_formed_timestamp": "2013-10-23T02:03:08Z",
"sequence_number": 0,
"sublocation_id": 1,
"sw_version": "0",
"updated_at": "2013-10-24T03:46:38Z",
"current_system_timestamp": "2013-10-24T03:46:43+00:00"
}
]
Parameters:
sublocation_id (required) - The id of the sublocation in which the bridge(s) are configured.
Page 12
GET /node/mac/:mac_address/photo.json?interval=1h
[
{
"created_at": "2012-12-10T22:42:23Z",
"id": 5,
"image":
{
"url": "/uploads/photo/image/1/1355179343-test.jpg",
"name": nil,
"node_id": 1,
"updated_at": "2012-12-10T22:42:23Z"
}
}
]
Parameters:
3.4 Sensors
3.4.1 Get all the sensors types on a given node
GET /nodes/:node_id/show-sensor-types
[
{
"bit_width": 16,
"created_at": "2013-09-18T06:09:14Z",
"description": "Not Used: ADC0: Light sensor",
"formula": null,
"id": 1,
"name": "Not Used: ADC0: Light",
"updated_at": "2013-09-18T06:09:14Z",
"use_formula": false
},
{
"bit_width": 16,
"created_at": "2013-09-18T06:09:14Z",
"description": "ADC1: Temperature sensor deg C",
"formula": null,
"id": 2,
"name": "ADC1: Temperature",
"updated_at": "2013-09-18T06:09:14Z",
"use_formula": false
},
{
"bit_width": 16,
Page 13
"created_at": "2013-09-18T06:09:14Z",
"description": "Not Used: ADC2",
"formula": null,
"id": 3,
"name": "Not Used: ADC2",
"updated_at": "2013-09-18T06:09:14Z",
"use_formula": false
},
{
"bit_width": 16,
"created_at": "2013-09-18T06:09:14Z",
"description": "ADC3: Battery in mV",
"formula": null,
"id": 4,
"name": "ADC3: Battery",
"updated_at": "2013-09-18T06:09:14Z",
"use_formula": false
},
{
"bit_width": 16,
"created_at": "2013-09-18T06:09:14Z",
"description": "The panic button",
"formula": null,
"id": 5,
"name": "Pushbutton",
"updated_at": "2013-09-18T06:09:14Z",
"use_formula": false
}
]
Parameters:
List the sensor values on a given node during the default interval or specified interval. The parameter is optional, with
the default specified by the
parameters default value is
dr2.yml
15m.
default_node_time_interval.
The
GET /nodes/:node_id/show-sensor-readings(?interval=:timespec)
[
{
"created_at": "2013-10-24T11:52:41Z",
"id": 236791,
"node_id": 22,
"reading": 8,
"sensor_type_id": 1,
"sequence": 52,
"updated_at": "2013-10-24T11:52:41Z"
},
...
]
Page 14
Parameters:
dr2.yml
15m.
default_node_time_interval.
GET /nodes/:node_id/get_diag.json(?interval=timespec)
[
{
"crc_bad": 2,
"crc_good": 56,
"created_at": "2013-01-17T00:23:09Z",
"id": 3,
"node_id": 5,
"packet_header_errors": 6,
"preamble_errors": 0,
"rx_sync_loss": 2,
"sfdto_errors": 0,
"tx_count": 33,
"updated_at": "2013-01-17T00:23:09Z"
}
]
Parameters:
dr2.yml
15m.
default_node_time_interval.
Returns a list of the link quality measurements originated from a given node.
GET /nodes/:node_id/get_link_qual.json(?interval=timespec)
[
{
"created_at": "2013-01-16T23:23:18Z",
"dst_node_id": 4,
"id": 1,
"rx_count": 9,
"src_node_id": 5,
"test_timestamp": "2013-01-16T23:23:18Z",
Page 15
"tx_count": 10,
"updated_at": "2013-01-16T23:23:18Z"
}
]
Parameters:
dr2.yml
15m.
default_node_time_interval.
Page 16
Publish/Subscribe Interface
require 'rbczmq'
PUB_SUB_COUNT = 100
context = ZMQ::Context.new
# Socket to talk to server
puts 'Collecting updates from weather server'
subscriber = context.socket :SUB
subscriber.connect('tcp://192.168.56.20:7001')
# subscribe to both sensor and position updates
subscriber.subscribe('')
# Sensor updates will be of format:
#
# channel time_epoch,node_id,datum_sequence_number,
number_of_sensor_readings,sensor1,sensor2,sensor3,sensor4,sensor5
#
# Did you see that channel is separated by space from the rest of data?
# So you will see something like:
#
# #sensor 1400111899,18,0,5,0,65515,0,65480,0
#
# 5th sensor is wired to be a push button
#
# Position updates will be of format:
#
# channel time_epoch,node_id,position_x,position_y,position_z,
sublocation_id
#
# #position 1400111899,18,100,100,100,1
1.upto(PUB_SUB_COUNT) do |update_nbr|
s = subscriber.recv
puts "received: #{s}"
end
4.2 Example C++ Subscriber
#include <zmq.hpp>
Page 17
#include <iostream>
#include <sstream>
// Need https://github.com/zeromq/cppzmq.git somewhere
// g++ ./rtls-cpp-subscriber.cpp -o rtls-cpp-subscriber -I /usr/local/opt/
zeromq/include -lzmq
//
int main (int argc, char *argv[])
{
zmq::context_t context (1);
Page 18
Non-REST API
Page 19
Contact
Page 20
References
Page 21