From e2f8f8e0bd36171246e99d96a5155a5b098f6700 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 29 Sep 2017 13:58:43 -0700 Subject: mpm: Added sensor API - Motherboard sensors are automatically populated into the property tree, they can be automatically enumerated and queried - Daughterboard sensors have an API for querying and enumerating sensors, but this commit does not automatically add them to the property tree --- host/lib/usrp/mpmd/mpmd_impl.cpp | 30 +++++++++++++++++++++++ mpm/python/usrp_mpm/dboard_manager/base.py | 38 ++++++++++++++++++++++++++++++ mpm/python/usrp_mpm/periph_manager/base.py | 38 ++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp index 38a089788..93e777af2 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -106,6 +106,36 @@ namespace { ); }) ; + + /*** Sensors ********************************************************/ + auto sensor_list = + mb->rpc->request_with_token>( + "get_mb_sensors" + ); + UHD_LOG_DEBUG("MPMD", + "Found " << sensor_list.size() << " motherboard sensors." + ); + for (const auto& sensor_name : sensor_list) { + UHD_LOG_TRACE("MPMD", + "Adding motherboard sensor `" << sensor_name << "'" + ); + tree->create( + mb_path / "sensors" / sensor_name) + .set_publisher([mb, sensor_name](){ + return sensor_value_t( + mb->rpc->request_with_token( + "get_mb_sensor", sensor_name + ) + ); + }) + .set_coercer([](const sensor_value_t &){ + throw uhd::runtime_error( + "Trying to write read-only sensor value!" + ); + return sensor_value_t("", "", ""); + }) + ; + } } void reset_time_synchronized(uhd::property_tree::sptr tree) diff --git a/mpm/python/usrp_mpm/dboard_manager/base.py b/mpm/python/usrp_mpm/dboard_manager/base.py index 56655f946..b87033860 100644 --- a/mpm/python/usrp_mpm/dboard_manager/base.py +++ b/mpm/python/usrp_mpm/dboard_manager/base.py @@ -34,6 +34,10 @@ class DboardManagerBase(object): # Very important: A list of PIDs that apply to the current device. Must be # list, even if there's only one entry. pids = [] + # See PeriphManager.mboard_sensor_callback_map for a description. + rx_sensor_callback_map = {} + # See PeriphManager.mboard_sensor_callback_map for a description. + tx_sensor_callback_map = {} # A dictionary that maps chips or components to chip selects for SPI. # If this is given, a dictionary called self._spi_nodes is created which # maps these keys to actual spidev paths. Also throws a warning/error if @@ -108,3 +112,37 @@ class DboardManagerBase(object): Call this function if the frequency of the reference clock changes. """ self.log.warning("update_ref_clock_freq() called but not implemented") + + def get_sensors(self, direction): + """ + Return a list of RX daughterboard sensor names. + + direction needs to be either RX or TX. + """ + if direction.lower() == 'rx': + return list(self.rx_sensor_callback_map.keys()) + else: + return list(self.tx_sensor_callback_map.keys()) + + def get_sensor(self, direction, sensor_name): + """ + Return a dictionary that represents the sensor values for a given + sensor. If the requested sensor sensor_name does not exist, throw an + exception. direction is either RX or TX. + + See PeriphManager.get_mb_sensor() for a description of the return value + format. + """ + callback_map = \ + rx_sensor_callback_map if direction.lower() == 'rx' \ + else tx_sensor_callback_map + if sensor_name not in callback_map: + error_msg = "Was asked for non-existent sensor `{}'.".format( + sensor_name + ) + self.log.error(error_msg) + raise RuntimeError(error_msg) + return getattr( + self, self.callback_map.get('sensor_name') + )() + diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index 0aa1adf59..72066b9ef 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -93,6 +93,9 @@ class PeriphManagerBase(object): # particular version of MPM supports. Leave at None to skip a max rev # check. mboard_max_rev = None + # A list of available sensors on the motherboard. This dictionary is a map + # of the form sensor_name -> method name + mboard_sensor_callback_map = {} # This is a sanity check value to see if the correct number of # daughterboards are detected. If somewhere along the line more than # max_num_dboards dboards are found, an error or warning is raised, @@ -461,3 +464,38 @@ class PeriphManagerBase(object): xbar_file.write(laddr_value) return True + def get_mb_sensors(self): + """ + Return a list of sensor names. + """ + return list(self.mboard_sensor_callback_map.keys()) + + def get_mb_sensor(self, sensor_name): + """ + Return a dictionary that represents the sensor values for a given + sensor. If the requested sensor sensor_name does not exist, throw an + exception. + + The returned dictionary has the following keys (all values are + strings): + - name: This is typically the same as sensor_name + - type: One of the following strings: BOOLEAN, INTEGER, REALNUM, STRING + Note that this matches uhd::sensor_value_t::data_type_t + - value: The value. If type is STRING, it is interpreted as-is. If it's + REALNUM or INTEGER, it needs to be convertable to float or + int, respectively. If it's BOOLEAN, it needs to be either + 'true' or 'false', although any string that is not 'true' will + be interpreted as false. + - unit: This depends on the type. It is generally only relevant for + pretty-printing the sensor value. + """ + if sensor_name not in self.get_mb_sensors(): + error_msg = "Was asked for non-existent sensor `{}'.".format( + sensor_name + ) + self.log.error(error_msg) + raise RuntimeError(error_msg) + return getattr( + self, self.mboard_sensor_callback_map.get(sensor_name) + )() + -- cgit v1.2.3