From 36a2be2e7c069fb07151e90a398f965b2a9b2743 Mon Sep 17 00:00:00 2001 From: jpunkt Date: Mon, 29 Jun 2020 13:01:34 +0200 Subject: [PATCH] Added error handling and exit statements --- blocklenium/blocklenium.py | 48 ++++++++++++++++++++++++------- blocklenium/main.py | 52 ++++++++++++++++++---------------- blocklenium/selenium_worker.py | 9 +++--- blocklenium/settings.py | 20 ++++++++++--- 4 files changed, 86 insertions(+), 43 deletions(-) diff --git a/blocklenium/blocklenium.py b/blocklenium/blocklenium.py index 7c9fbb2..2f5d3bd 100644 --- a/blocklenium/blocklenium.py +++ b/blocklenium/blocklenium.py @@ -14,19 +14,29 @@ class Blocklenium(object): def __init__(self, config): - self.plc_start_flag = config['PLC_START_FLAG'] + self.config = config + self.plc_start_flag = self.config['PLC_START_FLAG'] - self.queue = queue.Queue() + self.is_error = False + + try: + self._plc = pyads.Connection(config['PLC_ID'], 851) + except pyads.ADSError as e: + logger.exception(e) + self.is_error = True + exit(1) - self._t = SeleniumWorker(self.queue, config) + self.queue = queue.Queue() - self._plc = pyads.Connection(config['PLC_ID'], 851) + try: + self._t = SeleniumWorker(self.queue, config) + except ValueError as e: + self.handle_error('Error during setup. Check the logs.', e) + exit(1) self.callback = self._plc.notification(pyads. PLCTYPE_BOOL)( - self._callback) - - self.config = config + self._callback) def _callback(self, handle, name, timestamp, value): if value: @@ -37,6 +47,23 @@ def _callback(self, handle, name, timestamp, value): 'handle: {0} | name: {1} | timestamp: {2} | value: {3}'.format( handle, name, timestamp, value)) + def handle_error(self, message, error=None): + self.is_error = True + + self.queue.put(False) + self._t.join() + + self._plc.write_by_name(self.config['PLC_ERROR_FLAG'], True, + pyads.PLCTYPE_BOOL) + self._plc.write_by_name(self.config['PLC_ERROR_MSG'], message, + pyads.PLCTYPE_STRING) + + logging.error(message) + if error is not None: + logging.error(error, exc_info=True) + + exit(1) + def start(self): logger.info('Starting blocklenium...') @@ -58,17 +85,17 @@ def start(self): self._t.desk_username = user self._t.desk_password = pwd except pyads.ADSError as e: - logging.error('''{0} or {1} not defined on PLC with + self.handle_error('''{0} or {1} not defined on PLC with --login-required flag set.'''.format( self.config['PLC_DESK_USER'], - self.config['PLC_DESK_PW'])) + self.config['PLC_DESK_PW']), e) return self._plc.add_device_notification( self.plc_start_flag, attr, self.callback) - while True: + while not self.is_error: sleep(10) try: @@ -81,3 +108,4 @@ def start(self): self._t.join() logger.debug('Blocklenium terminated.') + exit(0) diff --git a/blocklenium/main.py b/blocklenium/main.py index 2341061..544fe25 100644 --- a/blocklenium/main.py +++ b/blocklenium/main.py @@ -9,27 +9,42 @@ logger = logging.getLogger('blocklenium.main') +if __name__ == '__main__': + print('Please use the click entry-point.') + pass + + + + + @click.command() @click.option('--plc_id', default=settings.PLC_ID, show_default=True, help='ADS Id of PLC') @click.option('--plc_flag', 'plc_start_flag', default=settings.PLC_START_FLAG, show_default=True, help='PLC variable name of flag to start browser (BOOL)') +@click.option('--plc_errorflag', 'plc_error_flag', + default=settings.PLC_ERROR_FLAG, show_default=True, + help='PLC variable name of flag set TRUE if an error occurs.' + ) +@click.option('--plc_errormsg', 'plc_error_msg', + default=settings.PLC_ERROR_MSG, show_default=True, + help='PLC variable name to hold error messages') @click.option('--webdriver', 'chromedriver_path', default=settings.CHROMEDRIVER_PATH, show_default=True, type=click.Path(exists=True, file_okay=True, dir_okay=False), help='Path to selenium webdriver for chrome') -@click.option('--insecure-con', 'chromedriver_insecure', is_flag=True, +@click.option('--insecure-con', 'browser_insecure_certs', is_flag=True, help='Suppress warning for insecure site certificates') -@click.option('--login-required', 'chromedriver_login', is_flag=True, +@click.option('--login-required', 'desk_login_required', is_flag=True, help='''Target URL requires a login. Requires the login credentials to be set to the appropriate variables in the PLC (see below for default values)''') -@click.option('--plc-desk-user', 'plc_desk_username', show_default=True, +@click.option('--plc-desk-user', 'plc_desk_user', show_default=True, default=settings.PLC_DESK_USER, help='''Change the PLC variable which stores the username for the target URL''') -@click.option('--plc-desk-password', 'plc_desk_password', +@click.option('--plc-desk-password', 'plc_desk_pw', show_default=True, default=settings.PLC_DESK_PW, help='''Change the PLC variable which stores the password for @@ -43,27 +58,21 @@ help='URL to run bookmarklet on') def main(plc_id, plc_start_flag, + plc_error_flag, + plc_error_msg, chromedriver_path, - chromedriver_insecure, - chromedriver_login, - plc_desk_username, - plc_desk_password, + browser_insecure_certs, + desk_login_required, + plc_desk_user, + plc_desk_pw, bookmarklet_path, desk_url): logging.basicConfig(level=logging.INFO, stream=sys.stdout) - logger.debug('Initializing...') + logger.info('Initializing blocklenium...') - config = dict() - config['PLC_ID'] = plc_id - config['PLC_START_FLAG'] = plc_start_flag - config['PLC_DESK_USER'] = plc_desk_username - config['PLC_DESK_PW'] = plc_desk_password - config['CHROMEDRIVER_PATH'] = chromedriver_path - config['BROWSER_INSECURE_CERTS'] = chromedriver_insecure - config['BOOKMARKLET_PATH'] = bookmarklet_path - config['DESK_LOGIN_REQUIRED'] = chromedriver_login - config['DESK_URL'] = desk_url + # Build config dictionary from passed arguments + config = {key.upper(): value for key, value in locals().items()} if logger.level == logging.DEBUG: for k in config.keys(): @@ -72,8 +81,3 @@ def main(plc_id, blknm = Blocklenium(config) blknm.start() - - -if __name__ == '__main__': - print('Please use the click entry-point.') - pass diff --git a/blocklenium/selenium_worker.py b/blocklenium/selenium_worker.py index aa08f95..afb73ed 100644 --- a/blocklenium/selenium_worker.py +++ b/blocklenium/selenium_worker.py @@ -40,7 +40,6 @@ def __init__(self, queue, config): else: raise ValueError('Bookmarklet file must be a web link!') else: - # TODO error handling with open(bookmarklet_path, "r") as f: self.js = f.read() @@ -68,7 +67,6 @@ def run(self): if self.login_required: self.desk_login() - # Execute JavaScript if self.js is not None: logger.info('Executing JavaScript...') @@ -91,7 +89,7 @@ def desk_login(self): pwdfields = self.chromedriver.find_elements_by_css_selector( "input[id*='Password']") - try: + if (len(userfields) > 0) and (len(pwdfields > 0)): userfields[0].send_keys(self.desk_username) pwdfields[0].send_keys(self.desk_password) @@ -104,5 +102,6 @@ def desk_login(self): EC.presence_of_element_located((By.CLASS_NAME, "timeline-header")) ) - except Exception as e: - logger.info("Attempting to login caused {0}.".format(e)) + else: + logger.info( + 'Expected Login page but found no login fields. Ignored') diff --git a/blocklenium/settings.py b/blocklenium/settings.py index 3c7c668..48c4ccc 100644 --- a/blocklenium/settings.py +++ b/blocklenium/settings.py @@ -1,17 +1,29 @@ +# The path to the Webdriver (for Chrome/Chromium) CHROMEDRIVER_PATH = 'C:\\WebDriver\\bin\\chromedriver.exe' -BOOKMARKLET_PATH = 'C:\\Users\\Administrator\\Desktop\\test-bookmarklet.js' - +# Tell the browser to ignore invalid/insecure https connections BROWSER_INSECURE_CERTS = True -DESK_LOGIN_REQUIRED = True - +# The URL pointing to the Franka Control Webinterface (Desk) DESK_URL = 'robot.franka.de' +# Expect a login page when calling Desk +DESK_LOGIN_REQUIRED = True + +# The ADS Id of the PLC (defaults to localhost) PLC_ID = '127.0.0.1.1.1' +# Boolean flag on the PLC, set TRUE to start the web browser PLC_START_FLAG = 'GVL.bStartBlockly' +# Blocklenium sets this flag TRUE if it terminates due to an exception +PLC_ERROR_FLAG = 'GVL.bBlockleniumError' + +# Blocklenium sets this to it's terminating error message +PLC_ERROR_MSG = 'GVL.sBlockleniumErrorMsg' + +# Set the Username for Desk on the PLC PLC_DESK_USER = 'GVL.sDeskUsername' +# Set the Password for Desk on the PLC PLC_DESK_PW = 'GVL.sDeskPassword'