diff --git a/RainEagle/EagleClass.py b/RainEagle/EagleClass.py index c313607..dc9da82 100644 --- a/RainEagle/EagleClass.py +++ b/RainEagle/EagleClass.py @@ -167,8 +167,8 @@ class Eagle(object) : print "debug : = ", self.debug - if self.addr is None : - raise AssertionError("no hostname or IP given") + if self.addr is None : + raise AssertionError("no hostname or IP given") # preload if self.mac is None : @@ -183,25 +183,25 @@ class Eagle(object) : 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) + 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): + def list_devices(self, macid=None): """ - Send the LIST_DEVICES command - returns information about the EAGLE device + Send the LIST_DEVICES command + returns information about the EAGLE device """ - comm_responce = self._send_soc_comm("list_devices") + comm_responce = self._send_soc_comm("list_devices", MacId=macid) if self.debug : print "comm_responce =", comm_responce if comm_responce is None: @@ -221,7 +221,7 @@ class Eagle(object) : if comm_responce is None: raise RainEagleResponseError("get_device_data : Null reply") if self.debug : - print comm_responce + print comm_responce etree = ET.fromstring('<S>' + comm_responce + '</S>') rv = _et2d(etree) return rv @@ -331,6 +331,7 @@ class Eagle(object) : return rv # 17 + # needs to be rewritten to stream the data via iter def get_history_data(self, macid=None, starttime="0x00000000", endtime=None, frequency=None) : """ Send the GET_HISTORY_DATA command get a series of summation values over an interval of time @@ -359,16 +360,16 @@ class Eagle(object) : # http commands as class functions - def get_device_list(self) : + def get_device_list(self, macid=None) : """ - Send the LIST_DEVICES command - returns information about the EAGLE device + Send the LIST_DEVICES command + returns information about the EAGLE device """ - comm_responce = self._send_http_comm("get_device_list") + comm_responce = self._send_http_comm("get_device_list", MacId=macid) return json.loads(comm_responce) - def get_uploaders(self) : + def get_uploaders(self, macid=None) : """ gets list of uploaders for Web UI @@ -379,10 +380,10 @@ class Eagle(object) : 'uploader_name[1]': 'Bidgely Inc.' """ - comm_responce = self._send_http_comm("get_uploaders") + comm_responce = self._send_http_comm("get_uploaders", MacId=macid) return json.loads(comm_responce) - def get_uploader(self) : + def get_uploader(self, macid=None) : """ gets current uploaders config @@ -401,27 +402,28 @@ class Eagle(object) : See also set_cloud() to set current uploader cloud config """ - comm_responce = self._send_http_comm("get_uploader") + comm_responce = self._send_http_comm("get_uploader", MacId=macid) return json.loads(comm_responce) - def set_message_read(self) : + def set_message_read(self, macid=None) : """ On Success returns dict with the values : 'remote_management_status' : 'success' """ - comm_responce = self._send_http_comm("set_message_read") + comm_responce = self._send_http_comm("set_message_read", MacId=macid) return json.loads(comm_responce) - def confirm_message(self, id) : + def confirm_message(self, macid=None, id=None) : """ """ id = _tohex(id) - comm_responce = self._send_http_comm("confirm_message", Id=id) + comm_responce = self._send_http_comm("confirm_message", + MacId=macid, Id=id) return json.loads(comm_responce) - def get_message(self) : + def get_message(self, macid=None) : """ On Success returns dict with the values (example): "meter_status" : "Connected" @@ -435,10 +437,10 @@ class Eagle(object) : "message_read" : "Y" """ - comm_responce = self._send_http_comm("get_message") + comm_responce = self._send_http_comm("get_message", MacId=macid) return json.loads(comm_responce) - def get_usage_data(self) : + def get_usage_data(self, macid=None) : """ Get current demand usage summation @@ -464,11 +466,11 @@ class Eagle(object) : 'usage_timestamp' : '1394505386' """ - comm_responce = self._send_http_comm("get_usage_data") + comm_responce = self._send_http_comm("get_usage_data", MacId=macid) return json.loads(comm_responce) - def get_historical_data(self, period="day") : + def get_historical_data(self, macid=None, period="day") : """ get a series of summation values over an interval of time ( http command api ) @@ -510,11 +512,11 @@ class Eagle(object) : """ if period not in ['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) + comm_responce = self._send_http_comm("get_historical_data", macid=macid, Period=period) return json.loads(comm_responce) - def get_setting_data(self) : + def get_setting_data(self, macid=None) : """ get settings data @@ -522,10 +524,10 @@ class Eagle(object) : relating to price, uploader, network & device """ - comm_responce = self._send_http_comm("get_setting_data") + comm_responce = self._send_http_comm("get_setting_data", MacId=macid) return json.loads(comm_responce) - def get_device_config(self) : + def get_device_config(self, macid=None) : """ get remote management status @@ -534,10 +536,10 @@ class Eagle(object) : 'config_vpn_enabled': 'Y' """ - comm_responce = self._send_http_comm("get_device_config") + comm_responce = self._send_http_comm("get_device_config", MacId=macid) return json.loads(comm_responce) - def get_gateway_info(self) : + def get_gateway_info(self, macid=None) : """ gets network status @@ -548,10 +550,10 @@ class Eagle(object) : 'gateway_mac_id': 'D8:D5:B9:00:90:24' """ - comm_responce = self._send_http_comm("get_gateway_info") + comm_responce = self._send_http_comm("get_gateway_info", MacId=macid) return json.loads(comm_responce) - def get_timezone(self) : + def get_timezone(self, macid=None) : """ get current timezone configuration @@ -564,7 +566,7 @@ class Eagle(object) : 'timezone_status': 'success' """ - comm_responce = self._send_http_comm("get_timezone") + comm_responce = self._send_http_comm("get_timezone", MacId=macid) return json.loads(comm_responce) def get_time_source(self, macid=None) : @@ -574,11 +576,11 @@ class Eagle(object) : On Success returns dict with value 'internet' or 'meter' : 'time_source': 'internet' """ - comm_responce = self._send_http_comm("get_time_source") + comm_responce = self._send_http_comm("get_time_source", MacId=macid) return json.loads(comm_responce) - def get_remote_management(self) : - return self.get_device_config(self) + def get_remote_management(self, macid=None) : + return self.get_device_config(self, MacId=macid) def set_remote_management(self, macid=None, status="on") : """ set_remote_management @@ -593,7 +595,8 @@ class Eagle(object) : """ if status not in ['on', 'off'] : raise ValueError("set_remote_management status must be 'on' or 'off'") - comm_responce = self._send_http_comm("set_remote_management", Status=status) + comm_responce = self._send_http_comm("set_remote_management", + MacId=macid, Status=status) return json.loads(comm_responce) @@ -612,10 +615,11 @@ class Eagle(object) : """ if source not in ['meter', 'internet'] : raise ValueError("set_time_source Source must be 'meter' or 'internet'") - comm_responce = self._send_http_comm("set_time_source", Source=source) + comm_responce = self._send_http_comm("set_time_source", + MacId=macid, Source=source) return json.loads(comm_responce) - def get_price(self) : + def get_price(self, macid=None) : """ get price for kWh @@ -627,10 +631,10 @@ class Eagle(object) : returns empty dict on Error """ - comm_responce = self._send_http_comm("get_price") + comm_responce = self._send_http_comm("get_price", MacId=macid) return json.loads(comm_responce) - def set_price(self, price) : + def set_price(self, macid=None, price=None) : """ Set price manualy @@ -658,12 +662,12 @@ class Eagle(object) : price_adj = "{:#x}".format(int(price * multiplier)) tdigits = "{:#x}".format(trailing_digits) - comm_responce = self._send_http_comm("set_price", + comm_responce = self._send_http_comm("set_price", MacId=macid, Price=price_adj, TrailingDigits=tdigits) return json.loads(comm_responce) - def set_price_auto(self) : + def set_price_auto(self, macid=None) : """ Set Price from Meter @@ -671,6 +675,7 @@ class Eagle(object) : 'set_price_status': 'success' """ comm_responce = self._send_http_comm("set_price", + MacId=macid, Price="0xFFFFFFFF", TrailingDigits="0x00") return json.loads(comm_responce) @@ -681,35 +686,35 @@ class Eagle(object) : # """ # multiplier = _tohex(multiplier, 8) # divisor = _tohex(divisor, 8) -# comm_responce = self._send_http_comm("set_multiplier_divisor", Multiplier=multiplier, Divisor=divisor) +# comm_responce = self._send_http_comm("set_multiplier_divisor", MacId=macid, Multiplier=multiplier, Divisor=divisor) # return json.loads(comm_responce) - def factory_reset(self) : + def factory_reset(self, macid=None) : """ Factory Reset """ - comm_responce = self._send_http_comm("factory_reset") + comm_responce = self._send_http_comm("factory_reset", MacId=macid) return json.loads(comm_responce) -# def disconnect_meter(self) : +# def disconnect_meter(self, macid=None) : # """ # disconnect from Smart Meter # """ -# comm_responce = self._send_http_comm("disconnect_meter") +# comm_responce = self._send_http_comm("disconnect_meter", MacId=macid) # return json.loads(comm_responce) - def cloud_reset(self) : + def cloud_reset(self, macid=None) : """ cloud_reset : Clear Cloud Configuration """ - comm_responce = self._send_http_comm("cloud_reset") + comm_responce = self._send_http_comm("cloud_reset", MacId=macid) return json.loads(comm_responce) - def set_cloud(self, url, authcode="", email="") : + def set_cloud(self, macid=None, url=None, authcode="", email="") : """ set cloud Url @@ -720,6 +725,9 @@ class Eagle(object) : See also get_uploader() to retrieve current uploader cloud config """ + if url is None : + raise ValueError("invalid url.\n") + if url.__len__() > 200 : raise ValueError("Max URL length is 200 characters long.\n") @@ -749,7 +757,7 @@ class Eagle(object) : else : password = "" - comm_responce = self._send_http_comm("set_cloud", + comm_responce = self._send_http_comm("set_cloud", MacId=macid, Provider="manual", Protocol=protocol, HostName=hostname, Url=url, Port=port, @@ -774,8 +782,8 @@ class Eagle(object) : def _send_http_comm(self, cmd, **kwargs): - if self.debug : - print "\n\n_send_http_comm : ", cmd + if self.debug : + print "\n\n_send_http_comm : ", cmd commstr = "<LocalCommand>\n" commstr += "<Name>{0!s}</Name>\n".format(cmd) @@ -784,8 +792,12 @@ class Eagle(object) : commstr += "<{0}>{1!s}</{0}>\n".format(k, v) commstr += "</LocalCommand>\n" - if self.debug : - print(commstr) + if cmd == "set_cloud" : + print(commstr) + return dict() + + if self.debug : + print(commstr) url = "http://{0}/cgi-bin/cgi_manager".format(self.addr) diff --git a/bin/meter_status.py b/bin/meter_status.py index 3db31f4..496b9e9 100755 --- a/bin/meter_status.py +++ b/bin/meter_status.py @@ -48,7 +48,10 @@ def create_parser(): def main() : parser = create_parser() - args = parser.parse_args() + args, unknown = parser.parse_known_args() + + # print "Args = ", args, vars(args) + # print "unknown = ", unknown eg = Eagle(**vars(args)) # timeout=45, @@ -90,9 +93,9 @@ def print_currentsummation(cs) : if 'TimeStamp' in cs : time_stamp = to_epoch_1970(cs['TimeStamp']) print "{0:s} : ".format(time.asctime(time.localtime(time_stamp))) - print "\tReceived = {0:{width}.3f} Kw".format(reading_received, width=10) - print "\tDelivered = {0:{width}.3f} Kw".format(reading_delivered, width=10) - print "\t\t{0:{width}.3f} Kw".format( (reading_delivered - reading_received), width=14) + print "\tReceived = {0:10.3f} Kw".format(reading_received) + print "\tDelivered = {0:10.3f} Kw".format(reading_delivered) + print "\tMeter = {0:10.3f} Kw".format( (reading_delivered - reading_received)) def print_instantdemand(idemand) : @@ -120,8 +123,8 @@ def print_instantdemand(idemand) : time_stamp = to_epoch_1970(idemand['TimeStamp']) 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 "\tDemand = {0:10.3f} Kw".format(reading) + print "\tAmps = {0:10.3f}".format( ((reading * 1000) / 240)) # diff --git a/bin/plot_power.py b/bin/plot_power.py index 2e464de..89ab525 100755 --- a/bin/plot_power.py +++ b/bin/plot_power.py @@ -31,17 +31,19 @@ def main(eg) : def print_data(eg) : rh = eg.get_history_data() #+ # endtime=None, frequency=None) : + global curr_day + + + curr_day = time.gmtime(1); for dat in rh['HistoryData']['CurrentSummation'] : print_currentsummation(dat) - print "# day_delta_received={0:0.4f}\t" \ - + " day_delta_delivered={1:0.4f} : {2:0.4f}".format( + 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}\t" \ - + " max_delta_delivered={1:0.4f}".format( + print "# max_delta_received={0:0.4f}\tmax_delta_delivered={1:0.4f}".format( max_delta_received, max_delta_delivered) @@ -85,12 +87,13 @@ def print_currentsummation(cs) : #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)) + if curr_day.tm_mday != time_struct.tm_mday : + curr_day = time_struct + print "# {0} day_delta_received={1:0.4f}".format( \ + time.strftime("%a %Y-%m-%d", curr_day), + day_delta_received) \ + + "\tday_delta_delivered={0:0.4f}".format(day_delta_delivered) \ + + " : {0:0.4f}".format((day_delta_delivered - day_delta_received)) day_delta_received = 0 day_delta_delivered = 0 diff --git a/setup.py b/setup.py index 6d8d919..0c11b4f 100644 --- a/setup.py +++ b/setup.py @@ -10,38 +10,27 @@ from distutils.core import setup class install_scripts_and_symlinks(install_scripts): '''Like install_scripts, but also replicating nonexistent symlinks''' def run(self): - print "=============install_scripts_and_symlinks run" - install_scripts.run(self) - # Replicate symlinks if they don't exist - print self - print "data_files = ", dir( self.distribution.data_files) - print type(self.distribution.data_files) - print self.distribution.data_files - for script in self.distribution.scripts: - print "\n---script = ",script - if os.path.islink(script): - target = os.readlink(script) - newlink = os.path.join(self.install_dir, os.path.basename(script)) - if not os.path.exists(newlink): - print "++++++++++", target, " -> ", newlink - # os.symlink(target, newlink) + install_scripts.run(self) + # Replicate symlinks if they don't exist + for script in self.distribution.scripts: + if os.path.islink(script): + newlink = os.path.join(self.install_dir, os.path.basename(script)) setup( name='RainEagle', - version='0.1.7', + version='0.1.7a', author='Peter Shipley', author_email='Peter.Shipley@gmail.com', packages=find_packages(), scripts=[ 'bin/meter_status.py', 'bin/plot_power.py' ], - data_files=[ ], -# ('examples', ['bin/isy_find.py', 'bin/isy_progs.py', -# 'bin/isy_log.py', 'bin/isy_net_wol.py']), -# ('bin', ['bin/isy_nodes.py', 'bin/isy_var.py']) ], + data_files=[ + ('examples', ['bin/plot_power.py', 'bin/gnup_poweruse.txt']), + ('bin', ['bin/meter_status.py']) ], url='https://github.com/evilpete/RainEagle', license='BSD', description='Python Class for utilizing the Rainforest Automation Eagle ( RFA-Z109 ) socket API.', - long_description=open('README.md').read(), + long_description=open('README.txt').read(), cmdclass = { 'install_scripts': install_scripts_and_symlinks } )