NodeRED: Who’s home?

Who is home? Let me tell you....

I’m an avid fan of what Fing app and Fingbox can do. You should seriously read about it! I also understand that splashing out $99 (or less with my promo code) on a complimentary network device may not be in everyone’s reach. This is why I decided to recreate one of the Fingbox features – checking who’s home. Having the ability to see who is currently home may seem useful to some or Orwellian to others. It’s a tool, and like with all tools it can be useful or it could be abused.

Who’s home?

Fingbox can track devices and post the online times automatically in a neat chart. On top of the nicely designed interface, there are notifications available for each device, letting you know if a device left the network. Recent IFTTT integration makes it even easier to use it as a trigger to perform some cool stuff. You can set the alerts for individual devices or people. It’s powerful knowledge.

If you are interested in the off the shelf solution – obviously getting the Fingbox is the way to go. These guys are super cool and push the updates and new features on a regular basis. I also have a nice $10 off your order.

If the Fingbox is too expensive…

There is another way. I have recreated the setup (to the best of my ability) in NodeRED. It may not look as beautiful as the Fing app version, but it is practical, comes with Android notifications and it will cost you only $5 if you don’t have a NodeRED server. It’s a budget option but knowing who’s home is worth a fiver!

Who’s home – how does it work?

Since the presence of residents will rely on their phone being connected to the WiFi, this system can be fooled. All you have to do is disconnect the WiFi to send a false negative message. If you are happy with this limitation – you may read on.

Before you can start monitoring the online presence of the devices (don’t be “that” guy, get the permission from your friends and family first) you will need to collect the IP’s & MAC for each connected mobiles and reserve their MAC address in the router configuration. Fing app is a perfect tool for that!

Fing - Network Tools
Price: Free

ARP vs PING

There are two ways we can monitor devices connected to the local network. Neither of which is perfect if I’m honest. Bear in mind, that due to the fact that Android WILL put your WiFi to sleep (depending on your phone, Android and Rom) you may not always get the correct readings. You will always get a notification when the device is connected to the network.

PING

The good old networking tool can be downloaded from the Palette Manager:

node-red-node-ping

The node will send the “ping” to a defined IP address and return the time in ms (if found) or false if the device appears to be offline. It can be triggered every X seconds in the node configuration.

ARP
node-red-contrib-arp

ARP probe checks the network and looks for a MAC address. If the device is found, the IP is returned to NodeRED, otherwise, the payload is empty. The node has to be triggered every X seconds to receive the update.

Personally, I found the ARP method more accurate, but it was harder to implement than just pinging the IP’s. On top of that, I wanted to limit false positive/negative readings while keeping the whole system as accurate as possible. The results are similar in the accuracy to the Fingbox.

Creating “Who’s home”

Every minute (inject node) I’m going to query selected MAC addresses using ARP node. The value will be either an array containing the IP addresses of the devices or an empty array. I struggled for a while, trying to put all that into a single function node, so I have up and I simply made a switch statement checking if the payload is empty, or else.

The message filtered this way would assign one of two possible payloads:

msg.payload = "home";
return msg;

OR

msg.payload = "away";
return msg;

I have done so, so I could manage the entire flow easier. Next, I had to deal with two problems. While the MAC query happens every minute, I only want to receive notification once then a person comes and leaves home.

RBE node allows just that. It will drop all the messages unless the payload itself changes. After a couple of hours of testing, I noticed that from time to time I got short breaks when the target device became inactive. I don’t mind charts having short breaks, but notifications would be very annoying. I created a script that would only send every 3rd message providing that:

  1. previous two messages are the same
  2. status of the device not changed
Function node: Subsequent reading
x =  context.get('count');
y =  context.get('message');
//set defaults & return payload
if (x === null || x === undefined && y === null || y === undefined){
    x = 1;
    context.set('count' , x);
    context.set('message', msg.payload);
    return msg;
}
//count only if payloads are the same or reset
if (x < 3){
    var current = msg.payload;
    var last    = context.get('message');
    if(current === last){  
        x++;
        context.set('count' , x);
        
    }
    else{
    x = 1;
    context.set('message', msg.payload);
    }
}
//return and reset
if (x == 3){
    var current = msg.payload;
    var last    = context.get('message');
    if(current === last){
        x = 1;
        context.set('count' , x);
        return msg;
    }
}

It’s time to compose the data, create a Join notification for Android devices and display the information about the household members on a dashboard.

Function node: Pixel
var x = global.get('JOIN_pixel3');


msg.person = "Pixel";


var d = new Date();
var h = d.getHours(); 
var m = d.getMinutes();

if(m < 10){
    var z = m.toString();
    var m = "0" + z;
} 
if(h < 10){
    var z = h.toString();
    var h = "0" + z;
}


var time = h + ":" + m;

if(msg.payload === "home"){
    msg.push = {
        "deviceIds": x,
        "title":"Home Update",
        "text":"Pixel just got home",
        "icon":"https://www.rawshorts.com/freeicons/wp-content/uploads/2017/01/green_repicthousebase_1484336387-1.png",
    };
    msg.status = "Pixel arrived home at";
    msg.payload = time;
    msg.color = "green";
    flow.set('Pixel', 3);
    msg.index = 3;
}
else{
    msg.push = {
        "deviceIds": x,
        "title":"Home Update",
        "text":"Pixel is no longer at home",
        "icon":"https://www.rawshorts.com/freeicons/wp-content/uploads/2017/01/red_repicthousebase_1484336386-1.png",
    }; 
    msg.status = "Pixel left home at";
    msg.payload = time;
    msg.color = "red";
    flow.set('Pixel', 0);
    msg.index = 0;
}

return msg;

To get the current time, I used the following script. In addition to this, I created 2 rules to substitute 0 when hours or minutes are under 10:

var d = new Date();
var h = d.getHours(); 
var m = d.getMinutes();

if(m < 10){
    var z = m.toString();
    var m = "0" + z;
} 
if(h < 10){
    var z = h.toString();
    var h = "0" + z;
}
var time = h + ":" + m;

When the payload is “home”  a push is created to send the message to Join app via NodeRED. You can learn more about Join and NodeRED here.

msg.push = {
        "deviceIds": x,
        "title":"Home Update",
        "text":"Pixel just got home",
        "icon":"https://www.rawshorts.com/freeicons/wp-content/uploads/2017/01/green_repicthousebase_1484336387-1.png",
    };

To populate the dashboard and chart, I have to push the time and the label (msg.status & msg.payload) to the text dashboard node. I also added the colour information (msg.color) so the time is displayed in green for arrival and red for departure.

Lastly, to populate the chart, I have to assign an index (msg.index) value to each person. Each number represents a horizontal line. When the value is “0” person is not home. When the value equals assigned (and unique) number the chart will display the line. I store this as a flow variable, as I have to access it from another function node.

My chart refreshes every 5 min. Each time, the function node reads my flow variable assigned to each member and posts the index value with the hardcoded topic. To display multiple lines in the chart, each payload has to have a unique topic:

msg.payload = flow.get('Pixel');
msg.topic = "Pixel";
return msg;

I limited the chart to display values from 0-4 over a 24h period.

Conclusion

Who’s home in NodeRED almost as accurate as the Fingbox feature. So if you really like this, you can recreate it on a $5 RaspberryPi device. You can also buy the Fingbox and have the access to unique features:

Remember sharing is caring!

Support NotEnoughTech
A lot of time and effort goes into keeping NotEnoughTech alive! If my work helped you out, consider buying me a coffee or check out exclusive rewards available to Patreon supporters.
SHARE