Automate office presence with Raspberry Pi

We at Firmhouse are a Remote company, but we do have an office in Rotterdam. Since there are a couple of tasks that need to happen when you're at the office: Water the plants or Do the dishes for example; we set up a Slack channel called #firmhouse-office.

The idea behind this was that if people work at the office, they will join that channel, so they get reminder notifications on that channel about those tasks.

Since we are all humans, we kept forgetting about this channel, or we would join and never leave the channel.

Because people are hard to "rewire" we started thinking about a better solution on how we could automate this system.

We all carry devices around, phones, laptops. All those devices are attached to our network. What if there would be a way to detect when one of those devices entered the network, and we can map that device to a particular user?

Well, it turns out there are tools to do so. We started playing around with the nmap and arp, two fantastic terminal based tools.

nmap

With nmap, you can get a list off all attached devices on a given subnet.
Nmap works by scanning all the IPs in a particular network subnet to check if there is any activity. You can choose to use TCP ports, UDP ports or just plain ping.

We decided to go with the ping option, since that way we can be mostly sure that firewalls are not going to halt that traffic.

The command we used was:

nmap -sn 192.168.1.0/24 | grep "scan report for" | awk '{print $5}'  

This command in the raw form (just nmap -sn IP) will return the following

Starting Nmap 7.12 ( https://nmap.org ) at 2016-09-21 09:14 CEST  
Nmap scan report for 192.168.1.1  
Host is up (0.013s latency).  
Nmap scan report for 192.168.1.143  
Host is up (0.00020s latency).  
Nmap scan report for 192.168.1.159  
Host is up (0.091s latency).  
Nmap scan report for 192.168.1.206  
Host is up (0.0092s latency).  
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.93 seconds  

When we pipe this data to grep, and awk we can boil the data down to just a list of IP addresses:

192.168.1.1  
192.168.1.143  
192.168.1.159  
192.168.1.206  

Since we want to identify devices on the network, we need to get the MAC address in some way. You can do this with nmap as well, but then you have to run it as sudo, which was a no-go for us.

Turns out, arp is excellent at this!

arp

When we got the list of the IP addresses, we looped over them and tried to fetch the MAC address for every IP address.

We used the following script for this:

arp -a | grep "(192.168.1.143)" | awk '{print $4}'  

Normally arp will return a list of all the known devices in the arp table. By passing it on to grep and then to awk we nicely get back the MAC address:

› arp -a | grep "(192.168.1.143)" | awk '{print $4}'
10:e1:30:15:36:a1  

The Ruby script

To map all the data together, we wrote a Ruby script. This script runs in a loop and on every loop it fetches all the active devices, gets their MAC addresses, and then checks that against a pre-defined hash of known devices.

Once a device is in the hash of known devices, we then map that device to their SlackID.

We can then make a request to the Slack API to invite or remove a user from the #firmhouse-office channel.

You can find the full script here: https://gist.github.com/jvanbaarsen/d60eb18fd27cbfb74ae0030759aedbad

The Raspberry Pi

We have the entire thing running on a raspberry pi. We configured the PI with upstart so that it will start this script automatically when it is powered on.

The script was copied via scp to the PI (We could have gone with git, but we were lazy :D ).

That's it!

You have any questions, or just want to say hi? I'm reachable on Twitter or by email