def __init__(self, configurationfilename, putdata_flag=True, logging=None, loglevel_in=logging.INFO): threading.Thread.__init__(self) # setup data-struct self._data = data.cdata() # set defaults self._logging = logging self._loglevel = loglevel_in self.__thread_run = True self.__filehandle = None self.__cfgfilename =str(configurationfilename) self.__data_input_mode="ASYNC " #default value self.__port = None # common used queues for RX- and TX-data exchange self.__decoded_data_queue = queue.Queue() self.__decoded_data_4_DBs = queue.Queue() self.__data_2_send_queue = queue.Queue() self.__putdata_flag = putdata_flag # create logging-file if not already done if self._logging == None: try: logfilepath = self._data.logfilepathname() abs_logfilepath = os.path.abspath(logfilepath) loggertag="ht_if_worker" self._logging = self._data.create_logfile(abs_logfilepath, self._loglevel, loggertag) except(EnvironmentError, TypeError) as e: errorstr = "cht_if_worker();Error; could not create logfile:{0};{1}".format(abs_logfilepath, e.args[0]) print(errorstr) raise e # read configurationfile try: self._data.read_db_config(self.__cfgfilename) except: errorstr='cht_if_worker();Error;could not get configuration-values' self._logging.critical(errorstr) print(errorstr) raise #using parameters from cfg-file self.__serialdevice = str(self._data.AsyncSerialdevice()) self.__baudrate = self._data.AsyncBaudrate() self._loglevel = self._data.loglevel() #setup current loglevel read from cfg-file self._logging.setLevel(self._loglevel) # setup interface self.__setup() self.__startup_time = time.time() self.__allowed_cmds = {}
hcsvfile.write(rtnstr) hcsvfile.flush() hcsvfile.close() return rtnstr def get_command_mapping(self): """ """ return self.__SPS_accessname_cmd_indexed #--- class cSPS_if end ---# ################################################ ### Runs only for test ########### if __name__ == "__main__": # create dummy-data dummydata = data.cdata() dummydata.setlogger(dummydata.create_mylogger()) dummydata.read_db_config("./../etc/config/4test/create_db_test.xml") # set SPS filename configurationfilename = './../etc/config/SPS_cfg.xml' # call interface-class sps_if = cSPS_if(configurationfilename, dummydata, cSPS_cfg.TT_SERVER) # return interface-data print("SPS-serveraddress:{0}".format(sps_if.serveraddress())) print("SPS-serverport :{0}".format(sps_if.portnumber()))
class ht3_cworker(object): """ class ht3_cworker for starting GUI if required, open ports, watching and writing results. """ # setup static data-struct _gdata = data.cdata() def __init__(self, configurationfilename, hexdump_window=True, gui_active=True, logfilename_in=None, loglevel_in=None): """ Initialisiation of class. """ self._logging = None self._loglevel = logging.INFO self.__port = None self.__filehandle = None self.__threadrun = True try: if not (isinstance(hexdump_window, int) or isinstance(hexdump_window, bool)): errorstr = "ht3_cworker();TypeError;hexdump_window" print(errorstr) raise TypeError(errorstr) self.__cfgfilename = str(configurationfilename) self.__hexdump_window = bool(hexdump_window) self.__gui_active = bool(gui_active) self.__gui_titel_input = "ASYNC " # default value except (EnvironmentError, TypeError) as e: errorstr = 'ht3_cworker();Error;Parameter:<{0}> has wrong type'.format(e.args[0]) print(errorstr) raise e # read configurationfile and setup default data try: ht3_cworker._gdata.read_db_config(self.__cfgfilename) except: errorstr = 'ht3_cworker();Error;could not get configuration-values' print(errorstr) raise try: if logfilename_in != None: ht3_cworker._gdata.logfilename(logfilename_in) if loglevel_in != None: loglevel = ht3_cworker._gdata.loglevel(loglevel_in) self._loglevel = ht3_cworker._gdata.loglevel() logfilepath = ht3_cworker._gdata.logfilepathname() abs_logfilepath = os.path.abspath(logfilepath) loggertag = "ht3_cworker" except: errorstr = 'ht3_cworker();Error;could not get cfg-logvalues' print(errorstr) raise EnvironmentError(errorstr) try: self._logging = ht3_cworker._gdata.create_logfile(abs_logfilepath, self._loglevel, loggertag) except(EnvironmentError, TypeError) as e: errorstr = "ht3_cworker();Error; could not create logfile:{0};{1}".format(abs_logfilepath, e.args[0]) print(errorstr) raise e self.__serialdevice = str(ht3_cworker._gdata.AsyncSerialdevice()) self.__baudrate = ht3_cworker._gdata.AsyncBaudrate() self.__inputfile = ht3_cworker._gdata.inputtestfilepath() if len(self.__inputfile) < 5: self.__inputfile = "" self.__autoerasechecktime = int(time.time()) + 120 def __del__(self): """ Destructor of class. """ if self.__port != None: self.__port.close() print("ht3_cworker.run(); End ----------------------") def run(self): """ Main loop doing the work. """ self._logging.info("ht3_cworker.run(); Start ----------------------") self._logging.info("ht3_cworker.run(); Loglevel :{0}".format(logging.getLevelName(self._loglevel))) if ((self.__inputfile != None) and (len(self.__inputfile) > 0)): # open input-file in readonly-binary mode for analysing binary HT3-data try: self.__filehandle = open(self.__inputfile, "rb") self.__gui_titel_input = "FILE" except: errorstr = 'ht3_cworker();Error; could not open file:{0}'.format(self.__inputfile) self._logging.critical(errorstr) quit() else: # open socket for client and connect to server, # socket-object is written to 'self.__port' if(ht3_cworker._gdata.IsDataIf_socket()): try: client_cfg_file = os.path.normcase(os.path.abspath(ht3_cworker._gdata.client_cfg_file())) if not os.path.exists(client_cfg_file): errorstr = "ht3_cworker();Error;couldn't find file:{0}".format(client_cfg_file) self._logging.critical(errorstr) raise EnvironmentError(errorstr) except: errorstr = "ht3_cworker();Error;couldn't find file:{0}".format(client_cfg_file) self._logging.critical(errorstr) raise EnvironmentError(errorstr) try: self.__port = ht_proxy_client(client_cfg_file, loglevel=self._loglevel) self.__gui_titel_input = "SOCKET" except: errorstr = "ht3_cworker();Error;couldn't open requested socket; cfg-file:{0}".format(client_cfg_file) self._logging.critical(errorstr) raise else: #open serial port for reading HT3-data try: self.__port = serial.Serial(self.__serialdevice, self.__baudrate) self.__port.setInterCharTimeout(0.1) # VTIME; set to 0.1*1sec self.__gui_titel_input = "ASYNC" except: errorstr = "ht3_cworker();Error;couldn't open requested device:{0}".format(self.__serialdevice) self._logging.critical(errorstr) raise EnvironmentError(errorstr) self._logging.info("ht3_cworker.run(); Datainput-Mode:{0}".format(self.__gui_titel_input)) if ht3_cworker._gdata.IsDataIf_async(): self._logging.info("ht3_cworker.run(); Baudrate :{0}".format(self.__baudrate)) self._logging.info("ht3_cworker.run(); Configuration:{0}".format(ht3_cworker._gdata.AsyncConfig())) try: db=db_sqlite.cdb_sqlite(self.__cfgfilename, logger=self._logging) # create database-sqlite if required if db.is_sql_db_enabled(): if not db.is_sqlite_db_available(): infostr = "ht3_cworker();Wait a bit, database: sqlite will be created" else: infostr = "ht3_cworker();sqlite-database already available" print(infostr) self._logging.info(infostr) db.connect() db.createdb_sqlite() db.close() # start thread for dispatching _thread.start_new_thread(self.__DispatchThread, (0,)) if self.__gui_active: # start GUI endless until 'Ende' is pressed GUI = gui_worker.gui_cworker(ht3_cworker._gdata, self.__hexdump_window, self.__gui_titel_input, logger=self._logging) self.__threadrun=GUI.run() except (sqlite3.OperationalError, ValueError) as e: errorstr = "ht3_cworker();Error; {0}".format(e) self._logging.critical(errorstr) self._logging.info("ht3_cworker.run(); End ----------------------") quit() def __Autoerasing_sqlitedb(self, h_database): """ check sqlite database for the oldest entries and delete them if time_limit is reached. """ if int(time.time()) >= int(self.__autoerasechecktime): time_limit = int(time.time()) - int(ht3_cworker._gdata.Sqlite_autoerase_seconds()) # get oldest UTC in database firstentry_UTC = self.__GetOldestEntry(h_database) if firstentry_UTC == None: firstentry_UTC = int(time.time()) if firstentry_UTC < time_limit: debugstr = "Autoerasing_sqlitedb(); UTCs current:{0}; oldest in db:{1}; limit:{2}".format(int(time.time()), firstentry_UTC, time_limit) self._logging.info(debugstr) try: debugstr = "sqlite-db autoerasing started; time:{0}".format(int(time.time())) self._logging.info(debugstr) # erase old datacontend in sqlite-db for systempartname in ht3_cworker._gdata.syspartnames(): h_database.delete(systempartname, "UTC", str(time_limit), "<") debugstr = "table-content:<{0}> deleted where UTC is less then:<{1}>".format(systempartname, time_limit) self._logging.info(debugstr) # cleanup db h_database.vacuum() debugstr = "sqlite-db autoerasing finished; time:{0}".format(int(time.time())) self._logging.info(debugstr) except (sqlite3.OperationalError, ValueError) as e: errorstr = "ht3_cworker.__Autoerasing_sqlitedb();Error; {0}".format(e) self._logging.critical(errorstr) # setup next check-time self.__autoerasechecktime = int(time.time()) + 120 def __GetOldestEntry(self, h_database): """ try to find the first timestamp-entry in column 'UTC' and table 'heizgeraet' and return the value. If not found then return 'None' search - excample: SELECT UTC FROM heizgeraet WHERE UTC NOT NULL ORDER UTC ASC """ sqlsearchstring = "NOT NULL" sqlorderbystring = "ORDER BY UTC ASC" rtnvalue = None try: selectrtn = h_database.selectwhere('heizgeraet', 'UTC', sqlorderbystring, sqlsearchstring, 'UTC') if not selectrtn == []: for valuetmp in list(selectrtn): # get first UTC-timestamp rtnvalue = int(valuetmp[0:1][0]) break except (sqlite3.OperationalError, ValueError) as e: errorstr = "ht3_cworker.__GetOldestEntry();Error; {0}".format(e) self._logging.critical(errorstr) rtnvalue = None return rtnvalue def __DispatchThread(self, parameter): """ Dispatch-Thread: open databases if required and storing the results in db. automatic draw for rrdtool-draw ist called every 60 sec. if db is enabled. automatic erase of old data is done in sqlite-db if it is enabled. """ debug = 0 rrdtooldb = None nextTimeStep = time.time() nextTimeautocreate = time.time() sqlite_autoerase = False # get db-instance database = db_sqlite.cdb_sqlite(self.__cfgfilename, logger=self._logging) database.connect() # set flag for erasing sqlite-db if enabled if database.is_sql_db_enabled() and ht3_cworker._gdata.Sqlite_autoerase_seconds() > 0: sqlite_autoerase = True if ht3_cworker._gdata.is_db_rrdtool_enabled(): try: rrdtooldb = db_rrdtool.cdb_rrdtool(self.__cfgfilename, logger=self._logging) rrdtooldb.createdb_rrdtool() # setup the first 'nextTimeStep' to 3 times stepseconds waiting for valid data nextTimeStep = time.time() + int(ht3_cworker._gdata.db_rrdtool_stepseconds()) * 3 except: errorstr = "ht3_cworker();Error; could not init rrdtool-db" self._logging.critical(errorstr) self._logging.info("ht3_cworker.run(); End ----------------------") quit() # setup first timestep-value for autocreating draw if ht3_cworker._gdata.IsAutocreate_draw() > 0: nextTimeautocreate = time.time() + 240 rawdata = ht_discode.cht_discode(self.__port, ht3_cworker._gdata, debug, self.__filehandle, logger=self._logging) while self.__threadrun: # get the decoded values and store them to db if enabled. (nickname, value) = rawdata.discoder() if value != None: if database.is_sql_db_enabled(): database.insert(str(ht3_cworker._gdata.getlongname(nickname)), value) database.commit() if ht3_cworker._gdata.is_db_rrdtool_enabled() and rrdtooldb != None: # write data to rrdtool-db after 'stepseconds' seconds if time.time() >= nextTimeStep: # setup next timestep nextTimeStep = time.time() + int(ht3_cworker._gdata.db_rrdtool_stepseconds()) # update rrdtool database for syspartshortname in rrdtooldb.syspartnames(): if syspartshortname.upper() == 'DT': continue syspartname = rrdtooldb.syspartnames()[syspartshortname] itemvalue_array = ht3_cworker._gdata.getall_sorted_items_with_values(syspartshortname) error = rrdtooldb.update(syspartname, itemvalue_array, time.time()) if error: self._logging.critical("rrdtooldb.update();Error;syspartname:{0}".format(syspartname)) if ht3_cworker._gdata.is_db_rrdtool_enabled() and ht3_cworker._gdata.IsAutocreate_draw() > 0: if time.time() >= nextTimeautocreate: # setup next timestep for autocreating draw nextTimeautocreate = time.time() + 60 * ht3_cworker._gdata.IsAutocreate_draw() # create draw calling script (db_path, dbfilename) = ht3_cworker._gdata.db_rrdtool_filepathname() (html_path, filename) = ht3_cworker._gdata.db_rrdtool_filepathname('.') rrdtooldb.create_draw(db_path, html_path, ht3_cworker._gdata.heatercircuits_amount(), ht3_cworker._gdata.controller_type_nr(), ht3_cworker._gdata.GetAllMixerFlags(), int(ht3_cworker._gdata.IsTempSensor_Hydrlic_Switch()), int(ht3_cworker._gdata.IsSolarAvailable()), int(ht3_cworker._gdata.IsSecondCollectorValue_SO())) if sqlite_autoerase: self.__Autoerasing_sqlitedb(database) #close db at the end of thread database.close()
elif self.__current_display==str(self.__gdata.getlongname("SO")): #"solar" self.__systempart_text("SO") self.__Info() self.__Solar() else: self.__System() if self.__hexdump_window : self.__g_i_hexheader_counter+=1 if not self.__g_i_hexheader_counter%40: self.__Hextext_bytecomment() self.__gdata.UpdateRead() #--- class gui_cworker end ---# ### Runs only for test ########### if __name__ == "__main__": import data configurationfilename='./../etc/config/4test/HT3_4dispatcher_test.xml' testdata=data.cdata() testdata.read_db_config(configurationfilename) hexdump_window=1 GUI=gui_cworker(testdata, hexdump_window) GUI.run() print("must be never reached") ############ end main - task ###############
else: debugstr="cht3_decode.Modem_MB_4();{0};FBxy !; ;mode:{1:02X};Frost-Mode".format(temptext, buffer[3]) # enable 'debug'-logging for test -> self._logging.debug(debugstr) return None #--- class cht3_decode end ---# ################################################ if __name__ == "__main__": print("----- do some checks -----") import data g_data=data.cdata() g_data.read_db_config("./../etc/config/HT3_db_cfg.xml") HT3_decode=cht3_decode(g_data) print("-- check with valid 'heizgeraet' Message 1 --") # Heizgeraet # HG: 88 00 18 00 27 01 31 54 00 01 03 20 c0 01 c5 80 # 00 01 2c ff ff ff 00 00 00 00 00 00 00 e9 00 length=31 heizgeraet = [ \ 0x88, 0x00 ,0x18, 0x00, 0x27, 0x01, 0x31, 0x54, 0x00, 0x01, 0x03, 0x20, 0xC0, 0x01, 0xC5, 0x80, 0x00, 0x01, 0x2C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00] values=HT3_decode.HeizgeraetMsg(heizgeraet, length) print(values)