Should I Leave The Window Open?

As the days start to get cooler again in North Carolina I’m always left with this conundrum… should I leave the window open or not?

On one hand I could feel a pleasant draft that cools me and my wife down all evening without having to pay for air conditioning, on the other hand I could end up waking up to a soaked wall as it’s rained in the middle of the night or the air conditioning has kicked on and I’m pumping lovely cool air that I’ve just paid for directly out the open window.

#firstworldproblems…. I know but it is never the less something I think about. So what can be done here? I’ve got a Nest thermostat and am a reasonably competent scripter.

Here is what I put together, a quick webpage that you can hit from any device on the home network and displays the following info…

selection_064

Turns out there are a few libraries that help us get off to a useful start.

  • weather-cli — this one allows us to pull real time hourly weather info for the next 24 hours based on precise location.
  • flask — flask can be used to quickly serve up a webpage in python
  • python-nest — this is used to get/set data with Nest thermostats.

Interestingly, python-nest and the nest-API  provides some hourly weather info back in a pretty useful form. However it is missing one pivotal piece of data… which is the actual weather conditions for those individual hours, is it raining? is it sunny? that very important datapoint is not present and pretty much the primary reason I’m using weather-cli here.

There’s not a ton of documentation on weather-cli but for the few things that I wanted to know that weren’t documented, there’s always the source-code, and the code was helpful here.

Installing Software

sudo apt-get install python-pip
sudo pip install pip --upgrade
sudo pip install setuptools --upgrade
sudo pip install  weather-cli flask python-nest

Setting Up Weather-CLI

To use weather-cli, you’re going to need a Forecast.io API key, register here to obtain one. With the basic free plan, you have 999 API calls per day for free, enough to check the weather a couple hundred times per day which is more than enough for me.

To get weather-cli set up we need to use the setup argument.

pi@underhousepi ~/scripts/weather_predictor $ sudo weather-cli --setup

Enter your forecast.io api key (required):xxxxxxxxxxxxxxxxx
Warning:
The script will try to geolocate your IP.
If you fill the latitude and longitude, you avoid the IP geolocation.
Use it if you want a more acurated result, use a different location,
or just avoid the IP geolocation.
Check your latitude and longitude from http://www.travelmath.com/

Enter the latitude (optional): 36.982917
Enter the longitude (optional): -75.402301
generating config file...
setup complete

Once setup is complete we can simply call weather-cli and it will return data for us based on the location we used for initial setup.

The rest is writing a quick flask app. Here is the code for that in the gist below. You’ll notice the flask app calls a template. I’ve placed that index.html template in a templates directory as shown below.

https://gist.github.com/ericpulvino/b7753c1f598642f3bbd64895553232db

Note that I’m also calling the nest api to query the target temperature of the nest device and using that as a basis for whether or not the window open. You could hard-code that value alternatively if you don’t have a nest or for testing purposes. I also have more than one nest in my home so in line 29 I’m calling devices[1] to get to query the second nest in my environment. You may want to change this to devices[0] or another value based on your output from the python-nest api’s documentation page.

user@raspi4 ~/scripts/window_open $ tree
.
├── templates
│   └── index.html
└── window_open.py

Here is the code for the template too.

https://gist.github.com/ericpulvino/8196a057493dec94d0f48c495ad5f706

Hope this might save you a few minutes in your search for cool air at an affordable price.

Autoplaying Files in Kodi Isengard

Almost all the affects of the change in naming from XBMC to Kodi have been realized at this point except for a few small areas. One of those areas is using the on-box API to send commands into Kodi or automate certain actions.

In my case I was trying to automatically play a file as soon as my Kodi player boots. To do that you simply place a file with the right content in the right place.

My System Details:

  • Hardware: Raspberry Pi 2 /w Edimax EW-7811UTC AC600 Wifi Adapter
  • Software: OpenELEC v6.0.3 (Kodi 15.2 Isengard)

Specifically, create a file called autoexec.py in the /storage/.kodi/userdata/ directory.

import xbmc
xbmc.executebuiltin( "PlayMedia(smb://192.168.1.20/usenet/Baby_Stream.strm)" )
xbmc.executebuiltin( "PlayerControl(repeat)" )

If you’re trying to test the script on the CLI via ssh by using the python interpreter you might notice that calls to import the xbmc module fail.

OpenELEC:~ # python
Python 2.7.3 (default, Feb 29 2016, 21:17:05) 
[GCC 4.9.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import xbmc
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ImportError: No module named xbmc
>>>

This is expected because the xbmc module is not exposed to the default python path.

Testing your Script:

In order to test your script try having Kodi send it through it’s python namespace using the kodi-send command:

OpenELEC:~ #kodi-send -a "RunScript(/storage/.kodi/userdata/autoexec.py)"

Quick and easy automation in Kodi. To see other functions that can be called either via kodi-send or  automated in xbmc.executebuiltin statements, check Kodi’s official docs on the subject.

Halloween Home Automation

Now that my son is 13 months old I finally had  at least a moment or two to work on a Halloween display so naturally I wanted to get some automation activities integrated with my platform of choice, the Raspberry Pi.

Note: My code is available at the bottom of the project.

My goal for this project was to use every trick I could with a minimal budget to scare as many neighborhood kids as I could. Mission Accomplished.

Here was the rough order of operations.

  1. Motion sensor runs in a loop looking for motion.
  2. When motion is detected start the smoke machine smoking immediately and run for all additional events in the list.
  3. Wait for a moment or two then cut all of the exterior property lighting.
  4. Wait for another moment then play one of the spooky sounds from the hidden speakers in the bushes very loudly.
  5. Revive the property lighting.
  6. Wait 15 seconds then repeat.

Controlling the Smoke Machine

The first order of business was to reverse engineer how the smoke machine remote actually works. Two years ago I had purchased the biggest non-commercial smoke machine I could find as part of my annual Halloween budget. That first year I just used the included remote but even then I knew I would eventually have to figure out how to automate the smoking functionality. I know they also sell remotes that don’t have the simple on/off button like mine has; instead you can pay $16.99 for a remote with an interval smoking function from a store like Spirit Halloween– but again, I didn’t want an interval– smoke juice is expensive I want to use it only when a person is actually nearby to enjoy it. So this led me down the path of figuring out how to control it.

Using a standard multimeter set to measure resistance I determined what each of the 3 pins in the remote did and determined that in order to produce smoke I needed simply to bridge two of them. This is the enterance-point for my 4-way relay I had purchased a year ago for just such a task.

IMG_20151031_120801

Hooking up the relay to bridge the necessary pins I was able to produce smoke — SUCCESS! Now to set this up a little more permanently, as it turns out the remote is actually switching 120v wall power so extra care is needed when wiring this up to do it right. I obtained some extra lumber I had from another project and started building a control board that everything would be permanently affixed to.

Breadboarding with 120v

At this point, I’ve used a combination of drilling and ziptieing to secure the raspberry pi (with case), breadboard, and relay bank to the control board which was a sheet of 1/4 inch MDF.

Adding Motion Sensing

The next phase was to setup the smoke machine to fire when motion was detected. To accomplish this I used a cheap PIR sensor that I had purchased off of E-bay last year for about $3.00 via the direct from China route.

It took a bit of adjusting on the PIR sensor to get it setup correctly for my application. In this case there are two adjustments, one is sensitivity, and the other is time-delay (how long the signal wire stays high when motion is detected). For this project I essentially set the PIR sensor to maximum sensitivity and the shortest time delay for a hair-trigger. I wanted to maximize the granularity of the sensor and push the false positive detection into software where I could control it with variables in a program instead of by turning physical knobs.

Once configured I did a bit of trial and error by moving back and forth in front of the sensor in my garage. My neighbors would probably have thought me crazy moving back and forth in my garage for 15 minutes but they know better by now. I found that the effective range of the sensor was about 15 feet.

Now that I had the sensor working with some test code (included PIR_test2.py) it was time to setup some spooky noises to be triggered with the motion sensing.

Setting up the Audio

I wanted to use the included headphone jack on the Pi to play audio into a little class T amplifier (I swear this used to cost just under $20 when I bought it, it has AMAZING PERFORMANCE for the price) and an old pair of extra speakers that had been collecting dust around my workshop.

IMG_20151108_140653

As it turns out there was an issue with some of the updates I had performed most recently on my Pi that left my audio broken, after a bit of soul-searching on google for the error message I saw when trying to use Aplay to play a sample audio file I decided to do some updates and see if that would solve the issue.

sudo apt-get update -y && sudo apt-get upgrade -y

Sure-enough my audio was now working with Aplay after the dust cleared from the updates and a reboot was performed.

At this point I began searching the net and collecting spooky noises from various sound effect websites. I collected all ten of the wav files which made the final cut and renamed them from 1-10 (My code actually randomly generates an integer from 1-10 and plays the corresponding file 1.wav – 10.wav for simplicity).

Adding The Exterior Lighting Control

Since the majority of my exterior property lighting is already wired for automation with WEMOs I wanted to include this in my Halloween setup. I bought 3 red LED bulbs and went to town replacing the exterior lights with an eerie red glow. They actually created a lovely scary effect. The bulbs were certainly not cheap though.

Regarding the code for the WEMOs, I already had this code built from various WEMO projects but I wanted to do something very simple for this project, just an on/off, no database tracking, no fancy behaviors, no logging etc. so I re-wrote some of the code to run a little faster and added a little pair of bash scripts (allon.sh and alloff.sh) to bring up multiple switches in rapid succession, the effect is truly instant when kicked off in this manner so I was very happy.

Carving the Monster Pumpkin

I’ll have to add a picture of the beast when it was all carved but I picked up a gigantic pumpkin from the Raleigh State Farmer’s Market for $50. I’ve always wanted a pumpkin this big. I figured with this no one would be able to doubt my Halloween spirit. This pumpkin was so large that it took two grown men to move it on a towel. I honestly could not lift it myself which was very emasculating but also thrilling that it was so incredibly huge.

IMG_20151004_152307

I know I have a carved picture of it somewhere but I can’t seem to find it at the moment so I’ll post that bit later. These super huge pumpkins are actually a different species and produce really nasty seeds that you can’t cook up which is an interesting fact I learned when I opened this bad-boy up.

When the scary face was all carved I then carved a 3inch diameter hole in the back for the dryer hose…. dryer hose you ask?  Of course you need dryer hose when you’re…

Building the Fog Chiller

One of my favorite pieces of Halloween tech is a good fog chiller. When you cool the fog down to a temperature that is lower than the outside air it will actually sink down to the ground and drift along making an extra scary effect. This was a trick I masterminded when I was organizing the annual public Haunted House in my fraternity days. The effect is great and luckily I had an old 50 gallon plastic drum that I had purchased off of Craigslist several years ago that was a perfect fit for the project.

IMG_20151031_202446

Essentially you cut a hole in your container, coil the dryer-hose around within the container then run the hose to your destination which in my case was the back of the gigantic pumpkin. I also added a string of green LED lights in the pumpkin as well to give the fog a cool effect.

Lastly you fill the container with a combination of ice and water. I actually began saving up ice from my refrigerator and storing it in my chest freezer several weeks in advance in order to be able to fill up the drum and not spend any direct dollars from the Halloween budget on frivolous things like store-bought ice.

Putting All the Pieces Together With Code

Now that all the individual pieces were functional all that was left to do was to write the code to unify the individual pieces and create the coordinated show.

This code can be found in the halloween.py file.

IMG_20151108_140600

Results

The effect was awesome! Many neighborhood kids and parents were scared some wouldn’t even set foot on the property which is a personal win because that means more candy for me and as an adult lets be honest, there are few joys in life like making kids you’ve never met cry. I will probably grow this by adding motion activated lawn effects next year but this year was a total success!

Get the Code

I’ve posted my code from the endeavor to my github page in a new Halloween 2015 repo: https://github.com/ericpulvino/halloween2015

Amazon Dash Button Automation

Screen-Shot-2015-03-31-at-9.23.22-AM-620x311

If you haven’t heard about them, Amazon is putting out these shiny new buttons which are basically walking advertisements for certain brands of products. You can stick them to a wall with the included adhesive or hang them somewhere with the included ring (not pictured). What is even more interesting is that when you press one of these buttons they are supposed to place an order for a new product without any interaction on your part. They connect up to your home WIFI (with a bit of initial setup through the Amazon app) and beam the order request out to Amazon on the double so you can have your new garbage bags in a jiffy.

They come in veritable cornucopia of flavors right now, 18 buttons in all at the time of this writing. With multiple different companies vying for the opportunity to pitch their wares to you and get a little ad-space on your wall. Rumor has it that these companies are even paying Amazon for the privilege of being button-ized.

856b77326349b311da4c8fa3f8c8082a

Amazon is pitching these things for $5 a piece right now to Amazon Prime members only. Although supposedly you’ll get a $5 discount when you place your first order of product X using the button. You’ve really got to hand it to Amazon here, they’re making money on both ends, from the business AND the user. Let’s forget the fact that the whole concept is just a bit ridiculous (even for a technophile like me)… that they’d expect you to pay $5 for the convenience of hitting a button to order a product. That you would be so lazy as to not even perform the most rudimentary of price comparisons. That you would be willing to pay the iron price Amazon price for whatever good… whatever it happens to be. Are we all really that lazy busy?

Poor product ideas aside, I immediately plopped down $10 in Amazon gift card money and bought two of them right before my Prime subscription ran up because something tells me these aren’t going to be on the market for very long. After being inspired by Ted Benson I had a feeling there must be something I could set these up for.

61yJkst6nVL._SY355_

I purchased the most basic dash button model I could find with the least offensive advertisements… in this case this was the Amazon Elements model. When they arrived I immediately covered up the amazon logos with a label maker and called the buttons, very memorably, #1 and #2.

IMG_20150921_080310
Here you can see the hanging rings included with the buttons, the button on the right is naked.

Setup of the buttons is really simple but you must be careful to NOT COMPLETE THE SETUP. You wouldn’t want these buttons to actually order something hahaha. If you accidentally do complete the setup (like I did), you can dissociate the button from whatever product you picked but I recall it being an extra annoying step. Read the Ted Benson article here for clues on where to abort the setup process. For me it was as simple as force-closing the app on my phone when it prompted me to select the radio-button for a corresponding product. Presto chango the button was now rendered useless. It will still connect to your home Wifi and communicate to Amazon but it will not complete the ordering process.

Actually if you were to stop right here things would be quite annoying for you because every time you hit the button it still communicates with Amazon and then the silly phone app blows-off an annoying message to you reminding you to finish setting up your button. This gets old really quickly even when I was testing– even more fun is that the notifications stack up in Android so you’d have a list a mile long of notifications unless you take the next steps.

1). Setup a static IP for the button

2). Block all traffic from that IP out to the internet

You can use “discover mode” shown in python code below to learn which MAC address your dash button has in order to properly bind it to a static IP. Regarding the ability to block traffic, not every home Wifi router can support this function but if you have a newer router like the super-awesome Asus RT-AC68U you’re good to go. In my case I built a rule that applied to all hours of every day and applied that to the IP addresses of the two buttons for all of both kinds of traffic, TCP and UDP. Basically these things are now entirely disconnected from the internet.

Selection_168

Sure enough, when I applied these rules and continued pressing these buttons, I no longer received any notifications from Amazon. One side effect of this action is that the buttons stay awake longer as they try (and fail) to communicate with Amazon; I would estimate about 30 seconds in total although I have not specifically timed it.

Onto the fun stuff.

Now that the buttons are setup I cannibalized and re-factored some code to listen for them on the network. Here is what I ended up with.

#!/usr/bin/python

import sys
import time
import socket
import struct
import logging
import binascii
import subprocess

logging.basicConfig(filename='/var/log/dashbutton.log',
                    level=logging.INFO,
                    format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S -- ')

discover_mode=False

if len(sys.argv) > 1:
    if sys.argv[1] == "discover": discover_mode=True

rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
buttons={
    "00bb3aff6aea_192.168.1.00":["Button One",0,["/home/pi/scripts/WEMO/send_wemo_commands.py","sendall.toggle"]],
    "747548bd4908_192.168.1.255":["Button Two",0,["/home/pi/scripts/WEMO/send_wemo_commands.py","kitchensink.toggle"]]}

logging.info(' ### Dash Button Service Started ### ')
while True:
    packet = rawSocket.recvfrom(2048)
    ethernet_header = packet[0][0:14]
    ethernet_detailed = struct.unpack('!6s6s2s', ethernet_header)
    arp_header = packet[0][14:42]
    arp_detailed = struct.unpack('2s2s1s1s2s6s4s6s4s', arp_header)
    # skip non-ARP packets
    ethertype = ethernet_detailed[2]
    if ethertype != '\x08\x06': continue
    source_mac = binascii.hexlify(arp_detailed[5])
    dest_ip = socket.inet_ntoa(arp_detailed[8])
    identifier=source_mac+"_"+str(dest_ip)

    if discover_mode:
       logging.info("We saw an arp from MAC: " + str(source_mac) + " ip: " + str(dest_ip)+ "\n")
       continue

    if identifier in buttons:
        buttons[identifier][1] += 1 #iterate the count of button presses
        logging.info(buttons[identifier][0] + " Pressed " + str(buttons[identifier][1]) + " times.\n")
        subprocess.Popen(buttons[identifier][2],stdout=subprocess.PIPE).communicate()[0]

Or download the code from my Github Gist page.

The code has two modes in which it can be run:

  • Discover mode: ./dash_button.py discover
  • Vanilla mode: ./dash_button.py

In discover mode the script will call out whatever MAC addresses it sees sourcing ARP packets… Press your button here and see what addresses your button owns. Once you’ve defined the static IPs in your router come back to the script and update the buttons dictionary with your “tuple” of MAC and IP address followed by your colloquial name for the button, the number of times it’s been pressed and lastly the command that should be executed by subprocess when the button is pressed.

Now you can run the script in vanilla mode to test pressing your button.

A simple few lines of code which sniff all incoming traffic listening for ARPs from a specific tuple of source MAC and IP address. Since this script is essentially sniffing all incoming packets you’ll want to situate this code on a remote part of your network that doesn’t process big file transfers or the like. In my case I have this code sitting on a Raspberry Pi that isn’t used for much.

Reading the code, you can see the “tuple” as the key for the “buttons” dictionary this is the key to identifying traffic we care about. The format for the buttons dictionary is rudimentary but functional and avoids making a class for something really simple.

In my example I’m kicking off WEMO Events whenever buttons are pressed. I keep button #2 by my nightstand and press it to turn off my kitchen light when I go to bed. Button #1 just toggles every light switch in the house for fun.

Starting the Script on Boot:

I built an Upstart job to start the script at each boot. In order to use this method, you’ll need to install Upstart on your Pi with:

pi@pi ~ $ sudo apt-get install upstart
Reading package lists... Done
Building dependency tree 
Reading state information... Done
Suggested packages:
 graphviz
The following packages will be REMOVED:
 sysvinit
The following NEW packages will be installed:
 upstart
WARNING: The following essential packages will be removed.
This should NOT be done unless you know exactly what you are doing!
 sysvinit
0 upgraded, 1 newly installed, 1 to remove and 81 not upgraded.
Need to get 502 kB of archives.
After this operation, 940 kB of additional disk space will be used.
You are about to do something potentially harmful.
To continue type in the phrase 'Yes, do as I say!'
 ?] Yes, do as I say!
Get:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main upstart armhf 1.6.1-1 [502 kB]

You can see during the Upstart install the system actually prompts you for such a big change with some special language [bolded above].

After Upstart is installed give your Pi a reboot:

sudo reboot

Lastly build the Upstart job by creating a file called “/etc/init/dashbutton.conf” and adding the following contents [replacing the exec line with the location where you have stored the script on your machine]:

author "Eric Pulvino -- AlwaysTinkering.wordpress.com"
description "Upstart Script to run Amazon Dash Button service"

start on runlevel [2345]
stop on runlevel [016]

respawn

exec /home/pi/scripts/dash_button.py

That’s it. You can reboot your Pi to automatically start the service now however you could also just run the following command to start the service manually:

sudo service dashbutton start

Summary:

I’m sure there will be more in store for the buttons down the road with Halloween so close by. My typical Halloween goal is to literally scare the neighborhood children (and adults to death) so I might setup the use of the buttons to disable some of the really scary effects for 30-60 seconds when I see little children coming up the walk. Either way I’ll be sure to post some of my Halloween antics this year!

Raspberry Pi WeMo Home Automation Control Center

WeMo PlugFor the last year I’ve had a Raspberry Pi that is always on mounted underneath my house. I power this device using PoE (Power over Ethernet) so there is literally a single ethernet cable that provides it with the ability to run for simplicity’s sake. This unit was the first Pi I had ever purchased so I’m a little nostalgic about it until you consider that I make it live in a crawlspace under my home.

While it is sitting under the house it’s performing a few vital services for me.

Service 1: Property Temperature Monitoring — Perhaps someday I’ll do a write up on this aspect.

Service 2: Amazon Dash Button Receiver

Service 3: Home Automation Control Center 

I have been meaning to write an article on Service 3 for some time. Of course I didn’t actually get around to doing it until there was a contest involved because it is a well known fact that I will do unspeakable things for free t-shirts. The write up on my Raspberry Pi Home Automation Control Center can be found on Instructables.com

http://www.instructables.com/id/Raspberry-Pi-WEMO-Control-Center/?ALLSTEPS

Raspberry Pi Nursery Cam

One of my most recent projects has centered on the new IMG_20150104_005102addition in my family. With the baby on the way I started looking at baby monitors and realizing that a simple little video-enabled baby monitor was around $300. I figured I could do much better than a tiny 2″ screen and integrate some useful features along the way.

Goal: Sub $300 Baby Monitor Camera

Result: $100 Nightvision Camera /w FM Audio Broadcast

Capabilities:

  • Full 1080p Streaming (cropped image) over Ethernet (Full Frame Image /w 1296×972 resolution)
  • Internet Streaming capabilities to broadcast video to Computers, Phones and HTPCs.
  • Selectable FM Frequency for Audio Transmission – any radio in the house is now a baby monitor including bedside clock radios.
  • Separate Audio and Video Transmission for all different kinds of endpoints
  • Full Nightvision capabilities with the PiNoir Camera Module and IR LED module (can be used in total darkness and picture is excellent)
  • IR LED module shuts itself off when not needed due to a built-in photoresistor
  • Authentic Camera look salvaging a dummy enclosure
  • Stream plays easily in XBMC making any HTPC double as a video receiving endpoint.

Parts list:

Dummy Camera Shell from Monoprice — $7.94
IR LED Light Array from Amazon — $5.90
Slice of Pi Breakout Board — $8.25
Cheap USB Microphone from Amazon — $7.95
Raspberry Pi Model B — ~$40
Raspberry PiNoir Camera Module — $25
Nylon Washers and Tiny Nuts/Bolts — $1.50

Misc Parts (freebies):

SD Card
Piece of Wire
Ethernet Cable
MIcro USB Cable
USB Power Brick
12vdc Power Adapter for LED’s

Project Details:

Gut The Dummy Camera Enclosure

The first order of business was to gut the innards of the dummy camera case to make room for the Pi. In my case I took my dremel cut off wheel and hollowed-out the back of the case to make room for all the wires and SD card which hangs out the back a bit. Removing all the Battery, LED components, and fake LED array left plenty of room for our frankencamera. The IR LED array is pretty much a direct fit for the fake one that was removed. I discarded the black plastic backer behind the fake LED array too. By countersinking the holes that hold the fake LED array in place I was able to reuse the mounting bracket to tighten down the new LED array as a direct replacement for the fake one.

You can see the LED array has mounting holes that line up almost perfectly with one of the pairs from the PiNoir module.
You can see the LED array has mounting holes that line up almost perfectly with one of the pairs from the PiNoir module. I used nylon washers and a pair of nylon spacers between the two boards to keep them from touching each other or anything conductive.
IMG_20141213_124430
You could even dremel-out the battery compartment and stick a little thumb drive here for local storage of video/audio content. Since my device is a network streamer I left this compartment alone after removing all the metallic components.
IMG_20141213_124446
Dremel out the back of the enclosure. This was only necessary for me because of my cheap USB microphone which could not bend very well in the case.
My pet black widow I caught in my workshop as I was working.
My pet black widow I caught in my workshop as I was working.

Install Software

For this project I just used the basic Raspbian image on the SD card. From there I enabled turbo-mode for on demand overclocking up to 1ghz. This project uses PiFM to broadcast audio on the FM bands. PiFM is a quick and dirty solution to acheive my goals. Be aware that PiFM is a pretty noisy transmission that has strong harmonics in bands you should not be transmitting on — that being said, your range is very small (about 30-300ft depending on the length of your antenna) and will probably not hurt anyone (use your judgement and check your local laws to make sure you’re in the clear here). Install PiFM and test that your broadcasting works. Once you’ve confirmed you’re broadcasting as expected you can use Radio Locator to determine which FM frequencies are vacant in your area. Broadcasting on a vacant frequency will give you the best performance and range. I ended up trying a few of the frequencies in the “BEST” category before I found one that was pretty much perfect for me and gave crystal clear audio. For a more permanent antenna attachment, I soldered my antenna wire to the “Slice of Pi” breakout board. I may also add a toggle switch for the FM transmission at some point so it’s nice to have the breakout board ready to go.

Configure Camera

The PiNoir camera module is actually a really capable camera and using the included raspivid software can be configured to behave however you could want it. It’s worth reading about the different modes the camera supports and making a decision as to what is most important for your application. For me I did not need a high quality 1080p stream so much as I did a wide field of view since the camera is close to the subject being filmed. For this reason I selected the 1296×972 resolution which uses the entire sensor for the widest possible field of view.

After selecting the resolution it’s time to tweak your raspivid settings to give you the best results. I after reading through all of the settings and doing a good bit of experimentation I settled on the string below:

#1296×972 1-42fps, 4:3 aspect binned full FOV.
raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

You’ll notice in my code above I’m using the color effects feature to skew all the colors to a nightvision color palette. I did this because occasionally due to power fluctuations on the camera module the image would shift a bit back and forth from green to red, the effect was significant enough for my wife to notice it which means I wanted to fix it. By specifying the color effects I was able to work around the color-shifting artifacts. FYI the color shift is due to the poor design of the Raspberry Pi power supply circuitry; I believe this may no longer be an issue with the enhancements made to the newest B+ model but since I don’t own one, I can’t say.

Create a Streaming File for XBMC/Kodi

If you want to play your stream on an XBMC/Kodi machine you can put the details of your stream into a simple text file and Kodi will play your stream when you play the file. Here’s my example file that I used.

Filename: Baby.strm

rtsp://[IP Address of PI]:8554

Startup Scripts

A bit of scripting will allow the video and audio to start when the machine boots. My startup scripts are provided below.

/etc/init.d/SCREEN_STARTUP — quick script that starts both Audio and Video streaming at boot time. Don’t forget to add it to your startup with “sudo update-rc.d SCREEN_STARTUP defaults”.

#!/bin/bash

#Raspberry Pi actually doesn't actually support MTU over 1500
#   but does not bark when you set it. See Link below:
#http://www.raspberrypi.org/forums/viewtopic.php?t=52807&p=405135
#ifconfig eth0 mtu 9198

/usr/bin/screen -d -m -S "RASPIVID SESSION" /home/pi/raspivid_abstraction &

sleep 2 

/usr/bin/screen -d -m -S "PIFM SESSION" /home/pi/pifm_stream_command &

echo "Script has attempted to start both screens"

sleep 1
echo "List of available screens is:"

screen -list

/home/pi/screen_watcher.sh &

exit

/home/pi/raspivid_abstraction — necessary to run VLC under the Pi user, VLC will not run as root without modification.

#!/bin/bash

su - pi -c "/home/pi/raspivid_stream_command"

/home/pi/raspivid_stream_command — starts the video stream (just uncomment whatever mode you want to use)

#!/bin/bash
#1296×972 1-42fps, video mode, 4:3 aspect binned full FOV.
raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

#Experimental adding sound -- does not work! Raspivid sends raw H264 Stream, would need to have an intermediary step with Gstreamer adding the timing information to the video stream in order to layer the audio on top of it.
#raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --input-slave=alsa://plughw:1,0 --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264


#1296×730 1-49fps, video mode, 16:9 aspect , binned, full FOV (width), used for 720p
#raspivid -h 730 -w 1296 -br 40 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

#1920×1080 1-30fps, video mode, 1080p30 cropped
#raspivid -h 1080 -w 1920 -br 40 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

/home/pi/pifm_stream_command — Starts PiFM

#!/bin/bash
arecord -fS16_LE -r 22050 -Dplughw:1,0 - |  /home/pi/software/pifm - 106.7 22050

/home/pi/screen_watcher.sh — Makes sure that both commands are still running, I’ve found PiFM occasionally dies out, so this script restarts it.

#!/bin/bash

while true; do
    sleep 30
    PIFM=$(screen -list | grep PIFM | wc -l)
    RASPIVID=$(screen -list | grep RASPIVID | wc -l)
    if [ "$PIFM" -ne "1" ]
    then
        /usr/bin/screen -d -m -S "PIFM SESSION" /home/pi/pifm_stream_command &
        echo " $(date) -- PIFM restarted." >> /var/log/screen_watcher.log
    #else
    #    echo "PIFM still running"
    fi

    if [ "$RASPIVID" -ne "1" ]
    then
        /usr/bin/screen -d -m -S "RASPIVID SESSION" /home/pi/raspivid_abstraction &
        echo " $(date) -- RASPIVID restarted." >> /var/log/screen_watcher.log
    #else
    #    echo "RASPIVID still running"
    fi
done

Ideas for Future Enhancements

  • A button to toggle the FM transmission on/off
  • Eventually I’ll do a similar build (minus the audio) for an exterior surveillance system. Monoprice sells actual camera enclosures for this purpose

Final Tests

Two sided tape was applied to the bottom of the microphone to stick it to the wall. I used the included hardware to mount the bracket as well.
Two sided tape was applied to the bottom of the microphone to stick it to the wall. I used the included hardware to mount the bracket as well.
The baby actually looks a bit creepy here but the picture quality is awesome on this old 25" monitor I had laying around. I purchased a flat screen TV wall mount for my Bedroom Media Center project.
The baby actually looks a bit creepy here; I think he is hypnotized by the faint red glow of the IR LEDs but the picture quality is awesome on this old 25″ monitor I had laying around. I purchased a flat screen TV wall mount for my Bedroom Media Center project which is what I’m using to view the video stream here.
The XBMC Bedroom Media Center playing the stream.
The XBMC Bedroom Media Center playing the stream.

Everything works like a charm. There is about a 6 second delay for both the audio and video transmission which does not really bother me for my application. In my brief research on the subject I think I read it was due to the buffering. One of the things I really like about this project is the separation of the audio and video transmission so you don’t have to have the whole media center on to listen to the audio. You can just use a bedside clock radio (not pictured) to listen to the stream.