Repository: XKNX/xknx

Issue:
'TunnellingRequest with sequence number not equal to expected' error every few hours
Every few hours 'Received TunnellingRequest with sequence number not equal to expected' error is stuck while the sequence finally loops around. During that time messages are sent but not read.

- [ ] using xknx standalone
- [x] using Home-Assistant knx integration

**Version information:**
- xknx / Home-Assistant release with the issue: 1.2.1
- last working xknx / Home-Assistant release (if known): unknown

**KNX installation:**
`configuration.yaml`
[knx.yaml.txt](https://github.com/XKNX/xknx/files/10067390/knx.yaml.txt)

**Diagnostic data of the config entry (only when Home Assistant is used)**
[config_entry-knx-ed093e5771cbc5d18e4307a64fd3a504.json.txt](https://github.com/XKNX/xknx/files/10067378/config_entry-knx-ed093e5771cbc5d18e4307a64fd3a504.json.txt)

**Traceback (if applicable):**
[log.txt](https://github.com/XKNX/xknx/files/10067435/log.txt)




Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/XKNX/xknx/pull/1114?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) Report
> Merging [#1114](https://codecov.io/gh/XKNX/xknx/pull/1114?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) (c0e250d) into [main](https://codecov.io/gh/XKNX/xknx/commit/d1d6085102331fe9430004e55085612fd993b2f7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) (d1d6085) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/XKNX/xknx/pull/1114/graphs/tree.svg?width=650&height=150&src=pr&token=irWbIygS84&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)](https://codecov.io/gh/XKNX/xknx/pull/1114?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)

```diff
@@           Coverage Diff           @@
##             main    #1114   +/-   ##
=======================================
  Coverage   96.34%   96.34%           
=======================================
  Files         138      138           
  Lines        8643     8644    +1     
=======================================
+ Hits         8327     8328    +1     
  Misses        316      316           
```


| [Impacted Files](https://codecov.io/gh/XKNX/xknx/pull/1114?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) | Coverage Δ | |
|---|---|---|
| [xknx/io/tunnel.py](https://codecov.io/gh/XKNX/xknx/pull/1114/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby90dW5uZWwucHk=) | `88.38% <100.00%> (+0.04%)` | :arrow_up: |


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 2cc605ca..b056f7de 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -12,6 +12,10 @@ nav_order: 2
 
 - ExposeSensor: Add `cooldown` option to allow rate-limiting of sent telegrams.
 
+### Connection
+
+- Disconnect when tunnelling sequence number (UDP) gets out of sync.
+
 ### Internals
 
 - Add `task.done()` to TaskRegistry tasks.
diff --git a/xknx/io/tunnel.py b/xknx/io/tunnel.py
index 20833f81..e57c871d 100644
--- a/xknx/io/tunnel.py
+++ b/xknx/io/tunnel.py
@@ -607,6 +607,9 @@ class UDPTunnel(_Tunnel):
             self.expected_sequence_number,
             tunneling_request,
         )
+        # Tunnelling server should repeat that frame and disconnect after that was also not ACKed.
+        # some don't seem to initiate disconnection here so we take a shortcut and disconnect ourselves
+        self._tunnel_lost()
 
     def _send_tunnelling_ack(
         self, communication_channel_id: int, sequence_counter: int


Test patch:
diff --git a/requirements/testing.txt b/requirements/testing.txt
index 7954b357..e07b3e32 100644
--- a/requirements/testing.txt
+++ b/requirements/testing.txt
@@ -1,13 +1,13 @@
 -r production.txt
-pre-commit==2.20.0
-isort==5.11.3
+pre-commit==2.21.0
+isort==5.11.4
 flake8==6.0.0
-flake8-isort==5.0.3
+flake8-isort==6.0.0
 pydocstyle==6.1.1
 pylint==2.15.9
 pytest==7.2.0
 pytest-asyncio==0.20.3
 pytest-cov==4.0.0
 setuptools==65.6.3
-tox==4.0.16
+tox==4.0.17
 mypy==0.991
diff --git a/test/io_tests/tunnel_test.py b/test/io_tests/tunnel_test.py
index cd177980..53178978 100644
--- a/test/io_tests/tunnel_test.py
+++ b/test/io_tests/tunnel_test.py
@@ -155,7 +155,9 @@ class TestUDPTunnel:
         assert self.tunnel.expected_sequence_number == 11
         assert self.tg_received_mock.call_count == 1
         # wrong sequence number - no ACK, not processed
-        self.tunnel._request_received(test_frame_9, None, None)
+        # reconnect if `auto_reconnect` was True
+        with pytest.raises(CommunicationError):
+            self.tunnel._request_received(test_frame_9, None, None)
         await time_travel(0)
         assert self.tunnel.transport.send.call_args_list == []
         self.tunnel.transport.send.reset_mock()