Skip to content

Commit

Permalink
Merge pull request #19 from thin-edge/feat-add-location-script
Browse files Browse the repository at this point in the history
feat: add c8y_Position inventory script which uses ipinfo.io for estimated location information
  • Loading branch information
reubenmiller authored Dec 9, 2024
2 parents 59d619c + bcd02db commit 3580ba1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/scripts.d/80_c8y_Position
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/sh
#
# Get position/location information about the device using the ipinfo.io service
# The output is stored on disk to reduce number of requests to once per startup
#
# Example
# $ ./80_c8y_Position
# ip="8.8.8.8"
# city="Hamburg"
# country="DE"
# timezone="Europe/Berlin"
#

fail() {
rc=$1
shift
echo "${0}: $*" >&2
exit "$rc"
}

TIMEOUT=30 # Request timeout
TEMPFILE="/tmp/tedge/device-location"

# the names of the attributes holding the localization data can be configured here
ATTR_NAME_IP="ip"
ATTR_NAME_CITY="city"
ATTR_NAME_COUNTRY="country"
ATTR_NAME_TIMEZONE="timezone"
# the following two attributes denote latitude (geo-lat) and longitude (geo-lon)
# as returned by the ipinfo.io in the loc field (loc=latitude,longitude)
ATTR_NAME_LAT="lat"
ATTR_NAME_LON="lng"

# check for empty file
if [ -f "${TEMPFILE}" ] && [ -z "$(cat "${TEMPFILE}")" ]; then
echo "Removing empty file. path=${TEMPFILE}" >&2
rm -f "${TEMPFILE}"
fi

if [ ! -f "${TEMPFILE}" ]; then
ip_info=$(
wget \
--timeout=${TIMEOUT} -q -O /dev/stdout \
--header 'Accept: application/json' \
https://ipinfo.io
)
# shellcheck disable=SC2181
if [ "$?" != 0 ] || [ -z "${ip_info}" ]; then
fail 2 "Unable to get IP info from ipinfo.io"
fi

# Fetch and cache geo location data
mkdir -p "$(dirname "${TEMPFILE}")" || \
fail $? "Failed to create temporary storage for geo location data. path=${TEMPFILE}"

# Convert pretty printed JSON to key=value format
ip_info=$(
echo "${ip_info}" \
| awk -F ': ?' '/[^{}]/ {printf "%s=%s\n", $1, $2}' \
| sed 's/,$//g' \
| sed 's/^ *//g' \
| tr -d '"'
)

echo "${ip_info}" | \
awk -F'=' -v attr_ip="${ATTR_NAME_IP}" \
-v attr_city="${ATTR_NAME_CITY}" \
-v attr_lat="${ATTR_NAME_LAT}" \
-v attr_lon="${ATTR_NAME_LON}" \
-v attr_country="${ATTR_NAME_COUNTRY}" \
-v attr_zone="${ATTR_NAME_TIMEZONE}" '
$1 ~ /^ip/ {printf "%s=\"%s\"\n", attr_ip, $2};
$1 ~ /^loc/ {split($2,a,","); printf "%s=%s\n%s=%s\n", attr_lat, a[1], attr_lon, a[2]};
$1 ~ /^city/ {printf "%s=\"%s\"\n", attr_city, $2};
$1 ~ /^country/ {printf "%s=\"%s\"\n", attr_country, $2};
$1 ~ /^timezone/ {printf "%s=\"%s\"\n", attr_zone, $2};
' > "${TEMPFILE}"
else
echo "Using cached location file. path=${TEMPFILE}" >&2
fi

cat "$TEMPFILE"
exit $?
11 changes: 11 additions & 0 deletions tests/main/telemetry.robot
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ Inventory Script: Hardware information
Should Not Be Empty ${mo["c8y_Hardware"]["serialNumber"]}
Should Not Be Empty ${mo["c8y_Hardware"]["revision"]}

Inventory Script: Position information
${mo}= Cumulocity.Device Should Have Fragments c8y_Position timeout=90
Log ${mo["c8y_Position"]}
Should Not Be Empty ${mo["c8y_Position"]["ip"]}
Should Not Be Empty ${mo["c8y_Position"]["city"]}
Should Not Be Empty ${mo["c8y_Position"]["country"]}
Should Not Be Empty ${mo["c8y_Position"]["timezone"]}

Should Be True ${mo["c8y_Position"]["lat"]} != 0
Should Be True ${mo["c8y_Position"]["lng"]} != 0

*** Keywords ***

Custom Setup
Expand Down

0 comments on commit 3580ba1

Please sign in to comment.