class IODataSampleRxIndicatorWifiPacket(XBeeAPIPacket): """ This class represents a IO data sample RX indicator (Wi-Fi) packet. Packet is built using the parameters of the constructor or providing a valid API payload. When the module receives an IO sample frame from a remote device, it sends the sample out the UART or SPI using this frame type. Only modules running API mode will be able to receive IO samples. Among received data, some options can also be received indicating transmission parameters. .. seealso:: | :class:`.XBeeAPIPacket` """ __MIN_PACKET_LENGTH = 16 def __init__(self, src_address, rssi, rx_options, rf_data=None, op_mode=OperatingMode.API_MODE): """ Class constructor. Instantiates a new :class:`.IODataSampleRxIndicatorWifiPacket` object with the provided parameters. Args: src_address (:class:`ipaddress.IPv4Address`): the 64-bit source address. rssi (Integer): received signal strength indicator. rx_options (Integer): bitfield indicating the receive options. rf_data (Bytearray, optional): received RF data. op_mode (:class:`.OperatingMode`, optional, default=`OperatingMode.API_MODE`): The mode in which the frame was captured. Raises: ValueError: if `rf_data` is not `None` and it's not valid for create an :class:`.IOSample`. .. seealso:: | :class:`.IOSample` | :class:`ipaddress.IPv4Address` | :class:`.ReceiveOptions` | :class:`.XBeeAPIPacket` """ super().__init__(ApiFrameType.IO_DATA_SAMPLE_RX_INDICATOR_WIFI, op_mode=op_mode) self.__src_addr = src_address self.__rssi = rssi self.__rx_opts = rx_options self.__data = rf_data self.__io_sample = IOSample( rf_data) if rf_data is not None and len(rf_data) >= 5 else None @staticmethod def create_packet(raw, operating_mode): """ Override method. Returns: :class:`.IODataSampleRxIndicatorWifiPacket`. Raises: InvalidPacketException: if the bytearray length is less than 16. (start delim. + length (2 bytes) + frame type + source addr. (4 bytes) + rssi + receive options + rf data (5 bytes) + checksum = 16 bytes). InvalidPacketException: if the length field of 'raw' is different from its real length. (length field: bytes 2 and 3) InvalidPacketException: if the first byte of 'raw' is not the header byte. See :class:`.SpecialByte`. InvalidPacketException: if the calculated checksum is different from the checksum field value (last byte). InvalidPacketException: if the frame type is not :attr:`.ApiFrameType.IO_DATA_SAMPLE_RX_INDICATOR_WIFI`. InvalidOperatingModeException: if `operating_mode` is not supported. .. seealso:: | :meth:`.XBeePacket.create_packet` | :meth:`.XBeeAPIPacket._check_api_packet` """ if operating_mode not in (OperatingMode.ESCAPED_API_MODE, OperatingMode.API_MODE): raise InvalidOperatingModeException(op_mode=operating_mode) XBeeAPIPacket._check_api_packet( raw, min_length=IODataSampleRxIndicatorWifiPacket.__MIN_PACKET_LENGTH) if raw[3] != ApiFrameType.IO_DATA_SAMPLE_RX_INDICATOR_WIFI.code: raise InvalidPacketException( message= "This packet is not an IO data sample RX indicator Wi-Fi packet." ) return IODataSampleRxIndicatorWifiPacket(IPv4Address(bytes(raw[4:8])), raw[7], raw[8], rf_data=raw[9:-1], op_mode=operating_mode) def needs_id(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket.needs_id` """ return False def _get_api_packet_spec_data(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data` """ ret = bytearray(self.__src_addr.packed) ret += utils.int_to_bytes(self.__rssi, num_bytes=1) ret += utils.int_to_bytes(self.__rx_opts, num_bytes=1) if self.__data is not None: ret += self.__data return ret def _get_api_packet_spec_data_dict(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data_dict` """ base = { DictKeys.SRC_IPV4_ADDR: "%s (%s)" % (self.__src_addr.packed, self.__src_addr.exploded), DictKeys.RSSI: self.__rssi, DictKeys.RECEIVE_OPTIONS: self.__rx_opts } if self.__io_sample is not None: base[DictKeys.NUM_SAMPLES] = 1 base[DictKeys.DIGITAL_MASK] = self.__io_sample.digital_mask base[DictKeys.ANALOG_MASK] = self.__io_sample.analog_mask # Digital values for i in range(16): if self.__io_sample.has_digital_value(IOLine.get(i)): base[IOLine.get(i).description + " digital value"] = \ self.__io_sample.get_digital_value(IOLine.get(i)).name # Analog values for i in range(6): if self.__io_sample.has_analog_value(IOLine.get(i)): base[IOLine.get(i).description + " analog value"] = \ self.__io_sample.get_analog_value(IOLine.get(i)) # Power supply if self.__io_sample.has_power_supply_value(): base[ "Power supply value "] = "%02X" % self.__io_sample.power_supply_value elif self.__data is not None: base[DictKeys.RF_DATA] = utils.hex_to_string(self.__data) return base @property def effective_len(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket.effective_len` """ return len(self) - 8 # Remove 64-bit address @property def source_address(self): """ Returns the IPv4 address of the source device. Returns: :class:`ipaddress.IPv4Address`: the IPv4 address of the source device. .. seealso:: | :class:`ipaddress.IPv4Address` """ return self.__src_addr @source_address.setter def source_address(self, source_address): """ Sets the IPv4 source address. Args: source_address (:class:`ipaddress.IPv4Address`): The new IPv4 source address. .. seealso:: | :class:`ipaddress.IPv4Address` """ if source_address is not None: self.__src_addr = source_address @property def rssi(self): """ Returns the received Signal Strength Indicator (RSSI). Returns: Integer: the received Signal Strength Indicator (RSSI). """ return self.__rssi @rssi.setter def rssi(self, rssi): """ Sets the received Signal Strength Indicator (RSSI). Args: rssi (Integer): the new received Signal Strength Indicator (RSSI). """ self.__rssi = rssi @property def receive_options(self): """ Returns the receive options bitfield. Returns: Integer: the receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ return self.__rx_opts @receive_options.setter def receive_options(self, receive_options): """ Sets the receive options bitfield. Args: receive_options (Integer): the new receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ self.__rx_opts = receive_options @property def rf_data(self): """ Returns the received RF data. Returns: Bytearray: the received RF data. """ if self.__data is None: return None return self.__data.copy() @rf_data.setter def rf_data(self, rf_data): """ Sets the received RF data. Args: rf_data (Bytearray): the new received RF data. """ if rf_data is None: self.__data = None else: self.__data = rf_data.copy() # Modify the IO sample accordingly if rf_data is not None and len(rf_data) >= 5: self.__io_sample = IOSample(self.__data) else: self.__io_sample = None @property def io_sample(self): """ Returns the IO sample corresponding to the data contained in the packet. Returns: :class:`.IOSample`: the IO sample of the packet, `None` if the packet has not any data or if the sample could not be generated correctly. .. seealso:: | :class:`.IOSample` """ return self.__io_sample @io_sample.setter def io_sample(self, io_sample): """ Sets the IO sample of the packet. Args: io_sample (:class:`.IOSample`): the new IO sample to set. .. seealso:: | :class:`.IOSample` """ self.__io_sample = io_sample
class RX64IOPacket(XBeeAPIPacket): """ This class represents an RX64 address IO packet. Packet is built using the parameters of the constructor or providing a valid API payload. I/O data is sent out the UART using an API frame. .. seealso:: | :class:`.XBeeAPIPacket` """ __MIN_PACKET_LENGTH = 20 def __init__(self, x64bit_addr, rssi, receive_options, rf_data): """ Class constructor. Instantiates an :class:`.RX64IOPacket` object with the provided parameters. Args: x64bit_addr (:class:`.XBee64BitAddress`): the 64-bit source address. rssi (Integer): received signal strength indicator. receive_options (Integer): bitfield indicating the receive options. rf_data (Bytearray): received RF data. .. seealso:: | :class:`.ReceiveOptions` | :class:`.XBee64BitAddress` | :class:`.XBeeAPIPacket` """ super().__init__(ApiFrameType.RX_IO_64) self.__x64bit_addr = x64bit_addr self.__rssi = rssi self.__receive_options = receive_options self.__rf_data = rf_data self.__io_sample = IOSample( rf_data) if rf_data is not None and len(rf_data) >= 5 else None @staticmethod def create_packet(raw, operating_mode): """ Override method. Returns: :class:`.RX64IOPacket`. Raises: InvalidPacketException: if the bytearray length is less than 20. (start delim. + length (2 bytes) + frame type + 64bit addr. + rssi + receive options + rf data (5 bytes) + checksum = 20 bytes) InvalidPacketException: if the length field of 'raw' is different than its real length. (length field: bytes 2 and 3) InvalidPacketException: if the first byte of 'raw' is not the header byte. See :class:`.SpecialByte`. InvalidPacketException: if the calculated checksum is different than the checksum field value (last byte). InvalidPacketException: if the frame type is different than :attr:`.ApiFrameType.RX_IO_64`. InvalidOperatingModeException: if ``operating_mode`` is not supported. .. seealso:: | :meth:`.XBeePacket.create_packet` | :meth:`.XBeeAPIPacket._check_api_packet` """ if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE: raise InvalidOperatingModeException(operating_mode.name + " is not supported.") raw = XBeeAPIPacket._unescape_data( raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw XBeeAPIPacket._check_api_packet( raw, min_length=RX64IOPacket.__MIN_PACKET_LENGTH) if raw[3] != ApiFrameType.RX_IO_64.code: raise InvalidPacketException( "This packet is not an RX 64 IO packet.") return RX64IOPacket(XBee64BitAddress(raw[4:12]), raw[12], raw[13], raw[14:-1]) def needs_id(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket.needs_id` """ return False def _get_api_packet_spec_data(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data` """ ret = self.__x64bit_addr.address ret.append(self.__rssi) ret.append(self.__receive_options) if self.__rf_data is not None: ret += self.__rf_data return ret def _get_api_packet_spec_data_dict(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data_dict` """ base = { DictKeys.X16BIT_ADDR: self.__x64bit_addr.address, DictKeys.RSSI: self.__rssi, DictKeys.RECEIVE_OPTIONS: self.__receive_options } if self.__io_sample is not None: base[DictKeys.NUM_SAMPLES] = 1 base[DictKeys.DIGITAL_MASK] = self.__io_sample.digital_mask base[DictKeys.ANALOG_MASK] = self.__io_sample.analog_mask # Digital values for i in range(16): if self.__io_sample.has_digital_value(IOLine.get(i)): base[IOLine.get(i).description + "digital value"] = \ utils.hex_to_string(self.__io_sample.get_digital_value(IOLine.get(i))) # Analog values for i in range(6): if self.__io_sample.has_analog_value(IOLine.get(i)): base[IOLine.get(i).description + "analog value"] = \ utils.hex_to_string(self.__io_sample.get_analog_value(IOLine.get(i))) # Power supply if self.__io_sample.has_power_supply_value(): base[ "Power supply value "] = "%02X" % self.__io_sample.power_supply_value elif self.__rf_data is not None: base[DictKeys.RF_DATA] = utils.hex_to_string(self.__rf_data) return base def __get_64bit_addr(self): """ Returns the 64-bit source address. Returns: :class:`XBee64BitAddress`: the 64-bit source address. .. seealso:: | :class:`.XBee64BitAddress` """ return self.__x64bit_addr def __set_64bit_addr(self, x64bit_addr): """ Sets the 64-bit source address. Args: x64bit_addr (:class:`.XBee64BitAddress`): the new 64-bit source address. .. seealso:: | :class:`.XBee64BitAddress` """ self.__x64bit_addr = x64bit_addr def __get_rssi(self): """ Returns the received Signal Strength Indicator (RSSI). Returns: Integer: the received Signal Strength Indicator (RSSI). """ return self.__rssi def __set_rssi(self, rssi): """ Sets the received Signal Strength Indicator (RSSI). Args: rssi (Integer): the new received Signal Strength Indicator (RSSI). """ self.__rssi = rssi def __get_options(self): """ Returns the receive options bitfield. Returns: Integer: the receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ return self.__receive_options def __set_options(self, receive_options): """ Sets the receive options bitfield. Args: receive_options (Integer): the new receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ self.__receive_options = receive_options def __get_rf_data(self): """ Returns the received RF data. Returns: Bytearray: the received RF data. """ if self.__rf_data is None: return None return self.__rf_data.copy() def __set_rf_data(self, rf_data): """ Sets the received RF data. Args: rf_data (Bytearray): the new received RF data. """ if rf_data is None: self.__rf_data = None else: self.__rf_data = rf_data.copy() # Modify the ioSample accordingly if rf_data is not None and len(rf_data) >= 5: self.__io_sample = IOSample(self.__rf_data) else: self.__io_sample = None def __get_io_sample(self): """ Returns the IO sample corresponding to the data contained in the packet. Returns: :class:`.IOSample`: the IO sample of the packet, ``None`` if the packet has not any data or if the sample could not be generated correctly. .. seealso:: | :class:`.IOSample` """ return self.__io_sample def __set_io_sample(self, io_sample): """ Sets the IO sample of the packet. Args: io_sample (:class:`.IOSample`): the new IO sample to set. .. seealso:: | :class:`.IOSample` """ self.__io_sample = io_sample x64bit_source_addr = property(__get_64bit_addr, __set_64bit_addr) """:class:`.XBee64BitAddress`. 64-bit source address.""" rssi = property(__get_rssi, __set_rssi) """Integer. Received Signal Strength Indicator (RSSI) value.""" receive_options = property(__get_options, __set_options) """Integer. Receive options bitfield.""" rf_data = property(__get_rf_data, __set_rf_data) """Bytearray. Received RF data.""" io_sample = property(__get_io_sample, __set_io_sample) """:class:`.IOSample`: IO sample corresponding to the data contained in the packet."""
class RX16IOPacket(XBeeAPIPacket): """ This class represents an RX16 address IO packet. Packet is built using the parameters of the constructor or providing a valid byte array. I/O data is sent out the UART using an API frame. .. seealso:: | :class:`.XBeeAPIPacket` """ __MIN_PACKET_LENGTH = 14 def __init__(self, x16bit_addr, rssi, receive_options, rf_data): """ Class constructor. Instantiates an :class:`.RX16IOPacket` object with the provided parameters. Args: x16bit_addr (:class:`.XBee16BitAddress`): the 16-bit source address. rssi (Integer): received signal strength indicator. receive_options (Integer): bitfield indicating the receive options. rf_data (Bytearray): received RF data. .. seealso:: | :class:`.ReceiveOptions` | :class:`.XBee16BitAddress` | :class:`.XBeeAPIPacket` """ super().__init__(ApiFrameType.RX_IO_16) self.__x16bit_addr = x16bit_addr self.__rssi = rssi self.__receive_options = receive_options self.__rf_data = rf_data self.__io_sample = IOSample( rf_data) if rf_data is not None and len(rf_data) >= 5 else None @staticmethod def create_packet(raw, operating_mode): """ Override method. Returns: :class:`.RX16IOPacket`. Raises: InvalidPacketException: if the bytearray length is less than 14. (start delim. + length (2 bytes) + frame type + 16bit addr. + rssi + receive options + rf data (5 bytes) + checksum = 14 bytes). InvalidPacketException: if the length field of 'raw' is different from its real length. (length field: bytes 2 and 3) InvalidPacketException: if the first byte of 'raw' is not the header byte. See :class:`.SpecialByte`. InvalidPacketException: if the calculated checksum is different from the checksum field value (last byte). InvalidPacketException: if the frame type is different from :attr:`.ApiFrameType.RX_IO_16`. InvalidOperatingModeException: if `operating_mode` is not supported. .. seealso:: | :meth:`.XBeePacket.create_packet` | :meth:`.XBeeAPIPacket._check_api_packet` """ if operating_mode not in (OperatingMode.ESCAPED_API_MODE, OperatingMode.API_MODE): raise InvalidOperatingModeException(op_mode=operating_mode) XBeeAPIPacket._check_api_packet( raw, min_length=RX16IOPacket.__MIN_PACKET_LENGTH) if raw[3] != ApiFrameType.RX_IO_16.code: raise InvalidPacketException( message="This packet is not an RX 16 IO packet.") return RX16IOPacket(XBee16BitAddress(raw[4:6]), raw[6], raw[7], raw[8:-1]) def needs_id(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket.needs_id` """ return False def is_broadcast(self): """ Override method. .. seealso:: | :meth:`XBeeAPIPacket.is_broadcast` """ return (utils.is_bit_enabled(self.__receive_options, 1) or utils.is_bit_enabled(self.__receive_options, 2)) def _get_api_packet_spec_data(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data` """ ret = self.__x16bit_addr.address ret.append(self.__rssi) ret.append(self.__receive_options) if self.__rf_data is not None: ret += self.__rf_data return ret def _get_api_packet_spec_data_dict(self): """ Override method. .. seealso:: | :meth:`.XBeeAPIPacket._get_api_packet_spec_data_dict` """ base = { DictKeys.X16BIT_ADDR: self.__x16bit_addr.address, DictKeys.RSSI: self.__rssi, DictKeys.RECEIVE_OPTIONS: self.__receive_options } if self.__io_sample is not None: base[DictKeys.NUM_SAMPLES] = 1 base[DictKeys.DIGITAL_MASK] = self.__io_sample.digital_mask base[DictKeys.ANALOG_MASK] = self.__io_sample.analog_mask # Digital values for i in range(16): if self.__io_sample.has_digital_value(IOLine.get(i)): base[IOLine.get(i).description + "digital value"] = \ utils.hex_to_string(self.__io_sample.get_digital_value(IOLine.get(i))) # Analog values for i in range(6): if self.__io_sample.has_analog_value(IOLine.get(i)): base[IOLine.get(i).description + "analog value"] = \ utils.hex_to_string(self.__io_sample.get_analog_value(IOLine.get(i))) # Power supply if self.__io_sample.has_power_supply_value(): base[ "Power supply value "] = "%02X" % self.__io_sample.power_supply_value elif self.__rf_data is not None: base[DictKeys.RF_DATA] = utils.hex_to_string(self.__rf_data) return base @property def x16bit_source_addr(self): """ Returns the 16-bit source address. Returns: :class:`.XBee16BitAddress`: the 16-bit source address. .. seealso:: | :class:`.XBee16BitAddress` """ return self.__x16bit_addr @x16bit_source_addr.setter def x16bit_source_addr(self, x16bit_addr): """ Sets the 16-bit source address. Args: x16bit_addr (:class:`.XBee16BitAddress`): the new 16-bit source address. .. seealso:: | :class:`.XBee16BitAddress` """ self.__x16bit_addr = x16bit_addr @property def rssi(self): """ Returns the received Signal Strength Indicator (RSSI). Returns: Integer: the received Signal Strength Indicator (RSSI). """ return self.__rssi @rssi.setter def rssi(self, rssi): """ Sets the received Signal Strength Indicator (RSSI). Args: rssi (Integer): the new received Signal Strength Indicator (RSSI). """ self.__rssi = rssi @property def receive_options(self): """ Returns the receive options bitfield. Returns: Integer: the receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ return self.__receive_options @receive_options.setter def receive_options(self, receive_options): """ Sets the receive options bitfield. Args: receive_options (Integer): the new receive options bitfield. .. seealso:: | :class:`.ReceiveOptions` """ self.__receive_options = receive_options @property def rf_data(self): """ Returns the received RF data. Returns: Bytearray: the received RF data. """ if self.__rf_data is None: return None return self.__rf_data.copy() @rf_data.setter def rf_data(self, rf_data): """ Sets the received RF data. Args: rf_data (Bytearray): the new received RF data. """ if rf_data is None: self.__rf_data = None else: self.__rf_data = rf_data.copy() # Modify the ioSample accordingly if rf_data is not None and len(rf_data) >= 5: self.__io_sample = IOSample(self.__rf_data) else: self.__io_sample = None @property def io_sample(self): """ Returns the IO sample corresponding to the data contained in the packet. Returns: :class:`.IOSample`: the IO sample of the packet, `None` if the packet has not any data or if the sample could not be generated correctly. .. seealso:: | :class:`.IOSample` """ return self.__io_sample @io_sample.setter def io_sample(self, io_sample): """ Sets the IO sample of the packet. Args: io_sample (:class:`.IOSample`): the new IO sample to set. .. seealso:: | :class:`.IOSample` """ self.__io_sample = io_sample