3

I would like to combine two tutorials (here and here) that I have found on sensing temperature with Raspberry Pis.

I am already able to retrieve the temperature from the DS18B20 on multiple pis. What I am not sure of is how to get the central pi (which will have a SQLite DB) to query all of the other Pis for their current temperature.

So, how do I have the server Pi poll the client for the current temperature value?

A python solution would be preferred since that's what I am most familiar with, but not required. Also, I am running Raspbian if that matters.

3
  • 1
    Hello and welcome! I am not sure whether the question is well suited for this site as it is not specific to the raspberry pi (to be honest).
    – Ghanima
    Apr 28 '15 at 20:45
  • That's fair. Would this be better suited to the Unix & Linux site? I put it here because of some of the specifics of the problem. The DS18B20 stores the information in a particular directory on the Pi and I want to access the information in that dir. But I could also see how this would be a "network between Linux machines" question.
    – JamesG
    Apr 28 '15 at 20:50
  • If you have more detailed information to make the question more pi specific feel free to edit the question accordingly!
    – Ghanima
    Apr 28 '15 at 21:06
4

Ok, I guess there are many different approaches possible so I will call this just one suggestion (I will henceforth call it the complicated way). Since you're into SQL databases anyways why not do it like that:

  1. install your favourite sql database server on each Pi
  2. set up a simple database on each of the Pi's (should contain something like id, time_stamp, temperature and a flag like is_uploaded)
  3. write a simple python script to poll for temperatures on each Pi and log those values to their respective local database (i.e. using pymysql); use an appropriate timing intervall
  4. set up another python script to read from the local database periodically and send to central instance; this step would be retried if the network connection is lost; cool thing is that sql databases can be directly accessed remotely - so all data transfer and network stuff is completely transparent to your scripts; after verifying the transfer set the is_uploaded flag in the local database (or simply remove the item if you like)
  5. have another script to periodically purge the local databases from already uploaded data (or keep it for some time if you like)

For clarification, the (additional) local database approach might be overkill here and only comes into play if connection losses are a possible issue as it allows local storage and later retrying of transfer. As suggested by ppumkins comment it is of course necessary to make the central Pi permanently addressable by all the other Pi's either by setting up a static IP or a proper name resolution scheme on the network.

PS: I hope all those Pi's do more than just measure temperature...

1
  • Remember to put the master Pi on a static IP so that the other Pi's can connect to it. You can even write data to a file and and push it to the other Pi using NFS or Samba and parse it there. There are hundreds of solutions to this but this is a good, solid example, and easy to do with Python. +1
    – Piotr Kula
    Apr 28 '15 at 21:33
3

As Ghanima points out there are many possible approaches.

Here is one using MQTT and the Python mosquitto module.

MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport.

You can have your slave Pi's publishing the temperature readings to a master device which has registered for those publications.

I have used the term master/slave but there need not be such a relationship.

In my example I have two slaves, Pis harry and tom, publishing their temperatures to a master laptop mercury.

Slave code

#!/usr/bin/env python

# 2015-04-29
# ds18b20_mq_slave.py
# Public Domain

import mosquitto
import time
import glob
import platform

node = platform.node()

mq = mosquitto.Mosquitto()

# Connect to mercury
mq.connect("mercury")

while True:

   for sensor in glob.glob("/sys/bus/w1/devices/28-*"):

      f = open(sensor+"/w1_slave", "r")
      data = f.read()
      f.close()

      (discard, sep, reading) = data.partition(' t=')

      temp = float(reading) / 1000.0

      report = '"{}", "{:.1f}"'.format(node, temp)

      print(report)

      mq.publish("temp/reading", report)

   time.sleep(3.0)

Master code

#!/usr/bin/env python

# 2015-04-29
# ds18b20_mq_master.py
# Public Domain

import mosquitto
import time

def on_connect(mosq, obj, msg):
   print "Connected"

def on_message(mosq, obj, msg):
   print ("msg={}".format(msg.payload))

mq = mosquitto.Mosquitto()

#define callbacks
mq.on_message = on_message
mq.on_connect = on_connect

#connect
mq.connect("mercury")

#subscribe to topic 
mq.subscribe("temp/reading")

#keep connected to broker
while mq.loop() == 0:
   time.sleep(1.0)

Typical master output

msg="harry", "16.7"
msg="tom", "17.7"
msg="harry", "16.7"
msg="tom", "17.6"
msg="harry", "16.7"
1
  • Valuable idea +1, hope to remember it till I need it!
    – Ghanima
    Apr 29 '15 at 19:51
2

You can use MQTT or ZeroMQ to communicate the two Pi boards.

3
  • how do you implement a ZeroMQ version of joan code above (which support callbacks so that the script can do other things while waiting for new subscribed message to arrive)?
    – Dennis
    Aug 6 '15 at 8:21
  • if @joan know how to do it in ZeroMQ, can help reply here too
    – Dennis
    Aug 6 '15 at 8:22
  • @Dennis If you look at the example I gave the Master code is using callbacks and nothing else. The main processing loop is empty, just a time.sleep(1.0). That is where you would put the main processing loop of your script.
    – joan
    Aug 6 '15 at 8:29
2

First, thanks for all of the suggestions. There is definitely more than one way to skin this cat.

For now I have decided to stand up a server using Node on the Pi's that are doing the temperature sensing and just issuing an http request as needed.

Here is the javascript that's on the Pi's reading temperature

var http = require('http');
var fs = require('fs');
var url = require('url');
var exec=require('child_process').exec;
var tempAddress = '<sensor address>';
var tempLocation = '/sys/bus/w1/devices/' + tempAddress + '/w1_slave';
var verbose = true;

http.createServer(function (req, res) {
  var request_url = url.parse(req.url).pathname;
  if(verbose) console.log("Request from " + req.connection.remoteAddress +
    ": " + request_url);

  if (request_url == '/temperature.json') {
    fs.readFile(tempLocation, 'utf8', function(err, data) {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      // if (err) throw err;
      if(err) {
        output = '{"status": "tempError"}'; 
      } else {
        matches = data.match(/t=([0-9]+)/);
        temperatureC = parseInt(matches[1]) / 1000;
        temperatureF = ((temperatureC * 1.8) + 32).toFixed(3);
        output = '{"status": "tempSuccess",' +
             '"temperature": {"celsius": ' + temperatureC + ',' +
                                  '"fahrenheit": ' + temperatureF + ' } }';
      }
      res.end(output);
    });
  } else {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('No route');
  }
}).listen(8037);

console.log('Server running on port 8037');

So far I have tested this on the command line using

curl http://<ipaddress>/temperature.json

and I am getting a response with the temperature in C and F.

Alternatively I think I can stand up the http server using python, but a buddy of mine had some sample js code from an existing project. This solution let's me poll the client Pi's as needed (as opposed to having the clients push their own data). This lets me sync up the data when I am getting it from multiple pis.

One thing I had to do before I could run this code was install node.

1

I think this is typically a project where one could apply a RESTful server and client situation, where the clients can independently scan for results (in this case, reading temperatures every x seconds) and send the results to the RESTful server when it suites them. No need to store information at the client side, the server would take care of everything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.