The Weather Outside Is Frightful (Or Is It?)

Four temperature sensors connected to a thermocouple module that is read using a single board computer acting as an SFTP file server. A web server in a different location is able to access the file server to store temperature data in its own database and present a nice-looking dashboard to an end user. This project guide is going to skim over the hardware setup, highlight a Python script that reads temperature data over RS-232 and spend some time on setting up an HTML dashboard using Google Charts. Hopefully it'll inspire your next project.

Setting Up the Hardware

One of the first considerations was where the temperature sensors should be located in order to provide the most valuable data. In our case, which is in a remote cabin, we wanted to monitor both the inside and outside temperature as well as under the floor where the pipes are located and the coldest bathroom.

Once the temperature probes were installed in those key locations, wires were run into a closet where the RS-232 thermocouple module and TS-7500 is housed. The wiring here was pretty straightforward, especially when consulting the manuals, so there's not a lot of value in going into detail here. We used some RJ45 wire and jacks to make things as clean as possible and hooked our thermocouple module to the TS-7500's RS-232 port using the DB9 to RJ45 adapter.

Another consideration you might want to keep in mind is power and internet connection reliability. This project was set up in a remote area that is more or less off the grid and very prone to power and internet outages. So, we hooked everything up to a battery backup. Not only that, but given the nature of Linux and power outages, we also set up the TS-7500 to boot from a read-only filesystem (after setting up our software). That's why we're using the USB thumbdrive to store our periodically collected temperature data. We could technically just poll for temperatures when we want them and then store them directly into our website database, but then we might miss collecting that historical data. A final consideration is to make sure to set up port forwarding on our router for SSH (port 22) and then use a service like dyndns.org to make it easy to access this server from the outside world.

Setting Up the Software

The next step is to come up with a script to read the temperature data coming from the RS-232 port. Python lends itself very nicely to this sort of thing, so that was the chosen solution. The script opens the RS-232 port (using xuartctl), sends a read command (RD) to the thermocouple module, reads the result, converts it and then saves it off to a CSV-formatted file on the USB thumbdrive. Here's what that script ended up looking like:


get-temps.py


#!/usr/bin/python
import os
import re
import sys
import csv
import time
import serial
import datetime
from subprocess import Popen, PIPE, STDOUT


def read_temp(probe_number):
    print("Sending command: $" + str(probe_number) + 'RD\\r\\n')
    ser.write("$" + str(probe_number) + 'RD\r\n')
    out = ''
    # let's wait one second before reading output (let's give device time to answer)
    print("Waiting for 1 seconds before reading")
    time.sleep(1)
    while ser.inWaiting() > 0:
        out += ser.read(1)
    if out != '':
        print("Received: " + out)
        return out
    else:
        print("ERROR: Did not receive")
        return ''


def getSerialPort():
  command = "/usr/local/sbin/xuartctl --port 0 --server --speed 300"
  p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
  output = p.stdout.read()
  regex = re.compile("ttyname=(.*)",re.DOTALL)
  r = regex.search(output)
  return r.groups()[0].strip()


print "Getting temperatures..."
print "Getting serial port to use..."
port = getSerialPort()
print "Going to use port: " + port
print "Setting up serial port..."
# configure the serial connections
ser = serial.Serial(
    port=port,
    baudrate=300,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)
already_open = ser.isOpen()
if not already_open:
    ser.open()


print "Getting datetime stamp..."
now = datetime.datetime.now()
date = now.strftime("%m/%d/%Y")
timestamp = now.strftime("%I:%M:%S %p")
print "Using datetime stamp of: " + timestamp


csv_row = []
csv_row.append(date)
csv_row.append(timestamp)
for i in range(1, 5):
    #Will get: *+00024.00
    data = read_temp(i)
    print "Read temp as: " + data
    if data[2] == "-":
        temp_c = data[2:]
    else:
        temp_c = data[3:]
    temp_f = str(float(temp_c) * 9.0 / 5.0 + 32)
    csv_row.append(temp_f)


print "Going to write the following to /mnt/usb/cabin_temps.csv: "
print csv_row


ofile_usb = open("/mnt/usb/cabin_temps.csv", 'a')
writer = csv.writer(ofile_usb, quoting=csv.QUOTE_NONNUMERIC)
writer.writerow(csv_row)
ofile_usb.close()


print "Done collecting temperatures"

______________________