class Plug(): def __init__(self, plug_ip): # Init plug self.plug = SmartPlug(plug_ip) # -- def info(self): print(' -- Plug Info -- ') print('Name: %s' % self.plug.name) print('Model: %s' % self.plug.model) print('Mac: %s' % self.plug.mac) print('Time: %s' % self.plug.time) print('Is on: %s' % self.plug.is_on) print('Nightmode: %s' % (not self.plug.led)) print('RSSI: %s' % self.plug.rssi) # -- def plug_on(self): time.sleep(1) if not self.plug.is_on: self.plug.turn_on() print('Plug turned on') # -- def plug_off(self): time.sleep(1) if self.plug.is_on: self.plug.turn_off() print('Plug turned off')
def main_loop(): # init inv = Inverter(0x1, '/dev/ttyUSB0') inv.version() if OWMKey: owm = Weather(OWMKey, OWMLat, OWMLon) owm.fresh = False else: owm = False pvo = PVOutputAPI(APIKEY, SYSTEMID) fan = SmartPlug(FAN_IP_ADDR) # Loop until end of universe while True: if owm: try: owm.get() owm.fresh = True except Exception as e: print('Error getting weather: {}'.format(e)) owm.fresh = False # get readings from inverter, if success send to pvoutput inv.read_inputs() if inv.status != -1: if inv.temp >= 30: fan.turn_on() else: fan.turn_off() temp = owm.temperature if owm and owm.fresh else None pvo.send_status(date=inv.date, energy_gen=inv.wh_today, power_gen=inv.ac_power, vdc=inv.pv_volts, vac=inv.ac_volts, temp=temp, temp_inv=inv.temp, energy_life=inv.wh_total, power_vdc=inv.pv_power) # sleep until next multiple of 5 minutes min = 5 - localnow().minute % 5 sleep(min * 60 - localnow().second) else: # some error sleep(60) # 1 minute before try again
def main(panel_ip='192.168.1.161/meters.xml', socket_ip='192.168.1.61', threshold=0.7, interval=30, single_shot=False, max_tries=None, log_file='C:\\Users\\eugen\\plugger\\log.csv', test_plug=False, daily_log_dir='C:\\Users\\eugen\\plugger\\daily_logs\\', timed_log_when='midnight', timed_log_interval=None, days_to_log=28): """ Do iterations over a loop which tests the power output at panel_ip, and manages the state of a plug at socket_ip, according to the threshold power output level. If pass single_shot=True, will do one test and exit, after making max_tries number of attempts to make a successful read and switch Otherwise will operate continuously. Interrupt with ctrl-c To test: pass socket_ip=None and test_plug=True to simulate the plug pass a test xml page on localserver as panel_ip, eg: <line1>x</line1> <OutputPower>99</OutputPower> <line3>x</line3> .. and serve the page the project folder with: $ python -m http.server (can edit and save this file on the fly to simulate panel output) """ # make a daily logging directory if doesn't exist if not os.path.exists(daily_log_dir): os.mkdir(daily_log_dir) # set up logging formatter = logging.Formatter('%(asctime)-15s %(msg)-10s') # formatter.datefmt = ('%d/%m/%y %H:%M:%S') file_path = os.path.join(daily_log_dir, 'log') print('made a folder for logs: {file_path}') if timed_log_interval is None: handler = TimedRotatingFileHandler(file_path, when=timed_log_when, backupCount=days_to_log) else: handler = TimedRotatingFileHandler(file_path, when=timed_log_when, interval=timed_log_interval, backupCount=days_to_log) handler.setLevel(logging.INFO) handler.setFormatter(formatter) log = logging.getLogger() log.setLevel(logging.INFO) log.addHandler(handler) # initial entry log.info('') log.info('*' * 50) log.info('') if single_shot: log.info('[main 0.01] Calling main, mode=single') else: log.info('[main 0.02] Calling main, mode=cont') # create a plug instance if socket_ip is not None: try: plug = SmartPlug(socket_ip) log.info('[main 0.05] initial plug found') except: print('Could not find a plug at', socket_ip) log.info('[main 0.10] initial plug NOT FOUND') return 1 elif test_plug: plug = TestPlug() log.info('[main 0.20] using test plug') else: print('need either a socket_ip or pass test_plug=True') log.info('[main 0.30] exiting as no plug') return 1 interval_by_min = f'{str(interval // 60)} min, {str(interval % 60)} sec' splash_width = 60 info = plug.info print('') print('*' * 12, 'PLUGGER ENERGY MANAGEMENT SYSTEM', '*' * 12) print('') print('version'.ljust(pads[0]), '0.1') print('') print('Plug IP address:'.ljust(pads[0]), socket_ip) print('Plug name'.ljust(pads[0]), info['alias']) print('Plug model'.ljust(pads[0]), info['model']) print('Initial plug state:'.ljust(pads[0]), "ON" if plug.is_on else "OFF") print('') print('Panel IP address:'.ljust(pads[0]), panel_ip) print('Panel power output threshold:'.ljust(pads[0]), threshold) print('') print('Test interval:'.ljust(pads[0]), interval_by_min) print('Testing mode:'.ljust(pads[0]), 'single shot' if single_shot else 'continuous') print('Max attempts (if single shot):'.ljust(pads[0]), max_tries if single_shot else 'n/a') print('') print('*' * 59) print('') time.sleep(1) # initialise the log file if reqd if not os.path.exists(log_file): with open(log_file, 'a', newline="") as f: writer = csv.writer(f, delimiter=",") writer.writerow(CSV_COLUMNS) tries = 0 # main loop while True: log.info('[main 0.40] entering main loop') ts = time.strftime('%d/%m/%y %H:%M:%S') log_list = [ts, 'single' if single_shot else 'cont'] if single_shot: print(ts, f'[{tries + 1}/{max_tries}]'.ljust(7), end=" ") else: print(ts, end=" ") # try to read the panel's current output log.info('[main 0.50] ready to read panel') success, panel_output = get_panel_output(panel_ip=panel_ip, target='OutputPower', log=log) log.info(f'[main 0.60] panel read: success={success}') log.info(f'[main 0.60] panel read: output={panel_output}') if not success: print(f'failed to get panel output, error: {panel_output}') if single_shot: tries += 1 if tries == max_tries: log.info('[main 0.70] reached max tries, exiting') return 0 time.sleep(interval) continue log_list.extend([success, panel_output]) print('panel reading: ' + str(panel_output).ljust(pads[1]), end=' ') try: socket_state = plug.is_on log.info(f'[main 0.80] read plug state: {socket_state}') except: print('cannot find plug') log.info(f'[main 0.90] cannot read plug') if single_shot: tries += 1 if tries == max_tries: log.info('[main 1.00] reached max tries, exiting') return 0 time.sleep(interval) continue log_list.append(socket_state) if panel_output >= threshold: if socket_state: log_list.append('leave on') log.info(f'[main 1.10] output over threshold, leaving on') print('leave on') else: try: plug.turn_on() log.info(f'[main 1.20] *** turned plug ON ***') except: print('cannot turn on plug') log.info(f'[main 1.30] cannot turn on plug') if single_shot: tries += 1 if tries == max_tries: log.info('[main 1.40] reached max tries, exiting') return 0 time.sleep(interval) continue print('** TURN ON **') log_list.append('activate') elif panel_output < threshold: if socket_state: try: plug.turn_off() log.info(f'[main 1.50] *** turned plug OFF ***') except: print('cannot find plug') log.info(f'[main 1.60] cannot turn off plug') if single_shot: tries += 1 if tries == max_tries: log.info('[main 1.70] reached max tries, exiting') return 0 time.sleep(interval) continue print('** TURN OFF **') log_list.append('deactivate') else: log_list.append('leave off') print('leave off') # log a plug reading after any changes try: socket_state = plug.is_on log.info( f'[main 1.80] got plug reading after changes: {socket_state}') except: print('cannot find plug') log.info(f'[main 1.90] cannot read plug after changes') socket_state = 'not found after changes' continue log_list.append(socket_state) # write out log with open(log_file, 'a', newline="") as f: writer = csv.writer(f, delimiter=",") writer.writerow(log_list) # exit loop if only a single shot required if single_shot: return 0 log.info(f'[main 2.00] reached end of main loop') time.sleep(interval)
import sys sys.path.append('../') from tplink_smartplug import SmartPlug plug = SmartPlug('192.168.xxx.xxx') if plug.is_on: plug.turn_off() print('Plug turned off') else: plug.turn_on() print('Plug turned on')