Close

Software Part II - Adapter Framework

A project log for Greenhouse Pi

Solar powered Raspberry Pi measuring greenhouse environmental data and driving some actors

dotpidotDotPiDot 09/04/2016 at 11:170 Comments

The first question to answer was how to store measurement data from the sensors in the database.

To give an example how it was done i'll start with a DS18B20 sensor. As a lot of stuff for the Rapsberry is avaiable in Python i decided to setup my adapter framework in Python. The DS18B20 is a 1W sensor where the reading can simply be done by opening a file (the mapping of sensor hw to the file is done by the Raspi OS already if setup properly - see project instructions on how to do that).

The adapter is setup as a python class:

#!/usr/bin/python
# Copyright (c) 2016
# Author: Andreas Wirthmueller
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import time
import datetime
from datetime import datetime
from config import HOSTNAME

import logging

MODULE_NAME = 'DS18B20'

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
    datefmt='%m-%d %H:%M',
    filename='/home/pi/sensors/GreenMon/adapter_log.log'
    )

class DS18B20_Adapter:
        SENSOR_TYPE = "temperature"
        MEASURE_T="Celsius"

        def __init__(self, sensor_id,slave_id):
                logging.info(MODULE_NAME+ ": constructor start")

                self.sensor_id = sensor_id
                self.slave_id = slave_id
                logging.info(MODULE_NAME +": constructor exit")


        def read(self):
                # 1-wire Slave Datei lesen
                filename = '/sys/bus/w1/devices/' + self.slave_id + '/w1_slave'
                file = open(filename)
                filecontent = file.read()
                file.close()

                # Temperaturwerte auslesen und konvertieren
                stringvalue = filecontent.split("\n")[1].split(" ")[9]
                temperature = float(stringvalue[2:]) / 1000

                # Temperatur ausgeben
                rueckgabewert = temperature
                return(rueckgabewert)
        def readJSON(self):
                temp = self.read()
                timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                d_temp =        {'hostname':HOSTNAME,
                                'type':self.SENSOR_TYPE,
                                "measure_temp": "Celsius",
                                'sensorid':self.sensor_id,
                                'temp':temp,
                                'datetime':str(timestamp)}
                return d_temp

It is simply opening the file as defined by the 1W interface, converting the value and returning it in the read-function. It provides a second function which build on read and provides back a JSON document instead of the simple temperatur. This JSON will be used to store the sensor reading in RethinkDB later.

To instantiate a class and call the reading a simple script will do:

from DS18B20_adapter import DS18B20_Adapter

#measure temperature sensor 1
soil_temperature = DS18B20_Adapter('t_0001','28-04165b7853ff')
d_temp1 =  soil_temperature.readJSON()
So now we have the adapter ready and we get back a JSON representation of the reading.

Now we need to use the snipet to call the reader and store the JSON document in RethinkDB - which happens in monitor_adapters.py. Here's the relevant snippeds:

[...]

import rethinkdb as r
import time
import datetime
import sys
from datetime import datetime

from config import HOSTNAME, DB_HOST, DB_PORT, DB_NAME
from DS18B20_adapter import DS18B20_Adapter

MODULE_NAME = 'Readall_apaters'
import logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
    datefmt='%m-%d %H:%M',
    filename='/home/pi/GreenMon/log/adapter_log.log'
    )
logging.info(MODULE_NAME+": ***************** Start ***************** ")

conn = r.connect(DB_HOST, DB_PORT, DB_NAME)
[...]

timezone = time.strftime("%z")
reql_tz = r.make_timezone(timezone[:3] + ":" + timezone[3:])

[...]

#measure temperature sensor 1
soil_temperature = DS18B20_Adapter('t_0001','28-04165b7853ff')
d_temp1 =  soil_temperature.readJSON()

[...]

d_observation = {'pressure':[d_pressure],
                 'temperature':[d_temp1,d_temp2,d_temp3,d_temp4],
                 'luminosity':[d_luminosity],
                 'timestamp': str(datetime.now(reql_tz)),
                 'type':'sensors'
                }

logging.info(MODULE_NAME+": measurement %s",str(d_observation))

r.table("observations").insert(d_observation).run(conn, durability='soft') #Soft durability since losing 't be the end of the world.
conn.close()
logging.info(MODULE_NAME+": measurements successfully written to db")
logging.info(MODULE_NAME+": ***************** End ***************** ")

This script now takes the reading and puts it into the table observations of RethinkDB database "greenhouse_pi". This script will be automatically triggered to run every five minutes to get up to date readings and store them in the database by

crontab -e
and adding
*/5 * * * * sudo /usr/bin/python  /home/pi/GreenMon/adapter_class/monitor_adapters.py >/home/pi/GreenMon/log/cron.log 2>&1 &

The full source code for the project including the adapters can be found on git: https://github.com/awirthmueller/GreenhousePi

Discussions