device location - fcorthay/xPL GitHub Wiki

Global Navigation Satellite Systems (GNSS) allows to determine the geographic coordinates of a device. Smartphone applications such as Sensor Logger or GPSLogger allow to send GNSS data to a personal server.

Table of Contents

Smartphone app setup

Whilst the HTTP POST method should create a new resource together with its value on the server, the PUT method solely updates the value of a resource. This is why locator apps are configured to use a POST request.

Sensor Logger

Sensor Logger runs on Android and iOS. It can be setup to send POST requests at the rate of 1 per second. Other rates require a subscription to be enabled.

Setup :

  • Logger tab
    • Location : on
    • Gear > Data Streaming
      • Enable HTTP Push : on
      • Push URL : http://server_address:service_port/device_namesensorLogger
    • Start recording button tap
The device_name is obviously set to determine which smartphone (or other device) is posting the location information. The sensorLogger subpath provides the information about the posted data structure.

The JSON data looks like:

b'{
  "messageId":109,
  "sessionId":"50946e48-77fa-49bd-8078-d5cfd12a1a16",
  "deviceId":"391c69b0-dc5f-4b54-b77c-f8cf16b16572",
  "payload":[
    {
      "values":
        {
          "bearingAccuracy":0,
          "speedAccuracy":1.5,
          "verticalAccuracy":1,
          "horizontalAccuracy":17.211000442504883,
          "speed":0.000000000000000000,
          "bearing":0,
          "altitude":0.0000000000,
          "longitude":0.0000000,
          "latitude":0.0000000
        },
      "name":"location",
      "time":1000000000000000000
    }
  ]
}'

GPSLogger

GPSLogger runs on Android only. It doesn't work with no GPS signal, e.g. inside some buildings.

Setup :

  • 3-bar menu > Logging details
    • Log to custom URL : on
      • URL : http://server_address:service_port/device_name/gpsLogger?latitude=%LAT&longitude=%LON&altitude=%ALT&time=%TIME&speed=%SPD
      • HTTP Method : POST
    • Performance
    • Log GPS/GNSS locations : on
    • Logging interval : 60 seconds
    • Accuracy filter : 100 m
    • Duration to match accuracy : 10 seconds
    • Absolute time to GPS fix accuracy : 15 seconds
  • Simple View tab
    • START LOGGING button tap
Here too, the gpsLogger subpath provides the information about the parameters' structure.

The HTTP parameters look like:

latitude=0.00000000&longitude=0.00000000&altitude=0.00000000000&time=2024-01-01T01:00:00.000Z&speed=0.0

Location service

Requirements

Drawing a map requires the NumPy and Matplotlib libraries. Install them:

sudo apt install -y python3-numpy
sudo apt install -y python3-matplotlib

Recording

Start the location service with:

XPL_BASE_DIR=~/Controls/xPL
$XPL_BASE_DIR/utilities/xpl-location.py -v

Start the locator app and enable recording. The service shows the reception of the messages.

Simulate a Sensor Logger location message (adapt):

LOCATION_SERVER='192.168.1.5'
LOCATION_PORT='8003'
DEVICE='FP3'
LOCATOR_APP='sensorLogger'
LATITUDE='46.2331'
LONGITUDE='7.3606'
ALTITUDE='500'
EPOCH=`date -d '01/01/2024 01:00:00' +"%s"`
EPOCH="${EPOCH}000000000"
locationData="{\"messageId\":1,\"sessionId\":\"12345678\",\"deviceId\":\"12345678\",\"payload\":[{\"values\":{\"bearingAccuracy\":1,\"speedAccuracy\":1,\"verticalAccuracy\":1,\"horizontalAccuracy\":1,\"speed\":0,\"bearing\":0,\"altitude\":$ALTITUDE,\"longitude\":$LONGITUDE,\"latitude\":$LATITUDE},\"name\":\"location\",\"time\":$EPOCH}]}"
curl --request POST -H 'Content-Type: application/json' -d $locationData "http://$LOCATION_SERVER:$LOCATION_PORT/$DEVICE/$LOCATOR_APP"

Simulate a GPSLogger location message (adapt):

LOCATION_SERVER='192.168.1.5'
LOCATION_PORT='8003'
DEVICE='FP3'
LOCATOR_APP='gpsLogger'
LATITUDE='46.2331'
LONGITUDE='7.3606'
ALTITUDE='500'
TIME=`date +"%Y-%m-%dT%H:%M:%S%:z"`
locationData="latitude=$LATITUDE&longitude=$LONGITUDE&altitude=$ALTITUDE&time=$TIME&speed=0.0"
curl --request POST "http://$LOCATION_SERVER:$LOCATION_PORT/$DEVICE/$LOCATOR_APP?$locationData"

Displaying a map

The plotting of a map is done by projecting the spherical coordinates onto a plane tangent to the earth at a specified reference point. Requesting for a map is done via a GET request.

The script locations/buildMap.py creates a map out of the coordinates provided in a log file. It is possible to run it manually:

XPL_BASE_DIR=~/Controls/xPL
LONGITUDE='7.3606'
LATITUDE='46.2331'
ALTITUDE='500'
LOG_FILE="$XPL_BASE_DIR/utilities/locations/test.log"
$XPL_BASE_DIR/utilities/locations/buildMap.py -x $LONGITUDE -y $LATITUDE -z $ALTITUDE -f $LOG_FILE -v

Yet, showing a map is best done by asking for it in a browser with an URL in the form of http://server_address:service_port/device_name.

xPL triggers

The xpl-location script receives the argument distances. They are given in meters and separated by commas. The first and last distance values of the list allow to trigger an xPL message. They work as a Schmitt trigger. If the distance gets greater than the last distance of the list, a message is sent. From that moment, if the distance gets smaller than the first distance of the list, a message is sent and the distance is compared anew with the last distance of the list.

Used in conjunction with the central control service, this allows to automate tasks such as opening a garage door on the way home.

The distances are also shown as circles on the generated map.

Clearing a recording

Clearing a recording can be done before starting a trip. Clearing a recording is done with a DELETE request:

LOCATION_SERVER='192.168.1.5'
LOCATION_PORT='8003'
DEVICE='FP3'
curl --request DELETE "http://$LOCATION_SERVER:$LOCATION_PORT/$DEVICE"

Updating the reference point

The reference point is used to define the zero coordinate on the generated map. Updating the value of a resource is done with a PUT request.

LOCATION_SERVER='192.168.1.5'
LOCATION_PORT='8003'
NEW_LATITUDE='45'
curl --request PUT --header 'Content-Type: application/json' -d "{\"latitude\": \"$NEW_LATITUDE\"}" "http://$LOCATION_SERVER:$LOCATION_PORT/reference"
⚠️ **GitHub.com Fallback** ⚠️