We learned the basics of how to turn a Raspberry Pi into a real-time temperature streamer in our IoT 101 Hello World Project (here). Let’s take the next step in IoT awesomeness and learn how to stream the temperature from multiple Raspberry Pis located anywhere (as in anywhere in the world) into a single data visualization right in your web browser. Once we have all of our streams streaming, I’ll show you you can instantly share your data with anyone (as in anyone in the world) so they can watch those temperatures update in real-time. If you thought the IoT 101 Project was easy, you will be able to do this project in your sleep.
You will need the same supplies required for the IoT 101 Project (except multiply by how ever many unique temperature streamers you want to build):
- Internet connected Raspberry Pis or your single-board computers of choice (at least two).
- DS18B20 temperature sensors (at least two; https://www.adafruit.com/product/381).
- Breadboards for wiring up a simple circuit (at least two; in the Adafruit Pi starter kit).
- 4.7K to 10K resistors (at least two; also in the Adafruit Pi starter kit).
I used two brand new Raspberry Pi 2 boards and a Raspberry Pi Model B+ for my project. You can mix and match single-board computers without a problem.
My new DS18B20 sensors came with three different color wires than before – red, blue, and yellow. Red connects to 3.3V, blue to GND, and yellow to a pull-up resistor and to GPIO 4 of your Pi.
To ensure your temperature sensors are working, SSH into your Pi and type the following into a command prompt:
sudo modprobe w1-gpio sudo modprobe w1-therm cd /sys/bus/w1/devices ls
You should see a sub-directory that starts with “28-“. If you do, everything is working and you are ready to proceed. If you do not, you may have the same issue I had with my brand new Raspberry Pi 2 (running the Raspbian release with v3.18 of the kernel). This issue is discussed here and here. The quick fix is to simply add the line “dtoverlay=w1-gpio,gpiopin=4″ to your /boot/config.txt file and reboot.
If you see random sub-directories that seem to change their prefix every few seconds (e.g. “00-“), you may have a bad DS18B20. One of my three DS18B20 sensors exhibited this behavior and turned out to be broken.
Install the Initial State streamer on each Pi (go here for instructions on setting up the Initial State streamer; it is super easy and takes less than two minutes). Once installed, we are ready to start streaming. We will use the same code as the IoT 101 Project for each temperature streamer, with only a simple modification. Don’t forget to put your Initial State account access key in line 6 after the access_key parameter (in between quotes) on each device (you can find your access key under your Initial State account settings).
import os import glob import time from ISStreamer.Streamer import Streamer streamer = Streamer(bucket_name="Temperatures", bucket_key="Whatever_You_Want", access_key="PUT YOUR ACCESS KEY HERE") os.system('modprobe w1-gpio') os.system('modprobe w1-therm') base_dir = '/sys/bus/w1/devices/' device_folder = glob.glob(base_dir + '28*') device_file = device_folder + '/w1_slave' def read_temp_raw(): f = open(device_file, 'r') lines = f.readlines() f.close() return lines def read_temp(): lines = read_temp_raw() while lines.strip()[-3:] != 'YES': time.sleep(0.2) lines = read_temp_raw() equals_pos = lines.find('t=') if equals_pos != -1: temp_string = lines[equals_pos+2:] temp_c = float(temp_string) / 1000.0 return temp_c while True: temp_c = read_temp() temp_f = temp_c * 9.0 / 5.0 + 32.0 streamer.log("Living Room(F)", temp_f) streamer.flush() time.sleep(60)
On line 6, a new parameter was added to the streamer constructor, bucket_key=”Whatever_You_Want”. This parameter allows you to create or append to a data bucket with that specific key. Appending to an existing data bucket from any device is as simple as using the same access_key and bucket_key. access_key directs data to your account. bucket_key directs data to a specific bucket in your account. Specify the bucket_key of your choice (in between quotes; don’t use : ” ‘ characters) and make sure every device has that same bucket_key.
For each device, you will want to modify line 35 to name the location of each stream. If you prefer Celsius over Fahrenheit, log the variable temp_c instead of temp_f on that same line.
Your streaming rate is specified on line 37. In the code above, a new temperature value will be streamed every 60 seconds. I used the streamer.flush() command on line 36 to clear the ISStreamer buffer. This command forces the data to instantly stream out since we are looping through sensor readings at a slower rate than the IoT 101 Project. If you don’t do a streamer.flush(), the streamer buffer will have to fill before that buffer is pushed out. This will make real-time updates seem slow with that capture rate. The streamer.flush() will make streaming out your temperature reading instantaneous. You have to be careful with how fast you push data out of a Pi as you can exceed its network capabilities (which is why we built in a buffer to the Python Streamer module). You can learn more about how the ISStreamer does buffering at https://github.com/InitialState/python_appender#manual-streamerflush.
We now have every device ready to stream temperature to a single destination. There is only one more detail left to point out before we start streaming. Each device is logging every data point with a timestamp. This timestamp is the current time on each device. If every device has a completely different time, our visualization is going to be confusing. Luckily, time should be automatically sync’d between all of your internet connected Raspberry Pis through NTPd. NTPd is the most common method to synchronize the software clock of a GNU/Linux system with internet time servers using the Network Time Protocol. NTPd should be automatically installed and running at boot for most versions of Raspbian (in other words, you shouldn’t have to do anything special for your Pis to be time-sync’d). You can read more about NTPd and how to use it at http://raspberrypi.stackexchange.com/questions/266/how-can-i-keep-system-time. If you are running your temperature streamer at boot and are having issues with NTP sync happening after streaming has started, check out this blog post for a solution: http://blog.initialstate.com/pi-shutdown-button-at-boot/.
We are ready to kick off each streamer by running the Python script above. I used the nohup (no hangup) command to allow my Pis to stream in the background and not be interrupted by any network hitches (“nohup sudo python temperature.py > tmp.txt &”). It does not matter what order you kick off your devices. You can start, restart, and add devices and their data will simply show up in your data bucket automatically. My temperature streams from three different rooms in my house looked like the following after running for three days:
I was pretty surprised to see how unevenly my house heats between even adjacent rooms. There are 5 degree differences between adjacent rooms at times. I also realized how different my thermostats detect the current room temperature. My Nest thermostat matches the Living Room reading dead-on. My old Honeywell thermostat is consistently 3 degrees off from my temperature stream in my Hallway.
I can see that my living room averages 66.61 (F) but spikes as high as 69.58 and as low as 60.35. That’s a pretty big temperature swing.
Once you have your streams going, you can instantly share them with anyone by clicking on the share button in the log shelf next to the data bucket you want to share. Type in the email addresses of everyone you want to share it with, and they will be able to see the same real-time updates that you see. Shared data buckets will automatically show up in a user’s log shelf, and an email notification will be sent telling them that you just shared a data bucket with them. If you want to see my current house temperature stream from this project, send me a message (email@example.com) and I’ll share it with you.
You now have the power to stream data from different devices into the one visualization in real-time. You can mix and match data sources, devices, and locations with ease. The parameter that allows you to append to an existing data bucket is especially handy when one of your streaming devices crashes and you want to restart it and keep streaming to the same visualization.
I can’t believe I made it through this entire tutorial talking about “streams” without a single “never cross the streams” Ghostbusters reference. Sorry, I just can’t resist: