Node-RED Geofence node

We’ve been looking at some new location based uses for Node-RED recently. To this end we’ve been standardising on adding the information under the msg.location property.

msg: {
  topic: "foo",
  payload: "bar",
  location: {
    lat: 51.02477
    lon: -1.39724
  }
}

As part of this I’ve been writing a geofence node. This will allow messages to be filtered against specific regions.

The first pass worked well supporting both circular and rectangular regions, but configuring it by entering coordinates is not the most user friendly.

Screenshot from 2014-11-11 22:23:33

After a bit of playing with leafletjs and the leaflet.draw plugin I managed to come up with this which should be a lot more intuitive.

Geofence config dialog

At the moment it needs to load the leaflet js and css from a external server until we come up with a way to bundle static content inside nodes. This shouldn’t really be a problem as it’s having to load the map tiles from the internet as well. I’d like to find a way to pass in a base URL for the map server and to gracefully fall back to the text version if there is no access to a map server.

The map version also supports creating arbitrary polygon regions by joining up multiple points.

I’m still trying to get the config dialog to gracefully fall back to the basic version when there is no access to a mapserver but having problems with detecting the failure to download a map title. Any pointers would be gratefully accepted.

The code is on github and on npm. It can be installed with:

npm install node-red-node-geofence

17 thoughts on “Node-RED Geofence node”

  1. I cannot get the node to show any signs of life. So I am not sure how to manage its input parameters. I have tried all sorts of payload combinations – the closest I think to your info above is as follows.

    { “topic”: “NaheTor”, “payload”: “bar, location: { lat: 50.898486 lon: -1.39724 }”, “qos”: 0, “retain”: false, “_msgid”: “33eb05e.fcc14fa” }

    The first parameter of the payload is only there to try an match the format you have above but as I am using MQTT transport I have a few extra things in the message. The quotes are inserted by MQTT. Any advice much appreciated.

    1. Neil,

      Not sure what you mean about showing signs of life, but your message object is going to need tweaking a bit. You will most likely need to use a function node to move somethings around after they arrived via MQTT.

      All the geo nodes work on a top level key in the message object of ‘location’ which has keys of ‘lat’ and ‘lon’. So assuming you can drop the ‘bar,’ from the incoming MQTT message you could use the following code in a function node to build what you need:


      var loc = JSON.parse('{' + msg.payload + '}');
      msg.location = loc.location;
      return msg;

      This wraps the ‘location: {lat:…, lon:…}’ in an extra set of {} to make it parse as JSON properly, parses it, then inserts the values at the right level in the msg object.

      Now the Geofence node should be able to filter based on these values.

  2. Hi, I have being trying to get your Geofence node to work. But my input is still not excepted. Can you please have a look at the simple Node-Red example I made and correct my mistakes. Thank you in advance.

    [{“id”:”ce181fc0.31e7e”,”type”:”geofence”,”z”:”3659906f.c9a67″,”name”:”Geofence”,”mode”:”circle”,”inside”:”both”,”rad”:42.7951854517347,”points”:[],”centre”:{“latitude”:51.98473270844999,”longitude”:5.105298757498531},”x”:440.6666259765625,”y”:89.66666412353516,”wires”:[[“829277b7.7d6d88″]]},{“id”:”829277b7.7d6d88″,”type”:”debug”,”z”:”3659906f.c9a67″,”name”:””,”active”:true,”console”:”true”,”complete”:”true”,”x”:581.6665954589844,”y”:90.66666412353516,”wires”:[]},{“id”:”25d7ac56.da2854″,”type”:”template”,”z”:”3659906f.c9a67″,”name”:””,”field”:”location”,”format”:”handlebars”,”template”:”{{Location.lat}}\n{{Location.lon}}\n”,”x”:303.6666564941406,”y”:90.66666412353516,”wires”:[[“ce181fc0.31e7e”]]},{“id”:”2dab52b9.d254ae”,”type”:”inject”,”z”:”3659906f.c9a67″,”name”:””,”topic”:””,”payload”:”{lat:51.99024,lon:5.08360}”,”payloadType”:”string”,”repeat”:””,”crontab”:””,”once”:false,”x”:172.66665649414062,”y”:89.66666412353516,”wires”:[[“25d7ac56.da2854″]]}]

    1. A couple of problems.

      1. The template node will not convert a string to a JSON object, you need to user the JSON parse node
      2. The Geofence node works on the mag.location property not the msg.payload

      I have updated your example flow to now work:

      [{"id":"8668751e.646b78","type":"geofence","z":"8670e20f.e636c","name":"Geofence","mode":"circle","inside":"both","rad":42.7951854517347,"points":[],"centre":{"latitude":51.98473270844999,"longitude":5.105298757498531},"x":542,"y":369,"wires":[["8f24a472.213f7"]]},{"id":"8f24a472.213f7","type":"debug","z":"8670e20f.e636c","name":"","active":true,"console":"true","complete":"true","x":681,"y":367,"wires":[]},{"id":"df5bf5d9.958588","type":"inject","z":"8670e20f.e636c","name":"","topic":"","payload":"{\"lat\":51.99024, \"lon\":5.08360}","payloadType":"string","repeat":"","crontab":"","once":false,"x":110.00003051757812,"y":366,"wires":[["2b7c2f94.a1ef88"]]},{"id":"2b7c2f94.a1ef88","type":"json","z":"8670e20f.e636c","name":"","x":256,"y":369,"wires":[["62939d17.e04cf4"]]},{"id":"62939d17.e04cf4","type":"function","z":"8670e20f.e636c","name":"","func":"msg.location = msg.payload;\nmsg.payload = \"foo\";\nreturn msg;","outputs":1,"noerr":0,"x":398,"y":368,"wires":[["8668751e.646b78"]]}]

  3. Hi,
    with MQTT Input node i’ll get following msg Object:

    { “topic”: “owntracks/phone/my”, “payload”: “{\”_type\”:\”location\”,\”lat\”:52.5367607,\”lon\”:8.1986322,\”tst\”:1449240737,\”acc\”:972,\”batt\”:78,\”tid\”:\”m7\”}”, “qos”: 1, “retain”: false, “_topic”: “owntracks/phone/my”, “_msgid”: “5ba1419f.a45ec” }

    Now i tried to convert it into msg.location:

    var loc = JSON.parse(msg.payload);
    msg.location = “{lat: ” + loc.lat + “, lon: ” + loc.lon + “}”;
    return msg;

    This leads to an error message:

    TypeError: Cannot call method ‘toString’ of undefined

    Any hint to to convert the string to an acceptable JSON (guess this is the failure)?

    1. got it:

      var loc = JSON.parse(msg.payload);
      var newmsg = { lat: loc.lat, lon: loc.lon };
      msg.location = newmsg;
      return msg;

      Great Node :)

  4. Good effort dude. I am having a problem with OpenStreetMap as most of map listing in my area are on Google maps. How can I use my Google maps api key with your geofence-node? I think I have to modify javascript code inside geofence.html file. May you suggest any solution?

    1. You will have to read the doc about using LeafletJS with Google Maps. The FAQ implies that it would be in breach of the Google API ToCs but may be possible with a plugin.

      You could also look at contributing data to the OpenStreetMap project, it’s not that hard.

  5. It seems that some type of incompatibility is generated when this node is used with node-red-contrib-web-worldmap, Do you know anything about it ?, I am using node-red in IBM Bluemix

    1. If you think there is a problem, raise an issue in github. You will have to include a LOT more detail for anybody to be able to help

      1. Could you indicate how we can pass the parameters of the geofence from outside the node?

Leave a Reply to Frank Cancel reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>