Server side geofencing with Owntracks, Node-Red and Domoticz

Where to start?

The first challenge was getting data from my phone on public networks to my private MQTT server. At home I run Mosquitto for handling any message brokering, particularly with Domoticz and Node-Red pushing messages around.

I won’t go into the details, but suffice to say I have Mosquitto at home, and Mosquitto on a server I rent in OVH. The one in OVH is TLS, and protected by a username and password. It is this server to which Owntracks is configured to push messages to.

In turn, the two Mosquitto servers are bridged, as per http://e.verything.co/post/62163759361/bridging-two-mqtt-brokers and http://owntracks.org/booklet/guide/bridge/ in order for the topic to which the phone publishes to be available internally at home.

The end result of this is the periodic announcement of my phones location on my internal home network

mqttitude/bagpuss_thecat/galaxys2 {“_type”: “location”, “lat”: “55.9182683”, “lon”: “-4.2232088”, “tst”: “1457045018”, “acc”: “20.0”, “batt”: “48”}

From here, it gets ingested into Node-Red by firstly subscribing to the mqttitude/bagpuss_thecat/galaxys2 topic, then the JSON is parsed out, and then it’s processed by a couple of node-red-node-geofence nodes in order to determine if the phone is in a certain location or not. These simply return the msg.location.isat parameter if the device matches any of the geofences.

Depending on the status of the .isat parameter, I then use the multiple messages feature of node-red to send messages to each of my Domoticz switches to alter their state.


if ( msg.location.isat == "Home") {
var home = { payload:'{"idx":181,"nvalue":1}' };
var work = { payload:'{"idx":180,"nvalue":0}' };
} else if ( msg.location.isat == "Work") {
var home = { payload:'{"idx":181,"nvalue":0}' };
var work = { payload:'{"idx":180,"nvalue":1}' };
} else {
var home = { payload:'{"idx":181,"nvalue":0}' };
var work = { payload:'{"idx":180,"nvalue":0}' };
}
return [ [ work, home ] ];

As you can see from the above code, the Domoticz IDX of the switch to say that I’m at work is 180, Home is 181, and I can then use those dummy switch states in Domoticz to do additional logic within the home automation system.

 

UPDATE: 08/08/2017

As requested, a copy of the flow. I haven’t used it for a while now, since moving to http://home-assistant.io with native Owntracks support, but it might prove useful.

Geofencing, with node-red

[{“id”:”ceb5e9b3.255318″,”type”:”mqtt-broker”,”z”:””,”broker”:”homeauto.vpn.glasgownet.com”,”port”:”1883″,”clientid”:””,”usetls”:false,”compatmode”:true,”keepalive”:”15″,”cleansession”:true,”willTopic”:””,”willQos”:”0″,”willPayload”:””,”birthTopic”:””,”birthQos”:”0″,”birthPayload”:””},{“id”:”5d41030f.a2ba8c”,”type”:”mqtt in”,”z”:”e55a6d11.377b9″,”name”:”KyleG Owntracks”,”topic”:”owntracks/bagpuss/a0001″,”broker”:”ceb5e9b3.255318″,”x”:121,”y”:107,”wires”:[[“d256ba45.4be048”]]},{“id”:”a2dace61.598″,”type”:”mqtt out”,”z”:”e55a6d11.377b9″,”name”:”domoticz/in”,”topic”:”domoticz/in”,”qos”:””,”retain”:””,”broker”:”ceb5e9b3.255318″,”x”:957,”y”:112,”wires”:[]},{“id”:”52f3dc6d.f8fbd4″,”type”:”geofence”,”z”:”e55a6d11.377b9″,”name”:”Home”,”mode”:”circle”,”inside”:”true”,”rad”:88.99011032254676,”points”:[],”centre”:{“latitude”:55.918150666279054,”longitude”:-4.223449230194092},”x”:480,”y”:64,”wires”:[[“b2213e67.26d87″,”4961a9e.b165358”]]},{“id”:”d256ba45.4be048″,”type”:”function”,”z”:”e55a6d11.377b9″,”name”:”Lat/Long”,”func”:”msg.location = JSON.parse(msg.payload);\n\nreturn msg;”,”outputs”:1,”noerr”:0,”x”:309,”y”:107,”wires”:[[“52f3dc6d.f8fbd4″,”2415d034.e094a”,”154cf4bc.0c969b”,”b3a50cee.841fd”,”cd886406.0e8ea8″]]},{“id”:”b2213e67.26d87″,”type”:”function”,”z”:”e55a6d11.377b9″,”name”:”Location selector”,”func”:”// Home == 10\n// Work == 20\n\nif ( msg.location.isat == \”Home\”) {\n var home = { payload:'{\”idx\”:181,\”nvalue\”:1}’ };\n var work = { payload:'{\”idx\”:180,\”nvalue\”:0}’ };\n} else if ( msg.location.isat == \”Work\”) {\n var home = { payload:'{\”idx\”:181,\”nvalue\”:0}’ };\n var work = { payload:'{\”idx\”:180,\”nvalue\”:1}’ };\n} else {\n var home = { payload:'{\”idx\”:181,\”nvalue\”:0}’ };\n var work = { payload:'{\”idx\”:180,\”nvalue\”:0}’ };\n}\n\n\nreturn [ [ work, home ] ];”,”outputs”:”1″,”noerr”:0,”x”:708,”y”:113,”wires”:[[“a2dace61.598″,”7d37ae41.94953”]]},{“id”:”2415d034.e094a”,”type”:”geofence”,”z”:”e55a6d11.377b9″,”name”:”Work”,”mode”:”circle”,”inside”:”true”,”rad”:691.5530147043348,”points”:[],”centre”:{“latitude”:55.756722472194724,”longitude”:-4.288358688354492},”x”:476,”y”:140,”wires”:[[“b2213e67.26d87″,”4961a9e.b165358”]]},{“id”:”4961a9e.b165358″,”type”:”debug”,”z”:”e55a6d11.377b9″,”name”:””,”active”:true,”console”:”false”,”complete”:”location.isat”,”x”:706,”y”:65,”wires”:[]},{“id”:”7d37ae41.94953″,”type”:”debug”,”z”:”e55a6d11.377b9″,”name”:”Domotic payload toggles”,”active”:true,”console”:”false”,”complete”:”payload”,”x”:997,”y”:69,”wires”:[]},{“id”:”154cf4bc.0c969b”,”type”:”geofence”,”z”:”e55a6d11.377b9″,”name”:”Canteen”,”mode”:”circle”,”inside”:”true”,”rad”:16.778117069341608,”points”:[],”centre”:{“latitude”:55.756552675540114,”longitude”:-4.287972450256348},”x”:489.3333435058594,”y”:203.33333587646484,”wires”:[[“d4136e7.f6cfc9”]]},{“id”:”d4136e7.f6cfc9″,”type”:”mqtt out”,”z”:”e55a6d11.377b9″,”name”:””,”topic”:”testing/canteen”,”qos”:””,”retain”:””,”broker”:”ceb5e9b3.255318″,”x”:720.3333740234375,”y”:206.33334350585938,”wires”:[]},{“id”:”332b5b84.1a89e4″,”type”:”file”,”z”:”e55a6d11.377b9″,”name”:”location”,”filename”:”/tmp/location.csv”,”appendNewline”:true,”createDir”:false,”overwriteFile”:”false”,”x”:711.3333435058594,”y”:294.33333587646484,”wires”:[]},{“id”:”b3a50cee.841fd”,”type”:”function”,”z”:”e55a6d11.377b9″,”name”:”csvify”,”func”:”//msg.timestamp = new Date().toISOString();\n\nvar now = new Date(); \nvar year = now.getFullYear();\nvar month = now.getMonth()+1; \nvar day = now.getDate();\nvar hour = now.getHours();\nvar minute = now.getMinutes();\nvar second = now.getSeconds(); \nif(month.toString().length == 1) {\nvar month = ‘0’+month;\n}\nif(day.toString().length == 1) {\nvar day = ‘0’+day;\n} \nif(hour.toString().length == 1) {\nvar hour = ‘0’+hour;\n}\nif(minute.toString().length == 1) {\nvar minute = ‘0’+minute;\n}\nif(second.toString().length == 1) {\nvar second = ‘0’+second;\n} \nmsg.timestamp = year+’-‘+month+’-‘+day+’ ‘+hour+’:’+minute+’:’+second;\n\n\nmsg.parameters = JSON.parse(msg.payload);\n\nmsg.payload = msg.timestamp + ‘,’ + msg.parameters.lat + ‘,’ + msg.parameters.lon;\n\nreturn msg;”,”outputs”:1,”noerr”:0,”x”:489.8333435058594,”y”:275.33333587646484,”wires”:[[“332b5b84.1a89e4”]]},{“id”:”cd886406.0e8ea8″,”type”:”debug”,”z”:”e55a6d11.377b9″,”name”:””,”active”:false,”console”:”false”,”complete”:”location.lat”,”x”:265,”y”:248,”wires”:[]}]

 

Attached Files:

4 Replies to “Server side geofencing with Owntracks, Node-Red and Domoticz”

  1. Ohh, cunning, yes, I’ll do that.

    I originally wrote this piece in March, and I that was just before the Owntracks node came out 🙂 I use a VPN between servers, but client < -> server would still be unencrypted, so it’s nice to see there’s a solution to that now.

    And yes, the Geofence and Owntracks nodes are great. Thank you very much for releasing them!

  2. Nice work! Would you mind sharing the flow from node-red? I’ve just started playing with this and would be helped by some examples.
  3. @Mattias, good point. I will post them up shortly.

    6 months ago I moved to Home-Assistant, which has native support for Owntracks location. I ended up deleting the node-red flow, but I have it in my backups. I’ll dig it out this weekend and make it available!

Leave a Reply

Your email address will not be published. Required fields are marked *