powerguru-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Powerguru-commit] [SCM] powerguru branch, master, updated. ee9306cf9c06


From: Rob Savoye
Subject: [Powerguru-commit] [SCM] powerguru branch, master, updated. ee9306cf9c06489bb20aed3fa8407bf61122b9a4
Date: Wed, 10 Apr 2019 16:49:43 -0400 (EDT)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "powerguru".

The branch, master has been updated
       via  ee9306cf9c06489bb20aed3fa8407bf61122b9a4 (commit)
      from  4e378ff713730a1c04e05aa4e0388de5b3f1e60c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/powerguru.git/commit/?id=ee9306cf9c06489bb20aed3fa8407bf61122b9a4


commit ee9306cf9c06489bb20aed3fa8407bf61122b9a4
Author: Rob Savoye <address@hidden>
Date:   Wed Apr 10 14:49:11 2019 -0600

    Fix copyright to no be i doxygen output, start adding doxygen comments

diff --git a/python/chart.py b/python/chart.py
index d28f00f..710238a 100755
--- a/python/chart.py
+++ b/python/chart.py
@@ -1,21 +1,24 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+
+## \file chart.py This file plots the data from a postgresql database.
 
 import epdb
 import logging
@@ -39,6 +42,7 @@ from mpld3 import plugins
 from options import CmdOptions
 from postgresql import Postgresql
 
+
 # Setup a disk space log filemode. By default, everything
 # gets logged to the disk file
 logging.basicConfig(
@@ -49,21 +53,21 @@ logging.basicConfig(
      datefmt='%Y-%m-%d %H:%M:%S'
 )
 
-#
-# Create local options class
-#
-class ChartOptions(CmdOptions):
-    """Command line options for this program"""
 
+## \class ChartOptions
+class ChartOptions(CmdOptions):
+    """A class to process command line options to this program"""
+    
     def __init__(self):
+        ## Initialize additional command line options
         """Initialize additional command line options"""
         super(ChartOptions, self).__init__()
-        self.options['starttime'] = ""
-        self.options['endtime'] = ""
+        #self.options['starttime'] = None
+        #self.options['endtime'] = None
         self.options['web'] = False
 
     def usage(self):
-        """Append additional help messages"""
+        """Append additional help messages to the base class's list"""
         print(argv[0] + ": options: ")
         help = """
         \t--starttime(-t)   Use timestanps after this, default begining of data
@@ -71,8 +75,9 @@ class ChartOptions(CmdOptions):
         \t--webpage(-w)     Enable HTML output for browser
         """
         super(ChartOptions, self).usage(help)
-
+   
 opts = ChartOptions()
+opts.dump()
 
 # Setup console logging, useful for debugging
 # By default, print nothing to the console. There
@@ -87,50 +92,31 @@ ch.setFormatter(formatter)
 root.addHandler(ch)
 ch.setLevel(opts.get('verbosity'))
 
-#opts.dump()
-#epdb.set_trace()
-
-# delta = 0
-# dbname = ""
-# connect = ""
-# if options['dbserver'] is "localhost":
-#     connect += " dbname='" + options['dbname'] + "'"
-# else:
-#     connect += "host='" + options['dbserver'] + "'"
-#     connect += " dbname='" + options['dbname'] + "'"
-
-# logging.debug(connect)
-# dbshell = psycopg2.connect(connect)
-# if dbshell.closed != 0:
-#     logging.error("Couldn't connect with %r" % connect)
-#     quit();
-
-# dbshell.autocommit = True
-# logging.info("Opened connection to %r" % options['dbserver'])
-
-# dbcursor = dbshell.cursor()
-# if dbcursor.closed != 0:
-#     logging.error("Couldn't get a cursor from %r" % options['dbname'])
-#     quit();
-
-# logging.info("Opened cursor in %r" % options['dbserver'])
-
 # Get the data on each sensor
 sensors = sensor.Sensors()
 
 db = Postgresql()
 
 # Setup optional timestamp filter
+## \var start 
 start = ""
+
 end = ""
-if opts.get('starttime') != "":
+if opts.get('starttime') != None:
     start = "AND timestamp>=%r" % opts.get('starttime')
-elif opts.get('endtime') != "" and opts.get('starttime') != "":
+else:
+    start = ""
+if opts.get('endtime') != None and opts.get('starttime') != "":
     end = " AND timestamp<=%r" % opts.get('endtime')
-    if opts.get('endtime') != "" and opts.get('starttime') == "":
+    if opts.get('endtime') != None and opts.get('starttime') == "":
         end = " AND timestamp<=%r" % opts.get('endtime')
+else:
+    end = ""
 
-# https://matplotlib.org/gallery/color/named_colors.html
+# Based on https://matplotlib.org/gallery/color/named_colors.html
+## \var colors
+##      Array to hold a indexed list of colors so each line
+##      can be a different color.
 colors = list()
 colors.append("red")
 colors.append("green")
@@ -146,110 +132,128 @@ colors.append("grey")
 colors.append("navy")
 
 # Create the subslots
-fig, (temp) = plt.subplots(1, 1, sharex=True)
+fig, ax = plt.subplots()
+#plotline = dict()
+cur = 0
+#for id in sensors.getIDs(sensor.SensorType.TEMPERATURE):
+#    plotline[id] = ax.plot([], [], lw=2, color=colors[cur])[0]
+#    cur += 1
+
+plotline, = ax.plot([], [], lw=2, color=colors[cur])
+
+#fig, (temp) = plt.subplots(1, 1, sharex=True)
+#temp = plt.subplot(111)
 #fig, (temp, humidity) = plt.subplots(2, 1, sharex=True)
 #fig, (temp, dcvolts, amps) = plt.subplots(3, 1, sharex=True)
 #plt.subplots_adjust(top=0.88, bottom=0.20, left=0.10, right=0.95, 
hspace=0.58,wspace=0.35)
 
-#fig, (temp) = plt.subplots(1, 1, sharex=True)
 fig.suptitle('PowerGuru')
 fig.set_figwidth(18)
 
-class plotTemps(object):
-    """Class to create a plot of temperatures"""
+# temp = plt.subplot()
+ax.yaxis.tick_right()
+ax.yaxis.set_label_position("right")
+ax.set_ylabel("Temperature in F")
+ax.set_title("Temperature")
+ax.grid(which='major', color='red')
+ax.grid(which='minor', color='blue', linestyle='dashed')
+ax.minorticks_on()
+ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d %H'))
+ax.xaxis.set_major_locator(mdates.HourLocator(byhour=range(0,24,6)))
+ax.xaxis.set_minor_locator(mdates.HourLocator())
+id= "6202"
+ids = list()
+labels = dict()
+for id in sensors.getIDs(sensor.SensorType.TEMPERATURE, ids):
+    sense = sensors.get(id)
+    if sense is not None:
+        location = sense.get('location')
+    else:
+        location = "Unknown"
+    labels[id] = location
 
-    def __init__(self):
+## \class plotData
+class plotData(object):
+    """Base class to hold data for a line"""
+
+    def __init__(self, id=0, color=3):
+        logging.debug("TRACE: plotData")
+        self.x = []
+        self.y = []
+        self.color = color
+        self.id = id
+        self.update()
+
+    def setClor(self, col):
+        self.color = colors[col]
+        
+    def getColor(self):
+        return self.color
+        
+    def append(self, x, y):
+        self.x.append(x)
+        self.y.append(y)
+
+    def getData(self):
+        yield self.x, self.y
+
+
+class plotPower(plotData):
+    """Class to hold data for a Power line"""
+
+    def __init__(self, id=0, color=3):
+        logging.debug("FIXME: plotTemp")
+        plotData.__init__(self, id, color)
+
+    def update(self):
+        logging.debug("TRACE: plotPower.update()")
+        query = "SELECT id,current,volts,timestamp FROM power WHERE (id='%s' 
%s %s) ORDER BY timestamp " % (self.id, start, end)
+        logging.debug(query)
+        db.query(query)
+        logging.debug("Query returned %r records" % db.rowcount())
         cur = 0
-        temp = plt.subplot()
-        for id in sensors.getIDs(sensor.SensorType.TEMPERATURE):
-            x = list()
-            y = list()
-            query = "SELECT id,temperature,humidity,timestamp FROM weather 
WHERE (id='%s' %s %s) ORDER BY timestamp;" % (id, start, end)
-            logging.debug(query)
-            db.query(query)
-            logging.debug("Query returned %r records" % db.rowcount())
-
-            for model,temperature,humidity,timestamp in db.fetchResult():
-                #print("TEMP: %r, %r" % (temperature,timestamp))
-                x.append(timestamp)
-                y.append(temperature)
-
-            #sensors.dump()
-            temp.set_ylabel("Temperature in F")
-            temp.set_title("Temperature")
-            temp.grid(which='major', color='red')
-            temp.grid(which='minor', color='blue', linestyle='dashed')
-            temp.minorticks_on()
-            legend = temp.legend(loc='upper left', shadow=True)
-            sense = sensors.get(id)
-            if sense != None:
-                location = sense.get('location')
-            else:
-                location = id
-            temp.plot(x, y, color=colors[cur], label=location)
-            cur += 1
-
-
-def animate(i):
-    logging.debug("Refreshing data...")
-    tplot = plotTemps()
-    # xx = list()
-    # yy = list()
-    # zz = list()
-    # query = "SELECT DISTINCT id FROM power"
-    # logging.debug(query)
-    # dbcursor.execute(query)
-    # logging.debug("Query returned %r records" % dbcursor.rowcount)
-    # if  dbcursor.rowcount > 0:
-    #     for id in dbcursor:
-    #         ids.append(id)
-    #         query = "SELECT id,current,volts,timestamp FROM power WHERE 
(id='%s' %s %s) ORDER BY timestamp " % (id[0], start, end)
-    #         logging.debug(query)
-    #         dbcursor.execute(query)
-    #         logging.debug("Query returned %r records" % dbcursor.rowcount)
-    #         cur = 0
-    #         for id,current,voltage,timestamp in dbcursor:
-    #             #print("BATTERY: %r, %r, %r, %r" % (id, current, voltage, 
timestamp))
-    #             xx.append(timestamp)
-    #             yy.append(voltage)
-    #             zz.append(current)
-
-    #     dcvolts.set_title("DC Voltage")
-    #     dcvolts.plot(xx, yy, color="purple")
-    #     dcvolts.legend([id])
-    #     dcvolts.set_ylabel("DC Volts")
-    #     #dcvolts.set_xlabel("Time (hourly)")
-    #     dcvolts.grid(which='major', color='red')
-    #     dcvolts.grid(which='minor', color='blue', linestyle='dashed')
-    #     dcvolts.minorticks_on()
-    
-    #     amps.set_title("DC Current")
-    #     amps.plot(xx, zz, color=colors[cur])
-    #     amps.legend([id])
-    #     cur += 1
-    #     amps.set_ylabel("Amps")
-    #     amps.set_xlabel("Time (hourly)")
-    #     amps.grid(which='major', color='red')
-    #     amps.grid(which='minor', color='blue', linestyle='dashed')
-    #     amps.minorticks_on()
-    #     plt.setp(amps.xaxis.get_majorticklabels(), rotation=90)
-    #     amps.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d %H'))
-    #     
amps.xaxis.set_major_locator(mdates.HourLocator(byhour=range(0,24,6)))
-    #     amps.xaxis.set_minor_locator(mdates.HourLocator())
-
-    # Get the time delta between data samples, as it's not worth updating there
-    # the display till their in fresh data. Sample may be minutes or hours 
apart,
-    # so o need to waste cpu cycles
-    #query = "SELECT AGE(%r::timestamp, %r::timestamp);" % 
(x[1].strftime("%Y-%m-%d %H:%M:%S"), x[0].strftime("%Y-%m-%d %H:%M:%S"))
-    #logging.debug(query)
-    #db.query(query)
-    #delta = (db.fetchResult())[0][0].total_seconds()
-    #logging.debug("Query returned %r" % delta)
-
-# The timeout is in miliseconds
-#seconds = 1000 * delta
+        for id,current,voltage,timestamp in dbcursor:
+            print("BATTERY: %r, %r, %r, %r" % (id, current, voltage, 
timestamp))
+            xx.append(timestamp)
+            yy.append(voltage)
+            zz.append(current)
+
+class plotTemp(plotData):
+    """Class to hold data for a Temperature line"""
+
+    def __init__(self, id=0, color=3):
+        logging.debug("TRACE: plotTemp")
+        plotData.__init__(self, id, color)
+        self.update()
+
+    def update(self, frame=""):
+        logging.debug("TRACE: plotTemp.update()")
+        query = "SELECT id,temperature,humidity,timestamp FROM weather WHERE 
(id='%s' %s %s) ORDER BY timestamp;" % (self.id, start, end)
+        logging.debug(query)
+        db.query(query)
+        logging.debug("Query returned %r records" % db.rowcount())
+
+        for model,temperature,humidity,timestamp in db.fetchResult():
+            #print("TEMP: %r, %r" % (temperature, timestamp))
+            self.x.append(timestamp)
+            self.y.append(temperature)
+        plotline.set_data(self.x, self.y)
+        return plotline,
+
+
 seconds = 1000 * opts.get('interval')
-ani = animation.FuncAnimation(fig, animate, interval=seconds)
+plottemp = plotTemp("6202")
+ani = animation.FuncAnimation(fig, plottemp.update, interval=seconds, 
blit=True)
+
+#for id in sensors.getIDs(sensor.SensorType.TEMPERATURE):
+#    plotdata[id] = plotTemp(id)
+
+#ax.legend(loc='upper left', shadow=True)
+handles, labels = ax.get_legend_handles_labels()
+ax.legend(handles, labels, loc='upper left')
+
+#plottemp2 = plotTemp("235")
+#ani = animation.FuncAnimation(fig, plottemp2.update, interval=seconds, 
blit=True)
 if opts.get('web') is True:
     mpld3.show(port=9999, open_browser=False)
 else:
diff --git a/python/gpio433.py b/python/gpio433.py
index 1960afa..67cad5a 100755
--- a/python/gpio433.py
+++ b/python/gpio433.py
@@ -1,21 +1,21 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
 import sys
 import epdb
diff --git a/python/gpiots.py b/python/gpiots.py
index c44fcb7..9bd08c9 100755
--- a/python/gpiots.py
+++ b/python/gpiots.py
@@ -1,22 +1,26 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
+## \file gpiots.py Wrapper to read wireless 433Mhz data when using circuit
+##                 board dedicated 433Mhz transceiver instead of an RTL-SDR
+##                 USB radio dongle.
+ 
 import sys
 from subprocess import PIPE, Popen, STDOUT
 from threading  import Thread
@@ -31,17 +35,8 @@ from options import CmdOptions
 from postgresql import Postgresql
 ON_POSIX = 'posix' in sys.builtin_module_names
 
-def follow(thefile):
-    thefile.seek(0,2)
-    while True:
-        line = thefile.readline()
-        if not line:
-            time.sleep(0.1)
-            continue
-        yield line
-
 #def gpio_ts_handler(sensors):
-def gpio_ts_handler():
+def gpiots_handler(sensors):
     """This is a handler for sensors using wireless at 433Mhz,
     commonly used by many wireless weather sensors. This requires
     a working gpio-ts driver module and the f007th utiity installed
@@ -59,53 +54,46 @@ def gpio_ts_handler():
     The thermometers send data on an interval, if nothing has changed it
     displays: "Data is not changed."
 
+    As I had problems getting output from STDOUT, it was easier to just
+    have the data get logged to a tect file, and parse that for each
+    new entry.
+
     """
     
     logging.debug("Start f007th-rpi_send...")
 
     options = CmdOptions()
-    #db = Postgresql()
+    db = Postgresql()
 
-    cmd = [ 'f007th-send', '-v', '-l', '/tmp/xxx', '-g', '27']
+    cmd = [ 'f007th-send', '-v', '-l', '/tmp/gpiots.log', '-g', '27']
     #cmd = [ 'f007th-send', '-v', '-V', '-g', '27']
     #ppp = Popen(cmd, stdout=PIPE, stderr=STDOUT, bufsize=0, 
close_fds=ON_POSIX)
-    #epdb.set_trace()
     ppp = Popen(cmd, stdout=PIPE, bufsize=0, close_fds=ON_POSIX)
-    foo = open('/tmp/xxx', 'r')
+    foo = open('/tmp/gpiots.log', 'r')
     while True:
-        #out, err = ppp.communicate()
-        out = follow(foo)
-        print("FIXME0: %r" % out)
-        for line in out:
-            print("FIXME1: %r" % line)
-        #mapper = map
-        #for line in ppp.readline():
+        out = sensor.follow(foo)
         temp = dict()
-        #temp['timestamp'] = tokens[0]
-        #temp['model'] = tokens[3]
-        #temp['id'] = tokens[4]
-        #temp['channel'] = tokens[6]
-        #temp['temperature'] = tokens[7]
-        #temp['humidity'] = tokens[8]
-        #if sensors.get(temp['id']) is None:
-        #    print("New sensor %r found!" % temp['id'])
-        #    sense = sensor.SensorDevice()
-        #    sense.set('id', temp['id'])
-        #    sense.set('alias', temp['model'])
-        #    sense.set('device', sensor.DeviceType.RTL433)
-        #    sense.set('sensor', sensor.SensorType.TEMPERATURE)
-        #    sense.set('channel', temp['channel'])
-        #    sensors.add(sense)
-        #if (options.get('scale') == 'F'):
-        #    temp['temperature'] = (float(temp['temperature']) * 1.8) + 32.0;
-            #temp['lowtemp'] =  (float(temp['lowtemp']) * 1.8) + 32.0;
-            #temp['hightemp'] =  (float(temp['hightemp']) * 1.8) + 32.0;
-        #query = """INSERT INTO weather VALUES( '%s', %s, %s, %s, %s, '%s', 
'%s' )  ON CONFLICT DO NOTHING;; """ % (temp['id'], temp['temperature'], "0", 
"0",  temp['humidity'], options.get('scale'), temp['timestamp'])
-        #logging.debug(query)
-        #db.query(query)
-        #time.sleep(options.get('interval'))
+        for line in out:
+            if line.find('=') < 0:
+                stamp = line.split(' ')
+                temp['timestamp'] = stamp[0] + ' ' + stamp[1]
+                continue
+            tokens = line.replace(' ', '').rstrip().split('=')
+            print("FIXME1: %r = %r" % (tokens[0], tokens[1]))
+            if tokens[0] == "temperature":
+                scale = tokens[1][len(tokens[1])-1]
+                temp['scale'] = scale
+                temp['temperature'] = tokens[1].rstrip(scale)
+                continue
+            elif tokens[0] == "humidity":
+                temp['humidity'] = tokens[1].rstrip('%')
+                continue
+            elif tokens[0] == "rollingcode":
+                temp['id'] = tokens[1]
+                continue
+            elif tokens[0] == "battery":            
+                query = """INSERT INTO weather VALUES( '%s', %s, %s, %s, %s, 
'%s', '%s' )  ON CONFLICT DO NOTHING;; """ % (temp['id'], temp['temperature'], 
"0", "0",  temp['humidity'], options.get('scale'), temp['timestamp'])
+                logging.debug(query)
+                db.query(query)
+        time.sleep(options.get('interval'))
  
-    # _sensors = list()
-
-
-gpio_ts_handler()
diff --git a/python/i2c.py b/python/i2c.py
index 9409453..8121118 100644
--- a/python/i2c.py
+++ b/python/i2c.py
@@ -1,21 +1,25 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file i2c.py Read data from an i2c sensor,. Currently only the
+##              ina219 current sensor is support.
+
 
 import epdb
 import logging
diff --git a/python/mergedb.py b/python/mergedb.py
index 3643d5c..0ef238b 100755
--- a/python/mergedb.py
+++ b/python/mergedb.py
@@ -1,21 +1,24 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file mergedb.py This file merges the data from a remote postgresql database
+##                into a local one.
 
 import epdb
 import logging
diff --git a/python/onewire.py b/python/onewire.py
index ca8f4b6..511263b 100755
--- a/python/onewire.py
+++ b/python/onewire.py
@@ -1,27 +1,24 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
-
-import epdb
-import logging
-
-
-# class Onewire
+## \file onewire.py Setup data array  to convert sensor ID to the type
+##                  of sensor and other configuration data,
 
 def onewire_handler(arg):
     print("Start onewire")
diff --git a/python/options.py b/python/options.py
index dcea4e0..e306171 100644
--- a/python/options.py
+++ b/python/options.py
@@ -1,21 +1,23 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+## \file options.py Base class for command line option processing.
 
 import epdb
 import logging
@@ -97,9 +99,9 @@ class CmdOptions(object):
             if opt == '--help' or opt == '-h':
                 self.usage()
             elif opt == "--starttime" or opt == '-t':
-                self.options['endtime'] = val
-            elif opt == "--endtime" or opt == '-e':
                 self.options['starttime'] = val
+            elif opt == "--endtime" or opt == '-e':
+                self.options['endtime'] = val
             elif opt == "--owserver" or opt == '-o':
                 self.options['owserver'] = val
             elif opt == "--interval" or opt == '-i':
@@ -125,7 +127,10 @@ class CmdOptions(object):
 
     def get(self, key):
         """Get the value of a command line option."""
-        return self.options[key]
+        if (key in self.options):
+            return self.options[key]
+        else:
+            None
 
     def dump(self):
         """Display all the internal option data"""
diff --git a/python/ownet.py b/python/ownet.py
index 4f7168a..4429081 100755
--- a/python/ownet.py
+++ b/python/ownet.py
@@ -1,23 +1,26 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
+## \file ownet.py Wrapper for pyownet and database support for this
+##                data.
 
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-  API documentation at: https://pyownet.readthedocs.io/en/latest/
-"""
+#  API documentation at: https://pyownet.readthedocs.io/en/latest/
 
 import epdb
 import logging
diff --git a/python/pgd.py b/python/pgd.py
index 3ec2925..b75664e 100755
--- a/python/pgd.py
+++ b/python/pgd.py
@@ -1,21 +1,23 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file pgd.py Daemon to read sensors and data log it all.
 
 import epdb
 import logging
@@ -117,12 +119,15 @@ rtlsdr_thread.start()
 # GPIO only works on a Raspberry PI
 if pi is True:
     import gpio433
-    gpio433_thread = Thread(target = gpio433.gpio433_handler, args = 
(sensors,))
-    gpio433_thread.start()
+    #gpio433_thread = Thread(target = gpio433.gpio433_handler, args = 
(sensors,))
+    #gpio433_thread.start()
 
-    i2c_thread = Thread(target = i2c.ina219_handler, args = (sensors,))
-    i2c_thread.start()
+    #i2c_thread = Thread(target = i2c.ina219_handler, args = (sensors,))
+    #i2c_thread.start()
 
+    #import gpiots
+    #gpiots_thread = Thread(target = gpiots.gpiots_handler, args = (sensors,))
+    #gpiots_thread.start()
 try:
     server = socketserver.TCPServer(("0.0.0.0", 7654), remote.client_handler)
     server.allow_reuse_address = True
@@ -156,6 +161,6 @@ print("ownet_thread finished...exiting")
 rtl433_thread.join()
 print("rtl433_thread finished...exiting")
 
-rtlsdr_thread.join()
-print("rtlsdr_thread finished...exiting")
+#rtlsdr_thread.join()
+#print("rtlsdr_thread finished...exiting")
 
diff --git a/python/postgresql.py b/python/postgresql.py
index abc6dfb..3de235a 100755
--- a/python/postgresql.py
+++ b/python/postgresql.py
@@ -1,21 +1,23 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file postgresql.py Wrapper for the psycopg2 module
 
 import epdb
 import glob
@@ -66,7 +68,7 @@ class Postgresql(object):
             if self.dbcursor.closed == 0:
                 logging.info("Opened cursor in %r %r" % (database, 
self.dbcursor))
 
-    def query(self, query):
+    def query(self, query=""):
         """Query a local or remote postgresql database"""
 
         logging.debug("postgresql.query(" + query + ")")
@@ -76,8 +78,8 @@ class Postgresql(object):
             return self.result
 
         self.result = list()
-        self.dbcursor.execute(query)
         try:
+            self.dbcursor.execute(query)
             self.result = self.dbcursor.fetchall()
         except psycopg2.ProgrammingError as e:
             if e.pgcode != None:
@@ -93,8 +95,8 @@ class Postgresql(object):
         if self.dbcursor.statusmessage == "INSERT 0 1":
             logging.debug("Inserted into %r" % (table))
             self.result = self.dbcursor.statusmessage
-        elif self.dbcursor.statusmessage == "INSERT 0 0":
-            logging.debug("Already exists in database %r" % (table))
+#        elif self.dbcursor.statusmessage == "INSERT 0 0":
+#            logging.debug("Already exists in database %r" % (table))
         return self.result
 
     def isConnected(self):
diff --git a/python/remote.py b/python/remote.py
index a3c139e..fd8ad45 100644
--- a/python/remote.py
+++ b/python/remote.py
@@ -1,21 +1,23 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file remote.py Handler for remote commands to the pgd daemon.
 
 import epdb
 import logging
diff --git a/python/rtl433.py b/python/rtl433.py
index 6a1d8b4..216f574 100755
--- a/python/rtl433.py
+++ b/python/rtl433.py
@@ -1,21 +1,25 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
 
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+## \file rtl433.py This file use the rtl_433 utility to collect data
+##                 from wireless sensors using an RTL-SDR USB dongle.
 
 import sys
 from subprocess import PIPE, Popen, STDOUT
@@ -32,6 +36,7 @@ from options import CmdOptions
 from postgresql import Postgresql
 ON_POSIX = 'posix' in sys.builtin_module_names
 
+
 def rtl433_handler(sensors):
     """This is a handler for sensors using wireless at 433Mhz,
     commonly used by many wireless weather sensors. This requires
@@ -48,9 +53,9 @@ def rtl433_handler(sensors):
     ppp = Popen(cmd, stdout=PIPE, bufsize=0, close_fds=ON_POSIX)
     foo = open('/tmp/rtl433.csv', 'r+')
     previous = dict()
+    foo.truncate()
     while True:
         out = sensor.follow(foo)
-        foo.truncate()
         temp = dict()
         #print("FIXME0: %r" % out)
         for line in out:
@@ -79,14 +84,18 @@ def rtl433_handler(sensors):
 
             # We don't want to record more samples than the specified interval,
             FMT = "%Y-%m-%d %H:%M:%S"
-            if (temp['id'] in previous) is False:
-                previous[temp['id']] = datetime.now().strftime(FMT)
-            tdelta = datetime.strptime(temp['timestamp'], FMT) - 
datetime.strptime(previous[temp['id']], FMT)
-            #logging.debug("TDELTA: %r: %r == %r" % (tdelta.seconds, 
temp['timestamp'],
-            #                              previous[temp['id']]))
+
+            try:
+                if ('id' in temp) is True:
+                    if (temp['id'] in previous) is False:
+                        previous[temp['id']] = datetime.now().strftime(FMT)
+                tdelta = datetime.strptime(temp['timestamp'], FMT) - 
datetime.strptime(previous[temp['id']], FMT)
+            #logging.debug("TDELTA: %r: %r == %r" % (tdelta.seconds, 
temp['timestamp'], previous[temp['id']]))
             #epdb.set_trace()
-            if tdelta.seconds <= options.get('interval') and tdelta.days != -1:
+                if tdelta.seconds <= options.get('interval') and tdelta.days 
!= -1:
                 #logging.debug("Not doing anything for %r!" % temp['id'])
+                    continue
+            except:
                 continue
             previous[temp['id']] = temp['timestamp']
             if sensors.get(temp['id']) is None:
diff --git a/python/rtlsdr.py b/python/rtlsdr.py
index 259ce21..2ec80ba 100755
--- a/python/rtlsdr.py
+++ b/python/rtlsdr.py
@@ -1,21 +1,23 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+## \file rtlsdr.py Read data from an RTL-SDR USB dongle
 
 #import epdb
 import logging
diff --git a/python/sensor.py b/python/sensor.py
index d688bf3..f5ecd18 100755
--- a/python/sensor.py
+++ b/python/sensor.py
@@ -1,30 +1,43 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file sensor.py These class contain all the data about each sensor,
+##                 and methods to operate on that data.
 
 import sys
 import epdb
+import time
 import logging
 import psycopg2
 from datetime import datetime
 from enum import Enum
 from postgresql import Postgresql
 
+# Follow a file as it's writteb, like the unix utility tail
+def follow(thefile):
+    thefile.seek(0,2)
+    while True:
+        line = thefile.readline()
+        if not line:
+            time.sleep(0.1)
+            continue
+        yield line
 
 # Types of sensors. These enums and their string values must match
 # the database schema's enum. See powerguru.sql for details.
@@ -105,6 +118,9 @@ class Sensors(object):
                 data['channel'] = channel
             self.sensors[id] = SensorDevice(data)
 
+    def count(self):
+        return len(self.sensors)
+
     def makeXML(self, xml=""):
         """Create an XML string of all the sensor data"""
         for id,sensor in self.sensors.items():
@@ -128,7 +144,7 @@ class Sensors(object):
     def add(self, sensor):
         id = sensor.get('id')
         self.sensors[id] = sensor
-        self.dbcursor.execute(sensor.MakeSQL())
+        self.db.query(sensor.MakeSQL())
 
     def get(self, id):
         try:
@@ -196,8 +212,11 @@ class SensorDevice(object):
 
     def MakeSQL(self):
         """ Format the SQL query to add this sensor"""
-        device = deviceStrings[self.data['device']]
-        sense = sensorStrings[self.data['sensor']]
+        try:
+            device = deviceStrings[self.data['device']]
+            sense = sensorStrings[self.data['sensor']]
+        except:
+            return None
 
         if self.data['channel'] is not None:
             channel = self.data['channel']
diff --git a/python/triggers.py b/python/triggers.py
index 1b0545e..a28eb42 100644
--- a/python/triggers.py
+++ b/python/triggers.py
@@ -1,21 +1,25 @@
 #!/usr/bin/python3
-
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+## \file triggers.py These classes add a trigger event timestamp
+##                   into the database so we can relate the changes
+##                   we see in the data to real world events. ie...
+##                   opening a door may change the temperature.
 
 import epdb
 import logging
diff --git a/python/weather.py b/python/weather.py
index 1344258..4cd1eb9 100755
--- a/python/weather.py
+++ b/python/weather.py
@@ -1,21 +1,21 @@
 #!/usr/bin/python3
 
-"""
-   Copyright (C) 2019 Free Software Foundation, Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-"""
+#
+#   Copyright (C) 2018,2019 Free Software Foundation, Inc.
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
 
 import sys
 import epdb

-----------------------------------------------------------------------

Summary of changes:
 python/chart.py      | 306 ++++++++++++++++++++++++++-------------------------
 python/gpio433.py    |  32 +++---
 python/gpiots.py     | 116 +++++++++----------
 python/i2c.py        |  36 +++---
 python/mergedb.py    |  35 +++---
 python/onewire.py    |  39 +++----
 python/options.py    |  41 ++++---
 python/ownet.py      |  35 +++---
 python/pgd.py        |  49 +++++----
 python/postgresql.py |  42 +++----
 python/remote.py     |  34 +++---
 python/rtl433.py     |  51 +++++----
 python/rtlsdr.py     |  32 +++---
 python/sensor.py     |  57 ++++++----
 python/triggers.py   |  38 ++++---
 python/weather.py    |  32 +++---
 16 files changed, 511 insertions(+), 464 deletions(-)


hooks/post-receive
-- 
powerguru



reply via email to

[Prev in Thread] Current Thread [Next in Thread]