Skip to content

Commit

Permalink
ffac-update-location-gp: initial package version
Browse files Browse the repository at this point in the history
* use bind and unbind to support coldplug
* restart micrond after adding service at runtime
  • Loading branch information
maurerle committed Jul 26, 2024
1 parent ed68c70 commit c49134d
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
22 changes: 22 additions & 0 deletions ffac-update-location-gps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: 2024 Florian Maurer, xelo
# SPDX-License-Identifier: MIT
include $(TOPDIR)/rules.mk

PKG_NAME:=ffac-update-location-gps
PKG_VERSION:=1.0
PKG_RELEASE:=1

PKG_LICENSE:=MIT

include $(TOPDIR)/../package/gluon.mk

define Package/$(PKG_NAME)
TITLE:=Use attached GPS controller to update location from it
DEPENDS:=+kmod-usb-core +kmod-usb-ohci +kmod-usb2 +kmod-usb-acm +kmod-usb-serial-pl2303 +micrond
endef

define Package/$(PKG_NAME)/description
If enabled, this package updates the gluon-node-info location based on the NMEA output of an attached GPS device.
endef

$(eval $(call BuildPackageGluon,$(PKG_NAME)))
22 changes: 22 additions & 0 deletions ffac-update-location-gps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ffac-update-location-gps

This package configures gluon to update the location based on tty output of an attached GPS device.

When a USB device which provides a tty is attached, it updates the location based on the output of it.
This is done using a lua rewrite of the script from the original forum posting.
It seems to work without coreutils-stty installed, which did fail the installation when selected as package dependency.

The location is only updated in memory - and only if a valid GPS fix is available.
After a reboot, the old location from the config is set.

## hotplug limitation

After a sysupgrade/autoupdate - the USB dongle has to be unplugged and plugged in once for the detection to work again.
For reboots, this works fine as is.

## further information

Further information can be found here:

* https://github.com/dmth/gluon-gps-locationupdate
* https://forum.freifunk.net/t/freifunk-location-update-via-gps/1493
2 changes: 2 additions & 0 deletions ffac-update-location-gps/files/etc/config/update-location-gps
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
config settings 'settings'
option enabled '0'
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/sh
TTYPATH="/sys${DEVPATH}/tty"
LOCKPATH="/tmp/update-location-gps"

ENABLED=$(uci get update-location-gps.settings.enabled)

if [ "${ACTION}" = "bind" ]; then
[ "${ENABLED}" != "1" ] && exit 0
test -e "${LOCKPATH}" && exit 0
if test -e "${TTYPATH}"; then
TTY_NAME=$(find "${TTYPATH}" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -n 's|.*/tty/||p')
logger -t hotplug "USB GPS device was plugged in"
echo "${DEVPATH}" > "${LOCKPATH}"
echo "*/5 * * * * /usr/bin/update-location-gps /dev/${TTY_NAME} | logger -t update-location-gps" > "/usr/lib/micron.d/update-location-gps"
/etc/init.d/micrond restart
fi
fi

if [ "${ACTION}" = "unbind" ]; then
if [ "${DEVPATH}" = "$(cat ${LOCKPATH})" ]; then
logger -t hotplug "USB GPS device was removed"
rm -f "/usr/lib/micron.d/update-location-gps"
/etc/init.d/micrond restart
rm "${LOCKPATH}"
fi
fi
78 changes: 78 additions & 0 deletions ffac-update-location-gps/luasrc/usr/bin/update-location-gps
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/lua

if not arg[1] then
print("Error: No /dev/tty* path specified. Please provide a TTY device path as the first argument.")
os.exit(1)
end

-- Get GPS device tty
local TTY_DEVICE = arg[1]

local uci = require('simple-uci').cursor()

-- Use GPS as Stream
local file = io.open(TTY_DEVICE, "r")

while true do
local this_line = file:read("*line")
if not this_line then break end -- Exit loop if no more lines

local nc = this_line:match("^([^,]+)")

if nc == '$GPRMC' then
local fields = {}
for field in this_line:gmatch("([^,]+)") do
table.insert(fields, field)
end

local valid = fields[3]

if valid == "A" then
-- First: Retrieve coordinate
local lat = fields[4]
local lon = fields[6]

-- Second: Determine if coordinate is oriented North/South or East/West
local latdir = fields[5]
local londir = fields[7]

-- Split DEGREES from coordinate
local latdeg = tonumber(lat:sub(1, 2))
local londeg = tonumber(lon:sub(1, 3))

-- Split MINUTES.SECONDS from coordinate
local latmin = tonumber(lat:sub(3))
local lonmin = tonumber(lon:sub(4))

-- Convert from Degree-Minutes to Decimal-Minutes
local latdec = latmin / 60
local londec = lonmin / 60

-- Use negative notation instead of North/South or East/West
if latdir == 'S' then
latdeg = -latdeg
end
if londir == 'W' then
londeg = -londeg
end
lat = string.format("%f", latdeg + latdec)
lon = string.format("%f", londeg + londec)

print("GPS position is valid Lat/Lon:", lat, lon)
-- set temp location in gluon-node-info
uci:set('gluon-node-info', '@location[0]', 'share_location', '1')
uci:set('gluon-node-info', '@location[0]', 'latitude', lat)
uci:set('gluon-node-info', '@location[0]', 'longitude', lon)
uci:save('gluon-node-info')
-- Link to Phip's comment: https://forum.freifunk.net/t/freifunk-location-update-via-gps/1493/2
-- Committing here would wear out the nvram very fast, so it should not be done.
break
else
print("GPS position is Invalid...", valid)
break
end
end
end

file:close()
os.exit(0)

0 comments on commit c49134d

Please sign in to comment.