def _handler_connect_failed_connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger and construct and initialize a protocol FSM for device interaction. @retval (next_state, result) tuple, (DriverConnectionState.CONNECTED, None) if successful. If unsuccessful, try again after self._reconnect_interval """ result = None self._build_protocol() try: for name, connection in self._connection.items(): connection.init_comms(self._slave_protocols[name].got_data, self._slave_protocols[name].got_raw, functools.partial(self._massp_got_config, name), self._got_exception, self._lost_connection_callback) self._slave_protocols[name]._connection = connection next_state = DriverConnectionState.CONNECTED except InstrumentConnectionException as e: log.error("Connection Exception: %s", e) log.error("Instrument Driver remaining in connect failed state.") # exponential backoff until max_reconnect_interval has been reached if self._reconnect_interval <= self._max_reconnect_interval: self._reconnect_interval *= 2 self._create_delayed_reconnect_event() next_state = None return next_state, result
def validate_driver_configuration(self, driver_config): """ Driver config must include 'oms_uri' entry. """ if 'oms_uri' not in driver_config: log.error("'oms_uri' not present in driver_config = %r", driver_config) raise PlatformDriverException(msg="driver_config does not indicate 'oms_uri'")
def _configure(self, driver_config): """ Nothing special done here, only calls super.configure(driver_config) @param driver_config with required 'oms_uri' entry. """ log.error("%r: _configure...", self._platform_id) PlatformDriver._configure(self, driver_config) self.nodeCfg = NodeConfiguration() self._platform_id = driver_config['node_id'] self.nodeCfg.openNode( self._platform_id, driver_config['driver_config_file']['node_cfg_file']) self.nms_source = self.nodeCfg.node_meta_data['nms_source'] self.oms_sample_rate = self.nodeCfg.node_meta_data['oms_sample_rate'] self.nodeCfg.Print() self._construct_resource_schema() self._lastRcvSampleTime = {}
def _configure(self, driver_config): """ Nothing special done here, only calls super.configure(driver_config) @param driver_config with required 'oms_uri' entry. """ log.error("%r: _configure...", self._platform_id) PlatformDriver._configure(self, driver_config) self.nodeCfg = NodeConfiguration() self._platform_id = driver_config['node_id'] self.nodeCfg.openNode(self._platform_id, driver_config['driver_config_file']['node_cfg_file']) self.nms_source = self.nodeCfg.node_meta_data['nms_source'] self.oms_sample_rate = self.nodeCfg.node_meta_data['oms_sample_rate'] self.nodeCfg.Print() self._construct_resource_schema() self._lastRcvSampleTime = {}
def _handler_unconfigured_configure(self, driver_config, *args, **kwargs): """ """ if driver_config is None: raise InstrumentException( 'configure: missing driver_config argument') try: result = self._configure(driver_config) next_state = PlatformDriverState.DISCONNECTED except NodeConfigurationFileException as e: next_state = None log.error("Node Configuration File Error " + e.msg) self._driver_event(DriverAsyncEvent.ERROR, "Node Configuration File Error " + e.msg) return next_state, None except PlatformDriverException as e: next_state = None log.error("Error in platform driver configuration" + e.msg) self._driver_event(DriverAsyncEvent.ERROR, "Node Configuration File Error " + e.msg) return next_state, None return next_state, result
def _handler_connect_failed_connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger and construct and initialize a protocol FSM for device interaction. @retval (next_state, result) tuple, (DriverConnectionState.CONNECTED, None) if successful. If unsuccessful, try again after self._reconnect_interval """ result = None self._build_protocol() try: for name, connection in self._connection.items(): connection.init_comms( self._slave_protocols[name].got_data, self._slave_protocols[name].got_raw, functools.partial(self._massp_got_config, name), self._got_exception, self._lost_connection_callback) self._slave_protocols[name]._connection = connection next_state = DriverConnectionState.CONNECTED except InstrumentConnectionException as e: log.error("Connection Exception: %s", e) log.error("Instrument Driver remaining in connect failed state.") # exponential backoff until max_reconnect_interval has been reached if self._reconnect_interval <= self._max_reconnect_interval: self._reconnect_interval *= 2 self._create_delayed_reconnect_event() next_state = None return next_state, result
def validate_driver_configuration(self, driver_config): """ Driver config must include 'oms_uri' entry. """ if "oms_uri" not in driver_config: log.error("'oms_uri' not present in driver_config = %r", driver_config) raise PlatformDriverException(msg="driver_config does not indicate 'oms_uri'")
def _handler_disconnected_connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger and construct and initialize a protocol FSM for device interaction. @return (next_state, result) tuple, (DriverConnectionState.CONNECTED, None) if successful. @raises InstrumentConnectionException if the attempt to connect failed. """ self._build_protocol() try: for name, connection in self._connection.items(): connection.init_comms(self._slave_protocols[name].got_data, self._slave_protocols[name].got_raw, functools.partial(self._massp_got_config, name), self._got_exception, self._lost_connection_callback) self._slave_protocols[name]._connection = connection next_state = DriverConnectionState.CONNECTED except InstrumentConnectionException as e: log.error("Connection Exception: %s", e) log.error("Instrument Driver remaining in disconnected state.") if self._autoconnect: next_state = DriverConnectionState.CONNECT_FAILED else: next_state = DriverConnectionState.DISCONNECTED log.debug('_handler_disconnected_connect exit') return next_state, None
def _handler_disconnected_connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger and construct and initialize a protocol FSM for device interaction. @return (next_state, result) tuple, (DriverConnectionState.CONNECTED, None) if successful. @raises InstrumentConnectionException if the attempt to connect failed. """ self._build_protocol() try: for name, connection in self._connection.items(): connection.init_comms( self._slave_protocols[name].got_data, self._slave_protocols[name].got_raw, functools.partial(self._massp_got_config, name), self._got_exception, self._lost_connection_callback) self._slave_protocols[name]._connection = connection next_state = DriverConnectionState.CONNECTED except InstrumentConnectionException as e: log.error("Connection Exception: %s", e) log.error("Instrument Driver remaining in disconnected state.") if self._autoconnect: next_state = DriverConnectionState.CONNECT_FAILED else: next_state = DriverConnectionState.DISCONNECTED log.debug('_handler_disconnected_connect exit') return next_state, None
def _handler_scan_exit(self, *args, **kwargs): """ Exit scan. Delete the scheduler. """ try: self._remove_scheduler(ScheduledJob.TAKE_SCAN) except KeyError: log.error("_remove_scheduler could not find: %s", ScheduledJob.TAKE_SCAN)
def _disconnect(self, recursion=None): log.error("%r: _disconnect...", self._platform_id) CIOMSClientFactory.destroy_instance(self._rsn_oms) self._rsn_oms = None log.debug("%r: CIOMSClient instance destroyed", self._platform_id) self._delete_scheduler() self._scheduler = None
def _failed_leveling(self, axis): """ Handle a failed leveling event. Set the failed flag, disable auto relevel and notify the operator @param axis: Axis which failed leveling """ log.error('Detected leveling error in %s axis!', axis) # Read only parameter, must be set outside of handler self._param_dict.set_value(Parameter.LEVELING_FAILED, True) # Use the handler to disable auto relevel to raise a config change event if needed. self._handler_autosample_set({Parameter.AUTO_RELEVEL: False}) raise InstrumentDataException('LILY Leveling (%s) Failed. Disabling auto relevel' % axis)
def _notify_driver_event(self, driver_event): """ Convenience method for subclasses to send a driver event to corresponding platform agent. @param driver_event a DriverEvent object. """ log.error("%r: _notify_driver_event: %s", self._platform_id, type(driver_event)) if isinstance(driver_event, DriverEvent): driver_event = str(driver_event) self._send_event(driver_event)
def _failed_leveling(self, axis): """ Handle a failed leveling event. Set the failed flag, disable auto relevel and notify the operator @param axis: Axis which failed leveling """ log.error('Detected leveling error in %s axis!', axis) # Read only parameter, must be set outside of handler self._param_dict.set_value(Parameter.LEVELING_FAILED, True) # Use the handler to disable auto relevel to raise a config change event if needed. self._handler_command_set({Parameter.AUTO_RELEVEL: False}) raise InstrumentDataException('LILY Leveling (%s) Failed. Disabling auto relevel' % axis)
def validate_driver_configuration(self, driver_config): """ Driver config must include 'oms_uri' entry. """ if not 'oms_uri' in driver_config: log.error("'oms_uri' not present in driver_config = %s", driver_config) raise PlatformDriverException(msg="driver_config does not indicate 'oms_uri'") # TODO(OOIION-1495) review the following added logic Commented out # for the moment. We need to determine where and how exactly port # information is maintained. """
def validate_driver_configuration(self, driver_config): """ Driver config must include 'oms_uri' entry. """ if not 'oms_uri' in driver_config: log.error("'oms_uri' not present in driver_config = %s", driver_config) raise PlatformDriverException( msg="driver_config does not indicate 'oms_uri'") # TODO(OOIION-1495) review the following added logic Commented out # for the moment. We need to determine where and how exactly port # information is maintained. """
def _handler_direct_access_exit(self, *args, **kwargs): """ Exit direct access state. Check slave protocol states and verify they all return to COMMAND, otherwise raise InstrumentProtocolException. @throws InstrumentProtocolException """ for attempt in range(DA_EXIT_MAX_RETRIES): slave_states = self._get_slave_states() if ProtocolState.DIRECT_ACCESS in slave_states: log.error('Slave protocol failed to return to command, attempt %d', attempt) time.sleep(1) else: return raise InstrumentProtocolException('Slave protocol never returned to command from DA.')
def _handler_scan_take_scan(self, *args, **kwargs): """ place a sentinel value in the chunker, then perform one analog scan from the RGA @return next_state, (next_agent_state, None) """ # empty the chunker self._chunker.clean() # place sentinel value in chunker self._chunker.add_chunk(SCAN_START_SENTINEL, ntplib.system_to_ntp_time(time.time())) self.scan_start_time = time.time() if self.in_scan: log.error('FAILED scan detected, in_scan sentinel set to TRUE') self.in_scan = True self._do_cmd_no_resp(InstrumentCommand.ANALOG_SCAN, 1) return None, (None, None)
def _handler_disconnected_connect(self, *args, **kwargs): """ """ recursion = kwargs.get('recursion', None) try: self._connect(recursion=recursion) except PlatformConnectionException as e: next_state = None log.error("Error in Connecting to OMS" + e.msg) self._driver_event(DriverAsyncEvent.ERROR, "Error Connecting to OMS " + e.msg) return next_state, None result = next_state = PlatformDriverState.CONNECTED return next_state, result
def _verify_instrument_id_in_response(self, port_id, instrument_id, dic): """ Verifies the presence of instrument_id in the dic. @param port_id Used for error reporting @param instrument_id The ID to verify @param dic Dictionary returned by _rsn_oms @return dic[instrument_id] """ if not instrument_id in dic: msg = "unexpected: dic does not contain entry for %r" % instrument_id log.error(msg) #raise PlatformException(msg=msg) return dic[instrument_id]
def _handler_unconfigured_configure(self, *args, **kwargs): """ """ driver_config = kwargs.get('driver_config', None) if driver_config is None: raise InstrumentException('configure: missing driver_config argument') try: result = self._configure(driver_config) next_state = PlatformDriverState.DISCONNECTED except PlatformDriverException as e: result = None next_state = None log.error("Error in platform driver configuration", e) return next_state, result
def _set_instrument_parameter(self, command): """ Set a parameter on the instrument. We will attempt up to MAX_SET_RETRIES to set the value correctly, according to the following sequence: 1. send set command 2. verify error byte, if returned (per Responses) 3. send query command 4. verify returned value equals the set value (within tolerance) @throws InstrumentParameterException """ response_type = getattr(Responses, command) parameter = getattr(Parameter, command) # store the configured setting old_value = self._param_dict.format(parameter) if old_value is None: raise exceptions.InstrumentParameterException( 'Missing required instrument parameter: %s' % parameter) log.debug('response_type: %s parameter: %s command: %s', response_type, getattr(Parameter, command), command) # attempt to set the value up to MAX_SET_RETRIES times for x in xrange(MAX_RETRIES): if response_type == STATUS: resp = self._do_cmd_resp(command, old_value) self._check_error_byte(resp) else: self._do_cmd_no_resp(command, old_value) # query the value from the instrument to load the parameter dictionary self._do_cmd_resp(command) # if values match, we were successful, return. difference = abs(self._param_dict.format(parameter) - old_value) if difference < CLOSE_ENOUGH: return log.error( 'Set attempt failed. Parameter: %s Set value: %s Returned value: %s difference: %.2f', parameter, old_value, self._param_dict.get(parameter), difference) # configuring the RGA failed, restore the setting from our configuration and raise an exception self._param_dict.set_value(parameter, old_value) raise exceptions.InstrumentParameterException( 'Unable to set instrument parameter: %s, attempted %d times' % (parameter, MAX_RETRIES))
def _handler_direct_access_exit(self, *args, **kwargs): """ Exit direct access state. Check slave protocol states and verify they all return to COMMAND, otherwise raise InstrumentProtocolException. @throws InstrumentProtocolException """ for attempt in range(DA_EXIT_MAX_RETRIES): slave_states = self._get_slave_states() if ProtocolState.DIRECT_ACCESS in slave_states: log.error( 'Slave protocol failed to return to command, attempt %d', attempt) time.sleep(1) else: return raise InstrumentProtocolException( 'Slave protocol never returned to command from DA.')
def _handler_scan_enter(self, *args, **kwargs): """ Enter the scan state. Configure the RGA, start the first scan and the scheduler. @throws InstrumentTimeoutException """ for attempt in range(1, MAX_RETRIES+1): try: self._handler_scan_configure_rga() self._async_raise_fsm_event(ProtocolEvent.TAKE_SCAN) self._build_scheduler() self._driver_event(DriverAsyncEvent.STATE_CHANGE) return except exceptions.InstrumentTimeoutException: log.error('Failed to configure the RGA - attempt %d', attempt) self._async_raise_fsm_event(ProtocolEvent.ERROR) error = 'Failed to configure RGA and start scanning.' self._param_dict.set_value(Parameter.ERROR_REASON, error) self._driver_event(DriverAsyncEvent.CONFIG_CHANGE) raise exceptions.InstrumentTimeoutException(error)
def _verify_platform_id_in_response(self, response): """ Verifies the presence of my platform_id in the response. @param response Dictionary returned by _rsn_oms @retval response[self._platform_id] """ if self._platform_id not in response: msg = "unexpected: response does not contain entry for %r" % self._platform_id log.error(msg) raise PlatformException(msg=msg) if response[self._platform_id] == InvalidResponse.PLATFORM_ID: msg = "response reports invalid platform_id for %r" % self._platform_id log.error(msg) raise PlatformException(msg=msg) else: return response[self._platform_id]
def _verify_platform_id_in_response(self, response): """ Verifies the presence of my platform_id in the response. @param response Dictionary returned by _rsn_oms @retval response[self._platform_id] """ if not self._platform_id in response: msg = "unexpected: response does not contain entry for %r" % self._platform_id log.error(msg) raise PlatformException(msg=msg) if response[self._platform_id] == InvalidResponse.PLATFORM_ID: msg = "response reports invalid platform_id for %r" % self._platform_id log.error(msg) raise PlatformException(msg=msg) else: return response[self._platform_id]
def _set_instrument_parameter(self, command): """ Set a parameter on the instrument. We will attempt up to MAX_SET_RETRIES to set the value correctly, according to the following sequence: 1. send set command 2. verify error byte, if returned (per Responses) 3. send query command 4. verify returned value equals the set value (within tolerance) @throws InstrumentParameterException """ response_type = getattr(Responses, command) parameter = getattr(Parameter, command) # store the configured setting old_value = self._param_dict.format(parameter) if old_value is None: raise exceptions.InstrumentParameterException('Missing required instrument parameter: %s' % parameter) log.debug('response_type: %s parameter: %s command: %s', response_type, getattr(Parameter, command), command) # attempt to set the value up to MAX_SET_RETRIES times for x in xrange(MAX_RETRIES): if response_type == STATUS: resp = self._do_cmd_resp(command, old_value) self._check_error_byte(resp) else: self._do_cmd_no_resp(command, old_value) # query the value from the instrument to load the parameter dictionary self._do_cmd_resp(command) # if values match, we were successful, return. difference = abs(self._param_dict.format(parameter) - old_value) if difference < CLOSE_ENOUGH: return log.error('Set attempt failed. Parameter: %s Set value: %s Returned value: %s difference: %.2f', parameter, old_value, self._param_dict.get(parameter), difference) # configuring the RGA failed, restore the setting from our configuration and raise an exception self._param_dict.set_value(parameter, old_value) raise exceptions.InstrumentParameterException('Unable to set instrument parameter: %s, attempted %d times' % (parameter, MAX_RETRIES))
def _handler_disconnected_connect(self, *args, **kwargs): """ Establish communications with the device via port agent / logger and construct and initialize a protocol FSM for device interaction. @return (next_state, result) tuple, (DriverConnectionState.CONNECTED, None) if successful. """ try: for connection in self._connection.values(): connection.init_comms() next_state = DriverConnectionState.INST_DISCONNECTED except InstrumentConnectionException as e: log.error("Connection Exception: %s", e) log.error("Instrument Driver returning to unconfigured state.") next_state = DriverConnectionState.UNCONFIGURED init_config = {} if len(args) > 0 and isinstance(args[0], dict): init_config = args[0] self.set_init_params(init_config) return next_state, None
def _verify_port_id_in_response(self, port_id, dic): """ Verifies the presence of port_id in the dic. @param port_id The ID to verify @param dic Dictionary returned by _rsn_oms @return dic[port_id] """ if not port_id in dic: msg = "unexpected: dic does not contain entry for %r" % port_id log.error(msg) #raise PlatformException(msg=msg) if dic[port_id] == InvalidResponse.PORT_ID: msg = "%r: response reports invalid port_id for %r" % ( self._platform_id, port_id) log.error(msg) #raise PlatformException(msg=msg) else: return dic[port_id]
def _handler_unconfigured_configure(self, driver_config, *args, **kwargs): """ """ if driver_config is None: raise InstrumentException('configure: missing driver_config argument') try: result = self._configure(driver_config) next_state = PlatformDriverState.DISCONNECTED except NodeConfigurationFileException as e: next_state = None log.error("Node Configuration File Error " + e.msg) self._driver_event(DriverAsyncEvent.ERROR, "Node Configuration File Error " + e.msg) return next_state, None except PlatformDriverException as e: next_state = None log.error("Error in platform driver configuration" + e.msg) self._driver_event(DriverAsyncEvent.ERROR, "Node Configuration File Error " + e.msg) return next_state, None return next_state, result
def _connect(self, recursion=None): """ Creates an CIOMSClient instance, does a ping to verify connection, and starts event dispatch. """ log.error("%r: _connect...", self._platform_id) # create CIOMSClient: oms_uri = self._driver_config['oms_uri'] log.debug("%r: creating CIOMSClient instance with oms_uri=%r", self._platform_id, oms_uri) self._rsn_oms = CIOMSClientFactory.create_instance(oms_uri) log.debug("%r: CIOMSClient instance created: %s", self._platform_id, self._rsn_oms) # ping to verify connection: self._ping() #self.get_eng_data() # call this once right away self._build_scheduler() # then start calling it every X seconds