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

27 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.


    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"]]}]

        1. Plying with the flow you provided above, but when I deploy it, I get the following error:

          Unexpected string in JSON at position 15

          1. Which one? There are several flows, but most are specific to the person asking a question.

            The one in Robert van der Veur’s post has all the quotes characters screwed up (it has both opening and closing quotes which is wrong) so won’t ever work, the one in my response to him works just fine.

  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: ” + + “, 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:, 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

  6. Hi Ben,

    Thank you for your geofence node. It works nicely for me. I am wondering if you or anybody else accomplished a flow that also outputs leave/enter information.

    I have a few fenced regions defined (in parallel) and the flow continues with the matched region information if there is a match. I am struggling with adding a branch that should result with the information that the previously matched region has been left.

    I had the idea to work with setting and unsetting global variables and a few sleep functions. I would start the flow with the information that the last known region was left and overwrite that when any of known regions matches with “new region entered” data. Regrettably this isn’t really working.

    Are there any other possible approaches?

    1. Comments on Blogs really are not the best place for this sort of thing (places like the Node-RED Slack mean the whole community can help).

      Don’t use parallel filters, just chain nodes in “inarea” mode that way you can store the array in the context and check the next message against the context to see which areas have been left.

  7. Hi, I’m using this node, but what I need is multi geofences and i can’t make more than one geofence in the node, ¿there’s another way to make multi fences with this node?

      1. Thanks for the reply.
        But constantly the geo-fences will be added to a database and I need every time new geo-fences are added to the database in the red node as well.

        1. That’s totally different to question you originally asked. No, there is no support for dynamic geofence areas in the node. You will have to write your own.

  8. So, the only way adding a new Geofence is adding the node?
    With a msg.payload can I add a new geofence in the node?

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.