def on_start(self): ''' Creates a publisher for each stream_id passed in as publish_streams Creates an attribute with the name matching the stream name which corresponds to the publisher ex: say we have publish_streams:{'output': my_output_stream_id } then the instance has an attribute output which corresponds to the publisher for the stream in my_output_stream_id ''' # Get the stream(s) stream_id = self.CFG.get('process',{}).get('stream_id','') self.greenlet_queue = [] self._usgs_def = USGS_stream_definition() # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_id = pubsub_cli.create_stream( name='Example USGS Data', stream_definition=self._usgs_def, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id = stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.warn('Starting publisher thread for simple usgs data.') g.start() self.greenlet_queue.append(g)
def _set_publisher_endpoints(self, service_instance, publisher_streams=None): service_instance.stream_publisher_registrar = StreamPublisherRegistrar( process=service_instance, node=self.container.node) publisher_streams = publisher_streams or {} for name, stream_id in publisher_streams.iteritems(): # problem is here pub = service_instance.stream_publisher_registrar.create_publisher( stream_id) setattr(service_instance, name, pub)
def on_init(self): """ Instrument agent pyon process initialization. Init objects that depend on the container services and start state machine. """ # The registrar to create publishers. self._stream_registrar = StreamPublisherRegistrar(process=self, node=self.container.node) # Set the driver config from the agent config if present. self._dvr_config = self.CFG.get('driver_config', None) # Construct stream publishers. self._construct_data_publishers() # Start state machine. self._fsm.start(self._initial_state)
def on_start(self): log.warn('Entering On Start!!!') # Get the stream(s) stream_id = self.CFG.get_safe('process.stream_id',{}) self.greenlet_queue = [] # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_def_id = pubsub_cli.create_stream_definition(name='Producer stream %s' % str(uuid4()),container=self.outgoing_stream_def) stream_id = pubsub_cli.create_stream( name='Example CTD Data', stream_definition_id = stream_def_id, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id= stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.debug('Starting publisher thread for simple ctd data.') g.start() log.warn('Publisher Greenlet started in "%s"' % self.__class__.__name__) self.greenlet_queue.append(g)
class UsgsPublisher(StandaloneProcess): def __init__(self, *args, **kwargs): super(StandaloneProcess, self).__init__(*args,**kwargs) #@todo Init stuff def on_start(self): ''' Creates a publisher for each stream_id passed in as publish_streams Creates an attribute with the name matching the stream name which corresponds to the publisher ex: say we have publish_streams:{'output': my_output_stream_id } then the instance has an attribute output which corresponds to the publisher for the stream in my_output_stream_id ''' # Get the stream(s) stream_id = self.CFG.get('process',{}).get('stream_id','') self.greenlet_queue = [] self._usgs_def = USGS_stream_definition() # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_id = pubsub_cli.create_stream( name='Example USGS Data', stream_definition=self._usgs_def, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id = stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.warn('Starting publisher thread for simple usgs data.') g.start() self.greenlet_queue.append(g) def on_quit(self): for greenlet in self.greenlet_queue: greenlet.kill() super(UsgsPublisher,self).on_quit() #overriding trigger function here to use PointSupplementConstructor def _trigger_func(self, stream_id): #point_def = usgs_stream_definition(stream_id=stream_id) point_constructor = PointSupplementConstructor(point_definition=self._usgs_def, stream_id=stream_id) damsP = DataAcquisitionManagementServicePlaceholder() dsh = damsP.get_data_handler(ds_id=USGS) dsh._block_size = 1 lon = 0 lon_iter = dsh.acquire_data(var_name='lon') for lon_vn, lon_slice_, lon_rng, lon_data in lon_iter: lon = lon_data[0] lat = 0 lat_iter = dsh.acquire_data(var_name='lat') for lat_vn, lat_slice_, lat_rng, lat_data in lat_iter: lat = lat_data[0] location = (lon,lat) data_iter = dsh.acquire_data(var_name='time') index = 0 for vn, slice_, rng, data in data_iter: #loop through each time step point_id = point_constructor.add_point(time=data[0], location=location) temp_iter = dsh.acquire_data(var_name=['water_temperature','water_height','streamflow'], slice_=index) for temp_vn, temp_slice_, temp_rng, temp_data in temp_iter: point_constructor.add_scalar_point_coverage(point_id=point_id, coverage_id=temp_vn, value=temp_data[0]) ctd_packet = point_constructor.close_stream_granule() self.publisher.publish(ctd_packet) index += 1 # time.sleep(2.0)
class SimpleCtdPublisher(StandaloneProcess): def __init__(self, *args, **kwargs): super(StandaloneProcess, self).__init__(*args,**kwargs) #@todo Init stuff def on_start(self): ''' Creates a publisher for each stream_id passed in as publish_streams Creates an attribute with the name matching the stream name which corresponds to the publisher ex: say we have publish_streams:{'output': my_output_stream_id } then the instance has an attribute output which corresponds to the publisher for the stream in my_output_stream_id ''' # Get the stream(s) stream_id = self.CFG.get('process',{}).get('stream_id','') self.greenlet_queue = [] # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: ctd_def = ctd_stream_definition(stream_id=stream_id) pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_id = pubsub_cli.create_stream( name='Example CTD Data', stream_definition=ctd_def, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id= stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.debug('Starting publisher thread for simple ctd data.') g.start() self.greenlet_queue.append(g) def on_quit(self): for greenlet in self.greenlet_queue: greenlet.kill() super(SimpleCtdPublisher,self).on_quit() def _trigger_func(self, stream_id): while True: length = random.randint(1,20) c = [random.uniform(0.0,75.0) for i in xrange(length)] t = [random.uniform(-1.7, 21.0) for i in xrange(length)] p = [random.lognormvariate(1,2) for i in xrange(length)] lat = [random.uniform(-90.0, 90.0) for i in xrange(length)] lon = [random.uniform(0.0, 360.0) for i in xrange(length)] tvar = [self.last_time + i for i in xrange(1,length+1)] self.last_time = max(tvar) ctd_packet = ctd_stream_packet(stream_id=stream_id, c=c, t=t, p=p, lat=lat, lon=lon, time=tvar) log.warn('SimpleCtdPublisher sending %d values!' % length) self.publisher.publish(ctd_packet) time.sleep(2.0)
class UsgsPublisher(StandaloneProcess): def __init__(self, *args, **kwargs): super(StandaloneProcess, self).__init__(*args,**kwargs) #@todo Init stuff def on_start(self): ''' Creates a publisher for each stream_id passed in as publish_streams Creates an attribute with the name matching the stream name which corresponds to the publisher ex: say we have publish_streams:{'output': my_output_stream_id } then the instance has an attribute output which corresponds to the publisher for the stream in my_output_stream_id ''' # Get the stream(s) stream_id = self.CFG.get('process',{}).get('stream_id','') self.greenlet_queue = [] self._usgs_def = USGS_stream_definition() # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_id = pubsub_cli.create_stream( name='Example USGS Data', stream_definition=self._usgs_def, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id = stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.warn('Starting publisher thread for simple usgs data.') g.start() self.greenlet_queue.append(g) def on_quit(self): for greenlet in self.greenlet_queue: greenlet.kill() super(UsgsPublisher,self).on_quit() #overriding trigger function here to use PointSupplementConstructor def _trigger_func(self, stream_id): #point_def = usgs_stream_definition(stream_id=stream_id) point_constructor = PointSupplementConstructor(point_definition=self._usgs_def, stream_id=stream_id) damsP = DataAcquisitionManagementServicePlaceholder() dsh = damsP.get_data_handler(ds_id=USGS) dsh._block_size = 1 lon = 0 lon_iter = dsh.acquire_data(var_name='lon') for lon_vn, lon_slice_, lon_rng, lon_data in lon_iter: lon = lon_data[0] lat = 0 lat_iter = dsh.acquire_data(var_name='lat') for lat_vn, lat_slice_, lat_rng, lat_data in lat_iter: lat = lat_data[0] location = (lon,lat) data_iter = dsh.acquire_data(var_name='time') index = 0 for vn, slice_, rng, data in data_iter: #loop through each time step point_id = point_constructor.add_point(time=data[0], location=location) temp_iter = dsh.acquire_data(var_name=['water_temperature','water_height','streamflow'], slice_=index) for temp_vn, temp_slice_, temp_rng, temp_data in temp_iter: point_constructor.add_scalar_point_coverage(point_id=point_id, coverage_id=temp_vn, value=temp_data[0]) ctd_packet = point_constructor.close_stream_granule() self.publisher.publish(ctd_packet) index += 1
class SimpleCtdPublisher(StandaloneProcess): def __init__(self, *args, **kwargs): super(SimpleCtdPublisher, self).__init__(*args,**kwargs) #@todo Init stuff outgoing_stream_def = SBE37_CDM_stream_definition() def on_start(self): log.warn('Entering On Start!!!') # Get the stream(s) stream_id = self.CFG.get_safe('process.stream_id',{}) self.greenlet_queue = [] # Stream creation is done in SA, but to make the example go for demonstration create one here if it is not provided... if not stream_id: pubsub_cli = PubsubManagementServiceClient(node=self.container.node) stream_def_id = pubsub_cli.create_stream_definition(name='Producer stream %s' % str(uuid4()),container=self.outgoing_stream_def) stream_id = pubsub_cli.create_stream( name='Example CTD Data', stream_definition_id = stream_def_id, original=True, encoding='ION R2') self.stream_publisher_registrar = StreamPublisherRegistrar(process=self,node=self.container.node) # Needed to get the originator's stream_id self.stream_id= stream_id self.publisher = self.stream_publisher_registrar.create_publisher(stream_id=stream_id) self.last_time = 0 g = Greenlet(self._trigger_func, stream_id) log.debug('Starting publisher thread for simple ctd data.') g.start() log.warn('Publisher Greenlet started in "%s"' % self.__class__.__name__) self.greenlet_queue.append(g) def on_quit(self): for greenlet in self.greenlet_queue: greenlet.kill() super(SimpleCtdPublisher,self).on_quit() def _trigger_func(self, stream_id): while True: length = random.randint(1,20) ctd_packet = self._get_ctd_packet(stream_id, length) log.info('SimpleCtdPublisher sending %d values!' % length) self.publisher.publish(ctd_packet) time.sleep(2.0) def _get_ctd_packet(self, stream_id, length): c = [random.uniform(0.0,75.0) for i in xrange(length)] t = [random.uniform(-1.7, 21.0) for i in xrange(length)] p = [random.lognormvariate(1,2) for i in xrange(length)] lat = [random.uniform(-90.0, 90.0) for i in xrange(length)] lon = [random.uniform(0.0, 360.0) for i in xrange(length)] tvar = [self.last_time + i for i in xrange(1,length+1)] self.last_time = max(tvar) ctd_packet = ctd_stream_packet(stream_id=stream_id, c=c, t=t, p=p, lat=lat, lon=lon, time=tvar) return ctd_packet
class InstrumentAgent(ResourceAgent): """ ResourceAgent derived class for the instrument agent. This class logically abstracts instruments as taskable resources in the ION system. It directly provides common functionality (common state model, common resource interface, point of publication) and creates a driver process to specialize for particular hardware. """ def __init__(self, initial_state=InstrumentAgentState.UNINITIALIZED): """ Initialize instrument agent prior to pyon process initialization. Define state machine, initialize member variables. """ ResourceAgent.__init__(self) # Instrument agent state machine. self._fsm = InstrumentFSM(InstrumentAgentState, InstrumentAgentEvent, InstrumentAgentEvent.ENTER, InstrumentAgentEvent.EXIT, InstErrorCode.UNHANDLED_EVENT) # Populate state machine for all state-events. self._fsm.add_handler(InstrumentAgentState.POWERED_DOWN, InstrumentAgentEvent.ENTER, self._handler_powered_down_enter) self._fsm.add_handler(InstrumentAgentState.POWERED_DOWN, InstrumentAgentEvent.EXIT, self._handler_powered_down_exit) self._fsm.add_handler(InstrumentAgentState.UNINITIALIZED, InstrumentAgentEvent.ENTER, self._handler_uninitialized_enter) self._fsm.add_handler(InstrumentAgentState.UNINITIALIZED, InstrumentAgentEvent.EXIT, self._handler_uninitialized_exit) self._fsm.add_handler(InstrumentAgentState.UNINITIALIZED, InstrumentAgentEvent.POWER_DOWN, self._handler_uninitialized_power_down) self._fsm.add_handler(InstrumentAgentState.UNINITIALIZED, InstrumentAgentEvent.INITIALIZE, self._handler_uninitialized_initialize) self._fsm.add_handler(InstrumentAgentState.UNINITIALIZED, InstrumentAgentEvent.RESET, self._handler_uninitialized_reset) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.ENTER, self._handler_inactive_enter) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.EXIT, self._handler_inactive_exit) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.INITIALIZE, self._handler_inactive_initialize) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.RESET, self._handler_inactive_reset) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.GO_ACTIVE, self._handler_inactive_go_active) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.INACTIVE, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.ENTER, self._handler_idle_enter) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.EXIT, self._handler_idle_exit) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.GO_INACTIVE, self._handler_idle_go_inactive) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.RESET, self._handler_idle_reset) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.RUN, self._handler_idle_run) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.IDLE, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.ENTER, self._handler_stopped_enter) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.EXIT, self._handler_stopped_exit) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.GO_INACTIVE, self._handler_stopped_go_inactive) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.RESET, self._handler_stopped_reset) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.CLEAR, self._handler_stopped_clear) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.RESUME, self._handler_stopped_resume) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.STOPPED, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.ENTER, self._handler_observatory_enter) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.EXIT, self._handler_observatory_exit) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GO_INACTIVE, self._handler_observatory_go_inactive) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.RESET, self._handler_observatory_reset) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.CLEAR, self._handler_observatory_clear) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.PAUSE, self._handler_observatory_pause) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GO_STREAMING, self._handler_observatory_go_streaming) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GO_DIRECT_ACCESS, self._handler_observatory_go_direct_access) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.GET_PARAMS, self._handler_get_params) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.SET_PARAMS, self._handler_observatory_set_params) self._fsm.add_handler(InstrumentAgentState.OBSERVATORY, InstrumentAgentEvent.EXECUTE_RESOURCE, self._handler_observatory_execute_resource) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.ENTER, self._handler_streaming_enter) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.EXIT, self._handler_streaming_exit) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.GO_INACTIVE, self._handler_streaming_go_inactive) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.RESET, self._handler_streaming_reset) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.GO_OBSERVATORY, self._handler_streaming_go_observatory) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) self._fsm.add_handler(InstrumentAgentState.STREAMING, InstrumentAgentEvent.GET_PARAMS, self._handler_get_params) self._fsm.add_handler(InstrumentAgentState.DIRECT_ACCESS, InstrumentAgentEvent.ENTER, self._handler_direct_access_enter) self._fsm.add_handler(InstrumentAgentState.DIRECT_ACCESS, InstrumentAgentEvent.EXIT, self._handler_direct_access_exit) self._fsm.add_handler(InstrumentAgentState.DIRECT_ACCESS, InstrumentAgentEvent.GO_OBSERVATORY, self._handler_direct_access_go_observatory) self._fsm.add_handler(InstrumentAgentState.DIRECT_ACCESS, InstrumentAgentEvent.GET_RESOURCE_COMMANDS, self._handler_get_resource_commands) self._fsm.add_handler(InstrumentAgentState.DIRECT_ACCESS, InstrumentAgentEvent.GET_RESOURCE_PARAMS, self._handler_get_resource_params) ############################################################################### # Instrument agent internal parameters. ############################################################################### # State machine start state, defaults to unconfigured. self._initial_state = initial_state # Driver configuration. Passed as part of the spawn configuration # or with an initialize command. Sets driver specific # context. self._dvr_config = None # Process ID of the driver process. Useful to identify and signal # the process if necessary. Set by transition to inactive. self._dvr_pid = None # The driver process popen object. To terminate, signal, wait on, # or otherwise interact with the driver process via subprocess. # Set by transition to inactive. self._dvr_proc = None # The driver client for communicating to the driver process in # request-response or event publication. Set by transition to # inactive. self._dvr_client = None # UUID of the current transaction. self.transaction_id = None # List of pending transactions. self._pending_transactions = [] # Dictionary of data stream IDs for data publishing. Constructed # by stream_config agent config member during process on_init. self._data_streams = {} # Dictionary of data stream publishers. Constructed by # stream_config agent config member during process on_init. self._data_publishers = {} # Factories for stream packets. Constructed by driver # configuration information on transition to inactive. self._packet_factories = {} # Stream registrar to create publishers. Used to create # stream publishers, set during process on_init. self._stream_registrar = None # Latitude value. Set by subscription to platform. Used to # append data packets prior to publication. self._lat = 0 # Longitude value. Set by subscription to platform. Used to # append data packets prior to publication. self._lon = 0 ############################################################################### # Instrument agent parameter capabilities. ############################################################################### self.aparam_ia_param = None def on_init(self): """ Instrument agent pyon process initialization. Init objects that depend on the container services and start state machine. """ # The registrar to create publishers. self._stream_registrar = StreamPublisherRegistrar(process=self, node=self.container.node) # Set the driver config from the agent config if present. self._dvr_config = self.CFG.get('driver_config', None) # Construct stream publishers. self._construct_data_publishers() # Start state machine. self._fsm.start(self._initial_state) ############################################################################### # Event callback and handling. ############################################################################### def evt_recv(self, evt): """ Callback to receive asynchronous driver events. @param evt The driver event received. """ log.info('Instrument agent %s received driver event %s', self._proc_name, str(evt)) try: if evt['type'] == 'sample': name = evt['name'] value = evt['value'] value['lat'] = [self._lat] value['lon'] = [self._lon] value['stream_id'] = self._data_streams[name] if isinstance(value, dict): packet = self._packet_factories[name](**value) self._data_publishers[name].publish(packet) log.info('Instrument agent %s published data packet.', self._proc_name) except (KeyError, TypeError) as e: pass except Exception as e: log.info('Instrument agent %s error %s', self._proc_name, str(e)) ############################################################################### # Instrument agent state transition interface. # All the following commands are forwarded as a eponymous event to # the agent state machine and return the state handler result. ############################################################################### def acmd_power_up(self, *args, **kwargs): """ Agent power_up command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.POWER_UP, *args, **kwargs) def acmd_power_down(self, *args, **kwargs): """ Agent power_down command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.POWER_DOWN, *args, **kwargs) def acmd_initialize(self, *args, **kwargs): """ Agent initialize command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.INITIALIZE, *args, **kwargs) def acmd_reset(self, *args, **kwargs): """ Agent reset command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.RESET, *args, **kwargs) def acmd_go_active(self, *args, **kwargs): """ Agent go_active command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.GO_ACTIVE, *args, **kwargs) def acmd_go_inactive(self, *args, **kwargs): """ Agent go_inactive command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.GO_INACTIVE, *args, **kwargs) def acmd_run(self, *args, **kwargs): """ Agent run command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.RUN, *args, **kwargs) def acmd_clear(self, *args, **kwargs): """ Agent clear command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.CLEAR, *args, **kwargs) def acmd_pause(self, *args, **kwargs): """ Agent pause command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.PAUSE, *args, **kwargs) def acmd_resume(self, *args, **kwargs): """ Agent resume command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.RESUME, *args, **kwargs) def acmd_go_streaming(self, *args, **kwargs): """ Agent go_streaming command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.GO_STREAMING, *args, **kwargs) def acmd_go_direct_access(self, *args, **kwargs): """ Agent go_direct_access command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.GO_DIRECT_ACCESS, *args, **kwargs) def acmd_go_observatory(self, *args, **kwargs): """ Agent go_observatory command. Forward with args to state machine. """ return self._fsm.on_event(InstrumentAgentEvent.GO_OBSERVATORY, *args, **kwargs) ############################################################################### # Misc instrument agent command interface. ############################################################################### def acmd_get_current_state(self, *args, **kwargs): """ Query the agent current state. """ return self._fsm.get_current_state() ############################################################################### # Instrument agent capabilities interface. These functions override base # class helper functinos for specialized instrument agent behavior. ############################################################################### def _get_resource_commands(self): """ Get driver resource commands. Send event to state machine and return response or empty list if none. """ return self._fsm.on_event(InstrumentAgentEvent.GET_RESOURCE_COMMANDS) or [] def _get_resource_params(self): """ Get driver resource parameters. Send event to state machine and return response or empty list if none. """ return self._fsm.on_event(InstrumentAgentEvent.GET_RESOURCE_PARAMS) or [] ############################################################################### # Instrument agent resource interface. These functions override ResourceAgent # base class functions to specialize behavior for instrument driver resources. ############################################################################### def get_param(self, resource_id="", name=''): """ Get driver resource parameters. Send get_params event and args to agent state machine to handle request. NOTE: Need to adjust the ResourceAgent class and client for instrument interface needs. @param resource_id @param name A list of (channel, name) tuples of driver parameter to retrieve @retval Dict of (channel, name) : value parameter values if handled. """ params = name return self._fsm.on_event(InstrumentAgentEvent.GET_PARAMS, params) or {} def set_param(self, resource_id="", name='', value=''): """ Set driver resource parameters. Send set_params event and args to agent state machine to handle set driver resource parameters request. NOTE: Need to adjust the ResourceAgent class and client for instrument interface needs. @param resource_id @param name a Dict of (channel, name) : value for driver parameters to be set. @retval Dict of (channel, name) : None or Error if handled. """ params = name return self._fsm.on_event(InstrumentAgentEvent.SET_PARAMS, params) or {} def execute(self, resource_id="", command=None): """ Execute driver resource command. Send execute_resource event and args to agent state machine to handle resource execute request. @param resource_id @param command agent command object containing the driver command to execute @retval Resrouce agent command response object if handled. """ return self._fsm.on_event(InstrumentAgentEvent.EXECUTE_RESOURCE, command) ############################################################################### # Instrument agent transaction interface. ############################################################################### def acmd_start_transaction(self): """ """ pass def acmd_end_transaction(self): """ """ pass ############################################################################### # Powered down state handlers. # TBD. This state requires clarification of use. ############################################################################### def _handler_powered_down_enter(self, *args, **kwargs): """ Handler upon entry to powered_down state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_powered_down_exit(self, *args, **kwargs): """ Handler upon exit from powered_down state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) ############################################################################### # Uninitialized state handlers. # Default start state. The driver has not been configured or started. ############################################################################### def _handler_uninitialized_enter(self, *args, **kwargs): """ Handler upon entry to uninitialized state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_uninitialized_exit(self, *args, **kwargs): """ Handler upon exit from uninitialized state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_uninitialized_power_down(self, *args, **kwargs): """ Handler for power_down agent command in uninitialized state. """ result = InstErrorCode.NOT_IMPLEMENTED next_state = None return (next_state, result) def _handler_uninitialized_initialize(self, dvr_config=None, *args, **kwargs): """ Handler for initialize agent command in uninitialized state. Attempt to start driver process with driver config supplied as argument or in agent configuration. Switch to inactive state if successful. """ result = None next_state = None self._dvr_config = dvr_config or self._dvr_config result = self._start_driver(self._dvr_config) if not result: next_state = InstrumentAgentState.INACTIVE return (next_state, result) def _handler_uninitialized_reset(self, *args, **kwargs): """ Handler for reset agent command in uninitialized state. Exit and reenter uninitializeds state. """ result = None next_state = InstrumentAgentState.UNINITIALIZED return (next_state, result) ############################################################################### # Inactive state handlers. # The driver is configured and started, but not connected. ############################################################################### def _handler_inactive_enter(self, *args, **kwargs): """ Handler upon entry to inactive state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_inactive_exit(self, *args, **kwargs): """ Handler upon exit from inactive state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_inactive_initialize(self, dvr_config=None, *args, **kwargs): """ Handler for initialize command in inactive state. Stop and restart driver process using new driver config if supplied. """ result = None next_state = None result = self._stop_driver() if result: return (next_state, result) self._dvr_config = dvr_config or self._dvr_config result = self._start_driver(self._dvr_config) if not result: next_state = InstrumentAgentState.INACTIVE return (next_state, result) def _handler_inactive_reset(self, *args, **kwargs): """ Handler for reset agent command in inactive state. Stop the driver process and switch to unitinitalized state if successful. """ result = None next_state = None result = self._stop_driver() if not result: next_state = InstrumentAgentState.UNINITIALIZED return (next_state, result) def _handler_inactive_go_active(self, dvr_comms=None, *args, **kwargs): """ Handler for go_active agent command in inactive state. Attempt to establsih communications with all device channels. Switch to active state if any channels activated. """ result = None next_state = None if not dvr_comms: dvr_comms = self._dvr_config.get('comms_config', None) cfg_result = self._dvr_client.cmd_dvr('configure', dvr_comms) channels = [key for (key, val) in cfg_result.iteritems() if not InstErrorCode.is_error(val)] con_result = self._dvr_client.cmd_dvr('connect', channels) result = cfg_result.copy() for (key, val) in con_result.iteritems(): result[key] = val self._active_channels = self._dvr_client.cmd_dvr('get_active_channels') if len(self._active_channels)>0: next_state = InstrumentAgentState.IDLE return (next_state, result) ############################################################################### # Idle state handlers. ############################################################################### def _handler_idle_enter(self, *args, **kwargs): """ Handler upon entry to idle state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_idle_exit(self, *args, **kwargs): """ Handler upon exit from idle state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_idle_go_inactive(self, *args, **kwargs): """ Handler for go_inactive agent command in idle state. Attempt to disconnect and initialize all active driver channels. Swtich to inactive state if successful. """ result = None next_state = None channels = self._dvr_client.cmd_dvr('get_active_channels') dis_result = self._dvr_client.cmd_dvr('disconnect', channels) [key for (key, val) in dis_result.iteritems() if not InstErrorCode.is_error(val)] init_result = self._dvr_client.cmd_dvr('initialize', channels) result = dis_result.copy() for (key, val) in init_result.iteritems(): result[key] = val self._active_channels = self._dvr_client.cmd_dvr('get_active_channels') if len(self._active_channels)==0: next_state = InstrumentAgentState.INACTIVE return (next_state, result) def _handler_idle_reset(self, *args, **kwargs): """ Handler for reset agent command in idle state. """ result = None next_state = None return (next_state, result) def _handler_idle_run(self, *args, **kwargs): """ Handler for run agent command in idle state. Switch to observatory state. """ result = None next_state = InstrumentAgentState.OBSERVATORY return (next_state, result) ############################################################################### # Stopped state handlers. ############################################################################### def _handler_stopped_enter(self, *args, **kwargs): """ Handler for entry into stopped state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_stopped_exit(self, *args, **kwargs): """ Handler for exit from stopped state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_stopped_go_inactive(self, *args, **kwargs): """ Handler for go_inactive agent command in stopped state. """ result = None next_state = None return (next_state, result) def _handler_stopped_reset(self, *args, **kwargs): """ Handler for reset agent command in stopped state. """ result = None next_state = None return (next_state, result) def _handler_stopped_clear(self, *args, **kwargs): """ Handler for clear agent command in stopped state. """ result = None next_state = None return (next_state, result) def _handler_stopped_resume(self, *args, **kwargs): """ Handler for resume agent command in stopped state. """ result = None next_state = None return (next_state, result) ############################################################################### # Observatory state handlers. ############################################################################### def _handler_observatory_enter(self, *args, **kwargs): """ Handler upon entry to observatory state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_observatory_exit(self, *args, **kwargs): """ Handler upon exit from observatory state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_observatory_go_inactive(self, *args, **kwargs): """ Handler for go_inactive agent command in observatory state. Attempt to disconnect and initialize all active driver channels. Switch to inactive state if successful. """ result = None next_state = None channels = self._dvr_client.cmd_dvr('get_active_channels') dis_result = self._dvr_client.cmd_dvr('disconnect', channels) [key for (key, val) in dis_result.iteritems() if not InstErrorCode.is_error(val)] init_result = self._dvr_client.cmd_dvr('initialize', channels) result = dis_result.copy() for (key, val) in init_result.iteritems(): result[key] = val self._active_channels = self._dvr_client.cmd_dvr('get_active_channels') if len(self._active_channels)==0: next_state = InstrumentAgentState.INACTIVE return (next_state, result) def _handler_observatory_reset(self, *args, **kwargs): """ Handler for reset agent command in observatory state. """ result = None next_state = None return (next_state, result) def _handler_observatory_clear(self, *args, **kwargs): """ Handler for clear agent command in observatory state. """ result = None next_state = None return (next_state, result) def _handler_observatory_pause(self, *args, **kwargs): """ Handler for pause agent command in observatory state. """ result = None next_state = None return (next_state, result) def _handler_observatory_go_streaming(self, *args, **kwargs): """ Handler for go_streaming agent command in observatory state. Send start autosample command to driver and switch to streaming state if successful. """ result = None next_state = None result = self._dvr_client.cmd_dvr('start_autosample', *args, **kwargs) if isinstance(result, dict): if any([val == None for val in result.values()]): next_state = InstrumentAgentState.STREAMING return (next_state, result) def _handler_observatory_go_direct_access(self, *args, **kwargs): """ Handler for go_direct_access agent ommand in observatory state. """ result = None next_state = None return (next_state, result) def _handler_get_params(self, params, *args, **kwargs): """ Handler for get_params resource command in observatory state. Send get command to driver and return result. """ result = self._dvr_client.cmd_dvr('get', params) next_state = None return (next_state, result) def _handler_observatory_set_params(self, params, *args, **kwargs): """ Handler for set_params resource command in observatory state. Send the set command to the driver and return result. """ result = self._dvr_client.cmd_dvr('set', params) next_state = None return (next_state, result) def _handler_observatory_execute_resource(self, command, *args, **kwargs): """ Handler for execute_resource command in observatory state. Issue driver command and return the result. """ result = None next_state = None if not command: raise iex.BadRequest("execute argument 'command' not present") if not command.command: raise iex.BadRequest("command not set") cmd_res = IonObject("AgentCommandResult", command_id=command.command_id, command=command.command) cmd_res.ts_execute = get_ion_ts() command.command = 'execute_' + command.command res = self._dvr_client.cmd_dvr(command.command, *command.args, **command.kwargs) cmd_res.status = 0 cmd_res.result = res result = cmd_res return (next_state, result) ############################################################################### # Streaming state handlers. ############################################################################### def _handler_streaming_enter(self, *args, **kwargs): """ Handler for entry to streaming state. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_streaming_exit(self, *args, **kwargs): """ Handler upon exit from streaming state. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_streaming_go_inactive(self, *args, **kwargs): """ Handler for go_inactive agent command within streaming state. """ result = None next_state = None return (next_state, result) def _handler_streaming_reset(self, *args, **kwargs): """ Handler for reset agent command within streaming state. """ result = None next_state = None return (next_state, result) def _handler_streaming_go_observatory(self, *args, **kwargs): """ Handler for go_observatory agent command within streaming state. Command driver to stop autosampling, and switch to observatory mode if successful. """ result = None next_state = None result = self._dvr_client.cmd_dvr('stop_autosample', *args, **kwargs) if isinstance(result, dict): if all([val == None for val in result.values()]): next_state = InstrumentAgentState.OBSERVATORY return (next_state, result) ############################################################################### # Direct access state handlers. ############################################################################### def _handler_direct_access_enter(self, *args, **kwargs): """ Handler upon direct access entry. """ log.info('Instrument agent entered state %s', self._fsm.get_current_state()) def _handler_direct_access_exit(self, *args, **kwargs): """ Handler upon direct access exit. """ log.info('Instrument agent left state %s', self._fsm.get_current_state()) def _handler_direct_access_go_observatory(self, *args, **kwargs): """ Handler for go_observatory agent command within direct access state. """ result = None next_state = None return (next_state, result) ############################################################################### # Get resource state handlers. # Available for all states with a valid driver process. ############################################################################### def _handler_get_resource_params(self, *args, **kwargs): """ Handler for get_resource_params resource command. Send get_resource_params and args to driver and return result. """ result = self._dvr_client.cmd_dvr('get_resource_params') next_state = None return (next_state, result) def _handler_get_resource_commands(self, *args, **kwargs): """ Handler for get_resource_commands resource command. Send get_resource_commands and args to driver and return result. """ result = self._dvr_client.cmd_dvr('get_resource_commands') next_state = None return (next_state, result) ############################################################################### # Private helpers. ############################################################################### def _start_driver(self, dvr_config): """ Start the driver process and driver client. @param dvr_config The driver configuration. @param comms_config The driver communications configuration. @retval None or error. """ try: cmd_port = dvr_config['cmd_port'] evt_port = dvr_config['evt_port'] dvr_mod = dvr_config['dvr_mod'] dvr_cls = dvr_config['dvr_cls'] svr_addr = dvr_config['svr_addr'] except (TypeError, KeyError): # Not a dict. or missing required parameter. log.error('Insturment agent %s missing required parameter in start_driver.', self._proc_name) return InstErrorCode.REQUIRED_PARAMETER # Launch driver process. self._dvr_proc = ZmqDriverProcess.launch_process(cmd_port, evt_port, dvr_mod, dvr_cls) self._dvr_proc.poll() if self._dvr_proc.returncode: # Error proc didn't start. log.error('Insturment agent %s driver process did not launch.', self._proc_name) return InstErrorCode.AGENT_INIT_FAILED log.info('Insturment agent %s launched driver process.', self._proc_name) # Create client and start messaging. self._dvr_client = ZmqDriverClient(svr_addr, cmd_port, evt_port) self._dvr_client.start_messaging(self.evt_recv) log.info('Insturment agent %s driver process client started.', self._proc_name) time.sleep(1) try: retval = self._dvr_client.cmd_dvr('process_echo', 'Test.') log.info('Insturment agent %s driver process echo test: %s.', self._proc_name, str(retval)) except Exception: self._dvr_proc.terminate() self._dvr_proc.wait() self._dvr_proc = None self._dvr_client = None log.error('Insturment agent %s error commanding driver process.', self._proc_name) return InstErrorCode.AGENT_INIT_FAILED else: log.info('Insturment agent %s started its driver.', self._proc_name) self._construct_packet_factories() def _stop_driver(self): """ Stop the driver process and driver client. @retval None. """ if self._dvr_client: self._dvr_client.done() self._dvr_proc.wait() self._dvr_proc = None self._dvr_client = None self._clear_packet_factories() log.info('Insturment agent %s stopped its driver.', self._proc_name) time.sleep(1) def _construct_data_publishers(self): """ Construct the stream publishers from the stream_config agent config variable. @retval None """ stream_config = self.CFG.stream_config for (name, stream_id) in stream_config.iteritems(): self._data_streams[name] = stream_id publisher = self._stream_registrar.create_publisher(stream_id=stream_id) self._data_publishers[name] = publisher log.info('Instrumen agent %s created publisher for stream %s', self._proc_name, name) def _construct_packet_factories(self): """ Construct packet factories from packet_config member of the driver_config. @retval None """ packet_config = self._dvr_config['packet_config'] for (name, val) in packet_config.iteritems(): if val: mod = val[0] cls = val[1] import_str = 'from %s import %s' % (mod, cls) ctor_str = 'ctor = %s' % cls try: exec import_str exec ctor_str except Exception: log.error('Instrument agent %s had error creating packet factories from %s.%s', self._proc_name, mod, cls) else: self._packet_factories[name] = ctor log.info('Instrument agent %s created packet factory for stream %s', self._proc_name, name) def _clear_packet_factories(self): """ Delete packet factories. @retval None """ self._packet_factories.clear() log.info('Instrument agent %s deleted packet factories.', self._proc_name) ############################################################################### # Misc and test. ############################################################################### def test_ia(self): log.info('Hello from the instrument agent!')