Raspberry Pi baby monitor
In this second of a multi-part post I will show how I added some lights to my Raspberry Pi baby monitor (using a RPi 3). The IR leds are not visible to humans, so it will not wake up the sleeping monster. I will also look at some of the software solutions for streaming audio/video over my network. Spoiler alert, in the end I have opted for the Fruitnanny system that Dmitry Ivanov developed.
Hardware, part 2
To be able to follow this guide, the hardware and associated installation from part 1 of this series (Raspberry Pi baby monitor – Hardware, part 1), is neither really advanced nor a requirement. The scripts I use are tailored to the hardware in part 1 and this part (i.e. you have a RPi, RPi Camera and BrightPi, however if you just want a smart RPi lamp this might help some too).
List of components
What you need (except the Raspberry Pi 3B with PiNOIR v2 camera):
- BrightPi kit (board with pre-soldered components + the leds and pin connector)
- Soldering iron and solder wire
- A sturdy holder for the board
- Sticky putty (brilliantly called “elephants bugger” in Denmark), which is good for holding LEDs in place while soldering
Soldering the LEDs
The BrightPi comes as a partial kit. There are two types of LEDs that need to be soldered on to the board, IR and visible light. Along with the LEDs there is also a connector that need to be soldered, if you want to use cables with connectors, and not solder the cables directly to the board. There are nice instructions at the Pi-supply site (https://learn.pi-supply.com/make/bright-pi-quickstart-faq/). I followed those and must admit that I am pretty happy with the results shown in the picture below.
Connect and mount the LEDs
Now we are ready to mount the LEDs to our set up. First I tested the LEDs though, just connecting the cables to the correct GPIO pins of the Pi. After this boot it up, and test the LEDs with the
i2cset command (after enabling I2C in
sudo raspi-config Interfacing Options>>I2C).
There are cool 3D print mounts for the BrightPi (e.g. https://www.thingiverse.com/thing:2784985), and the PiMoroni camera holder supports it (ugly though). Since I do not have a 3D printer (yet!) I opted for a LEGO mounting solution. I was already using a Raspberry Pi LEGO case, so I thought, if I get some nice pieces that fit and make it possible to direct the lamp that would be awesome. Another option might be to drill holes in the case to connect the screws of the BrightPi board to the camera board directly. Anyway, this is my current solution.
Now that is it, ready to flash the lights.
I also wanted to add some environmental sensors to monitor the baby room, because why not, this is a learning experience. So I bought the dirt-cheap but not great accuracy sensor DHT11. Hooked it up with wires according to specs and just let it hang outside the case for now.
During the past year I tested several solutions to streaming video over my local network, and to the outside through VPN. The main solutions I tested were:
- The RaspiCam interface.
- The UV4L project WebRTC and MJPEG streamer
- Simple VLC stream
- Python Flask app
- Python rpicam script
- Dmitry Ivanov’s FruitNanny (GStreamer, Janus, NodeJS)
After testing all these solutions I opted for the polished “FruitNanny” baby monitor, by Dmitry Ivanov (https://ivadim.github.io/2017-08-21-fruitnanny/). Its is perhaps a bit complex, a lot of software pieces need to fit. I cannot seem to access it from the outside through my VPN though, so a minus on that one. However I managed to set things up pretty quick using the guide on a fresh Raspbian install. Below are some comments on all the options.
Comments on (some of) the software
RaspiCam interface. (link)
I tested this through the DietPi distribution. Very easy to install and low usage. The landing page starts streaming directly, you can run scripts from the interface (i.e. toggle light). Full screen is possible. However, no audio, or audio noise meter.
UV4L project. (link)
Also tested through the DietPi dist. THe UV4L is an advanced project, with loads of functionality (such as running meeting rooms etc). The project has two way audio and video in the form of a native WebRTC client, in my use case it was one way. You just “call” the RPi and get audio + video. It was tricky to get the right parameters to see anything in the dark (gain, shutter speed etc), since I couldn’t trigger the lights manually. Also it was pretty unreliable, parameters would reset on reboot, slow and most importantly has some huge ugly text written all over (thus not really ‘open’ software). I read somewhere you can email someone to get a code to remove the text, but I decided to just give up on UV4L.
Python flask app. (link)
Very cool and interesting code by Miguel Grinberg, but how to tie in audio is not obvious, and probably expensive resource wise.
While some of the problems I ran into could be solved fairly easy, such as creating a background script that would turn on the LEDs for the UV4L solution, it was just too cumbersome. I would have a script take a photo to check if it’s too dark and then turn on the lights etc, but then the camera stream could not have been triggered before this. So in the end I went with the FruitNanny project. However there where a few things to fix because they were different in my setup, namely the LEDs and how I like my play/pause button.
Fix: Controlling the LEDs
For controlling the baby monitor’s LEDs there are basically two options. CLI/Bash script control through
i2cset or Python script with the BrightPi library. I ended up with the Python BrightPi library, and a script to replace the existing light.py file as follows.
#!/usr/bin/python # file: /opt/fruitnanny/bin/light.py import sys from brightpi import * # get cli argument par = sys.argv # define convenience variables LED_ALL = (1, 2, 3, 4, 5, 6, 7, 8) LED_IR = LED_ALL[4:8] ON = 1 OFF = 0 # now check the cli argument and do what is asked if par == 'on': # turn on the IR LEDs, but first reset them bpi = BrightPi() bpi.reset() bpi.set_led_on_off(LED_IR, ON) # gain can be 0 to 15 bpi.set_gain(13) elif par == 'off': bpi = BrightPi() bpi.set_led_on_off(LED_ALL, OFF) elif par == 'status': # here we are asking for the BrightPi status # so we use get_led_on_off method bpi = BrightPi() all = bpi.get_led_on_off(LED_ALL) # all now has the status of the LEDs # thus adding them all will show if any of them are on # but if all LEDs are off, 0+0...+0 = 0 if reduce( lambda x,y: x+y, all)>0: print(1) else: print(0)
This can now be run to check the status and turn on/off the IR LEDs of the BrightPi. For example
./light.py on should turn the IR LEDs on (make sure you
chmod +x light.py as well).
Now since the app previously used the Bash script
light.sh we need to change this in the
light.js file located in
/opt/fruitnanny/server/routes/. So open the file for editing, and change every
bin/light.sh status/on/off line to
bin/light.py status/on/off, simple.
Fix: the play/pause button
While the baby monitor setup by Dmitry Ivanov is super sleek, the play/pause button always got me confused. When paused it shows the pause button and the play button when playing. While I do see the logic and convenience in this, I feel I want a more YouTube-like experience, where the play button shows when it is paused and vice versa.
If you are like me you need to edit two files
/opt/fruitnanny/public/project/js/video-player.js and change every
fa-pause and every
fa-play. You can probably do it with some cool
sed command combo. The ‘fa’ stands for Font Awesome (https://fontawesome.com), just a font that has a lot of nice icons.
Things left to do (or: Wishlist)
There are a few things I want to do
- Light diffuser, the light is very spot-like. Would like to light the full image as evenly as possible.
- Wall holder, put the contraption in a more stationary location.
If I end up with new things, tweaks, I will post the updates here.