Linking Life360 and OH2 gpstracker [a simple script]

My family are on Life360, and I wanted to use gpstracker to manage presence, so I modified the ubiquitous Life360/mqtt script to post directly to gpstracker via HTTP.

Here’s a link to the code: https://gitlab.com/snippets/1865020

and for those that enjoy cut and paste:

#!/bin/bash

username360="xxxxx"
password360="yyyyy"

function check_error() {
    local error=$?
    if [ $error -ne 0 ]; then
        echo "error in $1: $error"
    fi
}

function bearer() {
    echo "$(date +%s) INFO: requesting access token"
    bearer_id=$(curl -s -X POST -H "Authorization: Basic cFJFcXVnYWJSZXRyZTRFc3RldGhlcnVmcmVQdW1hbUV4dWNyRUh1YzptM2ZydXBSZXRSZXN3ZXJFQ2hBUHJFOTZxYWtFZHI0Vg==" -F "grant_type=password" -F "username=$username360" -F "password=$password360" https://api.life360.com/v3/oauth2/token.json | ggrep -Po '(?<="access_token":")\w*')
    check_error bearer
}

function circles() {
    echo "$(date +%s) INFO: requesting circles."
    read -a circles_id <<<$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles.json | ggrep -Po '(?<="id":")[\w-]*')
    check_error circles
}

function members() {
    echo "$(date +%s) INFO: requesting members"
    members=$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles/$2)
    check_error member
}

function get_circles() {
    bearer
    circles $bearer_id
    if [ -z "$circles_id" ]; then
        get_circles
    fi
}

function get_members() {
    members $1 $2
    if [ -z "$members" ]; then
        get_circles
        get_members
    fi
}

get_circles

#Loop through circle ids
for i in "${circles_id[0]}"; do # @ is made 0 to include Family group only

    #request member list
    get_members $bearer_id $i

    members_id=$(echo $members | jq '.members[].id')
    IFS=$'\n' read -rd '' -a members_array <<<"$members_id"
    count=0
    for i in "${members_array[@]}"; do
        firstName=$(echo $members | jq .members[$count].firstName)
        lastName=$( echo $members | jq .members[$count].lastName)
        latitude=$( echo $members | jq .members[$count].location.latitude)
        longitude=$(echo $members | jq .members[$count].location.longitude)
        accuracy=$( echo $members | jq .members[$count].location.accuracy)
        battery=$(  echo $members | jq .members[$count].location.battery)
        timestamp=$(echo $members | jq .members[$count].location.timestamp)

        # change the following line if the first and last initials are
        # not unique in your Life360 family group

        tid=${firstName:1:1}${lastName:1:1}

        curl -H "Content-type: application/json" \
             -s -S \
             -d "{ \
                  \"_type\":\"location\", \
                  \"tid\":  \"$tid\",     \
                  \"tst\":  $timestamp,   \
                  \"lon\":  $longitude,   \
                  \"lat\":  $latitude,    \
                  \"batt\": $battery,     \
                  \"acc\":  $accuracy     \
                }" \
             http://192.168.0.120:8080/gpstracker/gpslogger >/dev/null

        check_error "sending $tid to gpstracker"
        count=$(($count + 1))
    done
done

echo "$(date +%s) INFO: done"
2 Likes

Thanks for posting! I’ve moved the post to the Tutorials and Examples category.

1 Like

I keep getting the error “ggrep: command not found” when I try and execute the script. I see the ggrep command at the end of the line getting the bearer_id and without that, the rest of the script fails as would be expected.

I’ve tried doing apt-get install ggrep, but I get “Unable to locate package ggrep”. I have also googled around a little to figure out ggrep is and all google gives me is info on grep. I am running on Rasbian.

Never mind. I just did a find and replace all instances of “ggrep” with “grep” and it looks like the script is working. Now time to try and hook it up with the binding.

Yeah, sorry about that. On my Mac, ggrep is gnu grep.

@Dave_Thomas thank you so much for this. This was a million times easier to set up and work with than “Life360 and MQTT”. These are the steps I took to get this setup and running.

  1. SSH into my openhabianpi using putty. I created a new script sudo nano /etc/openhab2/scripts/life360_presence.sh
  2. Paste in @Dave_Thomas’s script from above with some minor changes.
    2.1 change all occurrences of ggrep to grep there are two
    2.2 change the IP address http://192.168.0.120:8080/gpstracker/gpslogger >/dev/null to http://127.0.0.1:8080/gpstracker/gpslogger >/dev/null
  3. Add execute permissions to the script sudo chmod +x /etc/openhab2/scripts/life360_presence.sh
    3.1 You can test the script /etc/openhab2/scripts/life360_presence.sh
  4. Now we want to run the script on a timer. I set mine to run once a minute.
    4.1 Open crontab crontab -e and add the line */1 * * * * /etc/openhab2/scripts/life360_presence.sh >/dev/null 2>&1. Then exit and save.
    4.2 Restart crontab service cron reload
  5. Go into the paper UI and install the “GPSTracker Binding”
  6. Once the binding is installed you should automatically see each member of your family circle from life360 (They will show as GPS Tracker initials) appear in your inbox.
  7. Now you can work with this data the same as you would with the standard “GPSTracker Binding”

Thank you again @Dave_Thomas I have you give you all the credit for getting this working so easily for me.

3 Likes

@Jacob_Weigand , so just to make sure, the script should look like this ?

#!/bin/bash

username360="my email"
password360="my pass"

function check_error() {
    local error=$?
    if [ $error -ne 0 ]; then
        echo "error in $1: $error"
    fi
}

function bearer() {
    echo "$(date +%s) INFO: requesting access token"
    bearer_id=$(curl -s -X POST -H "Authorization: Basic cFJFcXVnYWJSZXRyZTRFc3RldGhlcnVmcmVQdW1hbUV4dWNyRUh1YzptM2ZydXBSZXRSZXN3ZXJFQ2hBUHJFOTZxYWtFZHI0Vg==" -F "grant_type=password" -F "username=$username360" -F "password=$password360" https://api.life360.com/v3/oauth2/token.json | grep -Po '(?<="access_token":")\w*')
    check_error bearer
}

function circles() {
    echo "$(date +%s) INFO: requesting circles."
    read -a circles_id <<<$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles.json | grep -Po '(?<="id":")[\w-]*')
    check_error circles
}

function members() {
    echo "$(date +%s) INFO: requesting members"
    members=$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles/$2)
    check_error member
}

function get_circles() {
    bearer
    circles $bearer_id
    if [ -z "$circles_id" ]; then
        get_circles
    fi
}

function get_members() {
    members $1 $2
    if [ -z "$members" ]; then
        get_circles
        get_members
    fi
}

get_circles

#Loop through circle ids
for i in "${circles_id[0]}"; do # @ is made 0 to include Family group only

    #request member list
    get_members $bearer_id $i

    members_id=$(echo $members | jq '.members[].id')
    IFS=$'\n' read -rd '' -a members_array <<<"$members_id"
    count=0
    for i in "${members_array[@]}"; do
        firstName=$(echo $members | jq .members[$count].firstName)
        lastName=$( echo $members | jq .members[$count].lastName)
        latitude=$( echo $members | jq .members[$count].location.latitude)
        longitude=$(echo $members | jq .members[$count].location.longitude)
        accuracy=$( echo $members | jq .members[$count].location.accuracy)
        battery=$(  echo $members | jq .members[$count].location.battery)
        timestamp=$(echo $members | jq .members[$count].location.timestamp)

        # change the following line if the first and last initials are
        # not unique in your Life360 family group

        tid=${firstName:1:1}${lastName:1:1}

        curl -H "Content-type: application/json" \
             -s -S \
             -d "{ \
                  \"_type\":\"location\", \
                  \"tid\":  \"$tid\",     \
                  \"tst\":  $timestamp,   \
                  \"lon\":  $longitude,   \
                  \"lat\":  $latitude,    \
                  \"batt\": $battery,     \
                  \"acc\":  $accuracy     \
                }" \
             http://127.0.0.1:8080/gpstracker/gpslogger >/dev/null

        check_error "sending $tid to gpstracker"
        count=$(($count + 1))
    done
done

echo "$(date +%s) INFO: done"

That looks correct, but here is my copy just in case I missed something

#!/bin/bash

username360="my email"
password360="my pass"
openhabIP="127.0.0.1:8080"

function check_error() {
    local error=$?
    if [ $error -ne 0 ]; then
        echo "error in $1: $error"
    fi
}

function bearer() {
    echo "$(date +%s) INFO: requesting access token"
    bearer_id=$(curl -s -X POST -H "Authorization: Basic cFJFcXVnYWJSZXRyZTRFc3RldGhlcnVmcmVQdW1hbUV4dWNyRUh1YzptM2ZydXBSZXRSZXN3ZXJFQ2hBUHJFOTZxYWtFZHI0Vg==" -F "grant_type=password" -F "username=$username360" -F "password=$password360" https://api.life360.com/v3/oauth2/token.json | grep -Po '(?<="access_token":")\w*')
    check_error bearer
}

function circles() {
    echo "$(date +%s) INFO: requesting circles."
    read -a circles_id <<<$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles.json | grep -Po '(?<="id":")[\w-]*')
    check_error circles
}

function members() {
    echo "$(date +%s) INFO: requesting members"
    members=$(curl -s -X GET -H "Authorization: Bearer $1" https://api.life360.com/v3/circles/$2)
    check_error member
}

function get_circles() {
    bearer
    circles $bearer_id
    if [ -z "$circles_id" ]; then
        get_circles
    fi
}

function get_members() {
    members $1 $2
    if [ -z "$members" ]; then
        get_circles
        get_members
    fi
}

get_circles

#Loop through circle ids
for i in "${circles_id[0]}"; do # @ is made 0 to include Family group only

    #request member list
    get_members $bearer_id $i

    members_id=$(echo $members | jq '.members[].id')
    IFS=$'\n' read -rd '' -a members_array <<<"$members_id"
    count=0
    for i in "${members_array[@]}"; do
        firstName=$(echo $members | jq .members[$count].firstName)
        lastName=$( echo $members | jq .members[$count].lastName)
        latitude=$( echo $members | jq .members[$count].location.latitude)
        longitude=$(echo $members | jq .members[$count].location.longitude)
        accuracy=$( echo $members | jq .members[$count].location.accuracy)
        battery=$(  echo $members | jq .members[$count].location.battery)
        timestamp=$(echo $members | jq .members[$count].location.timestamp)

        # change the following line if the first and last initials are
        # not unique in your Life360 family group

        tid=${firstName:1:1}${lastName:1:1}

        curl -H "Content-type: application/json" \
             -s -S \
             -d "{ \
                  \"_type\":\"location\", \
                  \"tid\":  $tid,     \
                  \"tst\":  $timestamp,   \
                  \"lon\":  $longitude,   \
                  \"lat\":  $latitude,    \
                  \"batt\": $battery,     \
                  \"acc\":  $accuracy     \
                }" \
             http://$openhabIP/gpstracker/gpslogger >/dev/null

        check_error "sending $tid to gpstracker"
        count=$(($count + 1))
    done
done

echo "$(date +%s) INFO: done"

Thanks for posting the steps, I had no idea where or how to copy and paste the script good job