def on_mqtt_message(client, userdata, message): global options global logger global n_hpsu logger.debug("complete topic: " + message.topic) mqtt_command = message.topic.split('/')[-1] logger.debug("command topic: " + mqtt_command) mqtt_value = str(message.payload.decode("utf-8")) logger.debug("value: " + mqtt_value) if mqtt_value == '' or mqtt_value == None or mqtt_value == "read": hpsu_command_string = mqtt_command else: hpsu_command_string = mqtt_command + ":" + mqtt_value hpsu_command_list = [hpsu_command_string] logger.info("setup HPSU to accept commands") n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=hpsu_command_list, lg_code=options.lg_code) logger.info("send command to hpsu: " + hpsu_command_string) #exec('thread_mqttdaemon = threading.Thread(target=read_can(hpsu_command_list, options.verbose, ["MQTTDAEMON"]))') #exec('thread_mqttdaemon.start()') read_can(hpsu_command_list, options.verbose, ["MQTTDAEMON"]) # if command was a write, re-read the value from HPSU and publish to MQTT if ":" in hpsu_command_string: hpsu_command_string_reread_after_write = hpsu_command_string.split( ":")[0] hpsu_command_string_reread_after_write_list = [ hpsu_command_string_reread_after_write ] #exec('thread_mqttdaemon_reread = threading.Thread(target=read_can(hpsu_command_string_reread_after_write_list, options.verbose, ["MQTTDAEMON"]))') #exec('thread_mqttdaemon_reread.start()') logger.info("send same command in read mode to hpsu: " + hpsu_command_string) read_can(hpsu_command_string_reread_after_write_list, options.verbose, ["MQTTDAEMON"]) # restarts the loop if options.auto: mqtt_client.loop_start()
def main2(self, argv): cmd = [] driver = None verbose = "1" help = False port = None lg_code = None languages = ["EN", "IT", "DE"] try: opts, args = getopt.getopt( argv, "hp:d:v:l:g:", ["help", "port=", "driver=", "verbose=", "language=", "log="]) except getopt.GetoptError: print('pyHPSUd.py -d DRIVER') print(' ') print( ' -d --driver driver name: [ELM327, PYCAN, EMU]' ) print( ' -p --port port (eg COM or /dev/tty*, only for ELM327 driver)' ) print( ' -v --verbose verbosity: [1, 2] default 1' ) print( ' -l --language set the language to use [%s]' % " ".join(languages)) print( ' -g --log set the log to file [_filename]' ) sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help = True elif opt in ("-d", "--driver"): driver = arg.upper() elif opt in ("-p", "--port"): port = arg elif opt in ("-v", "--verbose"): verbose = arg elif opt in ("-l", "--language"): lg_code = arg.upper() if lg_code not in languages: print("Error, please specify a correct language [%s]" % " ".join(languages)) sys.exit(9) elif opt in ("-g", "--log"): logger = logging.getLogger('domon') hdlr = logging.FileHandler(arg) formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.WARNING) self.hpsu = HPSU(driver=driver, logger=None, port=port, cmd=cmd, lg_code=lg_code) connection = pika.BlockingConnection( pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.queue_delete(queue='hpsu_queue') channel.queue_declare(queue='hpsu_queue', arguments={"x-max-priority": 3}) channel.basic_qos(prefetch_count=1) channel.basic_consume(self.on_request, queue='hpsu_queue') channel.start_consuming()
class MainHPSU(object): def main2(self, argv): cmd = [] driver = None verbose = "1" help = False port = None lg_code = None languages = ["EN", "IT", "DE"] try: opts, args = getopt.getopt( argv, "hp:d:v:l:g:", ["help", "port=", "driver=", "verbose=", "language=", "log="]) except getopt.GetoptError: print('pyHPSUd.py -d DRIVER') print(' ') print( ' -d --driver driver name: [ELM327, PYCAN, EMU]' ) print( ' -p --port port (eg COM or /dev/tty*, only for ELM327 driver)' ) print( ' -v --verbose verbosity: [1, 2] default 1' ) print( ' -l --language set the language to use [%s]' % " ".join(languages)) print( ' -g --log set the log to file [_filename]' ) sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help = True elif opt in ("-d", "--driver"): driver = arg.upper() elif opt in ("-p", "--port"): port = arg elif opt in ("-v", "--verbose"): verbose = arg elif opt in ("-l", "--language"): lg_code = arg.upper() if lg_code not in languages: print("Error, please specify a correct language [%s]" % " ".join(languages)) sys.exit(9) elif opt in ("-g", "--log"): logger = logging.getLogger('domon') hdlr = logging.FileHandler(arg) formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.WARNING) self.hpsu = HPSU(driver=driver, logger=None, port=port, cmd=cmd, lg_code=lg_code) connection = pika.BlockingConnection( pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.queue_delete(queue='hpsu_queue') channel.queue_declare(queue='hpsu_queue', arguments={"x-max-priority": 3}) channel.basic_qos(prefetch_count=1) channel.basic_consume(self.on_request, queue='hpsu_queue') channel.start_consuming() def on_request(self, ch, method, props, body): message = json.loads(body.decode('UTF-8')) name = message["name"] value = message["value"] type = message["type"] sec = 0 time.sleep(sec) rc = "KO" print("1") for cmd in self.hpsu.commands: print("1.5") if name == cmd["name"]: print(str(cmd)) print(name) print("set:%s:" % value) rc = self.hpsu.sendCommand(cmd, value) print("1.7") print("2") if type == "sync": priority = 2 response = rc print(rc) ch.basic_publish(exchange='', routing_key=props.reply_to, properties=pika.BasicProperties( priority=priority, correlation_id=props.correlation_id), body=str(response)) print("spedito" + props.reply_to) ch.basic_ack(delivery_tag=method.delivery_tag)
def main(argv): cmd = [] port = None driver = None verbose = "1" help = False output_type = "JSON" cloud_plugin = None lg_code = None languages = ["EN", "IT", "DE"] logger = None try: opts, args = getopt.getopt(argv,"hc:p:d:v:o:u:l:g:", ["help", "cmd=", "port=", "driver=", "verbose=", "output_type=", "upload=", "language=", "log="]) except getopt.GetoptError: print('pyHPSU.py -d DRIVER -c COMMAND') print(' ') print(' -d --driver driver name: [ELM327, PYCAN, EMU, HPSUD]') print(' -p --port port (eg COM or /dev/tty*, only for ELM327 driver)') print(' -o --output_type output type: [JSON, CSV, CLOUD] default JSON') print(' -c --cmd command: [see commands domain]') print(' -v --verbose verbosity: [1, 2] default 1') print(' -u --upload upload on cloud: [_PLUGIN_]') print(' -l --language set the language to use [%s]' % " ".join(languages)) print(' -g --log set the log to file [_filename]') sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help = True elif opt in ("-d", "--driver"): driver = arg.upper() elif opt in ("-p", "--port"): port = arg elif opt in ("-c", "--cmd"): cmd.append(arg) elif opt in ("-v", "--verbose"): verbose = arg elif opt in ("-o", "--output_type"): output_type = arg.upper() if output_type not in ["JSON", "CSV", "CLOUD"]: print("Error, please specify a correct output_type [JSON, CSV, CLOUD]") sys.exit(9) elif opt in ("-u", "--upload"): cloud_plugin = arg.upper() if cloud_plugin not in ["EMONCMS"]: print("Error, please specify a correct plugin") sys.exit(9) elif opt in ("-l", "--language"): lg_code = arg.upper() if lg_code not in languages: print("Error, please specify a correct language [%s]" % " ".join(languages)) sys.exit(9) elif opt in ("-g", "--log"): logger = logging.getLogger('domon') hdlr = logging.FileHandler(arg) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.ERROR) if verbose == "2": locale.setlocale(locale.LC_ALL, '') hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=cmd, lg_code=lg_code) if help: if len(cmd) == 0: print("List available commands:") print("%12s - %-10s" % ('COMMAND', 'LABEL')) print("%12s---%-10s" % ('------------', '----------')) for cmd in hpsu.listCommands: print("%12s - %-10s" % (cmd['name'], cmd['label'])) else: print("%12s - %-10s - %s" % ('COMMAND', 'LABEL', 'DESCRIPTION')) print("%12s---%-10s---%s" % ('------------', '----------', '---------------------------------------------------')) for c in hpsu.commands: print("%12s - %-10s - %s" % (c['name'], c['label'], c['desc'])) sys.exit(0) if not driver: print("Error, please specify driver [ELM327 or PYCAN, EMU, HPSUD]") sys.exit(9) arrResponse = [] for c in hpsu.commands: setValue = None for i in cmd: if ":" in i and c["name"] == i.split(":")[0]: setValue = i.split(":")[1] i = 0 while i <= 3: rc = hpsu.sendCommand(c, setValue) if rc != "KO": i = 4 if not setValue: response = hpsu.parseCommand(cmd=c, response=rc, verbose=verbose) resp = hpsu.umConversion(cmd=c, response=response, verbose=verbose) arrResponse.append({"name":c["name"], "resp":resp, "timestamp":response["timestamp"]}) else: i += 1 time.sleep(2.0) hpsu.printd('warning', 'retry %s command %s' % (i, c["name"])) if i == 4: hpsu.printd('error', 'command %s failed' % (c["name"])) if output_type == "JSON": print(arrResponse) elif output_type == "CSV": for r in arrResponse: print("%s\t%s\t%s" % (r["timestamp"], r["name"], r["resp"])) elif output_type == "CLOUD": if not cloud_plugin: print ("Error, please specify a cloud_plugin") sys.exit(9) module = importlib.import_module("plugins.cloud") cloud = module.Cloud(plugin=cloud_plugin, hpsu=hpsu, logger=logger) cloud.pushValues(vars=arrResponse)
def hpsu_handler(self, queue): ''' ''' hpsu = HPSU(driver=self.driver, logger=self.logger, port=self.port, cmd=[], lg_code=self.lg_code) while True: # get command t = queue.get() cmd = t.strip().split(':') paramName = cmd[1] print(cmd) if cmd[0] == 'g': # print("can getter") setValue = None cmd = [cmd[1]] if cmd[0] == 's': # print("can setter") setValue = cmd[2] cmd = [cmd[1], cmd[2]] print('CAN SET') print(cmd) # print(hpsu.commands) for c in hpsu.commands: if c['name'] == cmd[0]: # print(c) if setValue: # v = # v = int(float(setValue) * float(div)) print("Sending") val = cmd[1] div = c['div'] v = int(float(val) * float(div)) cmd[1] = str(v) setValue = cmd[1] # print(v) print('CAN: sending set command {0} {1}'.format(c, setValue)) # print("Receiving") rc = hpsu.sendCommand(c, setValue) if rc != "KO": if not setValue: # print("Current value") response = hpsu.parseCommand(cmd=c, response=rc, verbose=self.verbose) resp = hpsu.umConversion(cmd=c, response=response, verbose=self.verbose) div = c['div'] v = int(float(resp) * float(div)) # print(div) # print(resp) # print(v) # print("GET COMMAND OK") self.params.setValueByName(paramName, float(resp)) print("CAN: GET COMMAND OK") else: self.params.setParamChanged(paramName, 0) print("CAN: SET COMMAND OK") else: hpsu.printd('CAN: error', 'command %s failed' % (c["name"]))
def main(argv): cmd = [] port = None driver = "PYCAN" verbose = "1" show_help = False output_type = "JSON" upload = False lg_code = "EN" languages = ["EN", "IT", "DE"] logger = None pathCOMMANDS = "/etc/pyHPSU" global conf_file conf_file = None global default_conf_file default_conf_file = "/etc/pyHPSU/pyhpsu.conf" read_from_conf_file = False global auto global ticker ticker = 0 loop = True auto = False #commands = [] #listCommands = [] global config config = configparser.ConfigParser() global n_hpsu env_encoding = sys.stdout.encoding PLUGIN_PATH = "/usr/lib/python3/dist-packages/HPSU/plugins" backup_mode = False global backup_file restore_mode = False global options_list options_list = {} # # get all plugins # PLUGIN_LIST = ["JSON", "CSV", "BACKUP"] PLUGIN_STRING = "JSON, CSV, BACKUP" for file in os.listdir(PLUGIN_PATH): if file.endswith(".py") and not file.startswith("__"): PLUGIN = file.upper().split(".")[0] PLUGIN_STRING += ", " PLUGIN_STRING += PLUGIN PLUGIN_LIST.append(PLUGIN) try: opts, args = getopt.getopt(argv, "ahc:p:d:v:o:l:g:f:b:r:", [ "help", "cmd=", "port=", "driver=", "verbose=", "output_type=", "upload=", "language=", "log=", "config_file=" ]) except getopt.GetoptError: print('pyHPSU.py -d DRIVER -c COMMAND') print(' ') print(' -a --auto do atomatic queries') print( ' -f --config Configfile, overrides given commandline arguments' ) print( ' -d --driver driver name: [ELM327, PYCAN, EMU, HPSUD], Default: PYCAN' ) print( ' -p --port port (eg COM or /dev/tty*, only for ELM327 driver)' ) print(' -o --output_type output type: [' + PLUGIN_STRING + '] default JSON') print( ' -c --cmd command: [see commands domain]') print(' -v --verbose verbosity: [1, 2] default 1') print( ' -l --language set the language to use [%s], default is \"EN\" ' % " ".join(languages)) print( ' -b --backup backup configurable settings to file [filename]' ) print( ' -r --restore restore HPSU settings from file [filename]' ) print( ' -g --log set the log to file [_filename]') print(' -h --help show help') sys.exit(2) for opt, arg in opts: if opt in ("-a", "--auto"): auto = True options_list["auto"] = "" if opt in ("-f", "--config"): read_from_conf_file = True conf_file = arg options_list["config"] = arg if opt in ("-b", "--backup"): backup_mode = True backup_file = arg output_type = "BACKUP" options_list["backup"] = arg if opt in ("-r", "--restore"): restore_mode = True backup_file = arg options_list["restore"] = arg if opt in ("-h", "--help"): show_help = True options_list["help"] = "" elif opt in ("-d", "--driver"): driver = arg.upper() options_list["driver"] = arg.upper() elif opt in ("-p", "--port"): port = arg options_list["port"] = arg elif opt in ("-c", "--cmd"): cmd.append(arg) elif opt in ("-v", "--verbose"): verbose = arg options_list["verbose"] = "" elif opt in ("-o", "--output_type"): output_type = arg.upper() options_list["output_type"] = arg.upper() elif opt in ("-l", "--language"): lg_code = arg.upper() options_list["language"] = arg.upper() elif opt in ("-g", "--log"): logger = logging.getLogger('pyhpsu') hdlr = logging.FileHandler(arg) formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.ERROR) options_list["cmd"] = cmd if verbose == "2": locale.setlocale(locale.LC_ALL, '') # config if in auto mode if auto: read_from_conf_file = True conf_file = default_conf_file # get config from file if given.... if read_from_conf_file: if conf_file == None: print("Error, please provide a config file") sys.exit(9) else: try: with open(conf_file) as f: config.read_file(f) except IOError: print("Error: config file not found") sys.exit(9) config.read(conf_file) if driver == "" and config.has_option('PYHPSU', 'PYHPSU_DEVICE'): driver = config['PYHPSU']['PYHPSU_DEVICE'] if port == "" and config.has_option('PYHPSU', 'PYHPSU_PORT'): port = config['PYHPSU']['PYHPSU_PORT'] if lg_code == "" and config.has_option('PYHPSU', 'PYHPSU_LANG'): lg_code = config['PYHPSU']['PYHPSU_LANG'] if output_type == "" and config.has_option('PYHPSU', 'OUTPUT_TYPE'): output_type = config['PYHPSU']['OUTPUT_TYPE'] else: conf_file = default_conf_file # # now we should have all options...let's check them # # Check driver if driver not in ["ELM327", "PYCAN", "EMU", "HPSUD"]: print( "Error, please specify a correct driver [ELM327, PYCAN, EMU, HPSUD] " ) sys.exit(9) if driver == "ELM327" and port == "": print("Error, please specify a correct port for the ELM327 device ") sys.exit(9) # Check output type if output_type not in PLUGIN_LIST: print("Error, please specify a correct output_type [" + PLUGIN_STRING + "]") sys.exit(9) # Check Language if lg_code not in languages: print("Error, please specify a correct language [%s]" % " ".join(languages)) sys.exit(9) # ------------------------------------ # try to query different commands in different periods # Read them from config and group them # # create dictionary for the jobs if auto: timed_jobs = dict() if read_from_conf_file: # if config is read from file if len(config.options('JOBS')): # if there are configured jobs for each_key in config.options( 'JOBS'): # for each value to query job_period = config.get('JOBS', each_key) # get the period if not "timer_" + job_period in timed_jobs.keys( ): # if this period isn't still in the dict timed_jobs["timer_" + job_period] = [ ] # create a list for this period timed_jobs["timer_" + job_period].append( each_key) # and add the value to this period wanted_periods = list(timed_jobs.keys()) else: print("Error, please specify a value to query in config file ") sys.exit(9) # # Print help # if show_help: n_hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=cmd, lg_code=lg_code) if len(cmd) == 0: print("List available commands:") print("%20s - %-10s" % ('COMMAND', 'LABEL')) print("%20s---%-10s" % ('------------', '----------')) for cmd in sorted(n_hpsu.command_dict): try: print("%20s - %-10s" % (n_hpsu.command_dict[cmd]['name'], n_hpsu.command_dict[cmd]['label'])) except KeyError: print("""!!!!!! No translation for "%12s" !!!!!!!""" % (n_hpsu.command_dict[cmd]['name'])) else: print("%12s - %-10s - %s" % ('COMMAND', 'LABEL', 'DESCRIPTION')) print("%12s---%-10s---%s" % ('------------', '----------', '---------------------------------------------------')) for c in n_hpsu.commands: print("%12s - %-10s - %s" % (c['name'], c['label'], c['desc'])) sys.exit(0) # # now its time to call the hpsu and do the REAL can query # and handle the data as configured # if auto and not backup_mode: while loop: ticker += 1 collected_cmds = [] for period_string in timed_jobs.keys(): period = period_string.split("_")[1] if not ticker % int(period): for job in timed_jobs[period_string]: collected_cmds.append(str(job)) if len(collected_cmds): n_hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=collected_cmds, lg_code=lg_code) exec( 'thread_%s = threading.Thread(target=read_can, args=(driver,logger,port,collected_cmds,lg_code,verbose,output_type))' % (period)) exec('thread_%s.start()' % (period)) time.sleep(1) elif backup_mode: n_hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=cmd, lg_code=lg_code) read_can(driver, logger, port, n_hpsu.backup_commands, lg_code, verbose, output_type) elif restore_mode: restore_commands = [] try: with open(backup_file, 'rU') as jsonfile: restore_settings = json.load(jsonfile) for command in restore_settings: restore_commands.append( str(command["name"]) + ":" + str(command["resp"])) n_hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=restore_commands, lg_code=lg_code) read_can(driver, logger, port, restore_commands, lg_code, verbose, output_type) except FileNotFoundError: print("No such file or directory!!!") sys.exit(1) else: n_hpsu = HPSU(driver=driver, logger=logger, port=port, cmd=cmd, lg_code=lg_code) read_can(driver, logger, port, cmd, lg_code, verbose, output_type)
def main(argv): global options global logger global n_hpsu global mqtt_client global mqtt_prefix global mqtt_qos global mqtt_retain global mqtt_addtimestamp global mqttdaemon_command_topic global mqttdaemon_status_topic sys.excepthook = my_except_hook cmd = None languages = ["EN", "IT", "DE"] global default_conf_file default_conf_file = "/etc/pyHPSU/pyhpsu.conf" read_from_conf_file = False global ticker ticker = 0 loop = True LOG_LEVEL_LIST = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] # default log formatter log_formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s') #commands = [] #listCommands = [] global config config = configparser.ConfigParser() PLUGIN_PATH = "/usr/lib/python3/dist-packages/HPSU/plugins" # # get all plugins # PLUGIN_LIST = ["JSON", "CSV", "BACKUP"] PLUGIN_STRING = "JSON, CSV, BACKUP" for file in os.listdir(PLUGIN_PATH): if file.endswith(".py") and not file.startswith("__"): PLUGIN = file.upper().split(".")[0] PLUGIN_STRING += ", " PLUGIN_STRING += PLUGIN PLUGIN_LIST.append(PLUGIN) parser = argparse.ArgumentParser( description= "pyHPSU is a set of python scripts and other files to read and modify the values\nof the Rotex® HPSU (possibly) also identical heating pumps from Daikin®).", formatter_class=argparse.RawDescriptionHelpFormatter, epilog= "- If no command is specified, all commands in dictionary are executed\n- To set a value use <command>:<value>" ) parser.add_argument( "--dictionary", action="store_true", dest="show_help", help="show complete command dictionary or specific command help") parser.add_argument('--version', action='version', version='%(prog)s 1.0-BETA1') parser.add_argument("-a", "--auto", action="store_true", help="do automatic queries") parser.add_argument( "-f", "--config", dest="conf_file", help="Configfile, overrides given commandline arguments") backup_restore_group = parser.add_mutually_exclusive_group() backup_restore_group.add_argument( "-b", "--backup", dest="backup_file", help="backup configurable settings to file [filename]") backup_restore_group.add_argument( "-r", "--restore", dest="restore_file", help="restore HPSU settings from file [filename]") parser.add_argument("-g", "--log", dest="log_file", help="set the log to file [filename]") parser.add_argument("--log_level", choices=LOG_LEVEL_LIST, type=str.upper, default="ERROR", help="set the log level to [" + ", ".join(LOG_LEVEL_LIST) + "]") parser.add_argument( "-l", "--language", dest="lg_code", choices=languages, type=str.upper, default="EN", help="set the language to use [%s], default is \"EN\" " % " ".join(languages)) parser.add_argument( "-d", "--driver", type=str.upper, default="PYCAN", help="driver name: [ELM327, PYCAN, EMU, HPSUD], Default: PYCAN") parser.add_argument("-c", "--cmd", action="append", help="command: [see commands dictionary]") parser.add_argument("-o", "--output_type", action="append", type=str.upper, choices=PLUGIN_LIST, help="output type: [" + ", ".join(PLUGIN_LIST) + "] default JSON") parser.add_argument("-v", "--verbose", default="1", help="verbosity: [1, 2] default 1") parser.add_argument( "-p", "--port", help="port (eg COM or /dev/tty*, only for ELM327 driver)") parser.add_argument( "--mqtt_daemon", action="store_true", help= "set up an mqtt daemon that subscribe to a command topic and executes received command on HPSU" ) try: options = parser.parse_args() except IOError as e: parser.error(e) if (options == None): print(parser.usage) sys.exit(os.EX_USAGE) else: # set the default value if no output_type is chosen (not possible with add_argument() because it does # not detect duplication e.g. when JSON is also chosen) if options.output_type is None: options.output_type = ["JSON"] cmd = [] if options.cmd is None else options.cmd if options.backup_file is not None: options.output_type.append("BACKUP") read_from_conf_file = options.conf_file is not None # if no log file has been specified and driver is HPSUD then log nothing if options.log_file is None and options.driver == "HPSUD": _log_handler = logging.NullHandler elif options.log_file is not None: _log_handler = logging.FileHandler(options.log_file) else: # default log to stdout if no file specified _log_handler = logging.StreamHandler() logger = logging.getLogger('pyhpsu') _log_handler.setFormatter(log_formatter) logger.addHandler(_log_handler) logger.setLevel(options.log_level) if options.verbose == "2": locale.setlocale(locale.LC_ALL, '') # if no config file option is present... if not read_from_conf_file: # ...set the default one... # NOTE: other modules may need to load it later options.conf_file = default_conf_file # ...but auto or mqttdaemon mode needs it loaded... if options.auto or options.mqtt_daemon: # ...read it read_from_conf_file = True # get config from file if given.... if read_from_conf_file: try: with open(options.conf_file) as f: config.read_file(f) except IOError: logger.critical("config file not found") sys.exit(os.EX_CONFIG) config.read(options.conf_file) if options.driver == "" and config.has_option('PYHPSU', 'PYHPSU_DEVICE'): options.driver = config['PYHPSU']['PYHPSU_DEVICE'] if options.port == "" and config.has_option('PYHPSU', 'PYHPSU_PORT'): options.port = config['PYHPSU']['PYHPSU_PORT'] if options.lg_code == "" and config.has_option('PYHPSU', 'PYHPSU_LANG'): options.lg_code = config['PYHPSU']['PYHPSU_LANG'].upper() if len(options.output_type) == 0 and config.has_option( 'PYHPSU', 'OUTPUT_TYPE'): options.output_type.append(config['PYHPSU']['OUTPUT_TYPE']) # object to store entire MQTT config section mqtt_config = config['MQTT'] # MQTT Daemon command topic mqttdaemon_command_topic = mqtt_config.get('COMMAND', 'command') # MQTT Daemon status topic # FIXME to be used for pyHPSU status, including MQTTDAEMON mode, not for actual parameter reading mqttdaemon_status_topic = mqtt_config.get('STATUS', 'status') mqtt_brokerhost = mqtt_config.get('BROKER', 'localhost') mqtt_brokerport = mqtt_config.getint('PORT', 1883) mqtt_clientname = mqtt_config.get('CLIENTNAME', 'rotex') mqtt_username = mqtt_config.get('USERNAME', None) if mqtt_username is None: logger.error("Username not set!!!!!") mqtt_password = mqtt_config.get('PASSWORD', "NoPasswordSpecified") mqtt_prefix = mqtt_config.get('PREFIX', "") mqtt_qos = mqtt_config.getint('QOS', 0) # every other value implies false mqtt_retain = mqtt_config.get('RETAIN', "NOT TRUE") == "True" # every other value implies false mqtt_addtimestamp = mqtt_config.get('ADDTIMESTAMP', "NOT TRUE") == "True" logger.info("configuration parsing complete") # # now we should have all options...let's check them # if options.driver == "ELM327" and options.port == "": logger.critical("please specify a correct port for the ELM327 device ") sys.exit(os.EX_CONFIG) # ------------------------------------ # try to query different commands in different periods # Read them from config and group them # # create dictionary for the jobs if options.auto: timed_jobs = dict() if read_from_conf_file: # if config is read from file if len(config.options('JOBS')): # if there are configured jobs for each_key in config.options( 'JOBS'): # for each value to query job_period = config.get('JOBS', each_key) # get the period if not "timer_" + job_period in timed_jobs.keys( ): # if this period isn't still in the dict timed_jobs["timer_" + job_period] = [ ] # create a list for this period timed_jobs["timer_" + job_period].append( each_key) # and add the value to this period wanted_periods = list(timed_jobs.keys()) else: logger.critical( "please specify a value to query in config file ") sys.exit(os.EX_CONFIG) # # Print help # if options.show_help: n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=cmd, lg_code=options.lg_code) if len(cmd) == 0: print("List available commands:") print("%20s - %-10s" % ('COMMAND', 'LABEL')) print("%20s---%-10s" % ('------------', '----------')) for cmd in sorted(n_hpsu.command_dict): if 'label' in n_hpsu.command_dict[cmd]: print("%20s - %-10s" % (n_hpsu.command_dict[cmd]['name'], (n_hpsu.command_dict[cmd]['label']) + ('' if n_hpsu.command_dict[cmd]['writable'] == 'true' else ' (readonly)'))) else: error_message = """!!!!!! No translation for "%12s" !!!!!!!""" % ( n_hpsu.command_dict[cmd]['name']) print(error_message) logger.error(error_message) else: print("%12s - %-10s - %s" % ('COMMAND', 'LABEL', 'DESCRIPTION')) print("%12s---%-10s---%s" % ('------------', '----------', '---------------------------------------------------')) for c in n_hpsu.commands: print("%12s - %-10s - %s" % (c['name'], c['label'] + ('' if c['writable'] == 'true' else ' (readonly)'), c['desc'])) sys.exit(os.EX_USAGE) # # now its time to call the hpsu and do the REAL can query # and handle the data as configured # if options.mqtt_daemon: # adding the PID at the end of the client name ensures every process have a different client name _mqttdaemon_clientname = mqtt_clientname + "-mqttdaemon-" + str( os.getpid()) logger.info("creating new mqtt client instance: " + _mqttdaemon_clientname) # a different client name because otherwise mqtt output plugin closes this connection, too mqtt_client = mqtt.Client(_mqttdaemon_clientname) if mqtt_username: mqtt_client.username_pw_set(mqtt_username, password=mqtt_password) mqtt_client.enable_logger() mqtt_client.on_message = on_mqtt_message logger.info("connecting to broker: " + mqtt_brokerhost + ", port: " + str(mqtt_brokerport)) mqtt_client.connect(mqtt_brokerhost, mqtt_brokerport) command_topic = mqtt_prefix + "/" + mqttdaemon_command_topic + "/+" logger.info("Subscribing to command topic: " + command_topic) mqtt_client.subscribe(command_topic) # this blocks execution #mqtt_client.loop_forever() if options.auto: mqtt_client.loop_start() # if a backup file is specified we are in backup mode if options.backup_file is not None: n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=cmd, lg_code=options.lg_code) read_can(n_hpsu.backup_commands, options.verbose, options.output_type) elif options.auto: while loop: ticker += 1 collected_cmds = [] for period_string in timed_jobs.keys(): period = period_string.split("_")[1] if not ticker % int(period): for job in timed_jobs[period_string]: collected_cmds.append(str(job)) if len(collected_cmds): n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=collected_cmds, lg_code=options.lg_code) exec( 'thread_%s = threading.Thread(target=read_can, args=(collected_cmds,options.verbose,options.output_type))' % (period)) exec('thread_%s.start()' % (period)) time.sleep(1) # if a restore file is specified we are in restore mode elif options.restore_file is not None: restore_commands = [] try: with open(options.restore_file, 'rU') as jsonfile: restore_settings = json.load(jsonfile) for command in restore_settings: restore_commands.append( str(command["name"]) + ":" + str(command["resp"])) n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=restore_commands, lg_code=options.lg_code) read_can(restore_commands, options.verbose, options.output_type) except FileNotFoundError: logger.error("No such file or directory!!!") sys.exit(os.EX_NOINPUT) # FIXME if no command is specified and mqttdaemon mode is active, don't query all the commands (this has to be discussed) elif not (len(cmd) == 0 and options.mqtt_daemon): n_hpsu = HPSU(driver=options.driver, logger=logger, port=options.port, cmd=cmd, lg_code=options.lg_code) read_can(cmd, options.verbose, options.output_type) # if we reach this point (the end), we are not in auto mode so the loop is not started if mqtt_client is not None: mqtt_client.loop_forever()