def __init__(self, xknx): """Initialize CEMIFrame object.""" super().__init__(xknx) self.code = CEMIMessageCode.L_DATA_IND self.flags = 0 self.cmd = APCICommand.GROUP_READ self.src_addr = GroupAddress(None) self.dst_addr = GroupAddress(None) self.mpdu_len = 0 self.payload = None
def test_valid_command(frame): """Test for valid frame parsing""" packet_len = frame.from_knx(get_data(0x29, 0, 0, 0, 0, 1, 0, [])) assert frame.code == CEMIMessageCode.L_DATA_IND assert frame.cmd == APCICommand.GROUP_READ assert frame.flags == 0 assert frame.mpdu_len == 1 assert frame.payload == DPTBinary(0) assert frame.src_addr == PhysicalAddress(0) assert frame.dst_addr == PhysicalAddress(0) assert packet_len == 11
def test_no_payload(frame): """Test for having no payload set""" frame.code = CEMIMessageCode.L_DATA_IND frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = None frame.src_addr = PhysicalAddress(0) frame.dst_addr = PhysicalAddress(0) assert [41, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0] == frame.to_knx() assert 11 == frame.calculated_length()
def __init__(self): """Initialize DIBDeviceInformation class.""" super().__init__() self.knx_medium = KNXMedium.TP1 self.programming_mode = False self.individual_address = PhysicalAddress(None) self.installation_number = 0 self.project_number = 0 self.serial_number = "" self.multicast_address = "224.0.23.12" self.mac_address = "" self.name = ""
def from_knx_data_link_layer(self, cemi): """Parse L_DATA_IND, CEMIMessageCode.L_Data_REQ, CEMIMessageCode.L_DATA_CON.""" if len(cemi) < 11: # eg. ETS Line-Scan issues L_DATA_IND with length 10 raise UnsupportedCEMIMessage( "CEMI too small. Length: {}; CEMI: {}".format(len(cemi), cemi) ) # AddIL (Additional Info Length), as specified within # KNX Chapter 3.6.3/4.1.4.3 "Additional information." # Additional information is not yet parsed. addil = cemi[1] # Control field 1 and Control field 2 - first 2 octets after Additional information self.flags = cemi[2 + addil] * 256 + cemi[3 + addil] self.src_addr = PhysicalAddress((cemi[4 + addil], cemi[5 + addil])) if self.flags & CEMIFlags.DESTINATION_GROUP_ADDRESS: self.dst_addr = GroupAddress( (cemi[6 + addil], cemi[7 + addil]), levels=self.xknx.address_format ) else: self.dst_addr = PhysicalAddress((cemi[6 + addil], cemi[7 + addil])) self.mpdu_len = cemi[8 + addil] # TPCI (transport layer control information) -> First 14 bit # APCI (application layer control information) -> Last 10 bit tpci_apci = cemi[9 + addil] * 256 + cemi[10 + addil] try: self.cmd = APCICommand(tpci_apci & 0xFFC0) except ValueError: raise UnsupportedCEMIMessage( "APCI not supported: {:#012b}".format(tpci_apci & 0xFFC0) ) apdu = cemi[10 + addil :] if len(apdu) != self.mpdu_len: raise CouldNotParseKNXIP( "APDU LEN should be {} but is {}".format(self.mpdu_len, len(apdu)) ) if len(apdu) == 1: apci = tpci_apci & DPTBinary.APCI_BITMASK self.payload = DPTBinary(apci) else: self.payload = DPTArray(cemi[11 + addil :]) return 10 + addil + len(apdu)
def test_invalid_payload(frame): """Test for having wrong payload set""" frame.code = CEMIMessageCode.L_DATA_IND frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = DPTComparator() frame.src_addr = PhysicalAddress(0) frame.dst_addr = PhysicalAddress(0) with raises(TypeError): frame.calculated_length() with raises(TypeError): frame.to_knx()
def test_from_knx(self): """Test parsing and streaming CEMIFrame KNX/IP packet (payload=0xf0).""" raw = ( 0x06, 0x10, 0x05, 0x30, 0x00, 0x12, 0x29, 0x00, 0xBC, 0xD0, 0x12, 0x02, 0x01, 0x51, 0x02, 0x00, 0x40, 0xF0, ) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) self.assertTrue(isinstance(knxipframe.body, RoutingIndication)) self.assertTrue(isinstance(knxipframe.body.cemi, CEMIFrame)) self.assertEqual(knxipframe.body.cemi.src_addr, PhysicalAddress("1.2.2")) self.assertEqual(knxipframe.body.cemi.dst_addr, GroupAddress(337)) self.assertEqual(len(knxipframe.body.cemi.payload.value), 1) self.assertEqual(knxipframe.body.cemi.payload.value[0], 0xF0)
def test_EndTOEnd_group_response(self): """Test parsing and streaming CEMIFrame KNX/IP packet, group response.""" # Incoming state raw = ((0x06, 0x10, 0x05, 0x30, 0x00, 0x11, 0x29, 0x00, 0xbc, 0xd0, 0x13, 0x01, 0x01, 0x88, 0x01, 0x00, 0x41)) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) telegram = knxipframe.body.cemi.telegram self.assertEqual( telegram, Telegram(GroupAddress("392"), TelegramType.GROUP_RESPONSE, payload=DPTBinary(1))) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe2.body.cemi.src_addr = PhysicalAddress("1.3.1") knxipframe2.body.cemi.telegram = telegram knxipframe2.body.cemi.set_hops(5) knxipframe2.normalize() self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe2.to_knx(), list(raw))
async def main(): """Connect to a tunnel, send 2 telegrams and disconnect.""" xknx = XKNX() gatewayscanner = GatewayScanner(xknx) gateways = await gatewayscanner.scan() if not gateways: print("No Gateways found") return gateway = gateways[0] src_address = PhysicalAddress("15.15.249") print("Connecting to {}:{} from {}".format(gateway.ip_addr, gateway.port, gateway.local_ip)) tunnel = Tunnel(xknx, src_address, local_ip=gateway.local_ip, gateway_ip=gateway.ip_addr, gateway_port=gateway.port) await tunnel.connect_udp() await tunnel.connect() await tunnel.send_telegram( Telegram(GroupAddress('1/0/15'), payload=DPTBinary(1))) await asyncio.sleep(2) await tunnel.send_telegram( Telegram(GroupAddress('1/0/15'), payload=DPTBinary(0))) await asyncio.sleep(2) await tunnel.connectionstate() await tunnel.disconnect()
def __init__(self, config=None, loop=None, own_address=PhysicalAddress(DEFAULT_ADDRESS), address_format=GroupAddressType.LONG, telegram_received_cb=None, device_updated_cb=None, rate_limit=DEFAULT_RATE_LIMIT): """Initialize XKNX class.""" # pylint: disable=too-many-arguments self.devices = Devices() self.telegrams = asyncio.Queue() self.loop = loop or asyncio.get_event_loop() self.sigint_received = asyncio.Event() self.telegram_queue = TelegramQueue(self) self.state_updater = None self.knxip_interface = None self.started = False self.address_format = address_format self.own_address = own_address self.rate_limit = rate_limit self.logger = logging.getLogger('xknx.log') self.knx_logger = logging.getLogger('xknx.knx') self.telegram_logger = logging.getLogger('xknx.telegram') self.connection_config = None if config is not None: Config(self).read(config) if telegram_received_cb is not None: self.telegram_queue.register_telegram_received_cb( telegram_received_cb) if device_updated_cb is not None: self.devices.register_device_updated_cb(device_updated_cb)
def test_dib_device_informatio(self): """Test string representation of DIBDeviceInformation.""" dib = DIBDeviceInformation() dib.knx_medium = KNXMedium.TP1 dib.programming_mode = False dib.individual_address = PhysicalAddress("1.1.0") dib.name = "Gira KNX/IP-Router" dib.mac_address = "00:01:02:03:04:05" dib.multicast_address = "224.0.23.12" dib.serial_number = "13:37:13:37:13:37" dib.project_number = 564 dib.installation_number = 2 self.assertEqual( str(dib), "<DIBDeviceInformation \n" '\tknx_medium="KNXMedium.TP1" \n' '\tprogramming_mode="False" \n' '\tindividual_address="PhysicalAddress("1.1.0")" \n' '\tinstallation_number="2" \n' '\tproject_number="564" \n' '\tserial_number="13:37:13:37:13:37" \n' '\tmulticast_address="224.0.23.12" \n' '\tmac_address="00:01:02:03:04:05" \n' '\tname="Gira KNX/IP-Router" />', )
async def connect(self): """Connect/build tunnel.""" connect = Connect(self.xknx, self.udp_client) await connect.start() if not connect.success: if self.auto_reconnect: logger.warning( "Could not connect to KNX. Retry in %s seconds.", self.auto_reconnect_wait, ) self._reconnect_task = asyncio.create_task(self.schedule_reconnect()) return raise CommunicationError( "Could not establish connection", not self._is_reconnecting ) logger.debug( "Tunnel established communication_channel=%s, id=%s", connect.communication_channel, connect.identifier, ) if self._is_reconnecting: logger.info("Successfully reconnected to KNX bus.") self._reconnect_task = None self._is_reconnecting = False self.communication_channel = connect.communication_channel # Use the individual address provided by the tunnelling server self._src_address = PhysicalAddress(connect.identifier) self.sequence_number = 0 await self.start_heartbeat()
def test_telegram_set(self): """Test parsing and streaming CEMIFrame KNX/IP packet with DPTArray/DPTTime as payload.""" xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe.body.src_addr = PhysicalAddress("1.2.2") telegram = Telegram() telegram.group_address = GroupAddress(337) telegram.payload = DPTArray(DPTTime().to_knx({ 'hours': 13, 'minutes': 23, 'seconds': 42 })) knxipframe.body.telegram = telegram knxipframe.body.set_hops(5) knxipframe.normalize() raw = ((0x06, 0x10, 0x05, 0x30, 0x00, 0x14, 0x29, 0x00, 0xbc, 0xd0, 0x12, 0x02, 0x01, 0x51, 0x04, 0x00, 0x80, 13, 23, 42)) self.assertEqual(knxipframe.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe.to_knx(), list(raw))
def test_config_general(self): """Test reading general section from config file.""" self.assertEqual(TestConfig.xknx.own_address, PhysicalAddress('15.15.249')) self.assertEqual(TestConfig.xknx.rate_limit, 18) self.assertEqual(TestConfig.xknx.multicast_group, "224.1.2.3") self.assertEqual(TestConfig.xknx.multicast_port, 1337)
def test_tunnelling(self): """Test tunnelling from KNX bus.""" # pylint: disable=too-many-locals xknx = XKNX(loop=self.loop) communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) telegram = Telegram(GroupAddress('1/2/3'), payload=DPTArray((0x1, 0x2, 0x3))) sequence_counter = 42 src_address = PhysicalAddress('2.2.2') tunnelling = Tunnelling(xknx, udp_client, telegram, src_address, sequence_counter, communication_channel_id) tunnelling.timeout_in_seconds = 0 self.assertEqual(tunnelling.awaited_response_class, TunnellingAck) self.assertEqual(tunnelling.communication_channel_id, communication_channel_id) # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame(xknx) exp_knxipframe.init(KNXIPServiceType.TUNNELLING_REQUEST) exp_knxipframe.body.cemi.telegram = telegram exp_knxipframe.body.cemi.src_addr = src_address exp_knxipframe.body.communication_channel_id = communication_channel_id exp_knxipframe.body.sequence_counter = sequence_counter exp_knxipframe.normalize() with patch('xknx.io.UDPClient.send') as mock_udp_send, \ patch('xknx.io.UDPClient.getsockname') as mock_udp_getsockname: mock_udp_getsockname.return_value = ("192.168.1.3", 4321) self.loop.run_until_complete(asyncio.Task(tunnelling.start())) mock_udp_send.assert_called_with(exp_knxipframe) # Response KNX/IP-Frame with wrong type wrong_knxipframe = KNXIPFrame(xknx) wrong_knxipframe.init(KNXIPServiceType.CONNECTIONSTATE_REQUEST) with patch('logging.Logger.warning') as mock_warning: tunnelling.response_rec_callback(wrong_knxipframe, None) mock_warning.assert_called_with('Cant understand knxipframe') # Response KNX/IP-Frame with error: err_knxipframe = KNXIPFrame(xknx) err_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK) err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID with patch('logging.Logger.warning') as mock_warning: tunnelling.response_rec_callback(err_knxipframe, None) mock_warning.assert_called_with( "Error: KNX bus responded to request of type '%s' with error in '%s': %s", type(tunnelling).__name__, type(err_knxipframe.body).__name__, ErrorCode.E_CONNECTION_ID) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame(xknx) res_knxipframe.init(KNXIPServiceType.TUNNELLING_ACK) with patch('logging.Logger.debug') as mock_debug: tunnelling.response_rec_callback(res_knxipframe, None) mock_debug.assert_called_with( 'Success: received correct answer from KNX bus: %s', ErrorCode.E_NO_ERROR) self.assertTrue(tunnelling.success)
def test_with_invalid(self): """Test with some invalid addresses.""" invalid_addresses = ('15.15.256', '16.0.0', '0.16.0', '15.15.255a', 'a15.15.255', 'abc', '123', 65536, (0xff, 0xfff), (0xfff, 0xff), (-1, -1), []) for address in invalid_addresses: with self.subTest(address=address): with self.assertRaises(CouldNotParseAddress): PhysicalAddress(address)
def parse_general(self, doc): """Parse the general section of xknx.yaml.""" if "general" in doc: if "own_address" in doc["general"]: self.xknx.own_address = \ PhysicalAddress(doc["general"]["own_address"]) if "rate_limit" in doc["general"]: self.xknx.rate_limit = \ doc["general"]["rate_limit"]
def test_with_valid(self): """Test with some valid addresses.""" valid_addresses = (('0.0.0', 0), ('1.0.0', 4096), ('1.1.0', 4352), ('1.1.1', 4353), ('1.1.11', 4363), ('1.1.111', 4463), ('1.11.111', 7023), ('11.11.111', 47983), ('15.15.255', 65535), ((0xff, 0xff), 65535), (0, 0), (65535, 65535)) for address in valid_addresses: with self.subTest(address=address): self.assertEqual(PhysicalAddress(address[0]).raw, address[1])
def test_invalid_dst_addr(frame): """Test for invalid dst addr""" frame.code = CEMIMessageCode.L_DATA_IND frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = DPTBinary(0) frame.src_addr = PhysicalAddress(0) frame.dst_addr = None with raises(ConversionError, match=r"dst_addr not set"): frame.to_knx()
def test_with_valid(self): """Test with some valid addresses.""" valid_addresses = ( ("0.0.0", 0), ("123", 123), ("1.0.0", 4096), ("1.1.0", 4352), ("1.1.1", 4353), ("1.1.11", 4363), ("1.1.111", 4463), ("1.11.111", 7023), ("11.11.111", 47983), (PhysicalAddress("11.11.111"), 47983), ("15.15.255", 65535), ((0xFF, 0xFF), 65535), (0, 0), (65535, 65535), ) for address in valid_addresses: with self.subTest(address=address): self.assertEqual(PhysicalAddress(address[0]).raw, address[1])
def from_knx(self, raw): """Parse/deserialize from KNX/IP raw data.""" if len(raw) < DIBDeviceInformation.LENGTH: raise CouldNotParseKNXIP("wrong connection header length") if raw[0] != DIBDeviceInformation.LENGTH: raise CouldNotParseKNXIP("wrong connection header length") if DIBTypeCode(raw[1]) != DIBTypeCode.DEVICE_INFO: raise CouldNotParseKNXIP("DIB is no device info") self.knx_medium = KNXMedium(raw[2]) # last bit of device_status. All other bits are unused self.programming_mode = bool(raw[3]) self.individual_address = PhysicalAddress((raw[4], raw[5])) installation_project_identifier = raw[6] * 256 + raw[7] self.project_number = installation_project_identifier >> 4 self.installation_number = installation_project_identifier & 15 self.serial_number = ":".join("%02x" % i for i in raw[8:14]) self.multicast_address = ".".join("%i" % i for i in raw[14:18]) self.mac_address = ":".join("%02x" % i for i in raw[18:24]) self.name = "".join(map(chr, raw[24:54])).rstrip("\0") return DIBDeviceInformation.LENGTH
def test_equal(self): """Test if the equal operator works in all cases.""" self.assertEqual(PhysicalAddress("1.0.0"), PhysicalAddress(4096)) self.assertNotEqual(PhysicalAddress("1.0.0"), PhysicalAddress("1.1.1")) self.assertNotEqual(PhysicalAddress("1.0.0"), None) with self.assertRaises(TypeError): PhysicalAddress("1.0.0") == "example" # pylint: disable=expression-not-assigned
def __init__( self, config=None, own_address=DEFAULT_ADDRESS, address_format=GroupAddressType.LONG, telegram_received_cb=None, device_updated_cb=None, rate_limit=DEFAULT_RATE_LIMIT, multicast_group=DEFAULT_MCAST_GRP, multicast_port=DEFAULT_MCAST_PORT, log_directory=None, state_updater=False, daemon_mode=False, connection_config=ConnectionConfig(), ): """Initialize XKNX class.""" # pylint: disable=too-many-arguments self.devices = Devices() self.telegrams = asyncio.Queue() self.sigint_received = asyncio.Event() self.telegram_queue = TelegramQueue(self) self.state_updater = StateUpdater(self) self.knxip_interface = None self.started = asyncio.Event() self.address_format = address_format self.own_address = PhysicalAddress(own_address) self.rate_limit = rate_limit self.multicast_group = multicast_group self.multicast_port = multicast_port self.connection_config = connection_config self.start_state_updater = state_updater self.daemon_mode = daemon_mode self.version = VERSION if log_directory is not None: self.setup_logging(log_directory) if config is not None: Config(self).read(config) if telegram_received_cb is not None: self.telegram_queue.register_telegram_received_cb( telegram_received_cb) if device_updated_cb is not None: self.devices.register_device_updated_cb(device_updated_cb)
def test_telegram_set(self): """Test parsing and streaming CEMIFrame KNX/IP packet with DPTArray/DPTTime as payload.""" xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe.body.cemi.src_addr = PhysicalAddress("1.2.2") telegram = Telegram( group_address=GroupAddress(337), payload=DPTArray(DPTTime().to_knx( time.strptime("13:23:42", "%H:%M:%S"))), ) knxipframe.body.cemi.telegram = telegram knxipframe.body.cemi.set_hops(5) knxipframe.normalize() raw = ( 0x06, 0x10, 0x05, 0x30, 0x00, 0x14, 0x29, 0x00, 0xBC, 0xD0, 0x12, 0x02, 0x01, 0x51, 0x04, 0x00, 0x80, 13, 23, 42, ) self.assertEqual(knxipframe.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe.to_knx(), list(raw))
def test_EndTOEnd_group_write_2bytes(self): """Test parsing and streaming CEMIFrame KNX/IP packet, setting value of thermostat.""" # Incoming Temperature from thermostat raw = ( 0x06, 0x10, 0x05, 0x30, 0x00, 0x13, 0x29, 0x00, 0xBC, 0xD0, 0x14, 0x02, 0x08, 0x01, 0x03, 0x00, 0x80, 0x07, 0xC1, ) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) telegram = knxipframe.body.cemi.telegram self.assertEqual( telegram, Telegram(GroupAddress("2049"), payload=DPTArray(DPTTemperature().to_knx(19.85))), ) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe2.body.cemi.src_addr = PhysicalAddress("1.4.2") knxipframe2.body.cemi.telegram = telegram knxipframe2.body.cemi.set_hops(5) knxipframe2.normalize() self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe2.to_knx(), list(raw))
def __init__( self, config=None, loop=None, own_address=DEFAULT_ADDRESS, address_format=GroupAddressType.LONG, telegram_received_cb=None, device_updated_cb=None, rate_limit=DEFAULT_RATE_LIMIT, multicast_group=DEFAULT_MCAST_GRP, multicast_port=DEFAULT_MCAST_PORT, ): """Initialize XKNX class.""" # pylint: disable=too-many-arguments self.devices = Devices() self.telegrams = asyncio.Queue() self.loop = loop or asyncio.get_event_loop() self.sigint_received = asyncio.Event() self.telegram_queue = TelegramQueue(self) self.state_updater = StateUpdater(self) self.knxip_interface = None self.started = asyncio.Event() self.address_format = address_format self.own_address = PhysicalAddress(own_address) self.rate_limit = rate_limit self.multicast_group = multicast_group self.multicast_port = multicast_port self.logger = logging.getLogger("xknx.log") self.knx_logger = logging.getLogger("xknx.knx") self.telegram_logger = logging.getLogger("xknx.telegram") self.raw_socket_logger = logging.getLogger("xknx.raw_socket") self.connection_config = None self.version = VERSION if config is not None: Config(self).read(config) if telegram_received_cb is not None: self.telegram_queue.register_telegram_received_cb( telegram_received_cb) if device_updated_cb is not None: self.devices.register_device_updated_cb(device_updated_cb)
def test_with_invalid(self): """Test with some invalid addresses.""" invalid_addresses = ( "15.15.256", "16.0.0", "0.16.0", "15.15.255a", "a15.15.255", "abc", 65536, (0xFF, 0xFFF), (0xFFF, 0xFF), (-1, -1), [], ) for address in invalid_addresses: with self.subTest(address=address): with self.assertRaises(CouldNotParseAddress): PhysicalAddress(address)
def test_maximum_apci(self): """Test parsing and streaming CEMIFrame KNX/IP packet, testing maximum APCI.""" telegram = Telegram() telegram.group_address = GroupAddress(337) telegram.payload = DPTBinary(DPTBinary.APCI_MAX_VALUE) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe.body.cemi.src_addr = PhysicalAddress("1.3.1") knxipframe.body.cemi.telegram = telegram knxipframe.body.cemi.set_hops(5) knxipframe.normalize() raw = ((0x06, 0x10, 0x05, 0x30, 0x00, 0x11, 0x29, 0x00, 0xbc, 0xd0, 0x13, 0x01, 0x01, 0x51, 0x01, 0x00, 0xbf)) self.assertEqual(knxipframe.to_knx(), list(raw)) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe2.from_knx(knxipframe.to_knx()) self.assertEqual(knxipframe2.body.cemi.telegram, telegram)
def test_EndTOEnd_group_write_1byte(self): """Test parsing and streaming CEMIFrame KNX/IP packet, dimm light in my kitchen.""" # Dimm Kitchen L1 to 0x65 raw = ( 0x06, 0x10, 0x05, 0x30, 0x00, 0x12, 0x29, 0x00, 0xBC, 0xD0, 0xFF, 0xF9, 0x01, 0x4B, 0x02, 0x00, 0x80, 0x65, ) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) telegram = knxipframe.body.cemi.telegram self.assertEqual(telegram, Telegram(GroupAddress("331"), payload=DPTArray(0x65))) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe2.body.cemi.src_addr = PhysicalAddress("15.15.249") knxipframe2.body.cemi.telegram = telegram knxipframe2.body.cemi.set_hops(5) knxipframe2.normalize() self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe2.to_knx(), list(raw))
def test_EndTOEnd_group_read(self): """Test parsing and streaming CEMIFrame KNX/IP packet, group read.""" # State request raw = ( 0x06, 0x10, 0x05, 0x30, 0x00, 0x11, 0x29, 0x00, 0xBC, 0xD0, 0xFF, 0xF9, 0x01, 0xB8, 0x01, 0x00, 0x00, ) xknx = XKNX(loop=self.loop) knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) telegram = knxipframe.body.cemi.telegram self.assertEqual( telegram, Telegram(GroupAddress("440"), TelegramType.GROUP_READ)) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.ROUTING_INDICATION) knxipframe2.body.cemi.src_addr = PhysicalAddress("15.15.249") knxipframe2.body.cemi.telegram = telegram knxipframe2.body.cemi.set_hops(5) knxipframe2.normalize() self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6])) self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:])) self.assertEqual(knxipframe2.to_knx(), list(raw))