Example #1
0
  def setup_sensors(self):
    """Setup server sensors."""
    self.script.log(2, "KATCPServer::setup_sensors()")

    self._device_status = Sensor.discrete("device-status",
      description="Status of entire system",
      params=self.DEVICE_STATUSES,
      default="ok")
    self.add_sensor(self._device_status)

    self._beam_name = Sensor.string("beam-name",
      description="name of configured beam",
      unit="",
      default="")
    self.add_sensor(self._beam_name)

    # setup host based sensors   
    self._host_name = Sensor.string("host-name",
      description="hostname of this server",
      unit="",
      default="")
    self.add_sensor(self._host_name)

    self.script.log(2, "KATCPServer::setup_sensors lmc="+str(self.script.lmc))
    (host, port) = self.script.lmc.split(":")
    self.setup_sensors_host (host, port)

    self.script.log(2, "KATCPServer::setup_sensors beams="+str(self.script.beam))
    self.setup_sensors_beam (self.script.beam_name)
Example #2
0
    def setup_sensors(self):
        """
        @brief    Set up all sensors on the server

        @note     This is an internal method and is invoked by
                  the constructor of the base class.
        """
        super(EddMasterController, self).setup_sensors()
        self._control_mode_sensor = Sensor.string(
            "control-mode",
            description="The control mode for the EDD",
            default=self._control_mode,
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._control_mode_sensor)
        self._edd_config_sensor = Sensor.string(
            "current-config",
            description="The current configuration for the EDD backend",
            default="",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._edd_config_sensor)
        self._edd_scpi_interface_addr_sensor = Sensor.string(
            "scpi-interface-addr",
            description="The SCPI interface address for this instance",
            default="{}:{}".format(self._scpi_ip, self._scpi_port),
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._edd_scpi_interface_addr_sensor)
Example #3
0
 def setup_sensors(self):
     """
     @brief   Setup monitoring sensors
     """
     self._device_status_sensor = Sensor.discrete(
         "device-status",
         description="Health status of FIServer",
         params=self.DEVICE_STATUSES,
         default="ok",
         initial_status=Sensor.UNKNOWN)
     self.add_sensor(self._device_status_sensor)
     self._active_beams_sensor = Sensor.float(
         "nbeams",
         description="Number of beams that are currently active",
         default=1,
         initial_status=Sensor.UNKNOWN)
     self.add_sensor(self._active_beams_sensor)
     self._nchannels_sensor = Sensor.float(
         "nchannels",
         description="Number of channels in each beam",
         default=1,
         initial_status=Sensor.UNKNOWN)
     self.add_sensor(self._nchannels_sensor)
     self._integration_time_sensor = Sensor.float(
         "integration-time",
         description="The integration time for each beam",
         default=1,
         initial_status=Sensor.UNKNOWN)
     self.add_sensor(self._integration_time_sensor)
     self._nblank_phases_sensor = Sensor.integer(
         "nblank-phases",
         description="The number of blank phases",
         default=1,
         initial_status=Sensor.UNKNOWN)
     self.add_sensor(self._nblank_phases_sensor)
Example #4
0
    def add_input_stream_sensor(self, streamid):
        """
        @brief add sensors for i/o buffers for an input stream with given streamid.
        """
        self._polarization_sensors[streamid] = {}
        self._polarization_sensors[streamid]["mkrecv_sensors"] = MkrecvSensors(streamid)
        for s in self._polarization_sensors[streamid]["mkrecv_sensors"].sensors.values():
            self.add_sensor(s)
        self._polarization_sensors[streamid]["input-buffer-fill-level"] = Sensor.float(
                "input-buffer-fill-level-{}".format(streamid),
                description="Fill level of the input buffer for polarization{}".format(streamid),
                params=[0, 1])
        self.add_sensor(self._polarization_sensors[streamid]["input-buffer-fill-level"])
        self._polarization_sensors[streamid]["input-buffer-total-write"] = Sensor.float(
                "input-buffer-total-write-{}".format(streamid),
                description="Total write into input buffer for polarization {}".format(streamid),
                params=[0, 1])

        self.add_sensor(self._polarization_sensors[streamid]["input-buffer-total-write"])
        self._polarization_sensors[streamid]["output-buffer-fill-level"] = Sensor.float(
                "output-buffer-fill-level-{}".format(streamid),
                description="Fill level of the output buffer for polarization {}".format(streamid)
                )
        self._polarization_sensors[streamid]["output-buffer-total-read"] = Sensor.float(
                "output-buffer-total-read-{}".format(streamid),
                description="Total read from output buffer for polarization {}".format(streamid)
                )
        self.add_sensor(self._polarization_sensors[streamid]["output-buffer-total-read"])
        self.add_sensor(self._polarization_sensors[streamid]["output-buffer-fill-level"])
Example #5
0
    def __init__(self, name_suffix, nsum=100):
        """
        List of sensors and handler to be connected to a mkrecv process
        """
        self.sensors = {}

        self.sensors['global_payload_frac'] = Sensor.float(
            "global-payload-received-fraction-{}".format(name_suffix),
            description="Ratio of received and expected payload.",
            params=[0, 1])
        self.sensors['received_heaps_frac'] = Sensor.float(
            "received-heaps-frac-{}".format(name_suffix),
            description="Fraction of received heaps for last {} slots.".format(
                100),
            params=[0, 1])
        self.sensors['slot_received_heaps'] = Sensor.integer(
            "slot_received-heaps-{}".format(name_suffix),
            description="Received heaps.",
        )
        self.sensors['slot_expected_heaps'] = Sensor.integer(
            "slot_expected-heaps-{}".format(name_suffix),
            description="Expected heaps.",
        )

        self.sensors['missing_heaps'] = Sensor.string(
            "missing-heaps-{}".format(name_suffix),
            description="Missing heaps per multicast group.",
        )

        self.__received_heaps = 0.
        self.__expected_heaps = 0.
        self.__idx = 0
        self.__nsum = nsum

        self.__missing_heaps = np.zeros(8)
Example #6
0
    def setup_sensors(self):
        """
        @brief    Set up monitoring sensors.

        @note     The following sensors are made available on top of default
                  sensors implemented in AsynDeviceServer and its base classes.
        """
        self._device_status_sensor = Sensor.discrete(
            "device-status",
            description="Health status of ApsWorkerServer instance",
            params=self.DEVICE_STATUSES,
            default="ok",
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._device_status_sensor)

        self._capture_interface_sensor = Sensor.string(
            "capture-interface",
            description="The IP address of the NIC to be used for data capture",
            default=self._capture_interface,
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._capture_interface_sensor)

        self._state_sensor = LoggingSensor.discrete(
            "state",
            params=self.STATES,
            description="The current state of this worker instance",
            default=self.IDLE,
            initial_status=Sensor.NOMINAL)
        self._state_sensor.set_logger(log)
        self.add_sensor(self._state_sensor)
    def setup_sensors(self):
        """
        @brief    Set up monitoring sensors.

        @note     The following sensors are made available on top of defaul sensors
                  implemented in AsynDeviceServer and its base classes.

                  device-status:      Reports the health status of the FBFUSE and associated devices:
                                      Among other things report HW failure, SW failure and observation failure.
        """
        self._device_status = Sensor.discrete(
            "device-status",
            description="Health status of BLUSE",
            params=self.DEVICE_STATUSES,
            default="ok",
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._device_status)

        self._local_time_synced = Sensor.boolean(
            "local-time-synced",
            description="Indicates BLUSE is NTP syncronised.",
            default=True,  # TODO: implement actual NTP synchronization request
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._local_time_synced)

        self._version = Sensor.string(
            "version",
            description="Reports the current BLUSE version",
            default=str(self.VERSION_INFO[1:]).strip('()').replace(
                ' ', '').replace(",", '.'),  # e.g. '1.0'
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._version)
Example #8
0
 def setup_sensors(self):
     """Set up basic monitoring sensors.
     """
     for name, params in self._parser.items():
         if params["type"] == "float":
             sensor = Sensor.float(name,
                                   description=params["description"],
                                   unit=params.get("units", None),
                                   default=params.get("default", 0.0),
                                   initial_status=Sensor.UNKNOWN)
         elif params["type"] == "string":
             sensor = Sensor.string(name,
                                    description=params["description"],
                                    default=params.get("default", ""),
                                    initial_status=Sensor.UNKNOWN)
         elif params["type"] == "int":
             sensor = Sensor.integer(name,
                                     description=params["description"],
                                     default=params.get("default", 0),
                                     unit=params.get("units", None),
                                     initial_status=Sensor.UNKNOWN)
         elif params["type"] == "bool":
             sensor = Sensor.boolean(name,
                                     description=params["description"],
                                     default=params.get("default", False),
                                     initial_status=Sensor.UNKNOWN)
         else:
             raise Exception("Unknown sensor type '{0}' requested".format(
                 params["type"]))
         self.add_sensor(sensor)
 def setup_sensors(self):
     sensor = Sensor(int, "sensor1", "Test sensor 1", "count", [0, 10])
     sensor.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=1)
     self.add_sensor(sensor)
     sensor2 = Sensor(int, "sensor2", "Test sensor 2", "count", [0, 10])
     sensor2.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=0)
     self.add_sensor(sensor2)
Example #10
0
    def setup_sensors(self):
        """
        Setup monitoring sensors.

        The EDDPipeline base provides default sensors. Should be called by
        every subclass to ensure default sensors are available.

        """
        self._pipeline_sensor_status = Sensor.discrete(
            "pipeline-status",
            description="Status of the pipeline",
            params=self.PIPELINE_STATES,
            default="idle",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._pipeline_sensor_status)

        self._edd_config_sensor = Sensor.string(
            "current-config",
            description="The current configuration for the EDD backend",
            default=json.dumps(self._config, indent=4),
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._edd_config_sensor)

        self._log_level = Sensor.string("log-level",
                                        description="Log level",
                                        default=logging.getLevelName(
                                            log.level),
                                        initial_status=Sensor.NOMINAL)
        self.add_sensor(self._log_level)
Example #11
0
  def setup_sensors_beam (self, beam):

    b = str(beam)
    self._beam_sensors = {}

    self.script.log(2, "KATCPServer::setup_sensors_beam ="+b)

    self._beam_sensors["observing"] = Sensor.boolean("observing",
      description="Beam " + b + " is observing",
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["observing"])

    self._beam_sensors["snr"] = Sensor.float("snr",
      description="SNR of Beam "+b,
      unit="",
      params=[0,1e9],
      default=0)
    self.add_sensor(self._beam_sensors["snr"])

    self._beam_sensors["power"] = Sensor.float("power",
      description="Power Level of Beam "+b,
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["power"])

    self._beam_sensors["integrated"] = Sensor.float("integrated",
      description="Length of integration for Beam "+b,
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["integrated"])
Example #12
0
 def __init__(self, name, description, units, stype, device, proxy,
              *formatted_params):
     self.basename = name
     self.device = device
     stype = Sensor.parse_type(stype)
     params = Sensor.parse_params(stype, formatted_params)
     Sensor.__init__(self, stype, device.name + '.' + name, description,
                     units, params=params)
    def periodic_plot_snapshot(self):
        log.debug("Start periodic plot")

        passthrough = ["rxs.packetizer.systemstatus.snapshot.totalpwr.h", "rxs.packetizer.systemstatus.snapshot.totalpwr.v", "rxs.packetizer.1pps.length", "rxs.packetizer.1pps.last", "s-band.center-frequency", "s-band.bandwidth", "s-band.noise-diode", "s-band.sampling-rate", "s-band.time.synchronisation-epoch", "rxs.packetizer.1pps.length", "rxs.packetizer.40g.selected-filter", "rxs.packetizer.device-status"]

        self.__pass_through_sensors = {}

        if not self.has_sensor(passthrough[0]):
            # Checking first is enough
            log.debug("Adding pass-through sensors")
            yield self._client._client.until_synced()
            log.debug("Client synced through sensors")
            sensor_list = yield self._client._client.list_sensors()
            for st in sensor_list:
                if st.name not in passthrough:
                    log.debug(" - ignoring {}".format(st[1]))
                    continue

                log.debug(" - adding {}".format(st))
                try:
                    if st.type == "discrete":
                        t = "string"
                    else:
                        t = st.type
                    s = Sensor(Sensor.parse_type(t), st.name, st.description, st.units)
                    self.__pass_through_sensors[st.name] = st.object
                except Exception as E:
                    log.exception(E)
                self.add_sensor(s)
        else:
            log.debug("pass through sensors already added")


        log.debug("Starting periodic plot")
        with ProcessPoolExecutor(max_workers=1) as executor:
            try:
                while self.__plotting:
                    for key in passthrough:
                        sensor = self.get_sensor(key)
                        v =  yield self.__pass_through_sensors[key].get_reading() 
                        sensor.set_value(v.value, timestamp=v.timestamp)
                    starttime = time.time()
                    data = yield self._client.get_snapshot()
                    plt = yield executor.submit(plot_script, data)
                    log.debug("Setting bandpass sensor with timestamp %", v.timestamp)
                    self._bandpass.set_value(plt[0])
                    self._level.set_value(plt[1])

                    duration = time.time() - starttime
                    log.debug("Plot duration: {} s".format(duration))
                    if duration > self._config['snapshot_frequency']:
                        log.warning("Plot duration {} larger than plot interval!".format(duration, self._config["nplot"]))
                    else:
                        yield sleep(self._config['snapshot_frequency'] - duration)
            except Exception as E:
                log.error("Error in periodic plot. Abandon plotting.")
                log.exception(E)
Example #14
0
 def setup_sensors(self):
     sensor = Sensor(int, "sensor1", "Test sensor 1", "count",
                     [0,10])
     sensor._timestamp = 1
     self.add_sensor(sensor)
     sensor2 = Sensor(int, "sensor2", "Test sensor 2", "count",
                      [0, 10])
     sensor2._timestamp = 0
     self.add_sensor(sensor2)
Example #15
0
    def setup_sensors(self):
        """
        @brief  Set up monitoring sensors.

        @note   The following sensors are made available on top of default sensors
                implemented in AsynDeviceServer and its base classes.

                device-status:  Reports the health status of the controller and associated devices:
                                Among other things report HW failure, SW failure and observation failure.

                local-time-synced:  Indicates whether the local time of the servers
                                    is synchronised to the master time reference (use NTP).
                                    This sensor is aggregated from all nodes that are part
                                    of FBF and will return "not sync'd" if any nodes are
                                    unsyncronised.

                products:   The list of product_ids that controller is currently handling
        """
        self._device_status = Sensor.discrete(
            "device-status",
            description="Health status of FBFUSE",
            params=self.DEVICE_STATUSES,
            default="ok",
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._device_status)

        self._local_time_synced = Sensor.boolean(
            "local-time-synced",
            description="Indicates FBF is NTP syncronised.",
            default=True,
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._local_time_synced)

        def ntp_callback():
            log.debug("Checking NTP sync")
            try:
                synced = check_ntp_sync()
            except Exception:
                log.exception("Unable to check NTP sync")
                self._local_time_synced.set_value(False)
            else:
                if not synced:
                    log.warning("Server is not NTP synced")
                self._local_time_synced.set_value(synced)

        ntp_callback()
        self._ntp_callback = PeriodicCallback(ntp_callback,
                                              NTP_CALLBACK_PERIOD)
        self._ntp_callback.start()

        self._products_sensor = Sensor.string(
            "products",
            description="The names of the currently configured products",
            default="",
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._products_sensor)
Example #16
0
    def setup_sensors(self):
        """
        @brief    Set up monitoring sensors.

        Sensor list:
        - device-status
        - local-time-synced
        - fbf0-status
        - fbf1-status

        @note     The following sensors are made available on top of default sensors
                  implemented in AsynDeviceServer and its base classes.

                  device-status:      Reports the health status of the FBFUSE and associated devices:
                                      Among other things report HW failure, SW failure and observation failure.
        """
        self._device_status_sensor = Sensor.discrete(
            "device-status",
            description = "Health status of FbfWorkerServer instance",
            params = self.DEVICE_STATUSES,
            default = "ok",
            initial_status = Sensor.NOMINAL)
        self.add_sensor(self._device_status_sensor)

        self._state_sensor = LoggingSensor.discrete(
            "state",
            params = self.STATES,
            description = "The current state of this worker instance",
            default = self.IDLE,
            initial_status = Sensor.NOMINAL)
        self._state_sensor.set_logger(log)
        self.add_sensor(self._state_sensor)

        self._delay_client_sensor = Sensor.string(
            "delay-engine-server",
            description = "The address of the currently set delay engine",
            default = "",
            initial_status = Sensor.UNKNOWN)
        self.add_sensor(self._delay_client_sensor)

        self._antenna_capture_order_sensor = Sensor.string(
            "antenna-capture-order",
            description = "The order in which the worker will capture antennas internally",
            default = "",
            initial_status = Sensor.UNKNOWN)
        self.add_sensor(self._antenna_capture_order_sensor)

        self._mkrecv_header_sensor = Sensor.string(
            "mkrecv-header",
            description = "The MKRECV/DADA header used for configuring capture with MKRECV",
            default = "",
            initial_status = Sensor.UNKNOWN)
        self.add_sensor(self._mkrecv_header_sensor)
Example #17
0
 def __init__(self,polling_interval=1):
     super(CpuMonitor,self).__init__(polling_interval)
     for cpu_idx in range(psutil.cpu_count()):
         self._sensors["cpu%02d_percent"%cpu_idx] = Sensor.float("cpu%02d_percent"%cpu_idx,
             description = "percentage usage of cpu%02d"%cpu_idx,
             params = [0,200],
             unit = "%",
             default = 0)
         self._sensors["cpu%02d_temperature"%cpu_idx] = Sensor.float("cpu%02d_temperature"%cpu_idx,
             description = "temperature of cpu%02d"%cpu_idx,
             params = [0,200],
             unit = "Celsius",
             default = 0)
Example #18
0
    def setup_sensors(self):
        """Setup server sensors."""
        self.script.log(2, "KATCPServer::setup_sensors()")

        self._device_status = Sensor.discrete(
            "device-status",
            description="Status of entire system",
            params=self.DEVICE_STATUSES,
            default="ok")
        self.add_sensor(self._device_status)

        self._beam_name = Sensor.string("beam-name",
                                        description="name of configured beam",
                                        unit="",
                                        default="")
        self.add_sensor(self._beam_name)

        # setup host based sensors
        self._host_name = Sensor.string("host-name",
                                        description="hostname of this server",
                                        unit="",
                                        default="")
        self.add_sensor(self._host_name)

        # GUI URL TODO remove hardcoding
        guis = [{
            "title": "PTUSE Web Interface",
            "description": "Live Pulsar timing monitoring plots",
            "href": self.script.cfg["SPIP_ADDRESS"]
        }]
        encoded = json.dumps(guis)
        self._gui_urls = Sensor.string("gui-urls",
                                       description="PTUSE GUI URL",
                                       unit="",
                                       default=encoded)
        self.add_sensor(self._gui_urls)
        self._gui_urls.set_value(encoded)

        # give LMC some time to prepare the socket
        time.sleep(5)

        self.script.log(
            1, "KATCPServer::setup_sensors lmc=" + str(self.script.lmc))
        (host, port) = self.script.lmc.split(":")
        self.setup_sensors_host(host, port)

        self.script.log(
            2, "KATCPServer::setup_sensors beams=" + str(self.script.beam))
        self.setup_sensors_beam(self.script.beam_name)
Example #19
0
    def setup_sensors(self):
        super(PafMasterController, self).setup_sensors()
        self._paf_config_sensor = Sensor.string(
            "current-config",
            description="The currently set configuration for the PAF backend",
            default="",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._paf_config_sensor)

        self._status_server_sensor = Sensor.address(
            "status-server-address",
            description="The address of the status server",
            default="",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._status_server_sensor)
Example #20
0
 def __init__(self,polling_interval=1):
     super(MemoryMonitor,self).__init__(polling_interval)
     for node in get_meminfo().keys():
         name_ = "%s_memory_size"%node
         self._sensors[name_] = Sensor.float(name_,
             description = "total memory on %s"%node,
             params = [8192,1e9],
             unit = "MB",
             default = 0)
         name_ = "%s_memory_avail"%node
         self._sensors[name_] = Sensor.float(name_,
             description = "available memory on %s"%node,
             params = [8192,1e9],
             unit = "MB",
             default = 0)
Example #21
0
    def setup_sensors(self):
        """Setup some server sensors."""

        self._time_result = Sensor(Sensor.TIMESTAMP, "time.result",
            "Last ?time result.", "")

        self._read_result = Sensor(Sensor.STRING, "read.result",
            "Last ?read result.", "")
        
        self._write_result = Sensor(Sensor.STRING, "write.result",
            "Last ?write result.", "")


        self.add_sensor(self._time_result)
        self.add_sensor(self._read_result)
        self.add_sensor(self._write_result)
Example #22
0
    def setup_sensors(self):
        """
        @brief    Setup the default KATCP sensors.

        @note     As this call is made only upon an PAF configure call a mass inform
                  is required to let connected clients know that the proxy interface has
                  changed.
        """
        self._state_sensor = LoggingSensor.discrete(
            "state",
            description="Denotes the state of this PAF instance",
            params=self.STATES,
            default=self.IDLE,
            initial_status=Sensor.NOMINAL)
        self._state_sensor.set_logger(self.log)
        self.add_sensor(self._state_sensor)

        self._servers_sensor = Sensor.string(
            "servers",
            description=
            "The worker server instances currently allocated to this product",
            default=",".join([
                "{s.hostname}:{s.port}".format(s=server)
                for server in self._servers
            ]),
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._servers_sensor)
        self._parent.mass_inform(Message.inform('interface-changed'))
        self._state_sensor.set_value(self.IDLE)
Example #23
0
    def request_target_configuration_start(self, req, product_id,
                                           target_string):
        """
        @brief      Set up a beam configuration sensor for the FBFUSE instance

        @param      product_id     The product identifier
        @param      target_string  A KATPOINT target string (boresight pointing position)
        """
        log.info(
            "Received target configuration request for '{}' with target: {}".
            format(product_id, target_string))
        if not product_id in self._configuration_sensors:
            log.debug(
                "Creating configuration sensor for '{}'".format(product_id))
            self._configuration_sensors[product_id] = Sensor.string(
                "{}-beam-position-configuration".format(product_id),
                description="Configuration description for FBF beam placement",
                default="",
                initial_status=Sensor.UNKNOWN)
            self.add_sensor(self._configuration_sensors[product_id])
            self.mass_inform(Message.inform('interface-changed'))
        initial_config = yield self.get_target_config(product_id,
                                                      target_string)
        self.update_target_config(product_id, initial_config)
        raise Return(("ok", ))
Example #24
0
 def __init__(self,volumes,polling_interval=1):
     super(DiskMonitor,self).__init__(polling_interval)
     self._volumes = volumes
     for name,path in self._volumes:
         name_ = "%s_partition_size"%name
         self._sensors[name_] = Sensor.float(name_,
             description = "total size of %s partition"%name,
             params = [8192,1e9],
             unit = "MB",
             default = 0)
         name_ = "%s_partition_avail"%name
         self._sensors[name_] = Sensor.float(name_,
             description = "available space on %s partition"%name,
             params = [8192,1e9],
             unit = "MB",
             default = 0)
Example #25
0
 def setup_sensors(self):
     sensor = Sensor(int, "sensor1", "Test sensor 1", "count",
                     [0, 10])
     sensor.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=1)
     self.add_sensor(sensor)
     sensor2 = Sensor(int, "sensor2", "Test sensor 2", "count",
                      [0, 10])
     sensor2.set_value(sensor.value(), status=Sensor.UNKNOWN, timestamp=0)
     self.add_sensor(sensor2)
Example #26
0
    def setup_sensors(self):
        """
        @brief Setup monitoring sensors
        """
        self._beam_sensor0 = Sensor.float("beam0.id",
                                          description="The ID of current beam",
                                          default=0,
                                          initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._beam_sensor0)

        self._instant_sensor0 = Sensor.float(
            "beam0.inst-packet-loss-fraction",
            description="The instanteous packet loss fraction",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._instant_sensor0)

        self._time_sensor0 = Sensor.float(
            "beam0.time-elapsed",
            description="The time so far in seconds",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._time_sensor0)

        self._average_sensor0 = Sensor.float(
            "beam0.total-packet-loss-fraction",
            description="Fraction of packets lost",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._average_sensor0)

        self._beam_sensor1 = Sensor.float("beam1.id",
                                          description="The ID of current beam",
                                          default=0,
                                          initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._beam_sensor1)

        self._instant_sensor1 = Sensor.float(
            "beam1.inst-packet-loss-fraction",
            description="The instanteous packet loss fraction",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._instant_sensor1)

        self._time_sensor1 = Sensor.float(
            "beam1.time-elapsed",
            description="The time so far in seconds",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._time_sensor1)

        self._average_sensor1 = Sensor.float(
            "beam1.total-packet-loss-fraction",
            description="Fraction of packets lost",
            default=0,
            initial_status=Sensor.UNKNOWN)
        self.sensors.append(self._average_sensor1)
Example #27
0
 def test_differential_timestamp(self):
     # Test that the timetamp differential is stored correctly as
     # seconds. This is mainly to check the conversion of the katcp spec from
     # milliseconds to seconds for katcp v5 spec.
     time_diff = 4.12                  # Time differential in seconds
     ts_sensor = Sensor(Sensor.TIMESTAMP, 'ts', 'ts sensor', '')
     diff = sampling.SampleDifferential(self.inform, ts_sensor, time_diff)
     self.assertEqual(diff._threshold, time_diff)
Example #28
0
    def add_input_stream_sensor(self, streamid):
        """
        Add sensors for i/o buffers for an input stream with given streamid.
        """
        self._polarization_sensors[streamid] = {}
        self._polarization_sensors[streamid]["mkrecv_sensors"] = MkrecvSensors(
            streamid)
        for s in self._polarization_sensors[streamid][
                "mkrecv_sensors"].sensors.values():
            self.add_sensor(s)
        self._polarization_sensors[streamid][
            "input-buffer-fill-level"] = Sensor.float(
                "input-buffer-fill-level-{}".format(streamid),
                description="Fill level of the input buffer for polarization{}"
                .format(streamid),
                initial_status=Sensor.UNKNOWN,
                params=[0, 1])
        self.add_sensor(
            self._polarization_sensors[streamid]["input-buffer-fill-level"])
        self._polarization_sensors[streamid][
            "input-buffer-total-write"] = Sensor.float(
                "input-buffer-total-write-{}".format(streamid),
                description="Total write into input buffer for polarization {}"
                .format(streamid),
                initial_status=Sensor.UNKNOWN,
                params=[0, 1])

        self.add_sensor(
            self._polarization_sensors[streamid]["input-buffer-total-write"])
        self._polarization_sensors[streamid][
            "output-buffer-fill-level"] = Sensor.float(
                "output-buffer-fill-level-{}".format(streamid),
                description="Fill level of the output buffer for polarization {}"
                .format(streamid),
                initial_status=Sensor.UNKNOWN)
        self._polarization_sensors[streamid][
            "output-buffer-total-read"] = Sensor.float(
                "output-buffer-total-read-{}".format(streamid),
                description="Total read from output buffer for polarization {}"
                .format(streamid),
                initial_status=Sensor.UNKNOWN)
        self.add_sensor(
            self._polarization_sensors[streamid]["output-buffer-total-read"])
        self.add_sensor(
            self._polarization_sensors[streamid]["output-buffer-fill-level"])
        self.mass_inform(Message.inform('interface-changed'))
Example #29
0
    def add_sensors(self, sensor_infos):
        """Add fake sensors

        sensor_infos is a dict <sensor-name> : (
            <description>, <unit>, <sensor-type>, <params>*)
        The sensor info is string-reprs of whatever they are, as they would be on
        the wire in a real KATCP connection. Values are passed to a katcp.Message object,
        so some automatic conversions are done, hence it is OK to pass numbers without
        stringifying them.

        """
        # Check sensor validity. parse_type() and parse_params should raise if not OK
        for s_name, s_info in sensor_infos.items():
            s_type = Sensor.parse_type(s_info[2])
            s_params = Sensor.parse_params(s_type, s_info[3:])
        self.fake_sensor_infos.update(sensor_infos)
        self._fic._interface_changed.set()
Example #30
0
    def add_sensors(self, sensor_infos):
        """Add fake sensors

        sensor_infos is a dict <sensor-name> : (
            <description>, <unit>, <sensor-type>, <params>*)
        The sensor info is string-reprs of whatever they are, as they would be on
        the wire in a real KATCP connection. Values are passed to a katcp.Message object,
        so some automatic conversions are done, hence it is OK to pass numbers without
        stringifying them.

        """
        # Check sensor validity. parse_type() and parse_params should raise if not OK
        for s_name, s_info in sensor_infos.items():
            s_type = Sensor.parse_type(s_info[2])
            s_params = Sensor.parse_params(s_type, s_info[3:])
        self.fake_sensor_infos.update(sensor_infos)
        self._fic._interface_changed.set()
    def setup_sensors(self):
        """
        @brief Setup monitoring sensors
        """
        EDDPipeline.setup_sensors(self)

        self._bandpass = Sensor.string(
            "bandpass_PNG",
            description="band-pass data (base64 encoded)",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._bandpass)

        self._level = Sensor.string(
            "level_PNG",
            description="ADC Level (base64 encoded)",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._level)
Example #32
0
 def request_add_sensor(self, msg):
     self.factory.add_sensor(
         Sensor(int,
                'int_sensor%d' % len(self.factory.sensors),
                'descr',
                'unit',
                params=[-10, 10]))
     return Message.reply('add-sensor', 'ok')
    def setup_sensors(self):
        """
        @brief    Set up monitoring sensors.
        """
        self._target_sensors = []
        for beam in self._beam_manager.get_beams():
            sensor = Sensor.string("{}-target".format(beam.idx),
                                   description="Target for beam {}".format(
                                       beam.idx),
                                   default=beam.target.format_katcp(),
                                   initial_status=Sensor.UNKNOWN)
            self.add_sensor(sensor)
            beam.register_observer(lambda beam, sensor=sensor: sensor.
                                   set_value(beam.target.format_katcp()))

        antenna_map = {
            a.name: a.format_katcp()
            for a in self._beam_manager.antennas
        }
        self._antennas_sensor = Sensor.string(
            "antennas",
            description=
            "JSON breakdown of the antennas (in KATPOINT format) associated with this delay engine",
            default=json.dumps(antenna_map),
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._antennas_sensor)

        self._phase_reference_sensor = Sensor.string(
            "phase-reference",
            description=
            "A KATPOINT target string denoting the F-engine phasing centre",
            default="unset,radec,0,0",
            initial_status=Sensor.UNKNOWN)
        self.add_sensor(self._phase_reference_sensor)

        reference_antenna = Antenna(
            "reference,{ref.lat},{ref.lon},{ref.elev}".format(
                ref=self._beam_manager.antennas[0].ref_observer))
        self._reference_antenna_sensor = Sensor.string(
            "reference-antenna",
            description=
            "A KATPOINT antenna string denoting the reference antenna",
            default=reference_antenna.format_katcp(),
            initial_status=Sensor.NOMINAL)
        self.add_sensor(self._reference_antenna_sensor)
Example #34
0
    def setup_sensors(self):
        self._device_status = Sensor.discrete(
            "device-status",
            description="Health status of PafBackendController",
            params=self.DEVICE_STATUSES,
            default="ok",
            initial_status=Sensor.UNKNOWN)

        self.add_sensor(self._device_status)
Example #35
0
  def setup_sensors(self):
    """Setup server sensors."""
    self.script.log(2, "KATCPServer::setup_sensors()")

    self._device_status = Sensor.discrete("device-status",
      description="Status of entire system",
      params=self.DEVICE_STATUSES,
      default="ok")
    self.add_sensor(self._device_status)

    self._beam_name = Sensor.string("beam-name",
      description="name of configured beam",
      unit="",
      default="")
    self.add_sensor(self._beam_name)

    # setup host based sensors   
    self._host_name = Sensor.string("host-name",
      description="hostname of this server",
      unit="",
      default="")
    self.add_sensor(self._host_name)

    # GUI URL TODO remove hardcoding
    guis = [ { "title": "PTUSE Web Interface",
               "description": "Live Pulsar timing monitoring plots", 
               "href": self.script.cfg["SPIP_ADDRESS"] } ]
    encoded = json.dumps(guis)
    self._gui_urls = Sensor.string("gui-urls",
      description="PTUSE GUI URL",
      unit="",
      default=encoded)
    self.add_sensor(self._gui_urls) 
    self._gui_urls.set_value(encoded)

    # give LMC some time to prepare the socket
    time.sleep(5)

    self.script.log(1, "KATCPServer::setup_sensors lmc="+str(self.script.lmc))
    (host, port) = self.script.lmc.split(":")
    self.setup_sensors_host (host, port)

    self.script.log(2, "KATCPServer::setup_sensors beams="+str(self.script.beam))
    self.setup_sensors_beam (self.script.beam_name)
Example #36
0
    def setup_sensors(self):
        """Setup some server sensors."""
        self._add_result = Sensor.float("add.result",
            "Last ?add result.", "", [-10000, 10000])
        self._add_result.set_value(0, Sensor.UNREACHABLE)

        self._time_result = Sensor.timestamp("time.result",
            "Last ?time result.", "")
        self._time_result.set_value(0, Sensor.INACTIVE)

        self._eval_result = Sensor.string("eval.result",
            "Last ?eval result.", "")
        self._eval_result.set_value('', Sensor.UNKNOWN)

        self._fruit_result = Sensor.discrete("fruit.result",
            "Last ?pick-fruit result.", "", self.FRUIT)
        self._fruit_result.set_value('apple', Sensor.ERROR)

        self.add_sensor(self._add_result)
        self.add_sensor(self._time_result)
        self.add_sensor(self._eval_result)
        self.add_sensor(self._fruit_result)
    def setup_sensors(self):
        """Setup some server sensors."""
        self._add_result = Sensor.float("add.result",
            "Last ?add result.", "", [-10000, 10000])

        self._time_result = Sensor.timestamp("time.result",
            "Last ?time result.", "")

        self._eval_result = Sensor.string("eval.result",
            "Last ?eval result.", "")

        self._fruit_result = Sensor.discrete("fruit.result",
            "Last ?pick-fruit result.", "", self.FRUIT)

        self._james_result = Sensor.string("james.result",
            "Last ?james result.", "")

        self.add_sensor(self._add_result)
        self.add_sensor(self._time_result)
        self.add_sensor(self._eval_result)
        self.add_sensor(self._fruit_result)
        self.add_sensor(self._james_result)
Example #38
0
    def setup_sensors(self):
        """Setup some server sensors."""
        self._add_result = Sensor(Sensor.FLOAT, "add.result",
            "Last ?add result.", "", [-10000, 10000])

        self._time_result = Sensor(Sensor.TIMESTAMP, "time.result",
            "Last ?time result.", "")

        self._eval_result = Sensor(Sensor.STRING, "eval.result",
            "Last ?eval result.", "")

        self._fruit_result = Sensor(Sensor.DISCRETE, "fruit.result",
            "Last ?pick-fruit result.", "", self.FRUIT)

        self._band_result = Sensor(Sensor.DISCRETE, "band.result",
            "Last ?pick-band result.", "", self.BAND)


        self.add_sensor(self._add_result)
        self.add_sensor(self._time_result)
        self.add_sensor(self._eval_result)
        self.add_sensor(self._fruit_result)
        self.add_sensor(self._band_result)
Example #39
0
  def setup_sensors_beam (self, beam):

    b = str(beam)
    self._beam_sensors = {}

    self.script.log(2, "KATCPServer::setup_sensors_beam beam="+b)

    self._beam_sensors["observing"] = Sensor.boolean("observing",
      description="Beam " + b + " is observing",
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["observing"])

    self._beam_sensors["snr"] = Sensor.float("snr",
      description="SNR of Beam "+b,
      unit="",
      params=[0,1e9],
      default=0)
    self.add_sensor(self._beam_sensors["snr"])

    self._beam_sensors["beamformer_stddev_polh"] = Sensor.float("beamformer_stddev_polh",
      description="Standard deviation of beam voltages for pol H",
      unit="",
      params=[0,127],
      default=0)
    self.add_sensor(self._beam_sensors["beamformer_stddev_polh"])

    self._beam_sensors["beamformer_stddev_polv"] = Sensor.float("beamformer_stddev_polv",
      description="Standard deviation of beam voltages for pol V",
      unit="",
      params=[0,127],
      default=0)
    self.add_sensor(self._beam_sensors["beamformer_stddev_polv"])

    self._beam_sensors["integrated"] = Sensor.float("integrated",
      description="Length of integration for Beam "+b,
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["integrated"])

    self._beam_sensors["input_channels"] = Sensor.integer("input_channels",
      description="Number of configured input channels for Beam "+b,
      unit="",
      default=0)
    self.add_sensor(self._beam_sensors["input_channels"])
Example #40
0
    def __init__(self, sensor_description, sensor_manager):
        """Subclasses must arrange to call this in their __init__().

        Parameters
        ----------
        sensor_description : dict
           Description of the KATCP sensor, with keys same as the parameters of
           :class:`katcp.Sensor`
        sensor_manager : :class:`KATCPSensorsManager` instance
           Manages sensor strategies, allows sensor polling, and provides time
        """
        self._manager = sensor_manager
        self.clear_listeners()
        self._reading = KATCPSensorReading(0, 0, Sensor.UNKNOWN, None)
        # We'll be abusing a katcp.Sensor object slightly to make use of its
        # parsing and formatting functionality
        self._sensor = Sensor(**sensor_description)
        self._name = self._sensor.name
        # Overide the katpc.Sensor's set method with ours
        self._sensor.set = self.set
        # Steal the the katcp.Sensor's set_formatted method. Since we overrode
        # its set() method with ours, calling set_formatted will result in this
        # KATCPSensor object's value being set.
        self.set_formatted = self._sensor.set_formatted
Example #41
0
class KATCPSensor(object):
    """Wrapper around a specific KATCP sensor on a given KATCP device.

    Each available KATCP sensor for a particular device has an associated
    :class:`KATCPSensor` object in the object hierarchy. This wrapper is mainly
    for interactive convenience. It provides the KATCP request help string as a
    docstring and registers listeners. Subclasses need to call the base class
    version of __init__().
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, sensor_description, sensor_manager):
        """Subclasses must arrange to call this in their __init__().

        Parameters
        ----------
        sensor_description : dict
           Description of the KATCP sensor, with keys same as the parameters of
           :class:`katcp.Sensor`
        sensor_manager : :class:`KATCPSensorsManager` instance
           Manages sensor strategies, allows sensor polling, and provides time
        """
        self._manager = sensor_manager
        self.clear_listeners()
        self._reading = KATCPSensorReading(0, 0, Sensor.UNKNOWN, None)
        # We'll be abusing a katcp.Sensor object slightly to make use of its
        # parsing and formatting functionality
        self._sensor = Sensor(**sensor_description)
        self._name = self._sensor.name
        # Overide the katpc.Sensor's set method with ours
        self._sensor.set = self.set
        # Steal the the katcp.Sensor's set_formatted method. Since we overrode
        # its set() method with ours, calling set_formatted will result in this
        # KATCPSensor object's value being set.
        self.set_formatted = self._sensor.set_formatted

    @property
    def parent_name(self):
        """Name of the parent of this KATCPSensor"""
        return self._manager.resource_name

    @property
    def name(self):
        """Name of this KATCPSensor"""
        return self._name

    @property
    def normalised_name(self):
        """Normalised name of this KATCPSensor that can be used as a python identifier"""
        return escape_name(self._name)

    @property
    def reading(self):
        """Most recently received sensor reading as KATCPSensorReading instance"""
        return self._reading

    @property
    def value(self):
        return self._reading.value

    @property
    def status(self):
        return self._reading.status

    @property
    def sampling_strategy(self):
        """Current sampling strategy"""
        return self._manager.get_sampling_strategy(self.name)

    @property
    def description(self):
        return self._sensor.description

    @property
    def units(self):
        return self._sensor.units

    @property
    def type(self):
        return self._sensor.type

    def parse_value(self, s_value):
        """Parse a value from a string.

        Parameters
        ----------
        s_value : str
            A string value to attempt to convert to a value for
            the sensor.

        Returns
        -------
        value : object
            A value of a type appropriate to the sensor.

        """
        return self._sensor.parse_value(s_value)

    def set_strategy(self, strategy, params=None):
        """Set current sampling strategy for sensor.
        Add this footprint for backwards compatibility.

        Parameters
        ----------

        strategy : seq of str or str
            As tuple contains (<strat_name>, [<strat_parm1>, ...]) where the strategy
            names and parameters are as defined by the KATCP spec. As str contains the
            same elements in space-separated form.
        params : seq of str or str
            (<strat_name>, [<strat_parm1>, ...])

        Returns
        -------
        done : tornado Future that resolves when done or raises KATCPSensorError

        """
        if not params:
            param_args = []
        elif isinstance(params, basestring):
            param_args = [str(p) for p in params.split(' ')]
        else:
            if not isinstance(params, collections.Iterable):
                params = (params,)
            param_args = [str(p) for p in params]
        samp_strategy = " ".join([strategy] + param_args)
        return self._manager.set_sampling_strategy(self.name, samp_strategy)

    def set_sampling_strategy(self, strategy):
        """Set current sampling strategy for sensor

        Parameters
        ----------

        strategy : seq of str or str
            As tuple contains (<strat_name>, [<strat_parm1>, ...]) where the strategy
            names and parameters are as defined by the KATCP spec. As str contains the
            same elements in space-separated form.

        Returns
        -------
        done : tornado Future that resolves when done or raises KATCPSensorError

        """
        return self._manager.set_sampling_strategy(self.name, strategy)

    def register_listener(self, listener, reading=False):
        """Add a callback function that is called when sensor value is updated.
        The callback footprint is received_timestamp, timestamp, status, value.

        Parameters
        ----------
        listener : function
            Callback signature: if reading
            listener(katcp_sensor, reading) where
                `katcp_sensor` is this KATCPSensor instance
                `reading` is an instance of :class:`KATCPSensorReading`
            Callback signature: default, if not reading
                listener(received_timestamp, timestamp, status, value)
        """
        listener_id = hashable_identity(listener)
        self._listeners[listener_id] = (listener, reading)
        logger.debug(
                    'Register listener for {}'
                    .format(self.name))

    def unregister_listener(self, listener):
        """Remove a listener callback added with register_listener().

        Parameters
        ----------
        listener : function
            Reference to the callback function that should be removed

        """
        listener_id = hashable_identity(listener)
        self._listeners.pop(listener_id, None)

    def is_listener(self, listener):
        listener_id = hashable_identity(listener)
        return listener_id in self._listeners

    def clear_listeners(self):
        """Clear any registered listeners to updates from this sensor."""
        self._listeners = {}

    def call_listeners(self, reading):
        logger.debug(
                    'Calling listeners {}'
                    .format(self.name))
        for listener, use_reading in self._listeners.values():
            try:
                if use_reading:
                    listener(self, reading)
                else:
                    listener(reading.received_timestamp, reading.timestamp,
                             reading.status, reading.value)
            except Exception:
                logger.exception(
                    'Unhandled exception calling KATCPSensor callback {0!r}'
                    .format(listener))

    def set(self, timestamp, status, value):
        """Set sensor with a given received value, matches :meth:`katcp.Sensor.set`"""
        received_timestamp = self._manager.time()
        reading = KATCPSensorReading(received_timestamp, timestamp, status, value)
        self._reading = reading
        self.call_listeners(reading)

    def set_value(self, value, status=Sensor.NOMINAL, timestamp=None):
        """Set sensor value with optinal specification of status and timestamp"""
        if timestamp is None:
            timestamp = self._manager.time()
        self.set(timestamp, status, value)

    def set_formatted(self, raw_timestamp, raw_status, raw_value, major):
        """Set sensor using KATCP string formatted inputs

        Mirrors :meth:`katcp.Sensor.set_formatted`.

        This implementation is empty. Will, during instantiation, be overridden by the
        set_formatted() method of a katcp.Sensor object.
        """

    @tornado.gen.coroutine
    def get_reading(self):
        """Get a fresh sensor reading from the KATCP resource

        Returns
        -------
        reply : tornado Future resolving with  :class:`KATCPSensorReading` object

        Note
        ----

        As a side-effect this will update the reading stored in this object, and result in
        registered listeners being called.
        """
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading)

    @tornado.gen.coroutine
    def get_value(self):
        """Get a fresh sensor value from the KATCP resource

        Returns
        -------
        reply : tornado Future resolving with  :class:`KATCPSensorReading` object

        Note
        ----

        As a side-effect this will update the reading stored in this object, and result in
        registered listeners being called.
        """
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading.value)

    @tornado.gen.coroutine
    def get_status(self):
        """Get a fresh sensor status from the KATCP resource

        Returns
        -------
        reply : tornado Future resolving with  :class:`KATCPSensorReading` object

        Note
        ----

        As a side-effect this will update the reading stored in this object, and result in
        registered listeners being called.
        """
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading.status)

    def wait(self, condition_or_value, timeout=None):
        """Wait for the sensor to satisfy a condition.

        Parameters
        ----------
        condition_or_value : obj or callable, or seq of objs or callables
            If obj, sensor.value is compared with obj. If callable,
            condition_or_value(reading) is called, and must return True if its
            condition is satisfied. Since the reading is passed in, the value,
            status, timestamp or received_timestamp attributes can all be used
            in the check.
            TODO: Sequences of conditions (use SensorTransitionWaiter thingum?)
        timeout : float or None
            The timeout in seconds (None means wait forever)

        Returns
        -------
        This command returns a tornado Future that resolves with True when the
        sensor value satisfies the condition. It will never resolve with False;
        if a timeout is given a TimeoutError happens instead.

        Raises
        ------
        :class:`KATCPSensorError`
            If the sensor does not have a strategy set
        :class:`tornado.gen.TimeoutError`
            If the sensor condition still fails after a stated timeout period

        """
        if (isinstance(condition_or_value, collections.Sequence) and not
                isinstance(condition_or_value, basestring)):
            raise NotImplementedError(
                'Currently only single conditions are supported')
        condition_test = (condition_or_value if callable(condition_or_value)
                          else lambda s: s.value == condition_or_value)

        ioloop = tornado.ioloop.IOLoop.current()
        f = Future()
        if self.sampling_strategy == ('none', ):
            raise KATCPSensorError(
                'Cannot wait on a sensor that does not have a strategy set')

        def handle_update(sensor, reading):
            # This handler is called whenever a sensor update is received
            try:
                assert sensor is self
                if condition_test(reading):
                    self.unregister_listener(handle_update)
                    # Try and be idempotent if called multiple times after the
                    # condition is matched. This should not happen unless the
                    # sensor object is being updated in a thread outside of the
                    # ioloop.
                    if not f.done():
                        ioloop.add_callback(f.set_result, True)
            except Exception:
                f.set_exc_info(sys.exc_info())
                self.unregister_listener(handle_update)

        self.register_listener(handle_update, reading=True)
        # Handle case where sensor is already at the desired value
        ioloop.add_callback(handle_update, self, self._reading)

        if timeout:
            to = ioloop.time() + timeout
            timeout_f = with_timeout(to, f)
            # Make sure we stop listening if the wait times out to prevent a
            # buildup of listeners
            timeout_f.add_done_callback(
                lambda f: self.unregister_listener(handle_update))
            return timeout_f
        else:
            return f
Example #42
0
class MyServer(DeviceServer):

    VERSION_INFO = ("dummy-server", 1, 0)
    BUILD_INFO = ("hipsr-dummy-server", 0, 1, "")

    def setup_sensors(self):
        """Setup some server sensors."""

        self._time_result = Sensor(Sensor.TIMESTAMP, "time.result",
            "Last ?time result.", "")

        self._read_result = Sensor(Sensor.STRING, "read.result",
            "Last ?read result.", "")
        
        self._write_result = Sensor(Sensor.STRING, "write.result",
            "Last ?write result.", "")


        self.add_sensor(self._time_result)
        self.add_sensor(self._read_result)
        self.add_sensor(self._write_result)

    @request()
    @return_reply(Timestamp())
    def request_time(self, sock):
        """Return the current time in ms since the Unix Epoch."""
        r = time.time()
        self._time_result.set_value(r)
        return ("ok", r)

    @request(Str(),Int(),Int())
    @return_reply(Str())
    def request_read(self, sock, device_name, bytes, offset=0):
        """Dummy implementation of kactp ?read command
        
        Opens a pickled data file stored in /snap directory,
        and returns a packed struct of the data.
        
        Notes
        -----
        * The pickle should already be packed as a struct.
        * Currently ignoring the bytes and offset arguments.
        """
        # Attempt to load pickled data
        try:
           filename='%s/registers/%s.pkl'%(os.getcwd(),device_name)
           data   = pkl.load(open(filename,'r'))
        except:
           return ("fail", "Could not load %s."%filename)
        
        # Return data    
        self._read_result.set_value(data)
        return ("ok", data)
        
    @request(Str(),Int(),Str())
    @return_reply(Str())
    def request_write(self, sock, device_name, offset, data):
        """Dummy implementation of kactp ?write command
        
        Opens a pickled data file stored in /register directory,
        and writes a value to it.
        
        Notes
        -----
        * katcp_wrapper passes us already serialzed data, so no need to use struct
        """
        
        # Attempt to dump pickled data
        try:
          filename='%s/registers/%s.pkl'%(os.getcwd(),device_name)
          pkl.dump(data, open(filename,'w'))
        
        except:
          return ("fail", "Could not dump %s."%filename)

        return ("ok", data)
Example #43
0
def setup_sensors(instrument, katcp_server):
    """
    Set up compound sensors to be reported to CAM
    :param katcp_server: the katcp server with which to register the sensors
    :return:
    """

    nr_engines = len(instrument.fhosts + instrument.xhosts)
    executor = futures.ThreadPoolExecutor(max_workers=nr_engines)
    if not instrument._initialised:
        raise RuntimeError('Cannot set up sensors until instrument is initialised.')

    ioloop = getattr(instrument, 'ioloop', None)
    if not ioloop:
        ioloop = getattr(katcp_server, 'ioloop', None)
    if not ioloop:
        raise RuntimeError('IOLoop-containing katcp version required. Can go no further.')

    instrument._sensors = {}

    # f-engine lru
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_lru' % _f.host,
                                description='F-engine %s LRU okay' % _f.host,
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_cb_flru, sensor, executor, _f)

    # x-engine lru
    for _x in instrument.xhosts:
        sensor = Sensor.boolean(name='%s_xeng_lru' % _x.host,
                                description='X-engine %s LRU okay' % _x.host,
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_cb_xlru, sensor, executor, _x)

    # f-engine tx counters
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_tx' % _f.host,
                                description='F-engine TX okay - counters incrementing',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_feng_tx, sensor, executor, _f)

    # f-engine rx counters
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_rx' % _f.host,
                                description='F-engine RX okay - counters incrementing',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_feng_rx, sensor, executor, _f)

    # x-engine tx counters
    for _x in instrument.xhosts:
        sensor = Sensor.boolean(name='%s_xeng_tx' % _x.host,
                                description='X-engine TX okay - counters incrementing',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_xeng_tx, sensor, executor, _x)

    # x-engine rx counters
    for _x in instrument.xhosts:
        sensor = Sensor.boolean(name='%s_xeng_rx' % _x.host,
                                description='X-engine RX okay - counters incrementing',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_xeng_rx,  sensor, executor, _x)

    # x-engine QDR errors
    for _x in instrument.xhosts:
        sensor = Sensor.boolean(name='%s_xeng_qdr' % _x.host,
                                description='X-engine QDR okay',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_xeng_qdr_okay, sensor, executor, _x)

    # f-engine QDR errors
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_qdr' % _f.host,
                                description='F-engine QDR okay',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_feng_qdr_okay, sensor, executor, _f)

    # x-engine PHY counters
    for _x in instrument.xhosts:
        sensor = Sensor.boolean(name='%s_xeng_phy' % _x.host,
                                description='X-engine PHY okay',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_xeng_phy, sensor, executor, _x)

    # f-engine PHY counters
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_phy' % _f.host,
                                description='F-engine PHY okay',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_sensor_feng_phy, sensor, executor, _f)

    # f-engine PFB counters
    for _f in instrument.fhosts:
        sensor = Sensor.boolean(name='%s_feng_pfb' % _f.host,
                                description='F-engine PFB okay',
                                default=True)
        katcp_server.add_sensor(sensor)
        instrument._sensors[sensor.name] = sensor
        ioloop.add_callback(_feng_pfb_okay, sensor, executor, _f)

    # f-engine comms rx
    fengops = instrument.fops
    sensor = Sensor.boolean(name='fhosts_check_rx',
                            description='F-hosts rx okay',
                            default=True)
    katcp_server.add_sensor(sensor)
    instrument._sensors[sensor.name] = sensor
    ioloop.add_callback(_fhost_check_rx, sensor, executor, fengops)

    # # f-engine comms tx
    sensor = Sensor.boolean(name='fhosts_check_tx',
                            description='F-hosts tx okay',
                            default=True)
    katcp_server.add_sensor(sensor)
    instrument._sensors[sensor.name] = sensor
    ioloop.add_callback(_fhost_check_tx, sensor, executor, fengops)

    # x-engine comms rx
    xengops = instrument.xops
    sensor = Sensor.boolean(name='xhosts_check_rx',
                            description='X-hosts rx okay',
                            default=True)
    katcp_server.add_sensor(sensor)
    instrument._sensors[sensor.name] = sensor
    ioloop.add_callback(_xhost_check_rx, sensor, executor, xengops)
Example #44
0
 def setup_sensors(self):
     self.add_sensor(Sensor.boolean('asens'))
Example #45
0
  def setup_sensors_host (self, host, port):

    self.script.log(1, "KATCPServer::setup_sensors_host ("+host+","+port+")")
    sock = sockets.openSocket (DL, host, int(port), 1)

    if sock:
      self.script.log(2, "KATCPServer::setup_sensors_host sock.send(" + self.script.lmc_cmd + ")") 
      sock.send (self.script.lmc_cmd + "\r\n")
      lmc_reply = sock.recv (65536)
      sock.close()
      xml = xmltodict.parse(lmc_reply)
      self.script.log(2, "KATCPServer::setup_sensors_host sock.recv=" + str(xml))

      self._host_sensors = {}

      # Disk sensors
      self.script.log(2, "KATCPServer::setup_sensors_host configuring disk sensors")
      disk_prefix = host+".disk"
      self._host_sensors["disk_size"] = Sensor.float(disk_prefix+".size",
        description=host+": disk size",
        unit="MB",
        params=[8192,1e9],
        default=0)
      self._host_sensors["disk_available"] = Sensor.float(disk_prefix+".available",
        description=host+": disk available space",
        unit="MB",
        params=[1024,1e9],
        default=0)
      self.add_sensor(self._host_sensors["disk_size"])
      self.add_sensor(self._host_sensors["disk_available"])

      # Server Load sensors
      self.script.log(2, "KATCPServer::setup_sensors_host configuring load sensors")
      self._host_sensors["num_cores"] = Sensor.integer (host+".num_cores",
        description=host+": disk available space",
        unit="MB",
        params=[1,64],
        default=0)

      self._host_sensors["load1"] = Sensor.float(host+".load.1min",
        description=host+": 1 minute load ",
        unit="",
        default=0)

      self._host_sensors["load5"] = Sensor.float(host+".load.5min",
        description=host+": 5 minute load ",
        unit="",
        default=0)
      
      self._host_sensors["load15"] = Sensor.float(host+".load.15min",
        description=host+": 15 minute load ",
        unit="",
        default=0)

      self._host_sensors["local_time_synced"] = Sensor.boolean("local_time_synced",
        description=host+": NTP server synchronisation",
        unit="",
        default=0)

      self.add_sensor(self._host_sensors["num_cores"])
      self.add_sensor(self._host_sensors["num_cores"])
      self.add_sensor(self._host_sensors["load1"])
      self.add_sensor(self._host_sensors["load5"])
      self.add_sensor(self._host_sensors["load15"])
      self.add_sensor(self._host_sensors["local_time_synced"])

      cpu_temp_pattern  = re.compile("cpu[0-9]+_temp")
      fan_speed_pattern = re.compile("fan[0-9,a-z]+")
      power_supply_pattern = re.compile("ps[0-9]+_status")
        
      self.script.log(2, "KATCPServer::setup_sensors_host configuring other metrics")

      if not xml["lmc_reply"]["sensors"] == None:

        for sensor in xml["lmc_reply"]["sensors"]["metric"]:
          name = sensor["@name"]
          if name == "system_temp":
            self._host_sensors[name] = Sensor.float((host+".system_temp"),
              description=host+": system temperature",
              unit="C",
              params=[-20,150],
              default=0)
            self.add_sensor(self._host_sensors[name])

          if cpu_temp_pattern.match(name):
            (cpu, junk) = name.split("_")
            self._host_sensors[name] = Sensor.float((host+"." + name),
              description=host+": "+ cpu +" temperature",
              unit="C",
              params=[-20,150],
              default=0)
            self.add_sensor(self._host_sensors[name])

          if fan_speed_pattern.match(name):
            self._host_sensors[name] = Sensor.float((host+"." + name),
              description=host+": "+name+" speed",
              unit="RPM",
              params=[0,20000],
              default=0)
            self.add_sensor(self._host_sensors[name])

          if power_supply_pattern.match(name):
            self._host_sensors[name] = Sensor.boolean((host+"." + name),
              description=host+": "+name,
              unit="",
              default=0)
            self.add_sensor(self._host_sensors[name])

          # TODO consider adding power supply sensors: e.g.
          #   device-status-kronos1-powersupply1
          #   device-status-kronos1-powersupply2
          #   device-status-kronos2-powersupply1
          #   device-status-kronos2-powersupply2

          # TODO consider adding raid/disk sensors: e.g.
          #   device-status-<host>-raid
          #   device-status-<host>-raid-disk1
          #   device-status-<host>-raid-disk2

        self.script.log(2, "KATCPServer::setup_sensors_host done!")

      else:
        self.script.log(2, "KATCPServer::setup_sensors_host no sensors found")

    else:
      self.script.log(-2, "KATCPServer::setup_sensors_host: could not connect to LMC")
Example #46
0
class MyServer(DeviceServer):

    VERSION_INFO = ("dummy-server", 1, 0)
    BUILD_INFO = ("hipsr-dummy-server", 0, 1, "")

    FRUIT = [
        "apple", "banana", "pear", "kiwi",
    ]

    BANDS = [
        "autolux", "nirvana", "acdc", "tool",
    ]


    def setup_sensors(self):
        """Setup some server sensors."""
        self._add_result = Sensor(Sensor.FLOAT, "add.result",
            "Last ?add result.", "", [-10000, 10000])

        self._time_result = Sensor(Sensor.TIMESTAMP, "time.result",
            "Last ?time result.", "")

        self._eval_result = Sensor(Sensor.STRING, "eval.result",
            "Last ?eval result.", "")

        self._fruit_result = Sensor(Sensor.DISCRETE, "fruit.result",
            "Last ?pick-fruit result.", "", self.FRUIT)

        self._band_result = Sensor(Sensor.DISCRETE, "band.result",
            "Last ?pick-band result.", "", self.BAND)


        self.add_sensor(self._add_result)
        self.add_sensor(self._time_result)
        self.add_sensor(self._eval_result)
        self.add_sensor(self._fruit_result)
        self.add_sensor(self._band_result)

    @request(Float(), Float())
    @return_reply(Float())
    def request_add(self, sock, x, y):
        """Add two numbers"""
        r = x + y
        self._add_result.set_value(r)
        return ("ok", r)

    @request()
    @return_reply(Timestamp())
    def request_time(self, sock):
        """Return the current time in ms since the Unix Epoch."""
        r = time.time()
        self._time_result.set_value(r)
        return ("ok", r)

    @request(Str())
    @return_reply(Str())
    def request_eval(self, sock, expression):
        """Evaluate a Python expression."""
        r = str(eval(expression))
        self._eval_result.set_value(r)
        return ("ok", r)

    @request()
    @return_reply(Discrete(FRUIT))
    def request_pick_fruit(self, sock):
        """Pick a random fruit."""
        r = random.choice(self.FRUIT + [None])
        if r is None:
            return ("fail", "No fruit.")
        self._fruit_result.set_value(r)
        return ("ok", r)

    @request()
    @return_reply(Discrete(BAND))
    def request_pick_band(self, sock):
        """Pick a random fruit."""
        r = random.choice(self.BAND + [None])
        if r is None:
            return ("fail", "No band.")
        self._fruit_result.set_value(r)
        return ("ok", r)