def get_params(vars=None): """ Get parameters of the node. :param vars: `nodeid` as key - Node ID for the node, defaults to `None` :type vars: dict | None :raises Exception: If there is an HTTP issue while getting params or JSON format issue in HTTP response :return: None on Success :rtype: None """ try: n = node.Node(vars['nodeid'], session.Session()) params = n.get_node_params() except SSLError: log.error(SSLError()) except NetworkError as conn_err: print(conn_err) log.warn(conn_err) except Exception as get_params_err: log.error(get_params_err) else: if params is None: log.error('Node status not updated.') return else: print(json.dumps(params, indent=4)) return params
def ota_upgrade(vars=None): """ Upload OTA Firmware Image and Set image url returned in response as node params """ try: node_id = vars['nodeid'] img_file_path = vars['otaimagepath'] if os.path.isabs(img_file_path) is False: img_file_path = os.path.join(os.getcwd(), img_file_path) img_name = img_file_path.split('/')[-1].split('.bin')[0] with open(img_file_path, 'rb') as f: fw_img_bytes = f.read() base64_fw_img = base64.b64encode(fw_img_bytes).decode('ascii') retries = MAX_HTTP_CONNECTION_RETRIES node_object = None status = None response = None service_name = None service_obj = None service_config = None node_params = None param_url_to_set = None curr_session = None while retries > 0: try: # If session is expired then to initialise the new session # internet connection is required. if not curr_session: curr_session = session.Session() if not node_object: node_object = node.Node(node_id, curr_session) log.info("Creating service object...") if not service_obj: service_obj = service.Service() log.info("Checking service " + service.OTA_SERVICE_TYPE + " in node config...") print("Checking " + service.OTA_SERVICE_TYPE + " in node config...") if not service_config and not service_name: service_config, service_name = service_obj.verify_service_exists(node_object, service.OTA_SERVICE_TYPE) if not service_config: log.error(service.OTA_SERVICE_TYPE + " not found.") break log.info("Checking service " + service.OTA_SERVICE_TYPE + " in config...Success") log.debug("Service config received: " + str(service_config) + " Service name received: " + str(service_name)) print("Uploading OTA Firmware Image...This may take time...") log.info("Uploading OTA Firmware Image...This may take time...") if not status and not response: # Upload OTA Firwmare Image status, response = service_obj.upload_ota_image(node_object, img_name, base64_fw_img) if status: break except SSLError: log.error(SSLError()) break except (NetworkError, RequestTimeoutError) as conn_err: print(conn_err) log.warn(conn_err) except Exception as node_init_err: log.error(node_init_err) break time.sleep(5) retries -= 1 if retries: print("Retries left:", retries) log.info("Retries left: " + str(retries)) if node_object is None: log.error('Initialising new session...Failed\n') return if not status or not 'success' in status: print("\n") log.error("OTA Upgrade...Failed") log.debug('OTA Upgrade...Failed ' 'status: ' + str(status) + ' response: ' + str(response)) return log.info('Upload OTA Firmware Image Request...Success') log.debug("Upload OTA Firmware Image Request - Status: " + json.dumps(status) + " Response: " + json.dumps(response)) retries = MAX_HTTP_CONNECTION_RETRIES ota_start_status = None node_params = None service_read_params = None service_write_params = None ota_status = None while retries > 0: try: if 'image_url' in response: param_url_to_set = response["image_url"] if not service_read_params and not service_write_params: log.info("Getting service params from node config") service_read_params, service_write_params = service_obj.get_service_params(service_config) log.debug("Service params received with read properties: " + str(service_read_params) + " Service params received with write properties: " + str(service_write_params)) log.info("Getting node params...") if not node_params: node_params = node_object.get_node_params() log.debug("Node params received: " + json.dumps(node_params)) print("Setting the OTA URL parameter...") if not ota_start_status: ota_start_status = service_obj.start_ota(node_object, node_params, service_name, service_write_params, param_url_to_set) log.debug("OTA status received: " + str(ota_start_status)) if not ota_start_status: log.error("Failed to start OTA service...Exiting...") break print("Getting OTA Status...") if not ota_status: ota_status = service_obj.check_ota_status(node_object, service_name, service_read_params) break except SSLError: log.error(SSLError()) break except (NetworkError, RequestTimeoutError) as conn_err: print(conn_err) log.warn(conn_err) except Exception as node_init_err: log.error(node_init_err) break time.sleep(5) retries -= 1 if retries: print("Retries left:", retries) log.info("Retries left: " + str(retries)) if ota_status in [None, False]: log.error("OTA Upgrade...Failed") log.debug('OTA Upgrade...Failed ' 'ota_status: ' + str(ota_status)) except KeyError as key_err: log.error("Key Error: " + str(key_err)) except Exception as ota_err: log.error(ota_err) return
def set_params(vars=None): """ Set parameters of the node. :param vars: `nodeid` as key - Node ID for the node,\n `data` as key - JSON data containing parameters to be set `or`\n `filepath` as key - Path of the JSON file containing parameters to be set,\n defaults to `None` :type vars: dict | None :raises Exception: If there is an HTTP issue while setting params or JSON format issue in HTTP response :return: None on Success :rtype: None """ log.info('Setting params of the node with nodeid : ' + vars['nodeid']) if 'data' in vars: data = vars['data'] if 'filepath' in vars: filepath = vars['filepath'] if data is not None: log.debug('Setting node parameters using JSON data.') # Trimming white spaces except the ones between two strings data = re.sub(r"(?<![a-z]|[A-Z])\s(?![a-z]|[A-Z])|\ (?<=[a-z]|[A-Z])\s(?![a-z]|[A-Z])|\ (?<![a-z]|[A-Z])\s(?=[a-z]|[A-Z])", "", data) try: log.debug('JSON data : ' + data) data = json.loads(data) except Exception: raise InvalidJSONError return elif filepath is not None: log.debug('Setting node parameters using JSON file.') file = Path(filepath) if not file.exists(): log.error('File %s does not exist!' % file.name) return with open(file) as fh: try: data = json.load(fh) log.debug('JSON filename :' + file.name) except Exception: raise InvalidJSONError return try: n = node.Node(vars['nodeid'], session.Session()) status = n.set_node_params(data) except SSLError: log.error(SSLError()) except NetworkError as conn_err: print(conn_err) log.warn(conn_err) except Exception as set_params_err: log.error(set_params_err) else: print('Node state updated successfully.') return
def browser_login(): """ Opens browser with login url using Httpd Server. :raises Exception: If there is an HTTP issue while logging in through browser :return: None on Success and Failure :rtype: None """ log.info('Logging in through browser') server_instance = None for attempt in range(10): try: port = get_free_port() server_instance = HttpdServer(('localhost', port), HttpdRequestHandler) # Added timeout to handle keyboard interrupts for browser login. server_instance.timeout = 0.5 break except socket.error as err: log.warn('Error %s. Port %s is not available.' 'Trying with next port.', err, port) if server_instance is None: log.error('Error: Could not launch local webserver.' 'Use --email option instead.') return url = serverconfig.LOGIN_URL + str(port) +\ '&host_url=' + serverconfig.HOST + 'login' +\ '&github_url=' + serverconfig.EXTERNAL_LOGIN_URL +\ str(port) print('Opening browser window for login...') open_status = webbrowser.open(url) if open_status is False: log.error('Failed to open login page. Please try again.') return else: print('Use the browser for login. Press ctrl+C to abort.') log.debug('Web browser opened. Waiting for user login.') try: while True: server_instance.handle_request() if 'error' in server_instance.query_params: log.error('Authentication Error: "%s". Description: "%s" ' + server_instance.query_params['error'] + server_instance.query_params.ge('error_description')) return if 'code' in server_instance.query_params: log.debug('Login successful. Received authorization code.') code = server_instance.query_params['code'] get_tokens(code) print('Login successful') return if 'id_token' in server_instance.query_params and \ 'refresh_token' in server_instance.query_params: log.debug('Login successful.' 'Received idtoken and refresh token.') config_data = {} config_data['idtoken'] = server_instance.query_params[ 'id_token' ] config_data['refreshtoken'] = server_instance.query_params[ 'refresh_token' ] config_data['accesstoken'] = server_instance.query_params[ 'access_token' ] configmanager.Config().set_config(config_data) print('Login successful') return except Exception as browser_login_err: log.error(browser_login_err)
def provision(vars=None): """ Provisioning of the node. :raises NetworkError: If there is a network connection issue during provisioning :raises Exception: If there is an HTTP issue during provisioning :param vars: `pop` - Proof of Possession of the node, defaults to `None` :type vars: dict :return: None on Success and Failure :rtype: None """ try: from rmaker_tools.rmaker_prov.esp_rainmaker_prov\ import provision_device except ImportError as err: import google.protobuf if version.parse(google.protobuf.__version__)\ < version.parse(MINIMUM_PROTOBUF_VERSION): log.warn('Package protobuf does not satisfy\ the minimum required version.\n' 'Minimum required version is ' + MINIMUM_PROTOBUF_VERSION) else: log.error('Provisioning failed due to import error.', err) raise err log.info('Provisioning the node.') secret_key = str(uuid.uuid4()) pop = vars['pop'] try: config = configmanager.Config() userid = config.get_user_id() log.debug('User session is initialized for the user ' + userid) except Exception as get_user_id_err: log.error(get_user_id_err) sys.exit(1) try: input('Please connect to the wifi PROV_XXXXXX and ' 'Press Enter to continue...') except Exception: print("Exiting...") sys.exit(0) node_id = provision_device(TRANSPORT_MODE_SOFTAP, pop, userid, secret_key) if node_id is None: print(PROVISION_FAILURE_MSG) return log.debug('Node ' + node_id + ' provisioned successfully.') print('------------------------------------------') input('Please ensure host machine is connected to internet and' 'Press Enter to continue...') print('Adding User-Node association...') retries = MAX_HTTP_CONNECTION_RETRIES node_object = None while retries > 0: try: # If session is expired then to initialise the new session # internet connection is required. node_object = node.Node(node_id, session.Session()) except SSLError: log.error(SSLError()) print(PROVISION_FAILURE_MSG) return except NetworkError: time.sleep(5) log.warn("Session is expired. Initialising new session.") pass except Exception as node_init_err: log.error(node_init_err) print(PROVISION_FAILURE_MSG) return else: break retries -= 1 if node_object is None: print('Please check the internet connectivity.') print(PROVISION_FAILURE_MSG) return retries = MAX_HTTP_CONNECTION_RETRIES request_id = None while retries > 0: try: log.debug('Adding user-node association.') request_id = node_object.add_user_node_mapping(secret_key) except SSLError: log.error(SSLError()) print(PROVISION_FAILURE_MSG) return except Exception as user_node_mapping_err: print('Sending User-Node association request to ' 'ESP RainMaker Cloud - Failed\nRetrying...') log.warn(user_node_mapping_err) pass else: if request_id is not None: log.debug('User-node mapping added successfully' 'with request_id' + request_id) break time.sleep(5) retries -= 1 if request_id is None: print('Sending User-Node association request to' 'ESP RainMaker Cloud - Failed') print(PROVISION_FAILURE_MSG) return print('Sending User-Node association request to' 'ESP RainMaker Cloud - Successful') status = None while True: log.debug('Checking user-node association status.') try: status = node_object.get_mapping_status(request_id) except SSLError: log.error(SSLError()) print(PROVISION_FAILURE_MSG) return except Exception as mapping_status_err: log.warn(mapping_status_err) pass else: log.debug('User-node association status ' + status) if status == 'requested': print('Checking User Node association status -' 'Requested\nRetrying...') elif status == 'confirmed': print('Checking User Node association status - Confirmed') print('Provisioning was Successful.') return elif status == 'timedout': print('Checking User Node association status - Timeout') print(PROVISION_FAILURE_MSG) return elif status == 'discarded': print('Checking User Node association status - Discarded') print(PROVISION_FAILURE_MSG) return time.sleep(5) if status is None: print(PROVISION_FAILURE_MSG) print('Checking User Node association status failed. ' 'Please check the internet connectivity.') return return
def provision(vars=None): """ Provisioning of the node. :raises NetworkError: If there is a network connection issue during provisioning :raises Exception: If there is an HTTP issue during provisioning :param vars: `pop` - Proof of Possession of the node, defaults to `None` :type vars: dict :return: None on Success and Failure :rtype: None """ log.info('Provisioning the node.') secret_key = str(uuid.uuid4()) pop = vars['pop'] try: config = configmanager.Config() userid = config.get_user_id() log.debug('User session is initialized for the user ' + userid) except Exception as get_user_id_err: log.error(get_user_id_err) sys.exit(1) try: input('Please connect to the wifi PROV_XXXXXX and ' 'Press Enter to continue...') except Exception: print("Exiting...") sys.exit(0) node_id = provision_device(TRANSPORT_MODE_SOFTAP, pop, userid, secret_key) if node_id is None: log.error(PROVISION_FAILURE_MSG) return log.debug('Node ' + node_id + ' provisioned successfully.') print('------------------------------------------') input('Please ensure host machine is connected to internet and ' 'Press Enter to continue...') retries = MAX_HTTP_CONNECTION_RETRIES node_object = None while retries > 0: try: # If session is expired then to initialise the new session # internet connection is required. node_object = node.Node(node_id, session.Session()) except SSLError: log.error(SSLError()) break except (NetworkError, RequestTimeoutError) as conn_err: print(conn_err) log.warn(conn_err) except Exception as node_init_err: log.error(node_init_err) break else: break time.sleep(5) retries -= 1 if retries: print("Retries left:", retries) log.info("Retries left: " + str(retries)) if node_object is None: log.error('Initialising new session...Failed\n' + '\n' + PROVISION_FAILURE_MSG) return print('\nAdding User-Node association') log.info("Adding User-Node association") retries = MAX_HTTP_CONNECTION_RETRIES request_id = None log.info('Sending User-Node Association Request...') while retries > 0: print('Sending User-Node Association Request...') try: request_id = node_object.add_user_node_mapping(secret_key) except SSLError: log.error(SSLError()) break except (NetworkError, RequestTimeoutError) as conn_err: print(conn_err) log.warn(conn_err) except Exception as mapping_err: print(mapping_err) log.warn(mapping_err) break else: if request_id is not None: log.debug('User-Node mapping added successfully ' 'with request_id ' + request_id) break retries -= 1 if retries: print("Retries left:", retries) log.info("Retries left: " + str(retries)) time.sleep(5) if request_id is None: log.error('User-Node Association Request...Failed\n' + '\n' + PROVISION_FAILURE_MSG) return print('User-Node Association Request...Success') log.info('User-Node Association Request...Success') retries = MAX_HTTP_CONNECTION_RETRIES status = None log.info('Checking User-Node Association Status...') while retries > 0: print('Checking User-Node Association Status...') try: status = node_object.get_mapping_status(request_id) except SSLError: log.error(SSLError()) break except (NetworkError, RequestTimeoutError) as conn_err: print(conn_err) log.warn(conn_err) status = None except Exception as mapping_status_err: print(mapping_status_err) log.warn(mapping_status_err) break else: if status == 'requested': print('User-Node Association Status - Requested' '\n') log.debug('User-Node Association Status - Requested' '\n') elif status == 'confirmed': print('User-Node Association Status - Confirmed' '\nProvisioning was Successful.') log.debug('User-Node Association Status - Confirmed' '\nProvisioning was Successful.') break elif status == 'timedout': print('User-Node Association Status - Timedout') log.debug('User-Node Association Status - Timedout') break elif status == 'discarded': print('User-Node Association Status - Discarded') log.debug('User-Node Association Status - Discarded') break else: log.debug('User-Node Association Status - ' + status) break if status not in ["requested"]: retries -= 1 if retries: print("Retries left:", retries) log.info("Retries left: " + str(retries)) time.sleep(5) if status not in ["confirmed"]: log.error('Checking User-Node Association Status...Failed.\n' '\nCould not confirm User-Node Association Status. ' '\nPlease use cli command ' '`python3 rainmaker.py getnodes` to confirm.') return return