Custom URL logger to OwnTracks with speed in km/h
Closed this issue · 7 comments
I'm using GPSLogger as a client for my OwnTracks recorder server. I prefer GPSLogger because the android app for OwnTracks is more focused on location sharing and is also not able to log everything to a gpx file.
I use the custom URL logger in POST mode, pointing to the /pub
endpoint of my OwnTracks server. The HTTP payload (json):
{
"_type": "location",
"lat": %LAT,
"lon": %LON,
"vel": %SPD,
...
}
It works like a charm, with one totally unnecessary problem: The OwnTracks ecosystem expects the velocity in km/h. They might have reasons for that. But for now, GPSLogger and OwnTracks are incompatible because neither of them is configurable.
I decided to open this issue here because (a) the OwnTracks ecosystem does not really encourage using a third-party app and (b) GPSLogger already works well with custom setups.
I have two ways in mind that I could implement to make this work:
- Add another variable to the custom URL logger like
%SPEED_KMH
(%SPD_KMH
would probably not work, as replacing%SPD
might run first, right?). This would be a very small change. Though, having different variables for different units might clutter this functionality. - Add a setting for the custom URL logger to make the unit configurable. The setting could include "m/s", "km/h" and maybe even "mph" or "knots". And depending on what the user has selected,
%SPD
will be replaced by the converted value.
Tell me what you think about this. I tend towards the second option. But no matter what we decide, I can implement it and open a pull request afterwards.
I think I understand, did I get it right: although OwnTracks wants you to use their clients, GPSLogger is thiiiiis close to letting you use it as an unofficial client to push locations.
I think I won't mind the first option in a PR, which is a specific variable just for this. The variables list is already 'cluttered', and it has some duplicates for other things too, so one more is fine. Introducing per-variable configuration can get confusing.
I'd prefer the name %SPD_KPH
and it shouldn't be a problem having that "SPD" overlap, just put SPD_KPH in the replacement block before SPD. Here's an example with TIMESTAMP before TIME.
One more thing, because I'm introducing a big change, please could you do your PR against this branch: android_workmanager
. As you can see in this PR,
I'm switching to WorkManager so I'd like to test them together.
Now I have some questions. OwnTracks looks interesting, how strange that I'm only aware of it now (it's been mentioned before but I never searched for it). Do you host it yourself? I think there's a map feature which you can host on a custom domain, does it come with authentication? It looks like something you could use on a walking holiday to share your location or just view for yourself.
Thanks for the insights! And yes, you got it right. With the correct unit of speed, GPSLogger would be a perfect unofficial client.
I missed that you're using a LinkedHashMap which has a predictable iteration order. So, I will implement %SPD_KPH
as a new variable and create the PR against that branch. No problem!
As for OwnTracks: (disclaimer: I'm new to OwnTracks, so the following might not be 100% correct)
The core of OwnTracks is the recorder. It's a server that accepts and delivers JSON. You can publish your location and query different users, devices, timespans, regions and whatever (either by http, mqtt or command-line tooling). The frontend makes use of this data and provides a simple web-ui with a map. They provide docker images which I selfhost. I think you can configure some authentication, but I already have everything behind an nginx reverse proxy that requires basic auth.
I want to use this setup to publish my location during day trips so my friends and family can see where I am in realtime (log interval < 60s) on a very simple map.
Test APK is here:
https://github.com/mendhak/gpslogger/releases/tag/v131-rc2
Note that if you use the FDroid version of this app, installing this is like new, so you'll lose previous data and settings.
Ah I tried setting up OwnTracks in Docker today but gave up.
The quickstart instructions didn't work, and the docker-compose-mqtt.yml didn't work either. The recorder is either unable to find the MQTT or connection gets refused.
Do you happen to have a working docker command or docker compose? If you happen to have one could you share it (it's OK if not, I'm mostly looking out of curiosity).
I also had troubles to set up docker and nginx on my server, but with some copy and paste from different guides I finally got it working.
~/owntracks/config/config.js (must exist before starting the frontend container)
// Here you can overwite the default configuration values
window.owntracks = window.owntracks || {};
window.owntracks.config = {
api: {
baseUrl: "https://[mydomain]/owntracks/",
},
router: {
basePath: "/owntracks",
},
};
~/owntracks/docker-compose.yml
services:
owntracks-ui:
image: owntracks/frontend
ports:
- 127.0.0.1:7000:80
volumes:
- ./config/config.js:/usr/share/nginx/html/config/config.js
environment:
- SERVER_HOST=otrecorder
- SERVER_PORT=8083
restart: unless-stopped
owntracks-recorder:
container_name: otrecorder
image: owntracks/recorder
environment:
- OTR_PORT=0 # disables MQTT
volumes:
- ./recorder/store:/store
- ./recorder/config:/config
ports:
- 127.0.0.1:8083:8083
restart: unless-stopped
nginx location fragments
location /owntracks/ {
proxy_pass http://127.0.0.1:7000/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_request_buffering off;
proxy_buffering off;
}
location /owntracks/ws {
proxy_pass http://127.0.0.1:7000/;
rewrite ^/owntracks/(.*) /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /owntracks/pub {
# send directly to recorder server
proxy_pass http://127.0.0.1:8083/;
rewrite ^/owntracks/(.*) /$1 break;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_request_buffering off;
proxy_buffering off;
}
I also had to create some folders because the recorder wasn't able to find stuff (maybe they get generated by publishing locations, but I tried the frontend first, so maybe it was just me)
- ~/owntracks/recorder/store/last
- ~/owntracks/recorder/store/rec
But with this setup I'm now able to view the map at https://[mydomain]/owntracks/
and publish my locations to https://[mydomain]/owntracks/pub
.
Yes that's it thanks! Finally got it working! The OTR_PORT=0 was the crucial missing bit, the docker image kept failing and I couldn't figure out from the docs what was missing, that was it.
For future reference my docker compose
services:
owntracks-ui:
image: owntracks/frontend
ports:
- 0.0.0.0:7000:80
volumes:
- ${PWD}/config.js:/usr/share/nginx/html/config/config.js
environment:
- SERVER_HOST=otrecorder
- SERVER_PORT=8083
restart: unless-stopped
owntracks-recorder:
container_name: otrecorder
image: owntracks/recorder
environment:
- OTR_PORT=0 # disables MQTT
volumes:
- ./recorder/store:/store
- ./recorder/config:/config
ports:
- 0.0.0.0:8083:8083
restart: unless-stopped
config.js
// Here you can overwite the default configuration values
window.owntracks = window.owntracks || {};
window.owntracks.config = {
api: {
baseUrl: "https://localhost:8083/owntracks/",
},
router: {
basePath: "/owntracks",
},
};
In GPSLogger:
URL: http://192.x.x.x:8083/pub?u=user&d=device1
HTTP Body:
{ "_type": "location",
"t": "u",
"lon": %LON,
"lat": %LAT,
"tid": "test",
"tst": %TIMESTAMP,
"batt": %BATT,
"cog": %DIR,
"vel": %SPD_KPH,
"topic": "owntracks/user/device1"
}
HTTP Headers: Content-Type: application/json
HTTP Method: POST
I'll have a play with this at some point and maybe even see if I could put some Cloudflare in front of this. eg, the UI authentication via OAuth, and somehow if I can get the /pub endpoint via different authentication mechanism. Make the IPs local, run it on a Raspberry Pi, etc.