From e417b2565dbc86a8b9efc4c58c87ee7f933b4b98 Mon Sep 17 00:00:00 2001 From: Peter Shipley Date: Thu, 13 Mar 2014 18:03:11 -0700 Subject: [PATCH] added test for firmware verson added arg to demo app meter_status added version numbers removed hardcoded address --- .gitignore | 2 + RainEagle/EagleClass.py | 54 +++++++++++++++--- bin/gnup_poweruse.txt | 4 +- bin/meter_status.py | 90 ++++++++++++++++++++---------- bin/plot_power.py | 120 ++++++++++++++++------------------------ doc.txt | 2 +- setup.py | 2 +- 7 files changed, 160 insertions(+), 114 deletions(-) diff --git a/.gitignore b/.gitignore index 91bb707..898569d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,10 @@ EGG-INFO .exrc +Dump/* test.* Sav/* +Tests/* Bak/* *bak diff --git a/RainEagle/EagleClass.py b/RainEagle/EagleClass.py index c723e09..c313607 100644 --- a/RainEagle/EagleClass.py +++ b/RainEagle/EagleClass.py @@ -2,6 +2,7 @@ __author__ = 'Peter Shipley ' __copyright__ = "Copyright (C) 2014 Peter Shipley" __license__ = "BSD" +__version__ = "0.1.7" import socket import sys @@ -14,6 +15,9 @@ from math import floor from urlparse import urlparse import json from warnings import warn +from distutils.version import LooseVersion + +min_fw_ver = "2.0.21" from pprint import pprint @@ -143,14 +147,17 @@ class Eagle(object) : Currently there is very little error handling ( if any at all ) """ def __init__(self, **kwargs): + self.debug = kwargs.get("debug", 0) if self.debug : print self.__class__.__name__, __name__ + self.checkfw = kwargs.get("checkfirmware", True) self.addr = kwargs.get("addr", os.getenv('EAGLE_ADDR', None)) self.port = kwargs.get("port", os.getenv('EAGLE_PORT', 5002)) - self.getmac = kwargs.get("getmac", True) + self.mac = kwargs.get("mac", None) self.timeout = kwargs.get("timeout", 10) + self.soc = None self.macid = None @@ -159,8 +166,12 @@ class Eagle(object) : print "timeout : = ", self.timeout print "debug : = ", self.debug + + if self.addr is None : + raise AssertionError("no hostname or IP given") + # preload - if self.getmac : + if self.mac is None : self.device_info = self.list_devices() if self.device_info is None : raise IOError("Error connecting") @@ -171,11 +182,25 @@ class Eagle(object) : if self.debug : print "Init DeviceMacId = ", self.macid + if self.checkfw : + mysetting = self.get_setting_data() + dev_fw_ver = mysetting['device_fw_version'] + if ( LooseVersion(dev_fw_ver) < LooseVersion(min_fw_ver) ) : + warn_message = "Warning : device firmware " \ + + "{0} < {1} please concideer " \ + + "updating ".format(dev_fw_ver, min_fw_ver) + warn( warn_message, RuntimeWarning, stacklevel=3) + # socket commands as class functions def list_devices(self): + """ + Send the LIST_DEVICES command + returns information about the EAGLE device + + """ comm_responce = self._send_soc_comm("list_devices") if self.debug : print "comm_responce =", comm_responce @@ -195,6 +220,8 @@ class Eagle(object) : comm_responce = self._send_soc_comm("get_device_data", MacId=macid) if comm_responce is None: raise RainEagleResponseError("get_device_data : Null reply") + if self.debug : + print comm_responce etree = ET.fromstring('' + comm_responce + '') rv = _et2d(etree) return rv @@ -332,6 +359,15 @@ class Eagle(object) : # http commands as class functions + def get_device_list(self) : + """ + Send the LIST_DEVICES command + returns information about the EAGLE device + + """ + comm_responce = self._send_http_comm("get_device_list") + return json.loads(comm_responce) + def get_uploaders(self) : """ gets list of uploaders for Web UI @@ -346,7 +382,7 @@ class Eagle(object) : comm_responce = self._send_http_comm("get_uploaders") return json.loads(comm_responce) - def get_uploader() : + def get_uploader(self) : """ gets current uploaders config @@ -432,7 +468,7 @@ class Eagle(object) : return json.loads(comm_responce) - def get_historical_data_alt(self, period="day") : + def get_historical_data(self, period="day") : """ get a series of summation values over an interval of time ( http command api ) @@ -473,7 +509,7 @@ class Eagle(object) : """ if period not in ['day', 'week', 'month', 'year'] : - raise ValueError("get_historical_data_alt period must be one of day|week|month|year") + raise ValueError("get_historical_data : period must be one of day|week|month|year") comm_responce = self._send_http_comm("get_historical_data", Period=period) return json.loads(comm_responce) @@ -542,7 +578,7 @@ class Eagle(object) : return json.loads(comm_responce) def get_remote_management(self) : - return get_device_config(self) + return self.get_device_config(self) def set_remote_management(self, macid=None, status="on") : """ set_remote_management @@ -738,7 +774,8 @@ class Eagle(object) : def _send_http_comm(self, cmd, **kwargs): - print "\n\n_send_http_comm : ", cmd + if self.debug : + print "\n\n_send_http_comm : ", cmd commstr = "\n" commstr += "{0!s}\n".format(cmd) @@ -747,7 +784,8 @@ class Eagle(object) : commstr += "<{0}>{1!s}\n".format(k, v) commstr += "\n" - print(commstr) + if self.debug : + print(commstr) url = "http://{0}/cgi-bin/cgi_manager".format(self.addr) diff --git a/bin/gnup_poweruse.txt b/bin/gnup_poweruse.txt index 1c9643f..84a3147 100644 --- a/bin/gnup_poweruse.txt +++ b/bin/gnup_poweruse.txt @@ -27,16 +27,14 @@ set grid set key off set pointsize 0.5 -# 2014-03-09 13:24:21 24.2220 0.0970 2649.2700 0.0000 set xtics rotate set xtics 3600 set xdata time set timefmt "%Y-%m-%d %H:%M:%S" set format x "%a %b %d %H:%M" -#set xrange [ "2014-03-04 00:00:00" : ] -set xrange [ "2014-03-04 00:00:00" : ] +# set xrange [ "2014-03-04 00:00:00" : ] set style data lines set autoscale y diff --git a/bin/meter_status.py b/bin/meter_status.py index 1857504..3db31f4 100755 --- a/bin/meter_status.py +++ b/bin/meter_status.py @@ -2,27 +2,60 @@ """ A simple script get current meter values """ - -__author__ = "Peter Shipley" -import sys -sys.path.append('/usr/home/shipley/Projects/Eagle') # temp +__author__ = "Peter Shipley" +__version__ = "0.1.7" # import RainEagle from RainEagle import Eagle, to_epoch_1970 import time +import os +import argparse from pprint import pprint debug = 0 + +def create_parser(): + parser = argparse.ArgumentParser( + description="print power meter status") + + parser.add_argument("-a", "--address", dest="addr", + default=os.getenv('EAGLE_ADDR', None), + help="hostname or IP device") + + parser.add_argument("-p", "--port", dest="port", type=int, + default=os.getenv('EAGLE_PORT', 5002), + help="command socket port") + + parser.add_argument("-d", "--debug", dest="debug", + default=debug, action="count", + help="print debug info") + + parser.add_argument("-m", "--mac", dest="mac", + help="Eagle radio mac addrress") + + parser.add_argument("-t", "--timeout", dest="timeout", + help="Socket timeout") + + parser.add_argument("-v", '--version', action='version', + version="%(prog)s {0}".format(__version__) ) + + return parser + + def main() : - eg = Eagle( debug=debug , addr="10.1.1.39") + + parser = create_parser() + args = parser.parse_args() + + eg = Eagle(**vars(args)) # timeout=45, r = eg.get_device_data() - print_instantdemand( r['InstantaneousDemand']) + print_instantdemand(r['InstantaneousDemand']) print print_currentsummation(r['CurrentSummation']) @@ -30,12 +63,14 @@ def main() : exit(0) + def twos_comp(val, bits=32): """compute the 2's compliment of int value val""" if( (val&(1<<(bits-1))) != 0 ): - val = val - (1< 0x7FFFFFFF: - demand -= 0x100000000 + demand -= 0x100000000 if multiplier == 0 : - multiplier = 1 + multiplier = 1 if divisor == 0 : - divisor = 1 + divisor = 1 - reading = (demand * multiplier) / float (divisor ) + reading = (demand * multiplier) / float (divisor) + + if 'TimeStamp' in idemand : + time_stamp = to_epoch_1970(idemand['TimeStamp']) + print "{0:s} : ".format(time.asctime(time.localtime(time_stamp))) - print "{0:s} : ".format(time.asctime(time.localtime(time_stamp))) print "\tDemand = {0:{width}.3f} Kw".format(reading, width=10) - print "\tAmps = {0:{width}.3f}".format( ((reading * 1000) / 240), width=10 ) + print "\tAmps = {0:{width}.3f}".format( ((reading * 1000) / 240), width=10) -# +# if __name__ == "__main__": # import __main__ - # print(__main__.__file__) - # print("syntax ok") + # print(__main__.__file__) + # print("syntax ok") main() - exit(0) + exit(0) diff --git a/bin/plot_power.py b/bin/plot_power.py index 0932b67..2e464de 100755 --- a/bin/plot_power.py +++ b/bin/plot_power.py @@ -2,12 +2,10 @@ """ A simple script to generate guuplot data from meter history """ - -__author__ = "Peter Shipley" +__author__ = "Peter Shipley" +__version__ = "0.1.7" -import sys -sys.path.append('/usr/home/shipley/Projects/Eagle') # temp import RainEagle import time @@ -22,115 +20,95 @@ max_delta_received = 0 max_delta_delivered = 0 day_delta_received = 0 day_delta_delivered = 0 -curr_day=-1 +curr_day = -1 + def main(eg) : - # print_header() print_data(eg) - # print_footer() exit(0) -def print_header() : - print """ -set terminal png size 2600,500 -set datafile separator "\t" -set xlabel "time" -set ylabel "power" -set grid -set key off -set pointsize 0.5 -set xtics 3600 -set xdata time -set timefmt "%Y-%m-%d %H:%M:%S" -set format x "%a %b %d %H:%M" -#set xrange [ "2014-03-04 00:00:00" : ] -# set xrange [ "2014-03-04 00:00:00" : "2014-03-09 17:20:00" ] -set style data lines -set autoscale y -set title "Power Use" -set output "poweruse.png" -plot "-" using 1:3 t "inbound" w lines, "-" using 1:5 t "outbound" -""" - -def print_footer() : - pass def print_data(eg) : rh = eg.get_history_data() - #+ # endtime=None, frequency=None ) : + #+ # endtime=None, frequency=None) : for dat in rh['HistoryData']['CurrentSummation'] : - print_currentsummation(dat) + print_currentsummation(dat) + + print "# day_delta_received={0:0.4f}\t" \ + + " day_delta_delivered={1:0.4f} : {2:0.4f}".format( + day_delta_received, + day_delta_delivered, + (day_delta_delivered - day_delta_received)) + print "# max_delta_received={0:0.4f}\t" \ + + " max_delta_delivered={1:0.4f}".format( + max_delta_received, max_delta_delivered) - print "# day_delta_received={0:0.4f}\tday_delta_delivered={1:0.4f} : {2:0.4f}".format(day_delta_received, day_delta_delivered, ( day_delta_delivered - day_delta_received ) ) - print "# max_delta_received={0:0.4f}\tmax_delta_delivered={1:0.4f}".format(max_delta_received, max_delta_delivered) def print_currentsummation(cs) : global last_delivered global last_received - global max_delta_received + global max_delta_received global max_delta_delivered - global day_delta_received + global day_delta_received global day_delta_delivered global curr_day time_stamp = to_epoch_1970(cs['TimeStamp']) - multiplier=int(cs['Multiplier'], 16) - divisor=int(cs['Divisor'], 16) - delivered=int(cs['SummationDelivered'], 16) - received=int(cs['SummationReceived'], 16) + multiplier = int(cs['Multiplier'], 16) + divisor = int(cs['Divisor'], 16) + delivered = int(cs['SummationDelivered'], 16) + received = int(cs['SummationReceived'], 16) # print "Multiplier=", multiplier, "Divisor=", divisor, "Demand=", demand - + if multiplier == 0 : - multiplier=1 + multiplier = 1 if divisor == 0 : - divisor=1 + divisor = 1 - reading_received = received * multiplier / float (divisor ) + reading_received = received * multiplier / float(divisor) delta_received = (reading_received - last_received) last_received = reading_received - if ( delta_received > max_delta_received and delta_received < 1000) : - max_delta_received = delta_received - #print "new max_delta_received :", max_delta_received + if (delta_received > max_delta_received and delta_received < 1000) : + max_delta_received = delta_received + #print "new max_delta_received :", max_delta_received - - reading_delivered = delivered * multiplier / float (divisor ) + reading_delivered = delivered * multiplier / float(divisor) delta_delivered = (reading_delivered - last_delivered) last_delivered = reading_delivered - if ( delta_delivered > max_delta_delivered and delta_delivered < 1000) : - max_delta_delivered = delta_delivered - #print "\t\tnew max_delta_delivered :", max_delta_delivered - - - + if (delta_delivered > max_delta_delivered and delta_delivered < 1000) : + max_delta_delivered = delta_delivered + #print "\t\tnew max_delta_delivered :", max_delta_delivered time_struct = time.localtime(time_stamp) - if curr_day != time_struct.tm_mday : - curr_day = time_struct.tm_mday - print "# day_delta_received={0:0.4f}\tday_delta_delivered={1:0.4f} : {2:0.4f}".format(day_delta_received, day_delta_delivered, ( day_delta_delivered - day_delta_received ) ) - day_delta_received = 0 - day_delta_delivered = 0 + if curr_day != time_struct.tm_mday : + curr_day = time_struct.tm_mday + print "# day_delta_received={0:0.4f}\tday_delta_delivered={1:0.4f}" \ + + ": {2:0.4f}".format(day_delta_received, + day_delta_delivered, + (day_delta_delivered - day_delta_received)) + day_delta_received = 0 + day_delta_delivered = 0 day_delta_received += delta_received day_delta_delivered += delta_delivered print "{0}\t{1:.4f}\t{2:0.4f}\t{3:.4f}\t{4:0.4f}".format( - time.strftime("%Y-%m-%d %H:%M:%S", time_struct), - reading_received, - delta_received, - reading_delivered, - delta_delivered) - + time.strftime("%Y-%m-%d %H:%M:%S", time_struct), + reading_received, + delta_received, + reading_delivered, + delta_delivered) if __name__ == "__main__": # import __main__ - # print(__main__.__file__) - # print("syntax ok") - reagle = RainEagle.Eagle( debug=0 , addr="10.1.1.39") + # print(__main__.__file__) + # print("syntax ok") + reagle = RainEagle.Eagle(debug=0) main(reagle) - exit(0) + exit(0) diff --git a/doc.txt b/doc.txt index 4076668..83577d8 100644 --- a/doc.txt +++ b/doc.txt @@ -70,7 +70,7 @@ CLASSES | 'gateway_ip_addr': '10.11.12.13' | 'gateway_mac_id': 'D8:D5:B9:00:90:24' | - | get_historical_data_alt(self, period='day') + | get_historical_data(self, period='day') | get a series of summation values over an interval of time | ( http command api ) | diff --git a/setup.py b/setup.py index f9059fd..6d8d919 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ class install_scripts_and_symlinks(install_scripts): setup( name='RainEagle', - version='0.1.6', + version='0.1.7', author='Peter Shipley', author_email='Peter.Shipley@gmail.com', packages=find_packages(),