Esempio n. 1
0
 def _build_component_list(self) -> int:
     logger().debug("Building component list for DACM instrument.")
     for component_object in self.components:
         del component_object
     self.components = []
     component_dict = self._get_parameter("components")
     if not component_dict:
         return 0
     for component in component_dict:
         component_object = Component(component["component_id"],
                                      component["component_name"])
         # build sensor list
         for sensor in component["sensors"]:
             sensor_object = Sensor(sensor["sensor_id"],
                                    sensor["sensor_name"])
             # build measurand list
             for measurand in sensor["measurands"]:
                 try:
                     unit = measurand["measurand_unit"]
                 except Exception:  # pylint: disable=broad-except
                     unit = ""
                 try:
                     source = measurand["measurand_source"]
                 except Exception:  # pylint: disable=broad-except
                     source = None
                 measurand_object = Measurand(
                     measurand["measurand_id"],
                     measurand["measurand_name"],
                     unit,
                     source,
                 )
                 sensor_object.measurands += [measurand_object]
             component_object.sensors += [sensor_object]
         self.components += [component_object]
     return len(self.components)
Esempio n. 2
0
    def _get_battery_voltage(self):
        battery_bytes = self._get_parameter("battery_bytes")
        battery_coeff = self._get_parameter("battery_coeff")
        ok_byte = self.family["ok_byte"]
        if not (battery_coeff and battery_bytes):
            return "This instrument type doesn't provide \
            battery voltage information"

        reply = self.get_reply([b"\x0d", b""], battery_bytes + 1)
        if reply and (reply[0] == ok_byte):
            try:
                voltage = battery_coeff * int.from_bytes(
                    reply[1:], byteorder="little", signed=False)
                return round(voltage, 2)
            except TypeError:
                logger().error("TypeError when parsing the payload.")
                return False
            except ReferenceError:
                logger().error("ReferenceError when parsing the payload.")
                return False
            except LookupError:
                logger().error("LookupError when parsing the payload.")
                return False
            except Exception:  # pylint: disable=broad-except
                logger().error("Unknown error when parsing the payload.")
                raise
            else:
                pass
        else:
            logger().error("Device %s doesn't reply.", self.device_id)
            return False
Esempio n. 3
0
 def stop_cycle(self):
     """Stop the measuring cycle."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x16", b""], 1)
     if reply and (reply[0] == ok_byte):
         logger().debug("Cycle stopped at device %s.", self.device_id)
         return True
     logger().error("stop_cycle() failed at device %s.", self.device_id)
     return False
Esempio n. 4
0
 def _push_button(self):
     reply = self.get_reply([b"\x12", b""], 1)
     ok_byte = self.family["ok_byte"]
     if reply and (reply[0] == ok_byte):
         logger().debug("Push button simulated at device %s.",
                        self.device_id)
         return True
     logger().error("Push button failed at device %s.", self.device_id)
     return False
Esempio n. 5
0
 def set_short_interval(self):
     """Set the measuring interval to 1 h = 60 min = 3600 s"""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x04", b""], 1)
     if reply and (reply[0] == ok_byte):
         self.__interval = timedelta(hours=1)
         logger().debug("Device %s set to 1 h interval.", self.device_id)
         return True
     logger().error("Interval setup failed at device %s.", self.device_id)
     return False
Esempio n. 6
0
 def set_unlock(self):
     """Unlock the hardware button or switch at the device."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x02", b""], 1)
     if reply and (reply[0] == ok_byte):
         self.lock = self.Lock.UNLOCKED
         logger().debug("Device %s unlocked.", self.device_id)
         return True
     logger().error("Unlocking failed at device %s.", self.device_id)
     return False
Esempio n. 7
0
 def get_recent_value(self, component_id=None, sensor_id=None, _=None):
     """Fill component objects with recent measuring values.\
     This function does the same like get_all_recent_values()\
     and is only here to provide a compatible API to the DACM interface"""
     for measurand in self.components[component_id].sensors[
             sensor_id].measurands:
         logger().debug(measurand)
         if measurand.source == 8:  # battery voltage
             measurand.value = self._get_battery_voltage()
             measurand.time = datetime.utcnow().replace(microsecond=0)
             return measurand.value
     return self.get_all_recent_values()
Esempio n. 8
0
 def get_all_recent_values(self):
     """Fill the component objects with recent readings."""
     # Do nothing as long as the previous values are valid.
     if self._last_sampling_time is None:
         logger().warning(
             "The gathered values might be invalid. "
             "You should use function start_cycle() in your application "
             "for a regular initialization of the measuring cycle.")
         return self._gather_all_recent_values()
     if (datetime.utcnow() - self._last_sampling_time) < self.__interval:
         logger().debug(
             "We do not have new values yet. Sample interval = %s.",
             self.__interval)
         return True
     return self._gather_all_recent_values()
Esempio n. 9
0
 def set_real_time_clock(self, date_time) -> bool:
     """Set the instrument time."""
     ok_byte = self.family["ok_byte"]
     instr_datetime = bytearray([
         date_time.second,
         date_time.minute,
         date_time.hour,
         date_time.day,
         date_time.month,
     ])
     instr_datetime.extend((date_time.year).to_bytes(2, byteorder="big"))
     reply = self.get_reply([b"\x10", instr_datetime], 1)
     if reply and (reply[0] == ok_byte):
         logger().debug("Time on device %s set to UTC.", self.device_id)
         return True
     logger().error("Setting the time on device %s failed.", self.device_id)
     return False
Esempio n. 10
0
 def set_real_time_clock(self, date_time) -> bool:
     ok_byte = self.family["ok_byte"]
     instr_datetime = bytearray([
         date_time.second,
         date_time.minute,
         date_time.hour,
         date_time.day,
         date_time.month,
         date_time.year - 2000,
     ])
     reply = self.get_reply([b"\x05", instr_datetime], 1)
     if reply and (reply[0] == ok_byte):
         logger().debug("Time on device %s set to UTC.", self.device_id)
         return True
     logger().error("Setting the time on device %s failed.",
                    {self.device_id})
     return False
Esempio n. 11
0
    def get_message_payload(self, message, timeout) -> CheckedAnswerDict:
        """Send a message to the instrument and give back the payload of the reply.

        Args:
            message:
                The message to send.
            timeout:
                Timeout for waiting for a reply from instrument.
        Returns:
            A dictionary of
            is_valid: True if answer is valid, False otherwise,
            is_control_message: True if control message,
            is_last_frame: True if no follow-up B-E frame is expected,
            payload: Payload of answer,
            number_of_bytes_in_payload,
            raw: The raw byte string from _get_transparent_reply.
        """
        # Run _check_message to get the payload of the sent message.
        checked_message = self._check_message(message, False)
        # If this is a get-data command, we expect multiple B-E frames.
        _multiframe = checked_message["payload"] in [b"\x60", b"\x61"]
        answer = self._get_transparent_reply(message,
                                             timeout=timeout,
                                             keep=True)
        if answer == b"":
            # Workaround for firmware bug in SARAD instruments.
            logger().debug("Play it again, Sam!")
            answer = self._get_transparent_reply(message,
                                                 timeout=timeout,
                                                 keep=True)
        checked_answer = self._check_message(answer, True)
        return {
            "is_valid":
            checked_answer["is_valid"],
            "is_control":
            checked_answer["is_control"],
            "is_last_frame":
            checked_answer["is_last_frame"],
            "payload":
            checked_answer["payload"],
            "number_of_bytes_in_payload":
            checked_answer["number_of_bytes_in_payload"],
            "raw":
            answer,
        }
Esempio n. 12
0
 def start_cycle(self, cycle_index=0):
     """Start a measuring cycle."""
     logger().debug("Trying to start measuring cycle %d", cycle_index)
     self.__interval = self._read_cycle_start(cycle_index)["cycle_interval"]
     for component in self.components:
         for sensor in component.sensors:
             sensor.interval = self.__interval
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x15", bytes([cycle_index])], 3, timeout=5)
     if reply and (reply[0] == ok_byte):
         logger().debug("Cycle %s started at device %s.", cycle_index,
                        self.device_id)
         return True
     logger().error("start_cycle() failed at device %s.", self.device_id)
     if reply[0] == 11:
         logger().error("DACM instrument replied with error code %s.",
                        reply[1])
     return False
Esempio n. 13
0
 def set_config(self):
     """Upload a new configuration to the device."""
     ok_byte = self.family["ok_byte"]
     setup_word = self._encode_setup_word()
     interval = int(self.__interval.seconds / 60)
     setup_data = ((interval).to_bytes(1, byteorder="little") + setup_word +
                   (self.__alarm_level).to_bytes(4, byteorder="little"))
     logger().debug(setup_data)
     reply = self.get_reply([b"\x0f", setup_data], 1)
     if reply and (reply[0] == ok_byte):
         logger().debug("Set config. successful at device %s.",
                        self.device_id)
         return True
     logger().error("Set config. failed at device %s.", self.device_id)
     return False
Esempio n. 14
0
 def set_wifi_access(self, ssid, password, ip_address, server_port):
     """Set the WiFi access data."""
     ok_byte = self.family["ok_byte"]
     access_data = b"".join([
         bytes(ssid, "utf-8").ljust(33, b"0"),
         bytes(password, "utf-8").ljust(64, b"0"),
         bytes(ip_address, "utf-8").ljust(24, b"0"),
         server_port.to_bytes(2, "big"),
     ])
     logger().debug(access_data)
     reply = self.get_reply([b"\x17", access_data], 118)
     if reply and (reply[0] == ok_byte):
         logger().debug("WiFi access data on device %s set.",
                        self.device_id)
         return True
     logger().error("Setting WiFi access data on device %s failed.",
                    self.device_id)
     return False
Esempio n. 15
0
 def _get_description(self):
     """Get descriptive data about DACM instrument."""
     ok_byte = self.family["ok_byte"]
     id_cmd = self.family["get_id_cmd"]
     length_of_reply = self.family["length_of_reply"]
     reply = self.get_reply(id_cmd, length_of_reply)
     if reply and (reply[0] == ok_byte):
         logger().debug("Get description successful.")
         try:
             self._type_id = reply[1]
             self._software_version = reply[2]
             self._serial_number = int.from_bytes(reply[3:5],
                                                  byteorder="big",
                                                  signed=False)
             manu_day = reply[5]
             manu_month = reply[6]
             manu_year = int.from_bytes(reply[7:9],
                                        byteorder="big",
                                        signed=False)
             self._date_of_manufacture = datetime(manu_year, manu_month,
                                                  manu_day)
             upd_day = reply[9]
             upd_month = reply[10]
             upd_year = int.from_bytes(reply[11:13],
                                       byteorder="big",
                                       signed=False)
             self._date_of_update = datetime(upd_year, upd_month, upd_day)
             self._module_blocksize = reply[13]
             self._component_blocksize = reply[14]
             self._component_count = reply[15]
             self._bit_ctrl = BitVector(rawbytes=reply[16:20])
             self._value_ctrl = BitVector(rawbytes=reply[20:24])
             self._cycle_blocksize = reply[24]
             self._cycle_count_limit = reply[25]
             self._step_count_limit = reply[26]
             self._language = reply[27]
             return True and self._get_module_information()
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().debug(
                 "The connected instrument does not belong to the DACM family."
             )
             self._valid_family = False
             return False
     logger().debug("Get description failed.")
     return False
Esempio n. 16
0
 def get_recent_value(self, component, sensor=0, measurand=0):
     """Get a dictionaries with recent measuring values from one sensor.
     component_id: one of the 34 sensor/actor modules of the DACM system
     measurand_id:
     0 = recent sampling,
     1 = average of last completed interval,
     2 = minimum of last completed interval,
     3 = maximum
     sensor_id: only for sensors delivering multiple measurands"""
     component_id = self.components[component].component_id
     sensor_id = self.components[component].sensors[sensor].sensor_id
     measurand_id = (self.components[component].sensors[sensor].
                     measurands[measurand].measurand_id)
     reply = self.get_reply(
         [
             b"\x1a",
             bytes([component_id]) + bytes([sensor_id]) +
             bytes([measurand_id]),
         ],
         1000,
     )
     if reply and (reply[0] > 0):
         output = {}
         output["component_name"] = reply[1:17].split(b"\x00")[0].decode(
             "cp1252")
         output["measurand_id"] = measurand_id
         output["sensor_name"] = reply[18:34].split(b"\x00")[0].decode(
             "cp1252")
         output["measurand"] = (
             reply[35:51].split(b"\x00")[0].strip().decode("cp1252"))
         measurand_dict = self._parse_value_string(output["measurand"])
         output["measurand_operator"] = measurand_dict["measurand_operator"]
         output["value"] = measurand_dict["measurand_value"]
         output["measurand_unit"] = measurand_dict["measurand_unit"]
         date = reply[52:68].split(b"\x00")[0].split(b"/")
         meas_time = reply[69:85].split(b"\x00")[0].split(b":")
         if date != [b""]:
             output["datetime"] = datetime(
                 int(date[2]),
                 int(date[0]),
                 int(date[1]),
                 int(meas_time[0]),
                 int(meas_time[1]),
                 int(meas_time[2]),
             )
         else:
             output["datetime"] = None
         try:
             gps_list = re.split("[ ]+ |ø|M[ ]*",
                                 reply[86:].decode("cp1252"))
             gps_dict = {
                 "valid":
                 True,
                 "latitude":
                 float(gps_list[0])
                 if gps_list[1] == "N" else -float(gps_list[0]),
                 "longitude":
                 float(gps_list[2])
                 if gps_list[3] == "E" else -float(gps_list[2]),
                 "altitude":
                 float(gps_list[4]),
                 "deviation":
                 float(gps_list[5]),
             }
             output["gps"] = gps_dict
         except Exception:  # pylint: disable=broad-except
             gps_dict = {
                 "valid": False,
                 "latitude": None,
                 "longitude": None,
                 "altitude": None,
                 "deviation": None,
             }
         this_measurand = (self.components[component].sensors[sensor].
                           measurands[measurand])
         this_measurand.operator = measurand_dict["measurand_operator"]
         this_measurand.value = measurand_dict["measurand_value"]
         this_measurand.unit = measurand_dict["measurand_unit"]
         this_measurand.time = output["datetime"]
         this_measurand.gps = gps_dict
         return output
     if reply[0] == 0:
         logger().error("Measurand not available.")
         return False
     logger().error("The instrument doesn't reply.")
     return False
Esempio n. 17
0
 def get_config(self):
     """Get configuration from device."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x10", b""], 8)
     if reply and (reply[0] == ok_byte):
         logger().debug("Getting config. from device %s.", self.device_id)
         try:
             self.__interval = timedelta(minutes=reply[1])
             setup_word = reply[2:3]
             self._decode_setup_word(setup_word)
             self.__alarm_level = int.from_bytes(reply[4:8],
                                                 byteorder="little",
                                                 signed=False)
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().debug(
                 "The connected instrument does not belong to the RadonScout family."
             )
             self._valid_family = False
             return False
         return True
     logger().error("Get config. failed at device %s.", self.device_id)
     return False
Esempio n. 18
0
 def _read_cycle_continue(self):
     """Get description of subsequent cycle intervals."""
     reply = self.get_reply([b"\x07", b""], 16)
     if reply and not len(reply) < 16:
         logger().debug("Get information about cycle interval successful.")
         try:
             seconds = int.from_bytes(reply[0:4],
                                      byteorder="little",
                                      signed=False)
             bit_ctrl = BitVector(rawbytes=reply[4:8])
             value_ctrl = BitVector(rawbytes=reply[8:12])
             rest = BitVector(rawbytes=reply[12:16])
             return {
                 "seconds": seconds,
                 "bit_ctrl": bit_ctrl,
                 "value_ctrl": value_ctrl,
                 "rest": rest,
             }
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
     logger().debug("Get info about cycle interval failed.")
     return False
Esempio n. 19
0
 def _read_cycle_start(self, cycle_index=0):
     """Get description of a measuring cycle."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x06", bytes([cycle_index])], 28)
     if reply and (reply[0] == ok_byte) and reply[1]:
         logger().debug("Get primary cycle information successful.")
         try:
             cycle_name = reply[2:19].split(b"\x00")[0].decode("cp1252")
             cycle_interval = timedelta(seconds=int.from_bytes(
                 reply[19:21], byteorder="little", signed=False))
             cycle_steps = int.from_bytes(reply[21:24],
                                          byteorder="big",
                                          signed=False)
             cycle_repetitions = int.from_bytes(reply[24:28],
                                                byteorder="little",
                                                signed=False)
             return {
                 "cycle_name": cycle_name,
                 "cycle_interval": cycle_interval,
                 "cycle_steps": cycle_steps,
                 "cycle_repetitions": cycle_repetitions,
             }
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
     logger().debug("Get primary cycle info failed.")
     return False
Esempio n. 20
0
 def _get_component_configuration(self, component_index):
     """Get information about the configuration of a component
     of a DACM instrument."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x04", bytes([component_index])], 73)
     if reply and (reply[0] == ok_byte):
         logger().debug("Get component configuration successful.")
         try:
             sensor_name = reply[8:16].split(b"\x00")[0].decode("cp1252")
             sensor_value = reply[8:16].split(b"\x00")[0].decode("cp1252")
             sensor_unit = reply[8:16].split(b"\x00")[0].decode("cp1252")
             input_config = int.from_bytes(reply[6:8],
                                           byteorder="big",
                                           signed=False)
             alert_level_lo = int.from_bytes(reply[6:8],
                                             byteorder="big",
                                             signed=False)
             alert_level_hi = int.from_bytes(reply[6:8],
                                             byteorder="big",
                                             signed=False)
             alert_output_lo = int.from_bytes(reply[6:8],
                                              byteorder="big",
                                              signed=False)
             alert_output_hi = int.from_bytes(reply[6:8],
                                              byteorder="big",
                                              signed=False)
             return {
                 "sensor_name": sensor_name,
                 "sensor_value": sensor_value,
                 "sensor_unit": sensor_unit,
                 "input_config": input_config,
                 "alert_level_lo": alert_level_lo,
                 "alert_level_hi": alert_level_hi,
                 "alert_output_lo": alert_output_lo,
                 "alert_output_hi": alert_output_hi,
             }
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
     logger().debug("Get component configuration failed.")
     return False
Esempio n. 21
0
 def _get_component_information(self, component_index):
     """Get information about one component of a DACM instrument."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x03", bytes([component_index])], 21)
     if reply and (reply[0] == ok_byte):
         logger().debug("Get component information successful.")
         try:
             revision = reply[1]
             component_type = reply[2]
             availability = reply[3]
             ctrl_format = reply[4]
             conf_block_size = reply[5]
             data_record_size = int.from_bytes(reply[6:8],
                                               byteorder="big",
                                               signed=False)
             name = reply[8:16].split(b"\x00")[0].decode("cp1252")
             hw_capability = BitVector(rawbytes=reply[16:20])
             return {
                 "revision": revision,
                 "component_type": component_type,
                 "availability": availability,
                 "ctrl_format": ctrl_format,
                 "conf_block_size": conf_block_size,
                 "data_record_size": data_record_size,
                 "name": name,
                 "hw_capability": hw_capability,
             }
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
     logger().debug("Get component information failed.")
     return False
Esempio n. 22
0
 def _get_module_information(self):
     """Get descriptive data about DACM instrument."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x01", b""], 73)
     if reply and (reply[0] == ok_byte):
         logger().debug("Get module information successful.")
         try:
             self._address = reply[1]
             config_day = reply[2]
             config_month = reply[3]
             config_year = int.from_bytes(reply[4:6],
                                          byteorder="big",
                                          signed=False)
             self._date_of_config = datetime(config_year, config_month,
                                             config_day)
             self._module_name = reply[6:39].split(b"\x00")[0].decode(
                 "cp1252")
             self._config_name = reply[39:].split(b"\x00")[0].decode(
                 "cp1252")
             return True
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
     logger().debug("Get module information failed.")
     return False
Esempio n. 23
0
 def get_wifi_access(self):
     """Get the Wi-Fi access data from instrument."""
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x18", b""], 125)
     if reply and (reply[0] == ok_byte):
         try:
             logger().debug(reply)
             self.__wifi["ssid"] = reply[0:33].rstrip(b"0")
             self.__wifi["password"] = reply[33:97].rstrip(b"0")
             self.__wifi["ip_address"] = reply[97:121].rstrip(b"0")
             self.__wifi["server_port"] = int.from_bytes(
                 reply[121:123], "big")
             return True
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
         else:
             pass
     else:
         logger().error("Cannot get Wi-Fi access data from device %s.",
                        self.device_id)
         return False
Esempio n. 24
0
 def _gather_all_recent_values(self):
     ok_byte = self.family["ok_byte"]
     reply = self.get_reply([b"\x14", b""], 33)
     self._last_sampling_time = datetime.utcnow()
     if reply and (reply[0] == ok_byte):
         try:
             sample_interval = timedelta(minutes=reply[1])
             device_time_min = reply[2]
             device_time_h = reply[3]
             device_time_d = reply[4]
             device_time_m = reply[5]
             device_time_y = reply[6]
             source = []  # measurand_source
             source.append(round(self._bytes_to_float(reply[7:11]), 2))  # 0
             source.append(reply[11])  # 1
             source.append(round(self._bytes_to_float(reply[12:16]),
                                 2))  # 2
             source.append(reply[16])  # 3
             source.append(round(self._bytes_to_float(reply[17:21]),
                                 2))  # 4
             source.append(round(self._bytes_to_float(reply[21:25]),
                                 2))  # 5
             source.append(round(self._bytes_to_float(reply[25:29]),
                                 2))  # 6
             source.append(
                 int.from_bytes(reply[29:33], byteorder="big",
                                signed=False))  # 7
             source.append(self._get_battery_voltage())  # 8
             device_time = datetime(
                 device_time_y + 2000,
                 device_time_m,
                 device_time_d,
                 device_time_h,
                 device_time_min,
             )
         except TypeError:
             logger().error("TypeError when parsing the payload.")
             return False
         except ReferenceError:
             logger().error("ReferenceError when parsing the payload.")
             return False
         except LookupError:
             logger().error("LookupError when parsing the payload.")
             return False
         except ValueError:
             logger().error("ValueError when parsing the payload.")
             return False
         except Exception:  # pylint: disable=broad-except
             logger().error("Unknown error when parsing the payload.")
             return False
         self.__interval = sample_interval
         for component in self.components:
             for sensor in component.sensors:
                 sensor.interval = sample_interval
                 for measurand in sensor.measurands:
                     try:
                         measurand.value = source[measurand.source]
                         measurand.time = device_time
                         if measurand.source == 8:  # battery voltage
                             sensor.interval = timedelta(seconds=5)
                     except Exception:  # pylint: disable=broad-except
                         logger().error(
                             "Can't get value for source %s in %s/%s/%s.",
                             measurand.source,
                             component.name,
                             sensor.name,
                             measurand.name,
                         )
         return True
     logger().error("Device %s doesn't reply.", self.device_id)
     return False