async def main(): """Search for a Tunnelling device, walk through all possible channels and disconnect them.""" xknx = XKNX() gatewayscanner = GatewayScanner(xknx) gateways = await gatewayscanner.scan() if not gateways: print("No Gateways found") return gateway = gateways[0] if not gateway.supports_tunnelling: print("Gateway does not support tunneling") return udp_client = UDPClient(xknx, (gateway.local_ip, 0), (gateway.ip_addr, gateway.port)) await udp_client.connect() for i in range(0, 255): conn_state = ConnectionState(xknx, udp_client, communication_channel_id=i) await conn_state.start() if conn_state.success: print("Disconnecting ", i) disconnect = Disconnect(xknx, udp_client, communication_channel_id=i) await disconnect.start() if disconnect.success: print("Disconnected ", i)
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() print(exp_knxipframe) 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_create_knxipframe_err(self): """Test if create_knxipframe of base class raises an exception.""" xknx = XKNX(loop=self.loop) udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) request_response = RequestResponse(xknx, udp_client, DisconnectResponse) request_response.timeout_in_seconds = 0 with self.assertRaises(NotImplementedError): self.loop.run_until_complete(asyncio.Task(request_response.start()))
async def test_create_knxipframe_err(self): """Test if create_knxipframe of base class raises an exception.""" xknx = XKNX() udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) request_response = RequestResponse(xknx, udp_client, DisconnectResponse) request_response.timeout_in_seconds = 0 with pytest.raises(NotImplementedError): await request_response.start()
def test_connect(self): """Test connecting from KNX bus.""" xknx = XKNX() udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) connect = Connect(xknx, udp_client, route_back=False) connect.timeout_in_seconds = 0 self.assertEqual(connect.awaited_response_class, ConnectResponse) # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame.init_from_body( ConnectRequest( xknx, request_type=ConnectRequestType.TUNNEL_CONNECTION, control_endpoint=HPAI(ip_addr="192.168.1.3", port=4321), data_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(connect.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: connect.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.CONNECT_RESPONSE) err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID with patch("logging.Logger.debug") as mock_warning: connect.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(connect).__name__, type(err_knxipframe.body).__name__, ErrorCode.E_CONNECTION_ID, ) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame(xknx) res_knxipframe.init(KNXIPServiceType.CONNECT_RESPONSE) res_knxipframe.body.communication_channel = 23 res_knxipframe.body.identifier = 7 connect.response_rec_callback(res_knxipframe, None) self.assertTrue(connect.success) self.assertEqual(connect.communication_channel, 23) self.assertEqual(connect.identifier, 7)
async def test_request_response_cancelled(self, _send_request_mock): """Test RequestResponse: task cancelled. No callback shall be left.""" xknx = XKNX() udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) requ_resp = RequestResponse(xknx, udp_client, KNXIPBody) requ_resp.response_received_event.wait = MagicMock( side_effect=asyncio.CancelledError()) with pytest.raises(asyncio.CancelledError): await requ_resp.start() # Callback was removed again assert udp_client.callbacks == []
def test_request_response_cancelled(self, _send_request_mock): """Test RequestResponse: task cancelled. No callback shall be left.""" xknx = XKNX() udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) requ_resp = RequestResponse(xknx, udp_client, KNXIPBody) requ_resp.response_received_or_timeout.wait = MagicMock( side_effect=asyncio.CancelledError()) with self.assertRaises(asyncio.CancelledError): self.loop.run_until_complete(requ_resp.start()) # Callback was removed again self.assertEqual(udp_client.callbacks, [])
def test_connectionstate(self): """Test connectionstateing from KNX bus.""" xknx = XKNX(loop=self.loop) communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) connectionstate = ConnectionState(xknx, udp_client, communication_channel_id) connectionstate.timeout_in_seconds = 0 self.assertEqual(connectionstate.awaited_response_class, ConnectionStateResponse) self.assertEqual(connectionstate.communication_channel_id, communication_channel_id) # Expected KNX/IP-Frame: exp_knxipframe = KNXIPFrame(xknx) exp_knxipframe.init(KNXIPServiceType.CONNECTIONSTATE_REQUEST) exp_knxipframe.body.communication_channel_id = communication_channel_id exp_knxipframe.body.control_endpoint = HPAI(ip_addr='192.168.1.3', port=4321) 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(connectionstate.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: connectionstate.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.CONNECTIONSTATE_RESPONSE) err_knxipframe.body.status_code = ErrorCode.E_CONNECTION_ID with patch('logging.Logger.warning') as mock_warning: connectionstate.response_rec_callback(err_knxipframe, None) mock_warning.assert_called_with( 'Error: reading rading group address from KNX bus failed: %s', ErrorCode.E_CONNECTION_ID) # Correct Response KNX/IP-Frame: res_knxipframe = KNXIPFrame(xknx) res_knxipframe.init(KNXIPServiceType.CONNECTIONSTATE_RESPONSE) with patch('logging.Logger.info') as mock_info: connectionstate.response_rec_callback(res_knxipframe, None) mock_info.assert_called_with( 'Success: received correct answer from KNX bus: %s', ErrorCode.E_NO_ERROR) self.assertTrue(connectionstate.success)
def test_disconnect(self): """Test disconnecting from KNX bus.""" xknx = XKNX(loop=self.loop) 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) 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(xknx) exp_knxipframe.init(KNXIPServiceType.DISCONNECT_REQUEST) exp_knxipframe.body.communication_channel_id = communication_channel_id exp_knxipframe.body.control_endpoint = HPAI(ip_addr='192.168.1.3', port=4321) 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(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('Cant 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.warning') 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) with patch('logging.Logger.debug') as mock_debug: disconnect.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(disconnect.success)
async 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 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( 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) await 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) assert disconnect.success
async def test_request_response_timeout(self, _send_request_mock, logger_debug_mock): """Test RequestResponse: timeout. No callback shall be left.""" xknx = XKNX() udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) requ_resp = RequestResponse(xknx, udp_client, KNXIPBody) requ_resp.response_received_event.wait = MagicMock( side_effect=asyncio.TimeoutError()) await requ_resp.start() # Debug message was logged logger_debug_mock.assert_called_once_with( "Error: KNX bus did not respond in time (%s secs) to request of type '%s'", 1.0, "RequestResponse", ) # Callback was removed again assert udp_client.callbacks == []
def test_tunnelling(self): """Test tunnelling from KNX bus.""" # pylint: disable=too-many-locals xknx = XKNX() communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))), ) sequence_counter = 42 src_address = IndividualAddress("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: tunnelling_request = TunnellingRequest( xknx, communication_channel_id=communication_channel_id, sequence_counter=sequence_counter, ) tunnelling_request.cemi.telegram = telegram tunnelling_request.cemi.src_addr = src_address exp_knxipframe = KNXIPFrame.init_from_body(tunnelling_request) 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(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("Could not 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.debug") 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) tunnelling.response_rec_callback(res_knxipframe, None) self.assertTrue(tunnelling.success)
gatewayscanner.start() gatewayscanner.stop() if not gatewayscanner.found: raise Exception("No Gateways found") print("Connecting to {}:{} from {}".format(gatewayscanner.found_ip_addr, gatewayscanner.found_port, gatewayscanner.found_local_ip)) own_ip = "192.168.42.1" gateway_ip = "192.168.42.10" gateway_port = 3671 udp_client = UDPClient( xknx, (gatewayscanner.found_local_ip, 0), (gatewayscanner.found_ip_addr, gatewayscanner.found_port)) task = asyncio.Task(udp_client.connect()) xknx.loop.run_until_complete(task) for i in range(0, 255): conn_state = ConnectionState(xknx, udp_client, communication_channel_id=i) conn_state.start() if conn_state.success: print("Disconnecting ", i) disconnect = Disconnect(xknx, udp_client, communication_channel_id=i)