Rough location solution for location based rules

Hi all,

I thought I’d share my solution for location based rules, maybe somebody finds it useful. It can be used e.g. for preventing the lights from switching off at a certain location when you are still there or automatically start-up security or logging, or maybe stop security cameras depending on where you are.

It is based on the property that WiFi clients tend to connect to the closest access point. You obviously do need multiple access points to get a location within a house, otherwise you only get “home or not”. My setup consists of 2 APs and a separate router (without WiFi), all running OpenWRT. On each device I have usteer running. This app provides the means of extracting the required information on OpenWrt. On the router I have the following script executed once per minute:

#!/bin/ash

connected_nodes=$(ubus call usteer get_client_info '{"address":"aa:bb:cc:dd:ee:ff"}' | grep -B 1 '"connected": true' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
connected_nodes2=$(ubus call usteer get_client_info '{"address":"ab:bc:cd:de:ef:fa"}' | grep -B 1 '"connected": true' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')


mosquitto_pub -h 192.168.1.100 -t "test" -m "{\"aabbccddeeff\": \"$connected_nodes\",\"abbccddeefa\": \"$connected_nodes2\"}" -u "mosq" -P "password"

return 0

This script grabs for two different MAC addresses the APs they are connected to. . The example is for 2 MAC addresses, but it can be trivially extended to any number. You do of course also have to install the mosquitto-client either the SSL or non-SSL version.

On my RPi (192.168.1.100) which runs my OpenHAB, i also have a mosquitto server running, which will receive the message from the router.

Add a mqqt.things file:

Bridge mqtt:broker:rpiBroker [ host="127.0.0.1", secure=false, username="mosq", password="password"  ] 

Thing mqtt:topic:Presence (mqtt:broker:rpiBroker)  { 
    Channels: 
	Type string : PhoneLocation        "Location"     [ stateTopic="test",transformationPattern="JSONPATH:$.aabbccddeeff" ]
	Type string : Phone2Location       "Location"     [ stateTopic="test",transformationPattern="JSONPATH:$.abbccddeeffa" ] 
}

And add a mqqt.items file:

String        PresencePhone            {channel="mqtt:topic:Presence:PhoneLocation" }
String        PresencePhone2          {channel="mqtt:topic:Presence:Phone2Location" }

You can now use a rule like:

if (!PresencePhone.state.toString.contains("192.168.1.2")) 

Note that the state of the item may contain multiple APs with a space in between, as clients take some time to disconnect, hence the reason to use e.g. contains.

Hope this can inspire somebody.

Best regards,

Ramon

Nice approach. If you want to go to the next level or if you don’t have multiple APs to deploy, an alternative is to use FIND. Though that works better when there are lots of APs visible, but they can be the neighbor’s.

Thx for the suggestion, i did not know that FIND existed. Note that actually signal strength is already available in the same ubus call usteer get_client_info call. I decided not to use it, just to keep it simple, also because of the wildly different signal strength for 2.4 vs 5 GHz. Also if 802.11kv is enabled then clients typically do not scan when connected well, and if they do scan its only the bands where the closest APs are, not all bands. So not sure if it can be improved without draining the battery more? And indeed adding bluetooth helps with the location accuracy, but this does require an additional client to be run on the device, I guess, or else how do you get the info from the device?