Showing home status with just a single RGB LED
This week I decided to try out the Bluno (Bluetooth + Arduino Uno) and WiDo (WiFi + Arduino Lenardo) modules that I'd ordered from DFRobot.
The Bluno investigation was fairly short-lived: it works as advertised but it cannot scan for Bluetooth devices which is how I was hoping to use it.
Moving on to the WiDo, this is a very cheap way to get an Arduino + WIFI. It worked well despite the rather small on-board WIFI antenna. I added a NeoPixel single RGB LED to it on digital output 6.
After a short while configuring it to scan for SSIDs and connect to my local network I was able to get it calling out to my home automation server using POST requests. I quickly added a new API to report how recently each major area of the house had been occupied (minutes since last triggered) that produces JSON like this:
{ "first": 1.5860427216666666, "second":
29.900604178333335, "basement": 196.46606494, "barn":
446.73795961333332, "driveway": 162.16262138333335, "kitchen":
86.293791955 }
I quickly found many of the ways the WiDo could hang during Http requests and SSID scanning / joining networks so I plugged one of my Arduino Watchdog boards on top after moving the jumper from the ~10s position to ~40s.
I used the Adafruit library to connect to the server and make the request. Avoiding memory allocations is usually the best approach on a small memory device like this so I have a fixed buffer into which I read the response rather than using `String` or any other class that makes dynamic allocations.
int count = 0;
/* Read data until either the connection is closed, or the idle timeout
is reached. */
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS))
{
while (www.available()) { char c = www.read();
if (count < responseBufferLength) responseBuffer[count++] = c;
lastRead = millis();
}
}
Parsing JSON in Arduino isn't trivial. There is a library that many people recommend but it takes up a fair amount of RAM and I wanted something simpler so I used my trusty 'cheat' parsing code that looks for a string, skips a few characters and then reads a number:
static double getJsonDouble(const char* buffer, const char* name)
{
char* p = strstr(buffer, name) + strlen(name) + 2; if (p != NULL) { return atof(p); } return -1;
}
static int getJsonInt(const char* buffer, const char* name)
{
char* p = strstr(buffer, name) + strlen(name) + 2;
if (p != NULL) { return atoi(p); } return -1;
}
Using this it's easy to get each of the values being passed back from the API call:
double firstFloor = getJsonDouble((char*)responseBuffer, "first");
I decided to color the LED with Blue for barn, Green for house and Red for driveway with the brightness fading out the longer it has been since the last trigger. I also blip the LED to off each time any of the values reduces because that indicates it was triggered since last time it was read.
So now, at a glance I can see what's happening at home: Red = a car came down the drive but nobody is home, Yellow = a car came down the drive and someone is home, Green = someone is home, Blue = Someone is in the barn, White = lots happening, Black = all quiet, nobody around! Based on the brightness I can tell how recently each area was occupied.
Overall this one solitary RGB LED conveys quite a lot of information about what's happening at home. With a quick reconfigure of the SSID and password I had it running on my desk at work. Now I just need to put it in a translucent orb casing to make it look more attractive.
I'm also planning on building a few more to indicate other interesting data about the house, maybe one connected to my traffic alerts, another to my delta-weather reports, ... But rather than putting these out on desks as visible orbs I'm planning on putting them in places where they can cast a subtle light onto a wall - i.e. not something a visitor would notice but something we can see as we walk around - a 'glanceable information source.