Life360 and MQTT

Hello, i am trying to connect Life360 presence detection to my openhab. Just copied this script from a forum:

#!/bin/bash

#Set variables
username360="username"
password360="PASS"
mosquitto_pub="/path/to/mosquitto_pub"
mqtt_host="127.0.0.1"
mqtt_port="1883"
mqtt_user="USER"
mqtt_pass="PASS"
timeout=300


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*')
}

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-]*')
}

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

bearer
circles $bearer_id

#Main Loop
while :
do

#Check if circle id is valid. If not request new token.
if [ -z "$circles_id" ]; then
bearer
circles $bearer_id
fi

#Loop through circle ids
for i in "${circles_id[@]}"
do

#request member list
members $bearer_id $i

#Check if member array is valid. If not request new token
if [ -z "$members" ]; then
bearer
circles $bearer_id
members $bearer_id $i
fi

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)
    $mosquitto_pub -h $mqtt_host -p $mqtt_port -u $mqtt_user -P $mqtt_pass -t "owntracks/${firstName//\"/}/${i//\"/}" -m "{\"t\":\"p\",\"tst\":$(date +%s),\"acc\":${accuracy//\"/},\"_type\":\"location\",\"alt\":0,\"lon\":${longitude//\"/},\"lat\":${latitude//\"/},\"batt\": ${battery//\"/}}"
    count=$(($count+1))
done
done
sleep $timeout
done

and put it into conf/scripts folder. When i run the script it gives : "Error: Unknown option 'owntracks/…"
I really don’t know if i have to use owntracks or is this mosquitto_pub is defining something that i really need. What i really need is that i try to publish presence and battery status of the iphones that my family members have, in my openhab sitemap. But stuck at the MQTT part that i simply know nothing about. What will be the steps from this on? Any help appreciated…

OK Made it work. Leaving the mqtt_pass empty makes the script thought -t is the password and topic is an option. Silly mistake. :slight_smile:
You can get any status, lat, long, battery etc with an item including {mqtt="<[mosquitto:owntracks/Erkan:state:JSONPATH($.batt):.*]"}. However this script has to be run all the time in the background with nohup. Also, you can not get push messages from life360 like you do on owntracks. Time to decide whether i should go with life360 or owntracks…

So, i put this into use. For people who might want to use it instead of owntracks, since my whole family is currently using Life360 and it is not easy for me to convince them to use owntracks instead of Life360;

life360.sh:

#!/bin/bash

#Set variables
username360="Life360Username"
password360="Life360Password"
mosquitto_pub="/volume1/@appstore/mosquitto/bin/mosquitto_pub"
mqtt_host="127.0.0.1"
mqtt_port="1883"
mqtt_user="mosquitto"
mqtt_pass="mqtt_pass"
timeout=300


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*')
}

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-]*')
}

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

bearer
circles $bearer_id

#Check if circle id is valid. If not request new token.
if [ -z "$circles_id" ]; then
bearer
circles $bearer_id
fi

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

#request member list
members $bearer_id $i

#Check if member array is valid. If not request new token
if [ -z "$members" ]; then
bearer
circles $bearer_id
members $bearer_id $i
fi

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)
    locationname=$(echo $members | jq .members[$count].location.name)
    if [ "$locationname" = "\"Home"\" ]; then 
    locationname="ON"
    else
    locationname="OFF"
    fi
    $mosquitto_pub -h $mqtt_host -p $mqtt_port -u $mqtt_user -P $mqtt_pass -t "owntracks/${firstName//\"/}" -m "{\"t\":\"p\",\"tst\":$(date +%s),\"acc\":${accuracy//\"/},\"_type\":\"location\",\"alt\":0,\"lon\":${longitude//\"/},\"lat\":${latitude//\"/},\"batt\": ${battery//\"/},\"locname\": ${locationname//\"/}}"

#Forgot to put next line previously, will solve de ID problem   
    count=$(($count+1))

done
done

Life360.items:

Switch PresenceF_i360Home        "F @ Home [%s]"   {mqtt="<[mosquitto:owntracks/F:state:JSONPATH($.locname):.*]"}
Switch PresenceD_i360Home        "D @ Home [%s]"   {mqtt="<[mosquitto:owntracks/D:state:JSONPATH($.locname):.*]"}
Switch PresenceH_i360Home        "H @ Home [%s]"   {mqtt="<[mosquitto:owntracks/H:state:JSONPATH($.locname):.*]"}

myhome.sitemap:

               Text item=FamilyPresence  label="Presence" icon="athome" {
			Frame {
			    Text item=PresenceF_i360Home  icon="athome"
				Text item=PresenceD_i360Home  icon="athome"
				Text item=PresenceH_i360Home  icon="athome"
			}
		}

myhome.rules:

rule "Check Life360 Presence"
when
	Time cron "0 */5 * * * ? *" // every 5 minutes
then
	executeCommandLine("/etc/openhab2/scripts/life360.sh@@start", 5*1000)
	if (PresenceF_i360Home.state == ON || PresenceD_i360Home.state == ON || PresenceH_i360Home.state == ON) {
		postUpdate(FamilyPresence,ON)
		logInfo ("Life360", "Somebody Home")
	} else
	{
		postUpdate(FamilyPresence,OFF)
		logInfo ("Life360", "Nobody is Home")
	}
end

I really am not sure if this is the best or the most optimum way to do it, however i am a beginner and this just works for me.

and btw thanks to brazen1445 in https://community.home-assistant.io/t/life-360-support/1690/15 for the life360 script.

1 Like

Super solution which is just up my alley, I seem to just miss a point or two !
I got jq and mosquitto installed, conf’d and tested mosquitto successfully with this detailed guide: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-the-mosquitto-mqtt-messaging-broker-on-debian-8 , placed the above sh script in /etc/openhab2/Life360 and chmod +x on the script. Created the Circle named “Home” with members on https://www.life360.com. Also saw the MQTT receive correct messages on 5 min interval after adding a bash in the rules line to : executeCommandLine(‘bash /path/to/script/life360.sh’, 3*1000) on debian Turnkeylinux VM - otherwise the error: “function: not found” and “Syntax error: “}” unexpected”.
But I seem to lack some connection to the items or sitemaps in Openhab2, I don’t get the status’ shown in basicUI.
Items file:

Switch PresenceL_i360Home  "L @ Home [%s]"   {mqtt="<[mosquitto:owntracks/L:state:JSONPATH($.locname):.*]"}
Switch PresenceC_i360Home "C @ Home [%s]"   {mqtt="<[mosquitto:owntracks/C:state:JSONPATH($.locname):.*]"}
Switch PresenceT_i360Home  "T @ Home [%s]"   {mqtt="<[mosquitto:owntracks/T:state:JSONPATH($.locname):.*]"}

rules file:

rule "Check Life360 locations"
when
        Time cron "0 */5 * * * ? *" // every 5 minutes
then
        executeCommandLine('bash /etc/openhab2/Life360/Life360.sh', 3*1000)
end

sitemap file:

        Text item=PresenceL_i360Home  icon="present" valuecolor=[ON="green",OFF="blue"]
        Text item=PresenceC_i360Home  icon="present" valuecolor=[ON="green",OFF="blue"]
        Text item=PresenceT_i360Home  icon="present" valuecolor=[ON="green",OFF="blue"]

Tested MQTT with :slight_smile:

mosquitto_sub  -h 127.0.0.1 -p 1883 -t owntracks/L -d -u User -P password

got back:
Client mosqsub/30201-domain.lcl received PUBLISH (d0, q0, r0, m0, ‘owntracks/L’, … (131 bytes))
{“t”:“p”,“tst”:1408866501,“acc”:65,"_type":“location”,“alt”:0,“lon”:10.xxxxxxxxxx,“lat”:55.xxxxxxxxxxxx,“batt”: 46,“locname”: ON}

Hope someone can shed some light on the missing status’ or how to test/verify it !

Well, nothing is unsaid on the net, found an alternative working example here: https://pastebin.com/xrYTvtCR and mixed it with the above and got this running without the duplicate ID bug, successfully tested against MQTT for all IDs, which previous script did not count for. Removed the timeouts as the rule should control that.
Still got the status unwilling to report to Openhab2 though.

#!/bin/bash

#Set variables
username360="xxxxx"
password360="xxxx"
mosquitto_pub="/usr/bin/mosquitto_pub"
mqtt_host="127.0.0.1"
mqtt_port="1883"
mqtt_user="xxxxx"
mqtt_pass="xxxxx"

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*')
}

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-]*')
}

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

bearer
circles $bearer_id

#Check if circle id is valid. If not request new token.
if [ -z "$circles_id" ]; then
bearer
circles $bearer_id
fi

#Loop through circle ids
for i in "${circles_id[@]}"
do

#request member list
members $bearer_id $i

#Check if member array is valid. If not request new token
if [ -z "$members" ]; then
bearer
circles $bearer_id
members $bearer_id $i
fi

members_count=$(echo $members | jq '.members | (length)')
count=0
while [ $count -lt $members_count ]
do
    id=$(echo $members | jq .members[$count].id)
    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)
    avatar=$(echo $members | jq .members[$count].avatar)
    locationname=$(echo $members | jq .members[$count].location.name)
    if [ "$locationname" = "\"Home"\" ]; then
    locationname="ON"
    else
    locationname="OFF"
    fi
    #echo $firstName
    #echo "$(date +%s) INFO: owntracks/${firstName//\"/}/${id//\"/}" -m "{\"t\":\"p\",\"tst\":$(date +%s),\"acc\":${accuracy//\"/},\"_type\":\"location\",\"alt\":0,\"lon\":${longitude//\"/},\"lat\":${latitude//\"/},\"batt\": ${battery//\"/}}"
    $mosquitto_pub -h $mqtt_host -p $mqtt_port -u $mqtt_user -P $mqtt_pass -t "owntracks/${firstName//\"/}"            -m "{\"t\":\"p\",\"tst\":$(date +%s),\"acc\":${accuracy//\"/},\"_type\":\"location\",\"alt\":0,\"lon\":${longitude//\"/},\"lat\":${latitude//\"/},\"batt\": ${battery//\"/},\"locname\": ${locationname//\"/}}"
    count=$(($count+1))
done
done

Sorry that i moved to domoticz instead of openhab just because of zwave issues. However as i remember these might light up some solution:

  1. Add “count=$(($count+1))” to the end of bash script as shown in my previous message, this can solve ID problem, i updated the script. EDIT: Oh you did it :grinning:
  2. I also updated the myhome.sitemap in that message also.
  3. Also the rules file…
  4. You should add both mqtt and mqttitude(or owntracks) in openhab2. I remember the script stopped working when i remove mqttitude.

I still use this bash file on domoticz and it is the best presence detector for me; i tried many!..

And also in services/mqtt.cfg file:

mqtt:mosquitto.url=tcp://localhost:1883
mqtt:mosquitto.clientId=openhab
mqtt:mosquitto.retain=true
mqtt:mosquitto.async=false
mqtt:mosquitto.user=your_mqtt_username
mqtt:mosquitto.pwd=your_mqtt_password

Got it working on the TKL LAMP image - had to add the paperUI\Add Ons\Transformation\JSONPath Transformation to be able to transform the Items. Reminder to myself - to only have one or no Frames in sitemaps.
Using :

mosquitto_sub -v -t '#'

to monitor mqtt is better than previous example.

Thanks for the support on this.
Now I only need the actions taken, based on presence.

I can’t get this to work. I’m on openHAB 2.4.

The problem seems to me the JSON translation.

  • I have JSONpath binding installed.
  • I can execute the life360.sh script.
  • I can see the topic owntracks/Victor gets the string from life360 with all the options, lon, lat, batt, locname etc…

But the only thing that’s left is for my item to get updated by the locname which I guess would be ON/OFF ?

Since I have OH 2.4, I migrated to the new MQTT 2.0, so I turned on Include Legacy 1.x Bindings but it didn’t solve my problem.

My item looks like this:

Switch 	L360_victor	"Victor @ Home [%s]"      	{mqtt="<[mosquitto:owntracks/Victor:state:JSONPATH($.locname):.*]"}

Ok, of course, right after I wrote my message, I figured it out!
I had to rename my MQTT-string from mosquitto to broker, like this:

Switch 	L360_victor	"Victor @ Home [%s]"      	{mqtt="<[broker:owntracks/Victor:state:JSONPATH($.locname):.*]"}

After that, BINGO! Everything works, now I will go out and test it :wink:

So to recap. What needs to be done, with openHAB 2.4 (and above I guess) is:

  • Make the life360.sh script execute properly. See if you get the MQTT string, use the
    mosquitto_sub -v -t ‘#’ in the terminal.
  • Install JSON path Transformation.
  • Enable the Include Legacy 1.x Bindings since I’m on 2.4
  • Change mosquitto to broker in the mqtt-string at the end of the item.

Hope this will help!

hello, thanks for the info. I did everything indicated but I don’t see the presence.
I used the internal Openhab MQTT broker, the script works, in the mqtt client I see the information. I see the items in the configuration, if I go to the CONTROLs I don’t see any switch indicating the presence of the members of the circle in the house.
In the HabPanel I created switches that point to the items, but they are always off.
Some idea?

Thanks bye!

I am very new to IoT in general and I am trying to figure out how MQTT works and how OpenHab handles it in 2.4. I am working on figuring out how to turn what was posted above into a MQTT binding for version 2.4. You mention there you were able to do it, could you post a list of the steps you took to make it. It would help me a lot.

– Thank you –