def setup(): global anz_commands global options global config, mypri global logfile_name, configfile_name options = argu() # get commandline args pfad = os.path.dirname( os.path.realpath(__file__)) # pfad wo dieses script läuft logfile_name = pfad + logfile_name # create Instance of MyPrint Class mypri = MyPrint(appname=progname, debug_level=debug, logfile=logfile_name) # übergebe appname und logfilename config = ConfigRead(debug_level=debug) # instanz der ConfigRead Class anz_commands = len(valid_commands) configfile_name = pfad + "/" + configfile_name ret = config.config_read(configfile_name, "switcher", cfglist_swi) # alese von abschnitt if ret > 0: print("config_read hat retcode: {}".format(ret)) sys.exit(2) # fertig behandlung confifile if ret == 9: sys.exit(2)
def __init__(self, dosennummer, debug_in, config_filename_in): # Init Funktion self.errorcode = 8 self.nummer = Aktor_1.aktorzahler self.debug = debug_in self.dosennummer = dosennummer # arbeite für diese Dose (1 bis n) self.Pins2 = [] self.config_file = config_filename_in # pfad main switcher GPIO.setmode(GPIO.BCM) rev = GPIO.RPI_REVISION GPIO.setwarnings(False) # juni2018 ist neu hier, war in gpio_setup() self.action_type = "4 LED" # welche art Schalten ist dies hier self.myprint( DEBUG_LEVEL2, progname + "aktor_init called für Dose {}".format(self.dosennummer)) Aktor_1.aktorzahler += 1 # erhögen aktorzähler # nun alle GPIO Pins aus dem Config File holen # es müssen 5 Pins definiert werden, da maximal 5 Dosen vorkommen können config = ConfigRead(self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_file, config_section, cfglist_akt) ## ret=config.config_read(self.path + "/swconfig.ini","aktor_1",cfglist_akt) if ret > 0: self.myprint(DEBUG_LEVEL0, progname + "config_read hat retcode: {}".format(ret)) self.errorcode = 99 return None # get values fro config file try: # GPIO Pin 1 holen self.Pins2.append(int(cfglist_akt["gpio_1"])) # GPIO Pin 2 holen self.Pins2.append(int(cfglist_akt["gpio_2"])) # GPIO Pin 3 holen self.Pins2.append(int(cfglist_akt["gpio_3"])) # GPIO Pin 4 holen self.Pins2.append(int(cfglist_akt["gpio_4"])) # GPIO Pin 5 holen self.Pins2.append(int(cfglist_akt["gpio_5"])) except KeyError: self.myprint(DEBUG_LEVEL0, progname + "KeyError in cfglist_akt, check values!") # nun wurde alle 5 Pins geholt, diese Instanz verwendet genau einen der Pins in der Liste Pins2 self.mypin = self.Pins2[self.nummer] # hole Pin NUmmer GPIO.setup(self.mypin, GPIO.OUT) # GPIO.output(self.mypin, True) self.myprint( DEBUG_LEVEL3, progname + "aktor_init dose:{}, using GPIO:{}".format( self.dosennummer, self.mypin)) self.errorcode = 0 # init aktor ok
def setup(): global mymqtt, myprint, mqtt_connect, swhome, swinterface, sequencer print(progname + "started: {}".format(time.strftime('%X'))) argu() # get commandline argumants path = os.path.dirname(os.path.realpath(__file__)) # current path print("Name logfile: {} ".format(path + "/" + logfile_name)) print("Name configfile: {} ".format(path + "/" + configfile_name)) #Use BCM GPIO refernece instead of Pin numbers GPIO.setmode(GPIO.BCM) rev = GPIO.RPI_REVISION # create Instance of MyPrint Class myprint = MyPrint(appname=progname, debug_level=debug, logfile=path + "/" + logfile_name) # Create Instance of the ConfigRead Class myconfig = ConfigRead(debug_level=debug) myprint.myprint(DEBUG_LEVEL2, "\nswt_seq:Configdictionary before reading:") if (debug > 1): for x in cfglist_swi: print("{} : {}".format(x, cfglist_swi[x])) # Read from Configfile ret = myconfig.config_read(path + "/" + configfile_name, config_section, cfglist_swi) # call method config_read() myprint.myprint(DEBUG_LEVEL1, "swt_seq:config_read() returnvalue: {}".format( ret)) # für log und debug myprint.myprint(DEBUG_LEVEL2, "\nswt_seq:Configdictionary after reading:") if (debug > 1): for x in cfglist_swi: print("{} : {}".format(x, cfglist_swi[x])) if ret > 0: sys.exit(2) # xxx anpassen !! swhome = SwHomeDummy(debug=debug) # instance of dummy class swhome time.sleep(0.5) # Create instance of the sequencer sequencer = MySequencer(debug_in=debug, path_in=path, conf=path + "/" + configfile_name, callback1=swhome) print("swt_seq: Object created:{}".format(sequencer)) time.sleep(3) return
def __init__(self, dosennummer,debug_in , config_filename_in): # Init Funktion self.errorcode = 8 # init wert beliebig aber not zero self.nummer = Aktor_5.aktorzahler self.debug=debug_in self.config_file = config_filename_in self.dosennummer=dosennummer # arbeite für diese Dose (1 bis n) self.code="" self.pfad="" self.commandline="" self.pin=0 GPIO.setmode (GPIO.BCM) rev=GPIO.RPI_REVISION GPIO.setwarnings(False) # juni2018 ist neu hier, war in gpio_setup() self.action_type="Funk bei Habi" # welche art Schalten ist dies hier self.myprint (DEBUG_LEVEL2, progname + "aktor_init called für Dose:{}".format (self.dosennummer)) Aktor_5.aktorzahler +=1 # erhögen aktorzähler # nun alle GPIO Pins aus dem Config File holen config=ConfigRead(self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_file, config_section, cfglist_akt) if ret > 0: self.myprint (DEBUG_LEVEL1, progname + "config_read hat retcode:{}".format (ret)) self.errorcode=99 return None # get values fro config file try: self.pin = int(cfglist_akt["gpio_send"]) self.code = cfglist_akt["system_code"] self.pfad = cfglist_akt["pfad_1"] except KeyError : self.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_akt, check values!") self.myprint (DEBUG_LEVEL2, progname + "aktor_init : dose:{}, using code:{} und pfad:{} und pin:{}".format (self.dosennummer, self.code, self.pfad,self.pin)) self.commandline = "sudo " + self.pfad + "/send" + " " + str(self.pin)+ " " + self.code + " " + str(self.dosennummer) + " " self.myprint (DEBUG_LEVEL3, progname + "aktor_init : dose:{}, using commandline:{}".format (self.dosennummer, self.commandline))
def __init__(self, dosennummer,debug_in , config_filename_in): # Init Funktion self.errorcode = 8 # init wert beliebig aber not zero self.nummer = Aktor_5.aktorzahler self.debug=debug_in self.config_file = config_filename_in self.dosennummer=dosennummer # arbeite für diese Dose (1 bis n) self.code="" self.pfad="" self.commandline="" self.pin=0 GPIO.setmode (GPIO.BCM) rev=GPIO.RPI_REVISION GPIO.setwarnings(False) # juni2018 ist neu hier, war in gpio_setup() self.action_type="Funk bei Habi" # welche art Schalten ist dies hier self.myprint (DEBUG_LEVEL2, "--> aktor_5 {} aktor_init called für Dose {}".format (self.nummer,self.dosennummer)) Aktor_5.aktorzahler +=1 # erhögen aktorzähler # nun alle GPIO Pins aus dem Config File holen config=ConfigRead(self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_file,"aktor_5",cfglist_akt) if ret > 0: self.myprint (DEBUG_LEVEL1, "config_read hat retcode: {}".format (ret)) self.errorcode=99 return None self.myprint (DEBUG_LEVEL3, "--> aktor_5 {} aktor_init : dose {} configfile read {}".format (self.nummer,self.dosennummer, cfglist_akt)) # Hole Parameter aus config y=cfglist_akt.index("gpio_send") + 1 # suche den Wert im Config-file self.pin = str(cfglist_akt[y]) y=cfglist_akt.index("system_code") + 1 # suche den Wert im Config-file self.code = cfglist_akt[y].decode() y=cfglist_akt.index("pfad_1") + 1 # suche den Wert im Config-file self.pfad = cfglist_akt[y].decode() self.myprint (DEBUG_LEVEL1, "--> aktor_5 {} aktor_init : dose {}, using code {} und pfad: {} und pin:{}".format (self.nummer,self.dosennummer, self.code, self.pfad,self.pin)) self.commandline = "sudo " + self.pfad + "/send" + " " + str(self.pin)+ " " + self.code + " " + str(self.dosennummer) + " " self.myprint (DEBUG_LEVEL1, "--> aktor_5 {} aktor_init : dose {}, using commandline: {}".format (self.nummer,self.dosennummer, self.commandline))
def setup_server(): global mqttc, myprint, mqtt_connect, path global reboot_verlangt, shutdown_verlangt, swconnector global host_name, host_ip, debug error_return = 0 # return code setup function argu() # get commandline argumants path = os.path.dirname(os.path.realpath(__file__)) # current path # pfad = os.path.dirname(os.path.realpath(__file__)) # pfad wo dieses script läuft # create Instance of MyPrint Class myprint = MyPrint(appname=progname, debug_level=debug, logfile=path + "/" + logfile_name) myprint.myprint( DEBUG_LEVEL0, progname + "started <---------------------: {}".format(time.strftime('%X'))) myprint.myprint( DEBUG_LEVEL0, progname + "Name logfile: {} ".format(path + "/" + logfile_name)) myprint.myprint( DEBUG_LEVEL0, progname + "Name configfile: {} ".format(path + "/" + configfile_name)) # Red Configfile -------------------- # Create Instance of the ConfigRead Class myconfig = ConfigRead(debug_level=debug) myprint.myprint(DEBUG_LEVEL3, progname + "Configdictionary before reading:") if (debug > 2): for x in cfglist_swi: print("{} : {}".format(x, cfglist_swi[x])) # Read from Configfile ret = myconfig.config_read(path + "/" + configfile_name, config_section, cfglist_swi) # call method config_read() myprint.myprint( DEBUG_LEVEL1, progname + "config_read() returnvalue: {}".format(ret)) # für log und debug myprint.myprint(DEBUG_LEVEL3, progname + "Configdictionary after reading:") if (debug > 2): for x in cfglist_swi: print("{} : {}".format(x, cfglist_swi[x])) if ret > 0: print("swserver3 terminate after configread") sys.exit(2) # xxx anpassen !! # wenn gpio blink angegeben ist (ungleich 0) starten wir den Blink Thread <<--- try: debug_konf = int(cfglist_swi["debug"]) # debug flag aus konfigfile except KeyError: myprint.myprint(DEBUG_LEVEL0, progname + "KeyError in cfglist_swi, check values!") if debug_konf > 0: myprint.myprint( DEBUG_LEVEL0, progname + "debug verlangt in configfile, wert:{}".format(debug_konf)) if debug == 0: debug = debug_konf myprint.set_debug_level(debug) # set level in the myPrint object # fertig lesen config file ---------------------- # get hostname und IP Adr host_name, host_ip = get_Host_name_IP() myprint.myprint( DEBUG_LEVEL0, progname + "hostname/IP/Version:{}/{}/{}".format( host_name, host_ip, server_version)) #------------------------------------ # create Instance of SwConnector Class swconnector = SwConnector(debug=debug, path=path, configfile=configfile_name, endpoint=2, mqtt_client=None, callback=notifyServer) time.sleep(1) myprint.myprint(DEBUG_LEVEL0, progname + "object created: {}".format(swconnector)) # check mqtt status error_return = check_mqtt() if error_return > 0: error_return = MQTT_ERROR else: # init for receiving of sync messages (only needed on client (SWSERVER) side) swconnector.request_response_init(MQTT_TOPIC_RESP) # init for receiving of sync messages (only needed on client side) swconnector.request_response_init(MQTT_TOPIC_RESP) # aufsetzen und starten des reboot threads reboot_thread = threading.Thread(target=reboot_function) reboot_thread.setDaemon( True) # damit thread beendet wird, wenn main thread endet reboot_thread.start() count_thread = threading.active_count() thread_list = threading.enumerate() myprint.myprint( DEBUG_LEVEL1, progname + "Anzahl Threads: {}, List: {}".format(count_thread, thread_list)) myprint.myprint(DEBUG_LEVEL0, progname + "--> gestartet") myprint.myprint(DEBUG_LEVEL0, progname + "setup Server done") return (error_return)
pfad = os.path.dirname(os.path.realpath(__file__)) # current path print ("Name logfile: {} ".format( pfad + "/" + logfile_name) ) print ("Name configfile: {} ".format( pfad + "/" + configfile_name) ) # create Instance of MyPrint Class myprint = MyPrint( appname = progname, debug_level = debug, logfile = pfad + "/" + logfile_name ) # Create Instance of the ConfigRead Class myconfig = ConfigRead(debug_level = debug) # übergebe appname und logfilename actionList = ActionList(debug,pfad) # Instanz der actionLister Class configfile=pfad + "/swconfig.ini" # ret=config.config_read(configfile,"watering",cfglist_swi) # we use the configfile given by switcher, could also use our own ret = myconfig.config_read (configfile ,"sequencer", cfglist_seq) # call method config_read() if ret > 0: print("swlist3: config_read hat retcode: {}".format (ret)) sys.exit(2) myprint.myprint (DEBUG_LEVEL2, "\nConfigdictionary after reading:") if (debug > 1):
def __init__(self, debug, path, client, ipadr, retry, conf): # class instance variables self.debug = debug self.myprint(DEBUG_LEVEL2, "--> MQTTConn init_ called, ipadr: {}".format(ipadr)) self.path = path # pfad where the script is running self.mqtt_client_id = client self.mqtt_broker_ip = ipadr # value from commandline (if present) self.mqttc = 0 # Instance of mqtt self.broker_ok = False self.retry = retry self.s = 0 self.connect_flag = False self.mqtt_error = 0 self.config_filename = conf # path and name of config file self.config_section = "mqtt" self._IP = "" # this machines ip adr self.ipadr_to_use = "" # ipad we are going to use self.printstring = "--> MQTT_Conn: " self.retry_counter = 1 # Config Directory containing important parameters # will be updated from the configfile # here are the defaultvalues in a python directory (key value pair) self.cfgdir_mqtt = { "mqtt_ipadr": "", "mqtt_port": "1883", "mqtt_keepalive_intervall": "45", "mqtt_userid": "myuserid", "mqtt_pw": "mypassword", "mqtt_qos": 0, "mqtt_retain": 0, "retry_intervall": 1, # seconds "retry_counter": 2, "userdata": "u-data", } # get get data from configfile if (self.debug > 2): print(self.printstring + "Parameters before read configfile:") for x, y in self.cfgdir_mqtt.items(): print(x, y) config = ConfigRead( debug_level=self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_filename, self.config_section, self.cfgdir_mqtt) # alese von abschnitt mqtt # ret = 0 if ret > 0: self.myprint( DEBUG_LEVEL3, self.printstring + "MQTT_Conn: config_read has retcode: {}".format(ret)) self.errorcode = 99 return None self.myprint( DEBUG_LEVEL3, self.printstring + "mqtt_conn_init_ called, client_id:{}".format(self.mqtt_client_id)) if (self.debug > 2): print(self.printstring + "Parameters after read configfile:") for x, y in self.cfgdir_mqtt.items(): print(x, y) # add random chars to client-id (in case user runs program twice) self.mqtt_client_id = self.mqtt_client_id.join( random.choice("ABCDEFG") for _ in range(2)) # Eventhandler #----Function Callback (msg gekommen )-------------------------------- def __my_on_message__(client, userdata, msg): self.myprint(DEBUG_LEVEL3, "--> MQTT_Conn: my_on_message() called ") # Eventhandler #----Function Callback (msg gekommen )-------------------------------- def __my_on_publish__(client, rc, mid): self.myprint(DEBUG_LEVEL3, self.printstring + "my_on_publish() called") # Eventhandler #------------ def __my_on_subscribe__(client, userdata, mid, qos): self.myprint( DEBUG_LEVEL3, self.printstring + "my_on_subscribe() called, userdata: {}".format(userdata)) # Eventhandler #------------ def __my_on_disconnect__(client, userdata, rc): if rc != 0: self.myprint( DEBUG_LEVEL0, self.printstring + "unexpected disconnection from broker") else: self.myprint( DEBUG_LEVEL0, self.printstring + "regular disconnection from broker") self.connect_flag = False # Eventhandler #------------ def __my_on_connect__(client, userdata, flags, rc): self.mqtt_error = 0 self.myprint( DEBUG_LEVEL3, self.printstring + "my_on_connect() called, rc: {}".format(rc)) if rc == 0: self.myprint( DEBUG_LEVEL3, self.printstring + "connection OK, rc: {}".format(rc)) self.connect_flag = True else: self.myprint( DEBUG_LEVEL0, self.printstring + "connection NOTOK, rc: {}".format(rc)) if (rc == 5): self.myprint( DEBUG_LEVEL0, self.printstring + "user_id/password pair not correct") self.connect_flag = False self.mqtt_error = rc #--------------- # get this machines IP address self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: # doesn't even have to be reachable self.s.connect(('10.255.255.255', 1)) self._IP = self.s.getsockname()[0] except: self._IP = '127.0.0.1' finally: self.s.close() # now determine which ip addr to use: the one from the commandline parm has precendence # if none is given on the commandline check if the one in parameters is > 0 # if this is present, take it, if not use the machines own ip adr self.ipadr_to_use = self.cfgdir_mqtt["mqtt_ipadr"] if (len(self.mqtt_broker_ip) > 0): # from cammandline self.ipadr_to_use = self.mqtt_broker_ip # use this if present else: self.ipadr_to_use = self._IP self.myprint( DEBUG_LEVEL2, self.printstring + "Use this IP-Adr.: {}".format(self.ipadr_to_use)) self.myprint (DEBUG_LEVEL2, self.printstring + "UserID: {} , Passwort: {} , QoS: {} , Retain: {}".format \ (self.cfgdir_mqtt["mqtt_userid"], self.cfgdir_mqtt["mqtt_pw"], self.cfgdir_mqtt["mqtt_qos"], self.cfgdir_mqtt["mqtt_retain"])) self.myprint( DEBUG_LEVEL2, self.printstring + "retry_intervall: {} retry_counter: {}".format( self.cfgdir_mqtt["retry_intervall"], self.cfgdir_mqtt["retry_counter"])) # finally, we come the actual MQTT stuff, we know the ip addr to use self.mqttc = mqtt.Client( self.mqtt_client_id, True, self.cfgdir_mqtt["userdata"]) # Initiate MQTT Client # Register Event Handlers self.mqttc.on_connect = __my_on_connect__ # setup on connect callback self.mqttc.on_subscribe = __my_on_subscribe__ # setup on subscribe callback self.mqttc.on_message = __my_on_message__ self.mqttc.on_disconnect = __my_on_disconnect__ self.mqttc.on_publish = __my_on_publish__ # set userid and password self.mqttc.username_pw_set(username=self.cfgdir_mqtt["mqtt_userid"], password=self.cfgdir_mqtt["mqtt_pw"]) # Connect with MQTT Broker self.__connect_broker__() pass
def __init__(self, debug_in, all_weeks): # Init Funktion self.myprint (DEBUG_LEVEL2, progname + "CalcAdust_init called") self.debug = debug_in self.weeks = all_weeks self.dayofyear = 0 self.weekyear = 0 self.adjust_time_min = 0 # in minutes self.today = 0 self.do_adjustTime = 0 # adjust times normal self.do_adjustDaylight_saving = 0 # adjust daylight saving time self.sommer_winter = "S" # Sommer oder Winter (daylight Saving) self.evening_start_limit = 0 self.morning_start_limit = 0 self.evening_ontime = 0 self.morning_ontime = 0 self.counter = 0 self.spring_datef = 0 self.fall_datef = 0 self.spring_day = 0 self.fall_day = 0 self.daylight_saving_minutes = 0 # anzahl minuten anpassung im Sommer (ZERO) self.faktor = 0 self.myconfig = ConfigRead(debug_level = self.debug) # Create Instance of the ConfigRead Class # we use the configfile given by switcher, could also use our own ret = self.myconfig.config_read (configfile_name ,config_section, cfglist_seq) # call method config_read() self.myprint (DEBUG_LEVEL1, progname + "config_read() returnvalue: {}".format (ret)) # für log und debug self.myprint (DEBUG_LEVEL3, progname + "Configdictionary after reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # print (self.evening_start_limit) # print (self.morning_start_limit ) try: self.do_adjustTime = int(cfglist_seq ["adjust_needed"]) self.do_adjustDaylight_saving = int(cfglist_seq ["daylight_saving"]) if self.do_adjustDaylight_saving == 0: self.sommer_winter = "n.a" hhmm_s = cfglist_seq ["evening_start_limit"].split(".") hhmm_e = cfglist_seq ["morning_start_limit"].split(".") self.evening_ontime = int(cfglist_seq ["evening_ontime"]) self.morning_ontime = int(cfglist_seq ["morning_ontime"]) self.faktor = int(cfglist_seq ["faktor"]) / 100 self.spring_datef = cfglist_seq ["spring_date"].split(".") self.fall_datef = cfglist_seq ["fall_date"].split(".") # print ("===========================================") # print (self.spring_datef[0] + "-" + self.spring_datef[1]) # print (self.fall_datef[0] + "-" + self.fall_datef[1]) except KeyError : myprint.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_seq, check values!") self.today = datetime.now() self.dayofyear = int(self.today.strftime("%j")) # tag des Jahres ermitteln # print (hhmm_s) # print (hhmm_e) self.evening_start_limit = (60 * int(hhmm_s[0])) + int(hhmm_s[1]) # minuten des Tages self.morning_start_limit = (60 * int(hhmm_e[0])) + int(hhmm_e[1]) # minuten des Tages self.myprint (DEBUG_LEVEL1, progname + "evstart:{} evon:{} mostart:{} moon:{} faktor:{}".format(self.evening_start_limit, \ self.evening_ontime, \ self.morning_start_limit, \ self.morning_ontime , \ self.faktor))
class CalcAdjust (MyPrint): ' klasse CalcAdjust ' def __init__(self, debug_in, all_weeks): # Init Funktion self.myprint (DEBUG_LEVEL2, progname + "CalcAdust_init called") self.debug = debug_in self.weeks = all_weeks self.dayofyear = 0 self.weekyear = 0 self.adjust_time_min = 0 # in minutes self.today = 0 self.do_adjustTime = 0 # adjust times normal self.do_adjustDaylight_saving = 0 # adjust daylight saving time self.sommer_winter = "S" # Sommer oder Winter (daylight Saving) self.evening_start_limit = 0 self.morning_start_limit = 0 self.evening_ontime = 0 self.morning_ontime = 0 self.counter = 0 self.spring_datef = 0 self.fall_datef = 0 self.spring_day = 0 self.fall_day = 0 self.daylight_saving_minutes = 0 # anzahl minuten anpassung im Sommer (ZERO) self.faktor = 0 self.myconfig = ConfigRead(debug_level = self.debug) # Create Instance of the ConfigRead Class # we use the configfile given by switcher, could also use our own ret = self.myconfig.config_read (configfile_name ,config_section, cfglist_seq) # call method config_read() self.myprint (DEBUG_LEVEL1, progname + "config_read() returnvalue: {}".format (ret)) # für log und debug self.myprint (DEBUG_LEVEL3, progname + "Configdictionary after reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # print (self.evening_start_limit) # print (self.morning_start_limit ) try: self.do_adjustTime = int(cfglist_seq ["adjust_needed"]) self.do_adjustDaylight_saving = int(cfglist_seq ["daylight_saving"]) if self.do_adjustDaylight_saving == 0: self.sommer_winter = "n.a" hhmm_s = cfglist_seq ["evening_start_limit"].split(".") hhmm_e = cfglist_seq ["morning_start_limit"].split(".") self.evening_ontime = int(cfglist_seq ["evening_ontime"]) self.morning_ontime = int(cfglist_seq ["morning_ontime"]) self.faktor = int(cfglist_seq ["faktor"]) / 100 self.spring_datef = cfglist_seq ["spring_date"].split(".") self.fall_datef = cfglist_seq ["fall_date"].split(".") # print ("===========================================") # print (self.spring_datef[0] + "-" + self.spring_datef[1]) # print (self.fall_datef[0] + "-" + self.fall_datef[1]) except KeyError : myprint.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_seq, check values!") self.today = datetime.now() self.dayofyear = int(self.today.strftime("%j")) # tag des Jahres ermitteln # print (hhmm_s) # print (hhmm_e) self.evening_start_limit = (60 * int(hhmm_s[0])) + int(hhmm_s[1]) # minuten des Tages self.morning_start_limit = (60 * int(hhmm_e[0])) + int(hhmm_e[1]) # minuten des Tages self.myprint (DEBUG_LEVEL1, progname + "evstart:{} evon:{} mostart:{} moon:{} faktor:{}".format(self.evening_start_limit, \ self.evening_ontime, \ self.morning_start_limit, \ self.morning_ontime , \ self.faktor)) #------------------------------------------- # __repr__ function MySequencer # def __repr__ (self): rep = "CalcAdjust, evstart:{} evon:{} mostart:{} moon:{}".format(self.evening_start_limit, \ self.evening_ontime, \ self.morning_start_limit, \ self.morning_ontime ) return (rep) # --------------------------------------------------------------------------------------- #--Private Funktion convert time given ist switchtime in minutes of the day # --------------------------------------------------------------------------------------- def _convTime(self, min_in): c = min_in % 60 # c reminder is minutes b = (min_in - c) // 60 # calc hour of the day f = str(c) e = str(b) if c < 10: f = "0" + str(c) if b < 10: e = "0" + str(b) return (e + "." + f) # format "hh.mm" #--------------------------------------------------------------------------------- # Privat function adjust_init: calculate minutes to adjust based on week of year # also berücksichtige SommerWinterzeit, wenn verlangt #--------------------------------------------------------------------------------- def adjust_init (self, weeks): self.myprint (DEBUG_LEVEL2, progname + "adjust_init called, weeks:{}".format(weeks)) if weeks == 0: week = int(self.today.strftime("%V")) # use %V with Python 3.6 !! # see https://bugs.python.org/issue12006 self.weekyear = week else: self.weekyear = weeks # ajustierung der Schaltzeiten verlangt ? if self.do_adjustTime == 1: # 1 = verlangt self.adjust_time_min = int(abs( 60 * ((self.weekyear - 27) * (self.faktor)) )) # number of minutes we need to adjust, based on week of the year else: self.adjust_time_min = 0 # nicht verlangt, also 0 minuten # nun noch Sommer-Winterzeit berücksichtigen, falls verlangt im Config File. # Alle Schaltzeiten sind im XML File für den Sommer # wenn verlangt, ist also im Winter 60 Minuten zur Adjust Zeit hinzufügen # zuerst feststellen, ob Sommer oder Winter, im Config file ist der Tag des Wechsels im Frühling und im Herbst definiert. # aktueller Monat und Tag des Monats month = int(self.today.strftime("%-m")) # use with Python 3.6 !! day_month = int(self.today.strftime("%-d")) year = int(self.today.strftime("%-Y")) spring = datetime(year, int(self.spring_datef[1]), int(self.spring_datef[0])) fall = datetime(year, int(self.fall_datef[1]), int(self.fall_datef[0])) self.spring_day = int(spring.strftime("%j")) self.fall_day = int(fall.strftime("%j") ) # Sind wir Sommer oder Winterzeit ? self.daylight_saving_minutes = 0 # in Sommer zusätzlich 0 min früher # berücksichtigen Sommer/Winterzeit verlangt ? if self.do_adjustDaylight_saving == 1: # 1 = verlangt self.myprint (DEBUG_LEVEL1, progname + "berechne Daylight-Saving") # entscheiden, ab das aktuelle Datum im Sommer oder Winterhabljahr liegt. self.sommer_winter = "S" # nehme default an Sommer self.myprint (DEBUG_LEVEL2, progname + "TagJahr:{}/FallDay:{}/SpringDay:{}".format (self.dayofyear,self.fall_day, self.spring_day )) # print (self.dayofyear, self.fall_day) # print (self.spring_datef, self.dayofyear) # im Winter schieben wir Zeit um nochmals + 60 Minuten if (self.dayofyear > self.fall_day) and (self.dayofyear < self.spring_day): # winterzeit self.daylight_saving_minutes = 60 # in Winterzeit zusätzlich 60 min früher self.sommer_winter = "W" self.myprint (DEBUG_LEVEL1, progname + "Winter is here, adjust additional minutes:{}".format(self.daylight_saving_minutes)) else: self.myprint (DEBUG_LEVEL1, progname + "Summer is here, kein zusätzlicher adjust") else: self.myprint (DEBUG_LEVEL1, progname + "Daylight Saving nicht verlangt") # evening and morning limits (hour/min and ontime) # only adjust actions that are outside this boundary before_midnight = 1439 # shortly before midnigt (minutes of day) self.myprint (DEBUG_LEVEL3, progname + "Week des Jahres:{} ,adjust minutes:{}".format(self.weekyear,self.adjust_time_min)) self.myprint (DEBUG_LEVEL3, progname + "Evening:{}/{},Morning: {}/{}".format( \ self.evening_start_limit, \ self.evening_ontime, \ self.morning_start_limit, \ self.morning_ontime)) return (self.sommer_winter, self.adjust_time_min + self.daylight_saving_minutes,self.faktor ) #-------------------------------------------- # Public Function calc_adjust #-------------------------------------------- def adjust_time (self, action, week): # wird aufgerufen, wenn Schaltzeiten zu modifizieren sind, dies kann sein: # # > Anpassung an veränderten Sonnenuntergang zwischen den Saisons (Schaltzeiten sind für den Sommer definiert und müssen nach # vorne angepasst werden, weil es im Herbst/Winter früher dunkel wird). Dies wird pro Woche des Jahres berechnet. # > Anpassung Sommer/Winterzeit (in der Winterzeit werden Schaltzeiten generell um 60 Min nach vorne verschoben.) # # > Die beiden Anpassungen können im Configfile unabhängig konfiguriert werden. Es um das Total der Ajustierungen ajustiert. # # Input ist eine Aktion, welche folgende Struktur hat: #---------------------------------------------------------- # Eine Aktion sieht so aus: # Element action = ("HH.MM", Zeit in Min, Dauer in Min, "HH.MM", Dose, ON/OFF) # elemente: # erstes "HH.MM" element ist ev. korrigierte Schaltezeit # selbe Schaltzeit aner in Minuten des Tages # Dauer eingeschaltet in Minuten # zweites "HH.MM" element ist originale Schaltzeit # Dosennummer # 1 = einschalten # 0 = ausschalten #------------------------------------------------------------- self.myprint (DEBUG_LEVEL2, progname + "adjust_time called, week:{}, action in:{}".format(week,action)) # dies ist nur für Ausgabe, nicht sehr wichtig hier if week > 0: # >0 means = only calculate minutes, do nothing more... self.adjust_init (week) self.myprint (DEBUG_LEVEL2, progname + "adjust_time min:{}".format(self.adjust_time_min + self.daylight_saving_minutes)) return (action, self.adjust_time_min + self.daylight_saving_minutes) # self.adjust_init (week) nicht mehr nötig, Nov 21 # nun art der ajustierung ermitteln: changed = False evening_valid = False morning_valid = False # is action am Abend und zwischen 18'00 Uhr und dem Abend-Grenzwert (evening_start_limit) ? # und ist ontime länger als evening_ontime ? if (action[1] < self.evening_start_limit) and (action[1] > 1080) and (action[2] > self.evening_ontime): evening_valid = True # yes must be adjusted self.myprint (DEBUG_LEVEL3, "\t" + progname + "is valid evening action") # is action am Morgen und zwischen dem Morgen-Grenzwert und 6 Uhr Morgens ? # # und ist ontime länger als morning_ontime ? if (action[1] > self.morning_start_limit) and (action[1] < 360) and (action[2] > self.morning_ontime): morning_valid = True # yes must be adjusted self.myprint (DEBUG_LEVEL3, "\t" + progname + "is valid morning action") if evening_valid: action[1] = action[1] - self.adjust_time_min - self.daylight_saving_minutes # adjust switch on time (minutes) action [0] = self._convTime(action[1]) # adjust switch on time (hh.mm) changed = True self.myprint (DEBUG_LEVEL3, "\t" + progname + "new evening action:{}".format (action)) if morning_valid: action[1] = action[1] + self.adjust_time_min + self.daylight_saving_minutes # adjust switch on time (minutes) action [0] = self._convTime(action[1]) # adjust switch on time (hh.mm) changed = True self.myprint (DEBUG_LEVEL3, "\t" + progname + "new morning action:{}".format (action)) if changed: self.counter = self.counter + 1 # self.myprint (DEBUG_LEVEL1, progname + "modified action: {}".format (action)) pass # -- process the action given as parameter self.myprint (DEBUG_LEVEL2, progname + "adjust_time: new Action2:{}".format(action)) # gebe angepasste Aktionsstruktur zurück return (action, self.adjust_time_min + self.daylight_saving_minutes)
def _do_setup(self): self.myprint (DEBUG_LEVEL1, "\t" + progname + "setup MySequencer") try: locale.setlocale(locale.LC_TIME , 'de_CH.utf8') except: self.myprint (DEBUG_LEVEL0, "\t" + progname + "setzen Locale geht nicht, prüfe mit Befehl locale -a ") self.myconfig = ConfigRead(debug_level = self.debug) # Create Instance of the ConfigRead Class self.myprint (DEBUG_LEVEL3, "\nseq:Configdictionary before reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # we use the configfile given by switcher, could also use our own # all keys found in cfglist_seq are read from the config file <------------- ret = self.myconfig.config_read (self.configfile ,config_section, cfglist_seq) # call method config_read() self.myprint (DEBUG_LEVEL1, "config_read() returnvalue: {}".format (ret)) # für log und debug self.myprint (DEBUG_LEVEL3, "\nseq:Configdictionary after reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # aus den eingelesenen Werten werden hier nur 2 verwendet: # ist time adjust verlangt # ist Berücksichtigung Sommer/Winterzeit verlangt try: # input comes from configfile self.do_adjustTime = int(cfglist_seq ["adjust_needed"]) self.do_adjustDaylight_saving = int(cfglist_seq ["daylight_saving"]) except KeyError : self.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_seq, check values!") # print to log was verlangt ist if self.do_adjustTime > 0: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Schaltzeiten verlangt") else: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Schaltzeiten NICHT verlangt") if self.do_adjustDaylight_saving > 0: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Daylight-Saving verlangt") else: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Daylight-Saving NICHT verlangt") # create instance of Class ActionList self.actionList=ActionList(self.debug, self.path) # Instanz der actionLister Class # self.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(self.actionList)) # # Einlesen und Parsen der Steuer-Files alles neu juni2018 ret, self.file_id = self.actionList.get_actionList (self.list_tage, self.list_device, self.list_zimmer, cfglist_seq) # # nun sind alle Aktionen aus den XML-Files eingelesen und versorgt in den Listen list_tage, list_device und zimmer # #print what we got back from actionList Class if (self.debug > 2): print ("\nsequencer.py: got these lists from class actionList: <------------") # print all days and actions print ("Anzahl Tage gefunden: {}".format(len(self.list_tage))) for v , tag in enumerate(self.list_tage): print ("Tag: {}".format(v)) for action in tag: print ("action:{}".format(action)) # print all devices and all days and all actions # print ("\nAnzahl Dosen gefunden: {}".format(self.anz_dosen_xml)) for i, dose in enumerate (self.list_device): print ("Device: {}".format(i)) for y, tag in enumerate (self.list_device[i]): print ("Tag: {}".format(y)) for action in tag: print ("action:{}".format(action)) # print alle gefundenen Zimmer # print (" ") # print (self.list_zimmer) # print (" ") self.anz_dosen_xml = self.actionList.show_anzdevices() swdosconf = SWDos_conf (debug = self.debug, path = self.path) # instanz der Klasse erstellen self.myprint (DEBUG_LEVEL0 ,"\t" + progname + "object created: {}".format(swdosconf)) self.anz_dosen_config = swdosconf.read_dosenconfig() self.myprint (DEBUG_LEVEL1, "\t" + progname + "Setup, Anz. Dosen in swdosen.ini:{}".format( self.anz_dosen_config)) #Anzahl Dosen feststellen: loop über alle Saisons, alle Tage und schauen, wo maximum ist # anzahl Dosen in XML File kann verschieden sein von Anzahl in swdosen.ini self.myprint (DEBUG_LEVEL2, "\t" + progname + "Setup, Anz. Dosen (XML)/swdosen.ini:{}/{}".format (self.anz_dosen_xml,self.anz_dosen_config )) # check anzahl dosen if self.anz_dosen_xml >= self.anz_dosen_config: self.myprint (DEBUG_LEVEL0, "\t" + progname + "Nehme Anzahl Dosen aus swconfig.ini, Anzahl:{}".format(self.anz_dosen_config )) else: self.myprint (DEBUG_LEVEL0, "\t" + progname + "Achtung: in XML File sind weniger Dosen definiert als in swdosen.ini !") self.myprint (DEBUG_LEVEL0, "\t" + progname + "Nehme Anzahl Dosen aus xml File, Anzahl:{}".format(self.anz_dosen_xml)) self.anz_dosen_config = self.anz_dosen_xml # print ("Ausgabe") for y in range (len(self.list_device)): for i in range (len(self.list_device[0])): anz= (len(self.list_device[0][i])) if (anz > self.anz_devices): self.anz_devices=anz self.anz_devices -= 1 # liste hat 5 elemente , es gibt aber -1 dosen self.myprint (DEBUG_LEVEL2, "\t" + progname + "es wurden maximal {} Devices gefunden".format( self.anz_devices)) # for s in self.list_zimmer: # longest zimmer string feststellen if len(s) > self.maxchar_zimmer: self.maxchar_zimmer = len(s) # self.callback (UPDATE_EVENT, ....) # notify Update zimmer self.callback.handle_sequencer_event ( [ UPDATE_EVENT, self.list_zimmer, NOTUSED, NOTUSED, NOTUSED, NOTUSED, "00.00", ] ) # <<<<----Time of day event midnight reached uni2018 # self._ausgabe_liste() # lokale Funktion, keine Parameter if ret > 0 : sys.exit(2) ## xxx anpassen !!
def setup_server(): global mypri, ipc_data, pfad error = 0 reboot_verlangt = False # reboot noch nicht verlangt signal.signal(signal.SIGTERM, sigterm_handler) # setup Signal Handler for Term Signal pfad = os.path.dirname( os.path.realpath(__file__)) # pfad wo dieses script läuft # create Instance of MyPrint Class mypri = MyPrint(appname=progname, debug_level=debug, logfile=pfad + "/" + logfile_name) config_instance = ConfigRead( debug_level=debug) # instanz der ConfigRead Class config_filename = pfad + "/" + configfile_name ret = config_instance.config_read(config_filename, "switcher", cfglist_swi) # alese von abschnitt mqtt if ret > 0: mypri.myprint(DEBUG_LEVEL0, "config_read hat retcode: {}".format(ret)) error = 8 if version_info[0] < 3: mypri.myprint( DEBUG_LEVEL0, "swserver2.py läuft nur richtig unter Python 3.x, du verwendest Python {}" .format(version_info[0])) error = 9 if simulate_switcher_error > 0: mypri.myprint( DEBUG_LEVEL1, "swserver2.py simuliert verhalten des switchers, wert: {}".format( simulate_switcher_error)) try: ipc_data = values["ipc_endpoint_s"] except: ipc_data = "tcp://localhost:5555" # aufsetzen und starten des reboot threads reboot_thread = threading.Thread(target=reboot_function) reboot_thread.setDaemon( True) # damit thread beendet wird, wenn main thread endet reboot_thread.start() count_thread = threading.active_count() thread_list = threading.enumerate() mypri.myprint( DEBUG_LEVEL1, "Anzahl Threads: {}, List: {}".format(count_thread, thread_list)) mypri.myprint( DEBUG_LEVEL0, "--> swserver2.py gestartet, ipc_endpoint:{}".format(ipc_data)) mypri.myprint(DEBUG_LEVEL1, "swserver2.py setup Server done") return (error)
def __init__(self, dosennummer,debug_in, config_filename_in): # Init Funktion self.errorcode = 8 self.nummer = Aktor_2.aktorzahler self.debug = debug_in self.dosennummer = dosennummer # arbeite für diese Dose (1 bis n) self.config_file = config_filename_in # pfad main switcher self.action_type = "Funk2" # welche art Schalten ist dies hier self.myprint (DEBUG_LEVEL1, "--> aktor {} aktor_init called fuer Dose {}".format (self.nummer,self.dosennummer)) Aktor_2.aktorzahler += 1 # erhögen aktorzähler # nun alle notwendigen Parameter aus dem Config File holen config = ConfigRead(self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_file,"aktor_2",cfglist_akt) if ret > 0: self.myprint (DEBUG_LEVEL0, "config_read hat retcode: {}".format (ret)) self.errorcode=99 return None self.myprint (DEBUG_LEVEL3, "--> aktor_2 {} aktor_init : dose {} configfile read {}".format (self.nummer,self.dosennummer, cfglist_akt)) # zuerst den GPIO Pin für den 433 MHz Sender y = cfglist_akt.index("gpio_1") + 1 # suche den Wert im Config-file self.mypin = int(cfglist_akt[y]) # repeat für den 433 MHz Sender y = cfglist_akt.index("repeat") + 1 # suche den Wert im Config-file self.repeat = int(cfglist_akt[y]) # codelengt für den 433 MHz Sender y = cfglist_akt.index("codelength") + 1 # suche den Wert im Config-file self.codel = int(cfglist_akt[y]) self.myprint (DEBUG_LEVEL1, "--> aktor_2 init: Dose: {}, repeat: {} , codel:{}".format(self.dosennummer, self.repeat,self.codel)) # nun die Switch Codes und die Pulse Lenghts # zuerst die Parameter für das Einschalten such_base = "send_dat_" + str(self.dosennummer) such_ein = such_base+ "_ein" y = cfglist_akt.index(such_ein) + 1 # suche den Wert im Config-file self.data = cfglist_akt[y] self.data = self.data.decode() self.data = str(self.data) self.swcode_ein,self.pulselength_ein,self.protocoll_ein = self.data.split(",") self.myprint (DEBUG_LEVEL1, "--> aktor_2 init: Dose: {}, code: {} , length: {} , protocoll:{}".format(self.dosennummer, self.swcode_ein,self.pulselength_ein,self.protocoll_ein)) # For Testing # print (type(self.swcode_ein), self.swcode_ein) # self.swcode_ein=self.swcode_ein.decode() # print (type(self.swcode_ein), self.swcode_ein) self.swcode_ein = int(self.swcode_ein) self.pulselength_ein = int(self.pulselength_ein) self.protocoll_ein = int(self.protocoll_ein) # dann die Parameter für das Ausschalten such_aus = such_base+ "_aus" y=cfglist_akt.index(such_aus) + 1 # suche den Wert im Config-file self.data = cfglist_akt[y] self.data= self.data.decode() self.data= str(self.data) self.swcode_aus,self.pulselength_aus,self.protocoll_aus=self.data.split(",") self.myprint (DEBUG_LEVEL1, "--> aktor_2 init: Dose: {}, code: {} , length: {} , protocoll:{}".format(self.dosennummer, self.swcode_aus,self.pulselength_aus,self.protocoll_aus)) self.swcode_aus = int(self.swcode_aus) self.pulselength_aus = int(self.pulselength_aus) self.protocoll_aus = int(self.protocoll_aus) # verwende rfdevice von hier https://github.com/milaq/rpi-rf self.rfdevice = RFDevice(self.mypin,self.myprint) self.rfdevice.enable_tx() self.rfdevice.tx_repeat = self.repeat self.errorcode = 0 # aktor init ok
def setup(): global mymqtt, myprint, mqtt_connect, swhome, swinterface, sequencer, swconnector,my_wetter global start_switcher , setup_fortschritt, gpio_blink, wetter, testmode, host_name, host_ip, debug debug_konf = 0 # debug aus swconfig.ini 0() oder 1) print(progname + "started: {}".format(time.strftime('%X'))) argu() # get commandline argumants path = os.path.dirname(os.path.realpath(__file__)) # current path print ("Name logfile: {} ".format( path + "/" + logfile_name) ) print ("Name configfile: {} ".format( path + "/" + configfile_name) ) signal.signal(signal.SIGTERM, sigterm_handler) # setup Signal Handler for Term Signal signal.signal(signal.SIGHUP, sigterm_handler) # setup Signal Handler for Term Signal host_name, host_ip = get_Host_name_IP() start_switcher = date.today() setup_fortschritt = 0 #Use BCM GPIO refernece instead of Pin numbers GPIO.setmode (GPIO.BCM) rev = GPIO.RPI_REVISION GPIO.setwarnings(False) # juni2018 ist neu hier, war in gpio_setup() # create Instance of MyPrint Class myprint = MyPrint( appname = progname, debug_level = debug, logfile = path + "/" + logfile_name ) myprint.myprint (DEBUG_LEVEL0, progname + "started <-------------: {}".format(time.strftime('%X'))) myprint.myprint (DEBUG_LEVEL0, progname + "Name logfile: {} ".format( path + "/" + logfile_name) ) myprint.myprint (DEBUG_LEVEL0, progname + "Name configfile: {} ".format( path + "/" + configfile_name) ) # Create Instance of the ConfigRead Class myconfig = ConfigRead(debug_level = debug) myprint.myprint (DEBUG_LEVEL3, progname + "\nswi Configdictionary before reading:") if (debug > 2): for x in cfglist_swi: print ("{} : {}".format (x, cfglist_swi[x])) # Read from Configfile ret = myconfig.config_read (path+"/" + configfile_name ,config_section, cfglist_swi) # call method config_read() myprint.myprint (DEBUG_LEVEL1, progname + "swi:config_read() returnvalue: {}".format (ret)) # für log und debug myprint.myprint (DEBUG_LEVEL3, progname + "\nswi:Configdictionary after reading:") if (debug > 2): for x in cfglist_swi: print ("{} : {}".format (x, cfglist_swi[x])) if ret > 0 : print ("switcher3 terminate after configread") sys.exit(2) # xxx anpassen !! # wenn gpio blink angegeben ist (ungleich 0) starten wir den Blink Thread <<--- try: gpio_blink = int(cfglist_swi["gpio_blink"]) wetter = cfglist_swi["wetter"] testmode = cfglist_swi["testmode"] debug_konf = int(cfglist_swi["debug"]) # debug flag aus konfigfile except KeyError : myprint.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_swi, check values!") if debug_konf > 0: myprint.myprint (DEBUG_LEVEL0, progname + "debug verlangt in configfile, wert:{}".format(debug_konf)) if debug == 0: # debug von Commendline param debug = debug_konf myprint.set_debug_level(debug) # set level in the myPrint object # nicht schön, aber wir brauchens... testmodebol = False if testmode == "Ja": testmodebol = True myprint.myprint (DEBUG_LEVEL0, progname + "Testmode=Ja definiert in configfile !") # create instance of myBlink Class if pin is defined if (gpio_blink > 0): GPIO.setup(gpio_blink, GPIO.OUT) # set GPIO Pin as output my_blink = myBlink(gpio_blink) # create object my_blink.setDaemon (True) # set to daemon, does not block termination my_blink.start () # start the thread, start blinking #----------------------------------- # create Instance of MQTT-Conn Class mymqtt = MQTT_Conn ( debug = debug, path = path, client = progname, ipadr = mqtt_broker_ip_cmdline, retry = retry, conf = path + "/" + configfile_name) # creat instance, of Class MQTT_Conn #------------------------------------ # create Instance of SwConnector Class swconnector = SwConnector ( debug = debug, path = path, configfile = configfile_name, endpoint = 1, mqtt_client = mymqtt, callback = notifySwitcher) time.sleep(1) myprint.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(swconnector)) # Check connection status mqtt mqtt_connect, mqtt_error = swconnector.mqtt_status() # returns mqtt_error = 128 if not connected to broker if mqtt_connect == True: myprint.myprint (DEBUG_LEVEL1, progname + "connected to mqtt broker") # subscribe to MQTT topics # do_subscribe() # doing subscribe else: # we are quitting if no connection # you could also try again later... return (MQTT_ERROR) # wetter objekt erstellen,falls verlangt im config file if wetter == "Ja": # wetter ist verlangt, also kreiere instanz der Wetter Klasse myprint.myprint (DEBUG_LEVEL0 ,progname + "Wetter verlangt, also create wetter-object") my_wetter = Wetter (debug, path, mymqtt) # suscriptions werden in der Klasse wetter gemacht # myprint.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(my_wetter)) #-------------------------------------- # create Instance of SwHome Class swhome = SwHome ( debug = debug, path = path, conf = path + "/" + configfile_name, # creat instance, of Class MQTT_Conn test = testmodebol, mqtt_client = mymqtt, connector = swconnector ) time.sleep(0.5) #-------------------------------------- # Create an instance of the sequencer sequencer = MySequencer( debug_in = debug, path_in = path, conf = path + "/" + configfile_name, # callback1 = handle_sequencer) callback1 = swhome) myprint.myprint (DEBUG_LEVEL1, progname + "setup done, wait 1 sec.") myprint.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(sequencer)) myprint.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(swhome)) myprint.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(mymqtt)) time.sleep(1) return(0)
def __init__(self, dose,testmode_in,debug_in, config_filename_in, mqtt_status_in, mqttc_in, callback_function): # Init Methode der Dose, setzt Instanz Variablen self.errorcode = 8 # initwert, damit beim Del des Aktors richtig gehandelt wird self.nummer = Dose.dosenzahler self.status_intern = 0 # interner Status der Dose, gemäss programmierten Aktionen self.status_extern = 0 # externer Status der Dosen (für Status-Anzeige) # die folgenden drei variablen beeinflussen die Art und weise des schaltens der Dose self.schaltart = 0 # technische schaltart, bestimmt den Aktor, der benutzt werden muss self.schaltmodus = 0 # 0=auto, 1=manuell self.schaltprio = 0 # 1: normal, 2: dose schalten ohne berücksichtigung zuhause/nicht zuhause self.zuhause = False # False=abwesend, True=zuhause self.debug = debug_in self.zimmer_name = "" Dose.dosenzahler += 1 # erhögen dosenzahler self.status_extern = 0 self.configfile = config_filename_in self.dosen_nummer = Dose.dosenzahler self.myprint (DEBUG_LEVEL2 ,progname + "dose{} dosen_init called, debug:{} testmode:{}".format (self.dosen_nummer,debug_in,testmode_in)) self.testmode = testmode_in self.mqttc = mqttc_in # instanz mqtt client self.callback = callback_function self.mqtt_connect = mqtt_status_in self.msg_variante = 1 # default wert Test Pyload self.subscribe = 0 self.time_last_aktion = datetime.now() # zeit merken self.e = [] self.debug_level2_mod = DEBUG_LEVEL2 self.tmp = 0 self.schalt = "" # hilfsfeld self.schalton = 0 # anzahl schaltvorgänge ON self.schaltoff = 0 # anzahl schaltvorgänge OFF self.serr = 0 # schalterror # nun schaltart für die Dosen aus config holen self.myprint (DEBUG_LEVEL2 ,progname + "dose:{} init called, configfile: {}". format(dose, self.configfile)) config = ConfigRead(debug_level = debug_in) # instanz der ConfigRead Class ret=config.config_read(self.configfile,config_section,cfglist_dos) if ret > 0: self.myprint (DEBUG_LEVEL2 ,progname + "dosen init: config_read hat retcode:{}".format (ret)) self.errorcode=99 return None tmp = 0 try: # input comes from configfile self.schalt = "dose_" + str(self.dosen_nummer) + "_schaltart" self.schalt = cfglist_dos[self.schalt] # suche den Wert von schaltart aus Config-file self.tmp = "dose_" + str(self.dosen_nummer) + "_schaltprio" self.schaltprio = int(cfglist_dos[self.tmp]) # suche den Wert von modus aus Config-file tmp = int(cfglist_dos["debug_schalt"]) # suche den Wert von debug_schalt aus Config-file except KeyError : self.myprint (DEBUG_LEVEL1 ,progname + "dosen init: KeyError in cfglist_dos, check values!") self.schalt = "1,1,1" # default value in case of error self.schaltprio = 1 # default value if tmp > 0: self.debug_level2_mod = DEBUG_LEVEL0 self.myprint (DEBUG_LEVEL0 ,progname + "dose{} alle schaltaktionen werden logged (in configfile)".format(self.dosen_nummer)) if self.schaltprio == 2 : self.myprint (DEBUG_LEVEL1 ,progname + "dose{} hat modus_1 = 2".format(self.dosen_nummer)) # schaltart auswerten.... if len(self.schalt) == 0: self.myprint (DEBUG_LEVEL1 ,progname + "dose{} Schaltart ungueltig, nehme default 1".format(self.dosen_nummer)) self.schalt = "1,1,1" if len(self.schalt) == 1: self.schaltart = int(self.schalt) if len(self.schalt) > 1: self.e=self.schalt.split(",") if len(self.e) > 1: self.schaltart = int(self.e[0]) self.msg_variante = int(self.e[1]) if len(self.e) > 2: self.subscribe = int(self.e[2]) if self.schaltart == 3: self.myprint (DEBUG_LEVEL1 ,progname +"dose{} Schaltart:{}, MQTT_status:{}, msg_var:{}, subscribe:{}".format(self.dosen_nummer,self.schaltart, self.mqtt_connect, self.msg_variante, self.subscribe)) else: self.myprint (DEBUG_LEVEL1 ,progname + "dose{} Schaltart: {}".format(self.dosen_nummer,self.schaltart)) if self.testmode: self.myprint (DEBUG_LEVEL1 ,progname + "dose{} nehme Schaltart 1, Testmode ist Ja !".format(self.dosen_nummer)) self.schaltart = 1 # schaltart 3 benötigt mqtt und das muss zu diesem Zeitpunkt ok und connected sein, # falls nicht, nehmen wir schaltart 1 (led) if self.schaltart == 3 and self.mqtt_connect == False: self.myprint (DEBUG_LEVEL0 ,progname + "dose{} nehme Schaltart 1 da MQTT nicht definiert oder fehlerhaft ist !".format(self.dosen_nummer)) self.schaltart = 1 # plausicheck if self.dosen_nummer > 4 : if self.schaltart == 1 or self.schaltart == 3: # dosennummer 5 und ev. 6 dürfen nicht schaltart 2 haben (Funksteckdosen) pass else: self.myprint (DEBUG_LEVEL0 ,progname + "dose{} darf nur Schaltart 3 oder 1 haben, nehme 1".format(self.dosen_nummer)) self.schaltart = 1; if self.schaltart == 1: import sub.swc_aktor_1 # import actor 1 class self.myaktor=sub.swc_aktor_1.Aktor_1(self.dosen_nummer,self.debug,self.configfile) # Instanz der Aktor Class erstellenb elif self.schaltart == 2: import sub.swc_aktor_2 # import actor 2 class self.myaktor=sub.swc_aktor_2.Aktor_2(self.dosen_nummer,self.debug,self.configfile) # Instanz der Aktor Class erstellenb elif self.schaltart == 3: import sub.swc_aktor_3 # import actor 3 class self.myaktor=sub.swc_aktor_3.Aktor_3(self.dosen_nummer,self.debug,self.msg_variante,self.subscribe,self.configfile, self.mqttc, self.aktor_callback) # Instanz der Aktor Class erstellenb elif self.schaltart == 4: import sub.swc_aktor_4 # import actor 4 class self.myaktor=sub.swc_aktor_4.Aktor_4(self.dosen_nummer,self.debug,self.configfile) # Instanz der Aktor Class erstellenb elif self.schaltart == 5: import sub.swc_aktor_5 # import actor 5 class self.myaktor=sub.swc_aktor_5.Aktor_5(self.dosen_nummer,self.debug,self.configfile) # Instanz der Aktor Class erstellenb else: self.myprint (DEBUG_LEVEL2 ,progname + "dose{} falsche Schaltart {}".format (self.dosen_nummer,self.schaltart)) self.myprint (DEBUG_LEVEL2 ,progname + "dose{} Nehme Default-Schaltart 1".format (self.dosen_nummer)) import sub.swc_aktor_1 self.myaktor=swc_aktor_1.Aktor_1(self.dosen_nummer,self.debug) # Instanz der Aktor Class erstellenb if self.myaktor.errorcode == 99: self.myprint (DEBUG_LEVEL2 ,progname + "Aktor:{} meldet Fehler {}".format (self.dosen_nummer, self.myaktor.errorcode)) raise RuntimeError('---> Switcher ernsthafter Fehler, check switcher3.log <----') self.time_last_aktion = datetime.now() # zeit merken self.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(self.myaktor)) self.myprint (DEBUG_LEVEL2 ,progname + "dose{} ausschalten (init dose), schaltart:{}".format (self.dosen_nummer, self.schaltart)) self.myaktor.schalten(0, self.debug_level2_mod) self.errorcode = 0 # init der Dose ok
print( "swlist.py läuft nur richtig unter Python 3.x, du verwendest Python {}" .format(version_info[0])) sys.exit(2) options = argu() # Etablieren des Pfads pfad = os.path.dirname( os.path.realpath(__file__)) # pfad wo dieses script läuft logfile_name = pfad + logfile_name # create Instance of MyPrint Class mypri = MyPrint(appname=progname, debug_level=debug, logfile=logfile_name) config_instance = ConfigRead( debug_level=debug ) # instanz der ConfigRead Class # übergebe appname und logfilename actionpars = ActionParser(debug, pfad) # Instanz der ActionParser Class configfile_name = pfad + "/" + configfile_name ret = config_instance.config_read(configfile_name, "switcher", cfglist_swi) # alese von abschnitt if ret > 0: print("config_read hat retcode: {}".format(ret)) sys.exit(2) # fertig behandlung confifile # Einlesen und Parsen der Steuer-Files für alle Seasons alles neu juni2018 ret = actionpars.get_files(list_tage, list_dose, list_zimmer, cfglist_swi) # # nun sind alle Aktionen aus den XML-Files eingelesen und versorgt in den Listen list_tage, list_dosen und zimmer
if __name__ == '__main__': # options = argu() # get commandline args # Etablieren des Pfads path = os.path.dirname( os.path.realpath(__file__)) # pfad wo dieses script läuft # create Instance of MyPrint Class mypri = MyPrint(appname=progname, debug_level=debug, logfile=path + "/" + logfile_name) # Create Instance of the ConfigRead Class myconfig = ConfigRead(debug_level=debug) # Read from Configfile ret = myconfig.config_read(path + "/" + configfile_name, config_section, cfglist_swi) # call method config_read() mypri.myprint( DEBUG_LEVEL1, "config_read() returnvalue: {}".format(ret)) # für log und debug mypri.myprint(DEBUG_LEVEL2, "\nConfigdictionary after reading:") if (debug > 1): for x in cfglist_swi: print("{} : {}".format(x, cfglist_swi[x])) # suche selbst nach werten, gibt aber exception, wenn nicht gefunden
class MySequencer(threading.Thread, MyPrint): """Sequencer Class: knows about the switch_actions for the day, keeps track of time and issues events of different kinds""" def __init__(self, debug_in, path_in, conf, callback1 ) : """Initialize the 'thing'.""" super().__init__() self.debug = debug_in self.path = path_in # path switcher main self.callback = callback1 self.configfile = conf # full pfad switcher config file self.myprint (DEBUG_LEVEL1, "\t" + progname + "_init called") self.myconfig = None self.anz_devices=0 self.start_time = datetime.now() # setze start zeit # --------- 3 Lists are built bei the parser, see above for description self.list_tage = [ [] for z in range (7)] # list has 7 members: one for every day of the week self.list_device= [ [] for z in range (7)] # list has 7 members: one for every day of the week self.list_zimmer =[] # list of all rooms self.list_tage_new = None self.list_device_new = None # ------------------------ self.list_aktionen_past =[] self.list_aktionen_zukunft =[] self.total_aktionen_protag = [] self.status_currtime="" # fuer Statusanzeige self.do_adjustTime = 0 # 1: adjust times, 0: nichts ajustieren self.do_adjustDaylight_saving = 0 # 1 : adjust daylight saving time, 0: nichts machen self.term_verlangt = 0 self.daylight_saving_season = "" # S oder W (Sommer /Winter) self.maxchar_zimmer = 0 self.adjust_time = 0 self.anz_dosen_config = 0 self.anz_dosen_xml = 0 self.file_id = "" self.start_tag = 0 # mit diesem Wochentag starten wir (wird später auf aktuelen Tag gesetzt nach Start) self.weekyear = "" self.wochentag = 0 self.current_action = 0 # variables for status self.status_anzactions_done=0 # fuer Statusanzeige Anzahl Actions durchgefuehrt seit Start self.status_nextaction=[99,""] # fuer Statusanzeige was wird als naechstes geschaltet, dosennummer und string # 99 ist init self.status_lastaction=[99,"none"] # fuer Statusanzeige was wurde zuletzt geschaltet, dosennummer und string # 99 ist init self.status_waitfor="" # fuer Statusanzeige Zeit der noechsten, in der Zukunft liegenden Aktion self._do_setup() # do setup sequencer self.actioncalc = CalcAdjust(self.debug, 0 ) # instanz von CalcAdjust erstellen self.myprint (DEBUG_LEVEL0 ,"\t" + progname + "object created: {}".format(self.actioncalc)) time.sleep(.1) # initial wait self.myprint (DEBUG_LEVEL1, "\t" + progname + "_init done") #------------------------------------------- # __repr__ function MySequencer # def __repr__ (self): rep = "MySequencer ( )" return (rep) # --- Funktion zum Erstellen von zwei Listen ---------------- # a: Liste aller vergangenen Aktionen eines bestimmten Tages # b: Liste aller zukünfigen Aktionen eines bestimmten Tages # basierend auf aktueller Zeit # nur dosen nehmen, die kleiner/gleic max_dose sind # --------------------------------------------------------------------------------------- def _aktionen_pro_tag (self, liste, weekday, max_dose): self.myprint (DEBUG_LEVEL2, "\t" + progname + "aktionen_pro_tag() called, wochentag: {}".format(self.wochentag)) self.myprint (DEBUG_LEVEL2, "\t" + progname + "sammle alle aktionen pro Tag fuer Dosen kleiner/gleich: {}".format(max_dose)) hhmm_tag = [datetime.now().strftime("%H.%M"),datetime.today().strftime("%w")] # aktuelle Zeit holen # --> wir nehmen nur jenen Aktionen, die für die definierte Anzahl Dosen gelten # print (hhmm_tag) new_list_vergangen = [] new_list_zukunft =[] # print (liste) for n in liste[weekday]: # loop über alle Aktionen dieses Tages self.myprint (DEBUG_LEVEL3, "\t" + progname + "extrakt aktion: {}".format(n)) # ist aktio if (n[4] <= max_dose): # nehme nur jene die kleiner/glich sind if hhmm_tag[0] > n[0]: # hhmm_tag[0] sind Stunden.Minuten, check Actions times to current time new_list_vergangen.append(n) # addiere zur Liste vergangene Aktionen ## print ("vergangen: {}".format(n)) else: new_list_zukunft.append(n) # addiere zur Liste der zukünftigen Aktionen ## print ("zukunft: {}".format(n)) return (new_list_vergangen, new_list_zukunft) # gebe beide Listen zurück # --------------------------------------------------------------------------------------- # -- Funktion: warten bis der nächste wochentag wirklich eintrifft - # --------------------------------------------------------------------------------------- def warte_bis_tag_da(self,weekday): # self.myprint (DEBUG_LEVEL0, "\t" + progname + "warte_bis_tag_da() called. Es ist tag: {}".format(weekday)) # loop bis condition is erfüllt, alo neuer Tag ist gekommen... while True: hhmm_tag = [datetime.now().strftime("%H.%M"),datetime.today().strftime("%w")] # aktuelle Zeit holen self.status_currtime = hhmm_tag[0] # fuer status request =============== juni2018 wochentag_neu = int(hhmm_tag[1]) # get new weekday if wochentag_neu != weekday: # ist neuer Tag ? self.myprint (DEBUG_LEVEL0, "\t" + progname + "Neuer Tag ist da: {}".format(wochentag_neu)) return (wochentag_neu) # we have reached a new day hurray # no new day yet, continue... time.sleep(SLEEPTIME_DONE) self.myprint (DEBUG_LEVEL1, "\t" + progname + "Timemarching warte auf neuen tag, immer noch tag {} / {}".format(hhmm_tag[1], hhmm_tag[0])) self.do_stuff_regular() # do regular stuff if self.term_verlangt==1: self.myprint (DEBUG_LEVEL2, "\t" + progname + "wartend auf neuen Tag finds self.term_verlangt=1") return (5) # gebe irgendwas zurück, der form halber # --------------------------------------------------------------------------------------- # --Funktion: warten auf die Zeit der nächsten Aktion # --------------------------------------------------------------------------------------- def warte_bis_zeit_da(self,zeit): hhmm_tag = [datetime.now().strftime("%H.%M"),datetime.today().strftime("%w")] # aktuelle Zeit holen self.myprint (DEBUG_LEVEL2, "\t" + progname + "warte_bis_zeit_da() called. naechste Aktion um: {}".format(zeit)) while True: if hhmm_tag[0] >= zeit: # pruefe ob jetzt die Zeit da ist fuer aktuelle Aktion return self.myprint (DEBUG_LEVEL1, "\t" + progname + "neue Zeit ist da: {}".format(self.aktion[0])) return time.sleep(SLEEPTIME_DONE) hhmm_tag = [datetime.now().strftime("%H.%M"),datetime.today().strftime("%w")] # aktuelle Zeit holen HH.MM self.myprint (DEBUG_LEVEL2, "\t" + progname + "Timemarching warte auf zeit {}, jetzt ist {}".format (zeit, hhmm_tag[0])) self.status_currtime = hhmm_tag[0] # fuer status request =============== juni2018 self.do_stuff_regular() # mache diese sachen regelmässig... if (self.term_verlangt == 1): self.myprint (DEBUG_LEVEL2, "\t" + progname + "wartend auf neue zeit finds self.term_verlangt=1") break pass # ------------------------------------------------- #-------------------------------------------------- # actionList #------------------------------------------------- #--------------------------------------------------------------- #------ Funktion do_stuff regular #--------------------------------------------------------------- def do_stuff_regular(self): return # --------------------------------------------------------------------------------------- #------ Funktion adjust action times # wird aufgerufen, wenn dies im config file verlangt ist # --------------------------------------------------------------------------------------- def _adjust_switchtimes (self, list_in): self.myprint (DEBUG_LEVEL2, "\t" + progname + "_adjust_switchtimes called") self.today = datetime.now() self.weekyear = int(datetime.now().strftime("%V")) # use %V with Python 3.6 !! # see https://bugs.python.org/issue12006 # wenn a) # Anpassung der Schaltzeiten verlangt ist (im Configfile), # oder b) # Berücksichtigung Sommer-Winterzeit verlangt ist, # so machen wir das hier # wenn beides nicht verlangt ist, geben wir einfach die bestehende Liste zurück ohne Aenderung if (self.do_adjustTime == 0) and (self.do_adjustDaylight_saving == 0): # Nov 21 return (list_in) # eines von beiden (oder beides) ist verlangt, also machen wir das hier # init der adjust routine, liefert woche des Jahres und total ajustierung in min zurück self.daylight_saving_season, self.adjust_time, faktor = self.actioncalc.adjust_init (0) # init call #print ("++++++++++++++++++++++++") #print (self.daylight_saving_season) adjust_list_tag = [ [] for z in range (7)] # BIG Liste ueber alle Tage #--------------------------------------------------------------------------- # now let us iterate over all days and over all devices and over all actions per day in list_in for wochentag, tag in enumerate (list_in): # loop über alle 8 Tage # for tag in list_in: # for device in tag: for action in tag: new_action, minutes = self.actioncalc.adjust_time (action , 0) # adjust schalt zeit (minutes not used here) # append the updated (or unchanged) action to the two lists adjust_list_tag [wochentag].append (new_action) # now we need to sort the day list according to action time for wochentag, tag in enumerate (adjust_list_tag): adjust_list_tag[wochentag].sort(key=itemgetter(1)) if self.debug > 2: for wochentag, tag in enumerate (adjust_list_tag): print ("neue Liste (Tag_liste) tag: {}".format(wochentag)) for aktion in adjust_list_tag[wochentag]: print (aktion) # finally we are done adjusting self.myprint (DEBUG_LEVEL2, "\t\n" + progname + "_adjust_switchtimes ended") # wir geben eine neue Liste mit geänderten Aktionen zurück return (adjust_list_tag) #--------------------------------------------------------------- #------ Funktion show_status #--------------------------------------------------------------- def show_status(self): now_time = datetime.now() # return ([ str(self.weekyear) + "/" + str(self.adjust_time), \ return ([ self.do_adjustTime, \ self.weekyear, \ self.adjust_time, \ self.file_id, \ wochentage[self.wochentag], \ str(self.total_aktionen_protag), \ str(self.status_anzactions_done), \ self.status_waitfor, \ self.status_nextaction[1], \ self.status_lastaction[1], \ self.anz_dosen_config, \ self.start_time.strftime("%A, %d %B %Y : %H:%M:%S" ), \ now_time.strftime("%A, %d %B %Y : %H:%M:%S" ), \ now_time.strftime("%H:%M" ), \ self.do_adjustDaylight_saving, \ self.daylight_saving_season \ ]) #--------------------------------------------------------------- #------ Funktion RUn Sequencer #--------------------------------------------------------------- def run(self): time.sleep(1) # initial wait try: self.running() # execute the sequencer except Exception: self.myprint_exc ("Sequencer: etwas Schlimmes ist passiert.... !") finally: pass # print ("sequencer finally reached") # terminate Thread by returning return #--------------------------------------------------------------- #------ Funktion running the Sequencer #--------------------------------------------------------------- def running(self): self.myprint (DEBUG_LEVEL0, "\t" + progname + "now running ---->> Start Switching <<-----") self.myprint (DEBUG_LEVEL1, "\t" + progname + "Anzahl Dosen konfiguriert in swdosen.ini: {}". format(self.anz_dosen_config)) # print (self.list_zimmer) # hier beginnt run_switchter() ------------------------ if self.debug: time.sleep(1) hhmm_tag = [datetime.now().strftime("%H.%M"),datetime.today().strftime("%w")] # aktuelle Zeit holen self.myprint (DEBUG_LEVEL0, "\t" + progname + "start switching. Zeit und Wochentag: {}".format(hhmm_tag)) time_old = datetime.now() # fuer Zeitmessung self.start_tag = int(hhmm_tag[1]) # heutiger wochentag, starte damit, loop bis tag 6 self.list_tage_new = self._adjust_switchtimes (self.list_tage) # adjust SCHALTZEITEN WENN NÖTIG # Nun extrahieren von vergangenen und zukünftigen Aktionen (gemessen an der Startzeit des Switchers) für den aktuellen Tag # aber nur für dosen kleiner/gleich der anzahl konfigurierten dosen ! # entweder von bestehender oder von neuer Liste self.list_aktionen_past, self.list_aktionen_zukunft = self._aktionen_pro_tag (self.list_tage_new, self.start_tag , self.anz_dosen_config ) # Vorbereitung ist nun fertig-------------------------------------------------------------------- # nun haben wir also zwei Listen aller verlangten Aktionen des heutigen Tages, die müssen wir nun abarbeiten # Liste 1: alle Aktionen, die schon (gemessen an der aktuellen Zeit) in der Vergangenheit liegen # Liste 2: alle zukünftigen Aktionen des Tages #---------------------------------------------------------- # Eine Aktion sieht so aus (aus swactionlist.py kopiert) : # Element action = ("HH.MM", Zeit in Min, Dauer in Min, "HH.MM", Dose, ON/OFF) # elemente: # 0: erstes "HH.MM" element ist ev. korrigierte Schaltezeit # 1: selbe Schaltzeit aber in Minuten des Tages # 2: Dauer eingeschaltet in Minuten # 3: zweites "HH.MM" element ist originale Schaltzeit (vor adjust) # 4: Dosennummer # 5: 1 = einschalten / 0 = ausschalten #------------------------------------------------------------- # # -- Zuerst die vergagenen Aktionen des Tages behandeln --- # dies, falls der Switcher in Laufe des Tages gestartet wird - damit Status der Dosen aktuell ist # gibt es also nur bei Neustart innerhalb des Tages !!! self.myprint (DEBUG_LEVEL1, "\t" + progname + "behandle vergangene aktionen, anzahl: {}".format(len(self.list_aktionen_past))) self.status_anzactions_done = 0 # fuer statusanfrage # nur bei debug >1 if (self.debug > 1): print (progname + "vergangene aktionen:") for akt in self.list_aktionen_past: print (akt) # alle vergangenen Aktionen des Tages schnell virtuell machen for self.aktion in self.list_aktionen_past: # liste der vergagnenen aktionen des tages dosennu = int(self.aktion[4]) #xxx device nummer ein_aus = int(self.aktion[5]) # 1 = ON 0 = OFF # nur dosennummer kleiner als config behandeln ----- # wir rufen den callback, dieser ist lokalisiert in der swHome Class # sie ruft dann die betreffende Doseninstanz zu schlaten auf. if dosennu <= self.anz_dosen_config: self.callback.handle_sequencer_event ( [ ACTION_EVENT, NOTUSED, dosennu, ein_aus, NOTUSED, NOTUSED, self.aktion[0], ]) # <<<<----schalte die Dose (virtuell) uni2018 # bei Funkschaltung wollen wir nicht so lanke funken, bis alles abgearbeitet ist self.status_anzactions_done+=1 # increment anzahl getaner self.aktionen self.status_lastaction[1] = "{} Uhr, {} / {}".format (self.aktion[0],self.list_zimmer[self.aktion[4]-1], ONOFF[self.aktion[5]]) self.status_lastaction[0] = self.aktion[4] # nun haben wir die vergangenen Aktionen virtuell geschaltet - also bloss den internen Status gesetzt haben, # muessen wir nun noch die Dosen gemaess diesen Stati wirklich schalten. # wir teilen der swHome klasse mit, dass nun die Abarbeitung die aktuelle Zeit erreicht hat, also # ein TIME_OF_Day event. self.callback.handle_sequencer_event ( [ TIME_OFDAY_EVENT, ACTUAL_NOW, NOTUSED, NOTUSED, NOTUSED, NOTUSED, self.status_currtime, ]) # <<<<----Time of day event Time actual reached uni2018 self.myprint (DEBUG_LEVEL0, "\t" + progname + "vergangene aktionen sind erledigt") # ---- Alle vergangenen Aktionen des Tages erledigt. Nun gehts ans Schalten.. #---------------------------------------------------------------------------- # ---- Main Loop ----------------------------------------------------------- # hier werden die restlichen Aktionen des Tages behandelt. # # posit: solange, falls kein Ctlr-C kommt self.term_verlangt = 0 while True: # MAIN-LOOP run forever # check termination from daemon - signalled via global variable if (self.term_verlangt == 1): break # break from main Loop self.myprint (DEBUG_LEVEL1, "\t" + progname + "MAIN-LOOP: starte mit wochentag: {}".format(self.start_tag)) # LOOP---------- Loop ueber alle Tage der Woche ab start_tag --------------- for self.wochentag in range(self.start_tag, 7): self.total_aktionen_protag = len (self.list_aktionen_past) + len(self.list_aktionen_zukunft) # total number of actions for current day if self.debug: self.myprint (DEBUG_LEVEL1, "\t" + progname + "Arbeite an Wochentag: {} hat {} Aktionen, davon {} vergangene bereits erledigt".format( self.wochentag, self.total_aktionen_protag, len(self.list_aktionen_past)) ) time.sleep(1) self.myprint (DEBUG_LEVEL1, "\t" + progname + "behandle zukünftige aktionen, anzahl: {}".format(len(self.list_aktionen_zukunft))) if (self.debug > 2): print (progname + "zukünftige aktionen:") for akt in self.list_aktionen_zukunft: print (akt) #----- L2 ueber alle restlichen Actions eines Tages -------------------------------------------------- self.current_action = None # make empty for x in range (len(self.list_aktionen_zukunft)): # for self.aktion in self.list_aktionen_zukunft: self.current_action = self.list_aktionen_zukunft.pop(0) # get the next action into current self.status_nextaction[1] = "{} Uhr, {} / {}".format (self.current_action[0],self.list_zimmer[self.current_action[4]-1], ONOFF[self.current_action[5]]) self.status_nextaction[0] = self.current_action[4] # dosennummer fuer status request =============== self.status_waitfor = "{} Uhr".format(self.current_action[0]) # fuer status request Zeit auf die wir warten als String=============== self.warte_bis_zeit_da (self.current_action[0]) # hierin wird gewartet, is die Zeit reif ist... # ++++++++ Hier wird geschaltet +++++++++++ # ++++++++ Fuehre Aktion aus (Ein oder Aus schalten einer Dose) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ self.myprint (DEBUG_LEVEL2, "\t" + progname + "Schalten der Dose:{} Zeit:{}/{}".format ( self.current_action[4], self.current_action[0], ONOFF[self.current_action[5]] )) dosennu = int(self.current_action[4]) ein_aus = int(self.current_action[5]) self.callback.handle_sequencer_event ( [ ACTION_EVENT, NOTUSED, dosennu, ein_aus, NOTUSED, NOTUSED, self.current_action[0], ]) # <<<<----schalte die Dose self.list_aktionen_past.append(self.current_action) # add current (just done) action to past actions list # # ++++++++ Schalten fertig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ++++++++++++++++++++++++++++ # nun ss setzen für Statusanfrage self.status_lastaction[1] = "{} Uhr, {} / {}".format (self.current_action[0],self.list_zimmer[self.current_action[4]-1], ONOFF[self.current_action[5]]) self.status_lastaction[0] = self.current_action[4] self.status_anzactions_done+=1 # increment anzahl getaner Aktionen time.sleep(SLEEPTIME) if self.term_verlangt==1: # check in outer loop self.myprint (DEBUG_LEVEL2, "\t" + progname + "inner Loop finds self.term_verlangt=1") break self.current_action = None # make empty , no current action, all done pass #----- # hier kommt man, wenn alle Aktionen des aktuellen tages gemacht sind ----------------------------------------------- # Der Tag ist aber noch nichht vorbei... self.myprint (DEBUG_LEVEL0, "\t" + progname + "Alle Aktionen gemacht für Tag %d, nun warten auf neuen Tag " % self.wochentag) time.sleep(SLEEPTIME) # # fuer aktuellen Tag gibt es nichts mehr zu tun..... # das im Status angegeben werden - ueber den naechsten Tag wissen wir nichts if self.term_verlangt == 1: self.myprint (DEBUG_LEVEL2, "\t" + progname + "LOOP-1 finds self.term_verlangt=1") break # break loop ueber alle actions des Tages #wir warten auf den neuen Tag und es gibt keine Aktionen mehr fuer den aktuellen Tag #Daten ablegen fuer statusabfrage. Wir wissen noch nicht, welche Aktion dann im neuen Tag kommen wird self.status_waitfor = "Neuer Tag" self.status_nextaction[1] = "Vorlaeufig unbekannt" self.status_nextaction[0] = 99 # damit zimmer unbekannt gesetzt wird # warten bis Tag wechselt self.wochentag = self.warte_bis_tag_da(self.wochentag) # hierin wird gewartet, bis der neue tag kommt (mitternacht) if self.term_verlangt == 1: self.myprint (DEBUG_LEVEL2, "\t" + progname + "LOOP-1 finds self.term_verlangt=1") break # break loop ueber alle actions des Tages # wenn neuer Tag da ist, werden die Aktionslisten dieses neuen Tages erstellt self.list_aktionen_past, self.list_aktionen_zukunft = self._aktionen_pro_tag (self.list_tage_new, self.wochentag ,self.anz_dosen_config) self.status_anzactions_done = 0 # anzahl getaner Aktionen pro Tag # manuell im configfile: 0= forever, 1=nur bis Mitternacht) self.myprint (DEBUG_LEVEL0, "\t" + progname + "Neuer Tag, send midnight event") self.callback.handle_sequencer_event ( [ TIME_OFDAY_EVENT, MIDNIGHT, NOTUSED, NOTUSED, NOTUSED, NOTUSED, "00.00", ] ) # <<<<----Time of day event midnight reached uni2018 pass # Ende L1----------------------- alle Tage vorbei self.start_tag = 0 # fuer neuen durchlauf Main Loop , wir starten dann bei wochentag = 0 (Sonntag) # Ende MLoop #------------------------------------ # Diesein Loop wird nur beendet, wenn variable self.term_verlangt=1 ist oder # wenn Keyboard interrupt kommt, ctrl-c ---- self.myprint (DEBUG_LEVEL1, "\t" + progname + "Main Loop beendet, wir kommen zum Ende") #---------------------------------------------- # liefere 2 Listen: # alle vergangenen aktionen des aktuellen Tages # alle zukünftigen aktieonen des aktuellen Tages #--------------------------------------------- def show_dayactions (self): past_list =["keine vergangenen Aktionen"] zuku_list = ["keine zukünftigen Aktionen"] for i in range (len(self.list_aktionen_past)): print ("dose: {}".format(self.list_aktionen_past[i][4]-1)) # xxx past_list[i] = ("Zeit: {} ({}) {:3} Dose: {} {:15}".format ( self.list_aktionen_past[i][0], \ self.list_aktionen_past[i][3], \ ONOFF[self.list_aktionen_past[i][5]], \ self.list_aktionen_past[i][4], \ self.list_zimmer [self.list_aktionen_past[i][4]-1] )) # past_list[i] = self.list_aktionen_past[i][0] past_list.append("") if self.current_action != None: zuku_list[0] = ("Zeit: {} ({}) {:3} Dose: {} {:15}".format( self.current_action[0], \ self.current_action[3], \ ONOFF[self.current_action [5]] , \ self.current_action[4], \ self.list_zimmer [self.current_action[4]-1] )) zuku_list.append("") for i in range (len(self.list_aktionen_zukunft)): zuku_list[i+1] = ("Zeit: {} ({}) {:3} Dose: {} {:15}".format( self.list_aktionen_zukunft[i][0], \ self.list_aktionen_zukunft[i][3], \ ONOFF[self.list_aktionen_zukunft[i][5]] , \ self.list_aktionen_zukunft[i][4], \ self.list_zimmer [self.list_aktionen_zukunft[i][4]-1] )) zuku_list.append("") # return (self.list_aktionen_past, self.list_aktionen_zukunft) return (past_list, zuku_list) #---------------------------------------------- def _ausgabe_liste(self): # was solen wir ausgeben? # self.actionList.print_actions(self.list_tage, self.list_device, self.list_zimmer) # alle gefundenen Aktionen in Listen ausgeben # # #--------------------------------------------------------------- #------ Funktion do_setup #--------------------------------------------------------------- def _do_setup(self): self.myprint (DEBUG_LEVEL1, "\t" + progname + "setup MySequencer") try: locale.setlocale(locale.LC_TIME , 'de_CH.utf8') except: self.myprint (DEBUG_LEVEL0, "\t" + progname + "setzen Locale geht nicht, prüfe mit Befehl locale -a ") self.myconfig = ConfigRead(debug_level = self.debug) # Create Instance of the ConfigRead Class self.myprint (DEBUG_LEVEL3, "\nseq:Configdictionary before reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # we use the configfile given by switcher, could also use our own # all keys found in cfglist_seq are read from the config file <------------- ret = self.myconfig.config_read (self.configfile ,config_section, cfglist_seq) # call method config_read() self.myprint (DEBUG_LEVEL1, "config_read() returnvalue: {}".format (ret)) # für log und debug self.myprint (DEBUG_LEVEL3, "\nseq:Configdictionary after reading:") if (self.debug > 2): for x in cfglist_seq: print ("{} : {}".format (x, cfglist_seq[x])) # aus den eingelesenen Werten werden hier nur 2 verwendet: # ist time adjust verlangt # ist Berücksichtigung Sommer/Winterzeit verlangt try: # input comes from configfile self.do_adjustTime = int(cfglist_seq ["adjust_needed"]) self.do_adjustDaylight_saving = int(cfglist_seq ["daylight_saving"]) except KeyError : self.myprint (DEBUG_LEVEL0, progname + "KeyError in cfglist_seq, check values!") # print to log was verlangt ist if self.do_adjustTime > 0: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Schaltzeiten verlangt") else: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Schaltzeiten NICHT verlangt") if self.do_adjustDaylight_saving > 0: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Daylight-Saving verlangt") else: self.myprint (DEBUG_LEVEL1, "\t" + progname + "adjust Daylight-Saving NICHT verlangt") # create instance of Class ActionList self.actionList=ActionList(self.debug, self.path) # Instanz der actionLister Class # self.myprint (DEBUG_LEVEL0 ,progname + "object created: {}".format(self.actionList)) # # Einlesen und Parsen der Steuer-Files alles neu juni2018 ret, self.file_id = self.actionList.get_actionList (self.list_tage, self.list_device, self.list_zimmer, cfglist_seq) # # nun sind alle Aktionen aus den XML-Files eingelesen und versorgt in den Listen list_tage, list_device und zimmer # #print what we got back from actionList Class if (self.debug > 2): print ("\nsequencer.py: got these lists from class actionList: <------------") # print all days and actions print ("Anzahl Tage gefunden: {}".format(len(self.list_tage))) for v , tag in enumerate(self.list_tage): print ("Tag: {}".format(v)) for action in tag: print ("action:{}".format(action)) # print all devices and all days and all actions # print ("\nAnzahl Dosen gefunden: {}".format(self.anz_dosen_xml)) for i, dose in enumerate (self.list_device): print ("Device: {}".format(i)) for y, tag in enumerate (self.list_device[i]): print ("Tag: {}".format(y)) for action in tag: print ("action:{}".format(action)) # print alle gefundenen Zimmer # print (" ") # print (self.list_zimmer) # print (" ") self.anz_dosen_xml = self.actionList.show_anzdevices() swdosconf = SWDos_conf (debug = self.debug, path = self.path) # instanz der Klasse erstellen self.myprint (DEBUG_LEVEL0 ,"\t" + progname + "object created: {}".format(swdosconf)) self.anz_dosen_config = swdosconf.read_dosenconfig() self.myprint (DEBUG_LEVEL1, "\t" + progname + "Setup, Anz. Dosen in swdosen.ini:{}".format( self.anz_dosen_config)) #Anzahl Dosen feststellen: loop über alle Saisons, alle Tage und schauen, wo maximum ist # anzahl Dosen in XML File kann verschieden sein von Anzahl in swdosen.ini self.myprint (DEBUG_LEVEL2, "\t" + progname + "Setup, Anz. Dosen (XML)/swdosen.ini:{}/{}".format (self.anz_dosen_xml,self.anz_dosen_config )) # check anzahl dosen if self.anz_dosen_xml >= self.anz_dosen_config: self.myprint (DEBUG_LEVEL0, "\t" + progname + "Nehme Anzahl Dosen aus swconfig.ini, Anzahl:{}".format(self.anz_dosen_config )) else: self.myprint (DEBUG_LEVEL0, "\t" + progname + "Achtung: in XML File sind weniger Dosen definiert als in swdosen.ini !") self.myprint (DEBUG_LEVEL0, "\t" + progname + "Nehme Anzahl Dosen aus xml File, Anzahl:{}".format(self.anz_dosen_xml)) self.anz_dosen_config = self.anz_dosen_xml # print ("Ausgabe") for y in range (len(self.list_device)): for i in range (len(self.list_device[0])): anz= (len(self.list_device[0][i])) if (anz > self.anz_devices): self.anz_devices=anz self.anz_devices -= 1 # liste hat 5 elemente , es gibt aber -1 dosen self.myprint (DEBUG_LEVEL2, "\t" + progname + "es wurden maximal {} Devices gefunden".format( self.anz_devices)) # for s in self.list_zimmer: # longest zimmer string feststellen if len(s) > self.maxchar_zimmer: self.maxchar_zimmer = len(s) # self.callback (UPDATE_EVENT, ....) # notify Update zimmer self.callback.handle_sequencer_event ( [ UPDATE_EVENT, self.list_zimmer, NOTUSED, NOTUSED, NOTUSED, NOTUSED, "00.00", ] ) # <<<<----Time of day event midnight reached uni2018 # self._ausgabe_liste() # lokale Funktion, keine Parameter if ret > 0 : sys.exit(2) ## xxx anpassen !!
def __init__(self, dosennummer, debug_in, meldungs_typ, subscribe, config_filename_in, mqtt_client_in, callback_dosen): # Init Funktion self.errorcode = 8 # init wert beliebig aber not zero self.nummer = Aktor_3.aktorzahler self.debug = debug_in self.mqttc = mqtt_client_in self.meldungs_variante = meldungs_typ # typ der mqtt meldung und topic self.subscribe_noetig = subscribe self.config_file = config_filename_in # configfile self.dosencallback = callback_dosen self.dosennummer = dosennummer # arbeite für diese Dose (1 bis n) self.mqtt_broker_ip = "" self.mqtt_port = 0 self.mqtt_keepalive_intervall = 0 self.mqtt_topic = "" self.mqtt_client_id = "" self.action_type = "mqtt" # welche art Schalten ist dies hier self.broker_ok = False self.how = '' self.myprint( DEBUG_LEVEL1, "--> aktor_3 {} aktor_init called fuer Dose {}, msg_type:{}, subscribe:{}" .format(self.nummer, self.dosennummer, self.meldungs_variante, self.subscribe_noetig)) Aktor_3.aktorzahler += 1 # erhögen aktorzähler # nun mqtt Brokder data aus config holen config = ConfigRead(self.debug) # instanz der ConfigRead Class ret = config.config_read(self.config_file, "aktor_3", cfglist_akt) if ret > 0: self.myprint(DEBUG_LEVEL0, "config_read hat retcode: {}".format(ret)) self.errorcode = 99 return None self.myprint( DEBUG_LEVEL2, "--> aktor_3 {} aktor_init : dose {} configfile read {}".format( self.nummer, self.dosennummer, cfglist_akt)) self.broker_ok = True if self.subscribe_noetig > 0: # config verlangt, dass wir ein subscribe absetzen, damit die statusmeldungen # von smart switches (sonoff) empfangen werden können # NOTE: die Callback-Funktione liegt in der Dosenklasse, sie meldet uns # den pointer zur funktion first, second = TOPIC_S[self.meldungs_variante].split('%') topic_subscribe = first + str(self.dosennummer) + second self.mqttc.subscribe_topic( topic_subscribe, self.dosencallback) # subscribe to topic self.myprint( DEBUG_LEVEL0, "--> aktor3 done mqtt subscription, topic: {} ".format( topic_subscribe)) self.mqttc.subscribe_topic( "switcher2/switch/lw", self.last_will) # subscribe to Last Will Topic der Sensoren pass
def _do_setup(self): global myconfig self.myprint(DEBUG_LEVEL2, "\t" + progname + "setup SwHome") myconfig = ConfigRead( debug_level=self.debug) # Create Instance of the ConfigRead Class self.myprint(DEBUG_LEVEL3, "\nswhome: Configdictionary before reading:") if (self.debug > 2): for x in cfglist_home: print("{} : {}".format(x, cfglist_home[x])) # we use the configfile given by switcher, could also use our own ret = myconfig.config_read(self.configfile, config_section, cfglist_home) # call method config_read() self.myprint( DEBUG_LEVEL1, "config_read() returnvalue:{}".format(ret)) # für log und debug self.myprint(DEBUG_LEVEL3, "\nswhome:Configdictionary after reading:") if (self.debug > 2): for x in cfglist_home: print("{} : {}".format(x, cfglist_home[x])) if ret > 0: sys.exit(2) ## xxx anpassen !! try: # input comes from configfile self.home_led = int(cfglist_home["gpio_home_led"]) self.home_button = int(cfglist_home["gpio_home_button"]) self.manuelle_reset = int(cfglist_home["manuell_reset"]) except KeyError: self.myprint(DEBUG_LEVEL0, progname + "KeyError in cfglist_home, check values!") GPIO.setup(self.home_button, GPIO.IN) GPIO.setup(self.home_led, GPIO.OUT) GPIO.output(self.home_led, False) # set led off bei beginn GPIO.add_event_detect(self.home_button, GPIO.FALLING, callback=self.switch_change_local, bouncetime=300) # 20ms debounce time swdosconf = SWDos_conf(debug=self.debug, path=self.path) # instanz der Klasse erstellen self.myprint(DEBUG_LEVEL0, progname + "object created:{}".format(swdosconf)) self.anz_dosen_config = swdosconf.read_dosenconfig() self.myprint( DEBUG_LEVEL1, "\t" + progname + "Anzahl Dosen in swdosen.ini:{}".format(self.anz_dosen_config)) # instances of dosen class instantiieren for i in range(self.anz_dosen_config): self.dos = Dose(i, self.testmode, self.debug, self.configfile, self.mqtt_connect, self.mqttc, self.handle_device_event) if self.dos.errorcode == 99: self.myprint( DEBUG_LEVEL1, "\t" + progname + "Dose{} meldet Fehler:{}".format(i + 1, self.dos.errocode)) raise RuntimeError( "\t" + progname + 'ernsthafter Fehler, check switcher2.log <----') else: self.dosenlist.append(self.dos) # es wird dose 1 bis anz_dosen for dose in self.dosenlist: self.myprint(DEBUG_LEVEL0, progname + "object created:{}".format(dose)) self.test_dosen() self.myprint(DEBUG_LEVEL1, "\t" + progname + "setup SwHome DONE ") return
if __name__ == '__main__': # print("Start program: " + progname) options = argu() # get commandline args # get the current path path = os.path.dirname(os.path.realpath(__file__)) # current path logfile_name = path + "/configtest.log" print("Name logfile: {} ".format(logfile_name)) mypri = MyPrint(appname=progname, debug_level=debug, logfile=logfile_name) # Instanz von MyPrint Class erstellen # provide app_name and logfilename config = ConfigRead( debug_level=debug) # Create Instance of the ConfigRead Class print("\nConfigdictionary before reading:") for x in configval: print("{} : {}".format(x, configval[x])) ret = config.config_read(path + "/" + config_filename, config_section, configval) # call method config_read() mypri.myprint( DEBUG_LEVEL1, "config_read() returnvalue: {}".format(ret)) # für log und debug print("\nConfigdictionary after reading:") for x in configval: print("{} : {}".format(x, configval[x]))