def test_disconnect_request(self): """Test string representation of KNX/IP DisconnectRequest.""" xknx = XKNX(loop=self.loop) disconnect_request = DisconnectRequest(xknx) disconnect_request.communication_channel_id = 13 disconnect_request.control_endpoint = HPAI(ip_addr='192.168.42.1', port=33941) self.assertEqual( str(disconnect_request), '<DisconnectRequest CommunicationChannelID="13" control_endpoint="<HPAI 192.168.42.1:33941 />" />')
def test_disconnect_request(self): """Test string representation of KNX/IP DisconnectRequest.""" disconnect_request = DisconnectRequest() disconnect_request.communication_channel_id = 13 disconnect_request.control_endpoint = HPAI(ip_addr="192.168.42.1", port=33941) assert ( str(disconnect_request) == '<DisconnectRequest communication_channel_id="13" control_endpoint="192.168.42.1:33941/udp" />' )
def test_set_length(self): """Test setting length.""" xknx = XKNX() header = KNXIPHeader() header.set_length(DisconnectRequest(xknx)) # 6 (header) + 2 + 8 (HPAI length) self.assertEqual(header.total_length, 16)
def create_knxipframe(self) -> KNXIPFrame: """Create KNX/IP Frame object to be sent to device.""" disconnect_request = DisconnectRequest( communication_channel_id=self.communication_channel_id, control_endpoint=self.local_hpai, ) return KNXIPFrame.init_from_body(disconnect_request)
def create_knxipframe(self) -> KNXIPFrame: """Create KNX/IP Frame object to be sent to device.""" (local_addr, local_port) = self.udpclient.getsockname() disconnect_request = DisconnectRequest( self.xknx, communication_channel_id=self.communication_channel_id, control_endpoint=HPAI(ip_addr=local_addr, port=local_port), ) return KNXIPFrame.init_from_body(disconnect_request)
def test_disconnect(self): """Test disconnecting from KNX bus.""" xknx = XKNX() communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) disconnect = Disconnect(xknx, udp_client, communication_channel_id, route_back=False) disconnect.timeout_in_seconds = 0 self.assertEqual(disconnect.awaited_response_class, DisconnectResponse) self.assertEqual(disconnect.communication_channel_id, communication_channel_id) # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame.init_from_body( DisconnectRequest( xknx, communication_channel_id=communication_channel_id, control_endpoint=HPAI(ip_addr="192.168.1.3", port=4321), )) 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(disconnect.start()) mock_udp_send.assert_called_with(exp_knxipframe) # Response KNX/IP-Frame with wrong type wrong_knxipframe = KNXIPFrame(xknx) wrong_knxipframe.init(KNXIPServiceType.DISCONNECT_REQUEST) with patch("logging.Logger.warning") as mock_warning: disconnect.response_rec_callback(wrong_knxipframe, None) mock_warning.assert_called_with("Could not understand knxipframe") # Response KNX/IP-Frame with error: err_knxipframe = KNXIPFrame(xknx) err_knxipframe.init(KNXIPServiceType.DISCONNECT_RESPONSE) err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID with patch("logging.Logger.debug") as mock_warning: disconnect.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(disconnect).__name__, type(err_knxipframe.body).__name__, ErrorCode.E_CONNECTION_ID, ) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame(xknx) res_knxipframe.init(KNXIPServiceType.DISCONNECT_RESPONSE) disconnect.response_rec_callback(res_knxipframe, None) self.assertTrue(disconnect.success)
async def test_disconnect(self): """Test disconnecting from KNX bus.""" communication_channel_id = 23 udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234)) local_hpai = HPAI(ip_addr="192.168.1.3", port=4321) disconnect = Disconnect(udp_transport, communication_channel_id, local_hpai=local_hpai) disconnect.timeout_in_seconds = 0 assert disconnect.awaited_response_class == DisconnectResponse assert disconnect.communication_channel_id == communication_channel_id # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame.init_from_body( DisconnectRequest( communication_channel_id=communication_channel_id, control_endpoint=local_hpai, )) with patch( "xknx.io.transport.UDPTransport.send") as mock_udp_send, patch( "xknx.io.transport.UDPTransport.getsockname" ) as mock_udp_getsockname: mock_udp_getsockname.return_value = ("192.168.1.3", 4321) await disconnect.start() mock_udp_send.assert_called_with(exp_knxipframe) # Response KNX/IP-Frame with wrong type wrong_knxipframe = KNXIPFrame() wrong_knxipframe.init(KNXIPServiceType.DISCONNECT_REQUEST) with patch("logging.Logger.warning") as mock_warning: disconnect.response_rec_callback(wrong_knxipframe, HPAI(), None) mock_warning.assert_called_with("Could not understand knxipframe") # Response KNX/IP-Frame with error: err_knxipframe = KNXIPFrame() err_knxipframe.init(KNXIPServiceType.DISCONNECT_RESPONSE) err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID with patch("logging.Logger.debug") as mock_warning: disconnect.response_rec_callback(err_knxipframe, HPAI(), None) mock_warning.assert_called_with( "Error: KNX bus responded to request of type '%s' with error in '%s': %s", type(disconnect).__name__, type(err_knxipframe.body).__name__, ErrorCode.E_CONNECTION_ID, ) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame() res_knxipframe.init(KNXIPServiceType.DISCONNECT_RESPONSE) disconnect.response_rec_callback(res_knxipframe, HPAI(), None) assert disconnect.success
def test_disconnect_request(self): """Test parsing and streaming DisconnectRequest KNX/IP packet.""" raw = bytes.fromhex("06 10 02 09 00 10 15 00 08 01 C0 A8 C8 0C C3 B4") knxipframe = KNXIPFrame() knxipframe.from_knx(raw) assert isinstance(knxipframe.body, DisconnectRequest) assert knxipframe.body.communication_channel_id == 21 assert knxipframe.body.control_endpoint == HPAI( ip_addr="192.168.200.12", port=50100) disconnect_request = DisconnectRequest( communication_channel_id=21, control_endpoint=HPAI(ip_addr="192.168.200.12", port=50100), ) knxipframe2 = KNXIPFrame.init_from_body(disconnect_request) assert knxipframe2.to_knx() == raw
def test_disconnect_request(self): """Test parsing and streaming DisconnectRequest KNX/IP packet.""" raw = ( 0x06, 0x10, 0x02, 0x09, 0x00, 0x10, 0x15, 0x00, 0x08, 0x01, 0xC0, 0xA8, 0xC8, 0x0C, 0xC3, 0xB4, ) xknx = XKNX() knxipframe = KNXIPFrame(xknx) knxipframe.from_knx(raw) assert isinstance(knxipframe.body, DisconnectRequest) assert knxipframe.body.communication_channel_id == 21 assert knxipframe.body.control_endpoint == HPAI( ip_addr="192.168.200.12", port=50100) disconnect_request = DisconnectRequest( xknx, communication_channel_id=21, control_endpoint=HPAI(ip_addr="192.168.200.12", port=50100), ) knxipframe2 = KNXIPFrame.init_from_body(disconnect_request) assert knxipframe2.to_knx() == list(raw)
async def test_tunnel_connect_send_disconnect( self, time_travel, route_back, data_endpoint_addr, local_endpoint ): """Test initiating a tunnelling connection.""" local_addr = ("192.168.1.1", 12345) remote_addr = ("192.168.1.2", 3671) self.tunnel.route_back = route_back gateway_data_endpoint = ( HPAI(*data_endpoint_addr) if data_endpoint_addr else HPAI() ) self.tunnel.transport.connect = AsyncMock() self.tunnel.transport.getsockname = Mock(return_value=local_addr) self.tunnel.transport.send = Mock() self.tunnel.transport.stop = Mock() # Connect connect_request = ConnectRequest( control_endpoint=local_endpoint, data_endpoint=local_endpoint, ) connect_frame = KNXIPFrame.init_from_body(connect_request) connection_task = asyncio.create_task(self.tunnel.connect()) await time_travel(0) self.tunnel.transport.connect.assert_called_once() self.tunnel.transport.send.assert_called_once_with(connect_frame) connect_response_frame = KNXIPFrame.init_from_body( ConnectResponse( communication_channel=23, data_endpoint=gateway_data_endpoint, identifier=7, ) ) self.tunnel.transport.handle_knxipframe(connect_response_frame, remote_addr) await connection_task assert self.tunnel._data_endpoint_addr == data_endpoint_addr assert self.tunnel._src_address == IndividualAddress(7) # Send - use data endpoint self.tunnel.transport.send.reset_mock() test_telegram = Telegram(payload=GroupValueWrite(DPTArray((1,)))) test_telegram_frame = KNXIPFrame.init_from_body( TunnellingRequest( communication_channel_id=23, sequence_counter=0, cemi=CEMIFrame.init_from_telegram( test_telegram, code=CEMIMessageCode.L_DATA_REQ, src_addr=IndividualAddress(7), ), ) ) asyncio.create_task(self.tunnel.send_telegram(test_telegram)) await time_travel(0) self.tunnel.transport.send.assert_called_once_with( test_telegram_frame, addr=data_endpoint_addr ) # skip ack and confirmation # Disconnect self.tunnel.transport.send.reset_mock() disconnect_request = DisconnectRequest( communication_channel_id=23, control_endpoint=local_endpoint, ) disconnect_frame = KNXIPFrame.init_from_body(disconnect_request) disconnection_task = asyncio.create_task(self.tunnel.disconnect()) await time_travel(0) self.tunnel.transport.send.assert_called_once_with(disconnect_frame) disconnect_response_frame = KNXIPFrame.init_from_body( DisconnectResponse(communication_channel_id=23) ) self.tunnel.transport.handle_knxipframe(disconnect_response_frame, remote_addr) await disconnection_task assert self.tunnel._data_endpoint_addr is None self.tunnel.transport.stop.assert_called_once()
def test_set_length(self): """Test setting length.""" header = KNXIPHeader() header.set_length(DisconnectRequest()) # 6 (header) + 2 + 8 (HPAI length) assert header.total_length == 16