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)
Example #2
0
    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)
Example #3
0
    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):
        '''
        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_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)
Example #7
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
Example #10
0
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!')