Detect Presence using a FitBit, Node-RED and FRED

By hosting node-red in the cloud, FRED can act as an intermediary between devices and cloud services.  To illustrate this, let’s create a system that send a notification when a user wearing a Fitbit Flex comes in range of a Bluetooth scanner.  We’ll distribute the job of discovering and filtering bluetooth devices between a device and a FRED-hosted node-red instance.  This will allow us to change how notifications are delivered, or make use of the scanner for other purposes without changing the device flow.

For this example, we’ll need a Fitbit flex, and a computer with Bluetooth 4.0.  We’ll make use of a BLE scanner node to detect Bluetooth devices and run the flow on a Mac laptop.  It should be possible to run this flow on any Mac or Linux machine supported by the node and the noble Bluetooth scanning library it uses.  We’ll use FRED to host the cloud-hosted flow.

First install node and node-red on your Macintosh.  See http://nodered.org/docs/getting-started/installation.html

Once it is installed, install the BLE scanner node in your node-red directory:

cd ~/.node-red
npm install npm install node-red-contrib-noble

Now, start node-red on your Mac.

cd ~
node-red

Let’s get started creating our BLE scanner flow.  First we’ll make sure the scanner is working.  Drage a scan ble node to the canvas, and connect it to a debug node to see the output.  Be sure to configure the debug node output to show ‘complete msg object’ to ensure we see all of the properties in a message generated by the scanner.

fig1

Figure 1. Simple BLE scanner flow.

Once this is done, bring a Fitbit flex in range to the computer and deploy the flow.  If all is well you should should see output similar to Listing 1 in the debug pane when it discovers devices.  If not, try modifying the flow by changing the name of one of the nodes and deploying it again.  This will trigger another scan.

{ "payload": { "peripheralUuid": "88e1ab7bcfa4493dbaf16c55e69a4881", "localName": "Flex" }, "peripheralUuid": "88e1ab7bcfa4493dbaf16c55e69a4881", "localName": "Flex", "detectedAt": 1452023547186, "detectedBy": "myhost.local", "advertisement": { "localName": "Flex", "txPowerLevel": -6, "serviceData": [ { "uuid": "180a", "data": [ 7, 4 ] } ], "serviceUuids": [ "adab1fb86e7d4601bda2bffaa68956ba" ] }, "rssi": -89, "_msgid": "a017136d.5fe8f" }

Listing 1. Example from scan ble node on discovery of a fitbit Flex.

Now we’ll add some additional features to the flow to trigger scanning and simplify the output of our scanner for processing.  First, let’s add the nodes we need to start and stop scanning.  Add an inject, trigger and function node and wire them up to the scanner as shown in Figure 2.

fig2

Figure 2. Nodes needed to control scanning.

Configure the inject node to send an ‘on’ message every 10 seconds as shown in Figure 3.

fig3

Figure 3. Inject node configuration to send ‘on’ string every 10 seconds.

Then configure the trigger node to send an ‘on’ then an ‘off’ message 7 seconds later as shown in Figure 4.

fig4

Figure 4. Trigger node configured to send ‘on’ then ‘off’.

Finally, we’ll configure the function node to send the scan trigger message needed by the ble scanner to control scanning.  Add the code shown in Listing 2 to the function.

1. if (msg.payload === 'on') {
2.     msg.scan = true;
3. } else {
4.     msg.scan = false;
5. }
6. return msg;

Listing 2. Convert on and off to scan messages.

After deploying the flow will trigger a new scan every 10 seconds, turning off the scanner after 7 seconds.

Now we’ll add a node to clean up the output, only sending the local name of the device discovered.  Add a function node to the end of the scanner, along with a debug node to check the output.  Add the code shown in Listing 3 to the function node to simplify the output.

1. var newMsg = {};
2. if (msg.localName) {
3.     newMsg.payload = msg.localName;
4.     return newMsg;
5. }
6. return null;

Listing 3. Function to send only the localName property

The new flow will look something like Figure 5.

fig5

Figure 5. Bluetooth scanner flow.

Cool – we’ve built a nice bluetooth scanner.  Now lets connect it to the cloud.

On FRED create a flow that receives data from a public websocket, checks whether the payload is a ‘Flex’ and if so, sends a notification to pushbullet.  The flow is shown in Figure 6.

fig6

Figure 6. Flow to send notifications to pushbullet when Flex is detected.

Configure the web socket node as shown in Figure 7 to listen on /public/presence.  The ‘/public’ prefix is used on FRED to indicate that the URL should be open to the public; no authentication is required.  FRED this will map to wss://{userid}.fred.sensetecnic.com/api/public/presence where userid is your FRED username.

fig7

Figure 7. Web socket node configured to listen on /public/presence

The simple code for the filter function is shown in Listing 4.

1. if (msg.payload === 'Flex') {
2.     return msg;
3. }
4. return null;

Listing 4. Filter out messages that don’t contain ‘Flex’.

Now let’s connect our device to our cloud hosted notification service on FRED.  We’ll add a web socket client connection to the flow as shown in Figure 8.

fig8

Figure 8. Flow with websocket client connection from scanner to FRED service

The websocket client should be configured as shown in Figure 9 to connect to your FRED instance with the URL wss://{username}.fred.sensetecnic.com/api/public/presence

Figure 9. Client side websocket configuration to connect to FRED.
Whew!  Now that we’ve got everything hooked up, you should get a pushbullet notification whenever a Flex is in range.  Note that because we scan every 10 seconds, you may get a notification as often.  You can add additional nodes (hint: check out the delay node) to filter out repeated discovery messages, and or connect this presence information to other services and cloud connected devices.