def main():
    # Change URL to point to a valid portal node.
    # If you are not interested in any subarray specific information
    # (e.g. schedule blocks), then the number can be omitted, as below.
    portal_client = KATPortalClient('http://{}/api/client'.format(args.host),
                                    on_update_callback,
                                    logger=logger)

    # First connect to the websocket, before subscribing.
    yield portal_client.connect()

    # Use a namespace with a unique name when subscribing to avoid a
    # clash with existing namespaces.
    namespace = 'namespace_' + str(uuid.uuid4())

    # Subscribe to the namespace (async call) - no messages will be received yet,
    # as this is a new namespace.
    result = yield portal_client.subscribe(namespace)
    print "Subscription result: {} identifier(s).".format(result)

    # Set the sampling strategies for the sensors of interest, on our custom
    # namespace.  In this example, we are interested in a number of patterns,
    # e.g. any sensor with "mode" in the name.  The response messages will
    # be published to our namespace every 5 seconds.
    result = yield portal_client.set_sampling_strategies(
        namespace, args.sensors, 'period 5.0')
    print "\nSet sampling strategies result: {}.\n".format(result)
Exemplo n.º 2
0
class SensorTracker(object):
    """This class heavily based on that from E. Barr (2020)
    """
    def __init__(self, host, component, sensor_name):
        log.debug(("Building sensor tracker activity tracker "
                   "on {} for sensor={} and component={}").format(
            host, sensor_name, component))
        self._client = KATPortalClient(
            host,
            on_update_callback=self.event_handler,
            logger=logging.getLogger(LOG_FILE))
        self._namespace = 'namespace_' + str(uuid.uuid4())
        self._sensor_name = sensor_name
        self._component = component
        self._full_sensor_name = None
        self._state = None
        self._has_started = False

    @coroutine
    def start(self):
        if self._has_started:
            return
        log.debug("Starting sensor tracker")
        yield self._client.connect()
        log.debug("Connected")
        result = yield self._client.subscribe(self._namespace)
        self._full_sensor_name = yield self._client.sensor_subarray_lookup(
            component=self._component, sensor=self._sensor_name,
            return_katcp_name=False)
        log.debug("Tracking sensor: {}".format(self._full_sensor_name))
        result = yield self._client.set_sampling_strategies(
            self._namespace, self._full_sensor_name,
            'event')
        sensor_sample = yield self._client.sensor_value(
            self._full_sensor_name,
            include_value_ts=False)
        self._state = sensor_sample.value
        log.debug("Initial state: {}".format(self._state))
        self._has_started = True

    @coroutine
    def stop(self):
        log.info("Unsubscribing and disconnecting")
        yield self._client.unsubscribe(self._namespace)
        yield self._client.disconnect()

    def event_handler(self, msg_dict):
        status = msg_dict['msg_data']['status']
        if status == "nominal":
            log.debug("Sensor value update: {} -> {}".format(
                self._state, msg_dict['msg_data']['value']))
            self._state = msg_dict['msg_data']['value']
            log.info("{}:{}".format(self._full_sensor_name, self._state))
Exemplo n.º 3
0
class SensorTracker(object):
    def __init__(self, host, component, sensor_name):
        log.debug(("Building sensor tracker activity tracker "
                   "on {} for sensor={} and component={}").format(
                       host, sensor_name, component))
        self._client = KATPortalClient(host,
                                       on_update_callback=self.event_handler,
                                       logger=logging.getLogger('katcp'))
        self._namespace = 'namespace_' + str(uuid.uuid4())
        self._sensor_name = sensor_name
        self._component = component
        self._full_sensor_name = None
        self._state = None
        self._has_started = False

    @coroutine
    def start(self):
        if self._has_started:
            return
        log.debug("Starting sensor tracker")
        yield self._client.connect()
        result = yield self._client.subscribe(self._namespace)
        self._full_sensor_name = yield self._client.sensor_subarray_lookup(
            component=self._component,
            sensor=self._sensor_name,
            return_katcp_name=False)
        log.debug("Tracking sensor: {}".format(self._full_sensor_name))
        result = yield self._client.set_sampling_strategies(
            self._namespace, self._full_sensor_name, 'event')
        sensor_sample = yield self._client.sensor_value(self._full_sensor_name,
                                                        include_value_ts=False)
        self._state = sensor_sample.value
        log.debug("Initial state: {}".format(self._state))
        self._has_started = True

    @coroutine
    def stop(self):
        yield self._client.unsubscribe(self._namespace)
        yield self._client.disconnect()

    def event_handler(self, msg_dict):
        status = msg_dict['msg_data']['status']
        if status == "nominal":
            log.debug("Sensor value update: {} -> {}".format(
                self._state, msg_dict['msg_data']['value']))
            self._state = msg_dict['msg_data']['value']

    @coroutine
    def wait_until(self, state, interrupt):
        log.debug("Waiting for state='{}'".format(state))
        while True:
            if self._state == state:
                log.debug("Desired state reached")
                raise Return(self._state)
            else:
                try:
                    log.debug("Waiting on interrupt in wait_until loop")
                    yield interrupt.wait(timeout=datetime.timedelta(seconds=1))
                    log.debug("Moving to next loop iteration")
                except TimeoutError:
                    continue
                else:
                    log.debug("Wait was interrupted")
                    raise Interrupt("Interrupt event was set")
Exemplo n.º 4
0
class PubSubThread (threading.Thread):

  def __init__ (self, script, id):
    threading.Thread.__init__(self)
    self.script = script
   
    self.script.log(2, "PubSubThread.__init__()")

    self.curr_utc = times.getUTCTime()
    self.prev_utc = self.curr_utc
   
    self.metadata_server = self.script.cfg["PUBSUB_ADDRESS"]
    self.logger = logging.getLogger('katportalclient.example') 
    self.logger.setLevel(logging.INFO)
    self.beam = -1
    self.sub_array = -1
    self.subs = []
    self.io_loop = []
    self.policy = "event-rate 1.0 300.0"
    self.title  = "ptuse_unconfigured"
    self.running = False
    self.restart_io_loop = True

  def configure (self):

    self.subs = []

    dp_prefix = self.data_product_prefix.replace("_", ".")
    sa_prefix = self.sub_array_prefix.replace("_", ".")

    self.subs.append ( dp_prefix + ".cbf.synchronisation.epoch")
    self.subs.append ( sa_prefix +".state")
    self.subs.append ( sa_prefix +".pool.resources")
    self.subs.append ( sa_prefix +".script.target")
    self.subs.append ( sa_prefix +".script.ra")
    self.subs.append ( sa_prefix +".script.dec")
    self.subs.append ( sa_prefix +".script.ants")
    self.subs.append ( sa_prefix +".script.observer")
    self.subs.append ( sa_prefix +".script.tsubint")
    self.subs.append ( sa_prefix +".script.experiment.id")
    self.subs.append ( sa_prefix +".script.active.sbs")
    self.subs.append ( sa_prefix +".script.description")

  # configure the pub/sub instance to 
  def set_sub_array (self, sub_array, beam):
    self.script.log(2, "PubSubThread::set_sub_array sub_array="+ str(sub_array) + " beam=" + str(beam))
    self.sub_array = str(sub_array)
    self.beam = str(beam )
    self.data_product_prefix = "data_" + self.sub_array
    self.sub_array_prefix = "subarray_" + self.sub_array
    self.title = "ptuse_beam_" + str(beam)
    self.configure()

  def run (self):
    self.script.log(1, "PubSubThread::run starting while")
    while self.restart_io_loop:

      # open connection to CAM
      self.io_loop = tornado.ioloop.IOLoop.current()
      self.io_loop.add_callback (self.connect, self.logger)

      self.running = True
      self.restart_io_loop = False
      self.io_loop.start()
      self.running = False
      self.io_loop = []

      # unsubscribe and disconnect from CAM
      self.ws_client.unsubscribe(self.title)
      self.ws_client.disconnect()

    self.script.log(2, "PubSubThread::run exiting")

  def join (self):
    self.script.log(2, "PubSubThread::join self.stop()")
    self.stop()

  def stop (self):
    self.script.log(2, "PubSubThread::stop()")
    if self.running:
      self.script.log(2, "PubSubThread::stop io_loop.stop()")
      self.io_loop.stop()
    return

  def restart (self):
    # get the IO loop to restart on the call to stop()
    self.restart_io_loop = True
    if self.running:
      self.script.log(2, "PubSubThread::restart self.stop()")
      self.stop()
    return

  @tornado.gen.coroutine
  def connect (self, logger):
    self.script.log(2, "PubSubThread::connect()")
    self.ws_client = KATPortalClient(self.metadata_server, self.on_update_callback, logger=logger)
    self.script.log(2, "PubSubThread::connect self.ws_client.connect()")
    yield self.ws_client.connect()
    self.script.log(2, "PubSubThread::connect self.ws_client.subscribe(" + self.title + ")")
    result = yield self.ws_client.subscribe(self.title)
    self.script.log(2, "PubSubThread::connect self.ws_client.set_sampling_strategies (" + self.title + ", " + str(self.subs) + ", " + self.policy + ")")
    results = yield self.ws_client.set_sampling_strategies( self.title, self.subs, self.policy) 

    for result in results:
      self.script.log(2, "PubSubThread::connect subscribed to " + str(result))

  def on_update_callback (self, msg):

    self.curr_utc = times.getUTCTime()
    if times.diffUTCTimes(self.prev_utc, self.curr_utc) > 60:
      self.script.log(2, "PubSubThread::on_update_callback: heartbeat msg="+str(msg))
      self.prev_utc = self.curr_utc

    self.update_config (msg)

  def update_cam_config (self, key, name, value):
    if self.script.cam_config[key] != value:
      self.script.log(1, "PubSubThread::update_cam_config " + key + "=" + value + " from " + name)
      self.script.cam_config[key] = value

  def update_config (self, msg):

    # ignore empty messages
    if msg == []: 
      return

    status = msg["msg_data"]["status"]
    value = msg["msg_data"]["value"]
    name = msg["msg_data"]["name"]

    self.script.log(2, "PubSubThread::update_config " + name + "=" + str(value))
   
    if name == self.sub_array_prefix + "_script_target":
      self.update_cam_config("SOURCE", name, str(value))

    elif name == self.sub_array_prefix + "_script_ra":
      self.update_cam_config("RA", name, str(value))

    elif name == self.sub_array_prefix + "_script_dec":
      self.update_cam_config("DEC", name, str(value))

    elif name == self.data_product_prefix + "_cbf_synchronisation_epoch":
      self.update_cam_config("ADC_SYNC_TIME", name, str(value))

    elif name == self.sub_array_prefix + "_script_observer":
      self.update_cam_config("OBSERVER", name, str(value))

    elif name == self.sub_array_prefix + "_script_tsubint":
      self.update_cam_config("TSUBINT", name, str(value))

    elif name == self.sub_array_prefix + "_script_ants":
      self.update_cam_config("ANTENNAE", name, str(value))

    elif name == self.sub_array_prefix + "_active_sbs":
      self.update_cam_config("SCHEDULE_BLOCK_ID", name, str(value))

    elif name == self.sub_array_prefix + "_script_experiment_id":
      self.update_cam_config("EXPERIMENT_ID", name, str(value))

    elif name == self.sub_array_prefix + "_pool_resources":
      self.update_cam_config("POOL_RESOURCES", name, str(value))

    elif name == self.sub_array_prefix + "_script_description":
      self.update_cam_config("DESCRIPTION", name, str(value))

    elif name == self.sub_array_prefix + "_state":
      self.update_cam_config("SUBARRAY_STATE", name, str(value))

    else:
      self.script.log(1, "PubSubThread::update_config no match on " + name)

    self.script.log(3, "PubSubThread::update_config done")