Skip to content

Commit 2cced00

Browse files
authored
Merge pull request #59 from CoMPaTech/upd
Bug Fixes Improved resilience to network errors and timeouts with clearer cancellation behavior and log messages. Prevented failures when devices lack GPS data (e.g., certain NanoStation units). Tests Added test coverage and fixtures for scenarios with missing or extended GPS metadata.
2 parents 5f7e778 + 475dc24 commit 2cced00

11 files changed

+679
-26
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [0.2.8] - 2025-08-12
6+
7+
### Changed
8+
9+
- Improved exception handling
10+
- GPS data optional (reported on NanoStation via HA Core Issue 150491)
11+
12+
## [0.2.7] - 2025-08-08
13+
14+
### Added
15+
16+
- Added support for 8.7.11 NanoStation not having 'age' in the 'remote'(s)
17+
- Added debugging script for pinpointing issues in the dataclass
18+
519
## [0.2.6] - 2025-08-06
620

721
### Added

airos/airos8.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from __future__ import annotations
44

5+
import asyncio
56
import json
67
import logging
78
from typing import Any
@@ -185,12 +186,12 @@ async def login(self) -> bool:
185186
log = f"Login failed with status {response.status}. Full Response: {response.text}"
186187
_LOGGER.error(log)
187188
raise AirOSConnectionAuthenticationError from None
188-
except (
189-
aiohttp.ClientError,
190-
aiohttp.client_exceptions.ConnectionTimeoutError,
191-
) as err:
189+
except (TimeoutError, aiohttp.client_exceptions.ClientError) as err:
192190
_LOGGER.exception("Error during login")
193191
raise AirOSDeviceConnectionError from err
192+
except asyncio.CancelledError:
193+
_LOGGER.info("Login task was cancelled")
194+
raise
194195

195196
def derived_data(
196197
self, response: dict[str, Any] | None = None
@@ -301,12 +302,12 @@ async def status(self) -> AirOSData:
301302
response_text,
302303
)
303304
raise AirOSDeviceConnectionError
304-
except (
305-
aiohttp.ClientError,
306-
aiohttp.client_exceptions.ConnectionTimeoutError,
307-
) as err:
308-
_LOGGER.error("Status API call failed: %s", err)
305+
except (TimeoutError, aiohttp.client_exceptions.ClientError) as err:
306+
_LOGGER.exception("Status API call failed: %s", err)
309307
raise AirOSDeviceConnectionError from err
308+
except asyncio.CancelledError:
309+
_LOGGER.info("API status retrieval task was cancelled")
310+
raise
310311

311312
async def stakick(self, mac_address: str = None) -> bool:
312313
"""Reconnect client station."""
@@ -339,12 +340,12 @@ async def stakick(self, mac_address: str = None) -> bool:
339340
log = f"Unable to restart connection response status {response.status} with {response_text}"
340341
_LOGGER.error(log)
341342
return False
342-
except (
343-
aiohttp.ClientError,
344-
aiohttp.client_exceptions.ConnectionTimeoutError,
345-
) as err:
346-
_LOGGER.exception("Error during reconnect request call")
343+
except (TimeoutError, aiohttp.client_exceptions.ClientError) as err:
344+
_LOGGER.exception("Error during call to reconnect remote: %s", err)
347345
raise AirOSDeviceConnectionError from err
346+
except asyncio.CancelledError:
347+
_LOGGER.info("Reconnect task was cancelled")
348+
raise
348349

349350
async def provmode(self, active: bool = False) -> bool:
350351
"""Set provisioning mode."""
@@ -378,9 +379,9 @@ async def provmode(self, active: bool = False) -> bool:
378379
log = f"Unable to change provisioning mode response status {response.status} with {response_text}"
379380
_LOGGER.error(log)
380381
return False
381-
except (
382-
aiohttp.ClientError,
383-
aiohttp.client_exceptions.ConnectionTimeoutError,
384-
) as err:
385-
_LOGGER.exception("Error during provisioning mode call")
382+
except (TimeoutError, aiohttp.client_exceptions.ClientError) as err:
383+
_LOGGER.exception("Error during call to change provisioning mode: %s", err)
386384
raise AirOSDeviceConnectionError from err
385+
except asyncio.CancelledError:
386+
_LOGGER.info("Provisioning mode change task was cancelled")
387+
raise

airos/data.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ class Remote(AirOSDataClass):
348348
cable_loss: int
349349
ethlist: list[EthList]
350350
ipaddr: list[str]
351-
gps: GPSData
352351
oob: bool
353352
unms: UnmsStatus
354353
airview: int
@@ -357,6 +356,9 @@ class Remote(AirOSDataClass):
357356
ip6addr: list[str] | None = None # For v4 only devices
358357
height: int | None = None
359358
age: int | None = None # At least not present on 8.7.11
359+
gps: GPSData | None = (
360+
None # Reported NanoStation 5AC 8.7.18 without GPS Core 150491
361+
)
360362

361363
@classmethod
362364
def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
@@ -556,5 +558,7 @@ class AirOS8Data(AirOSDataClass):
556558
provmode: Any
557559
ntpclient: Any
558560
unms: UnmsStatus
559-
gps: GPSMain
560561
derived: Derived
562+
gps: GPSData | None = (
563+
None # Reported NanoStation 5AC 8.7.18 without GPS Core 150491
564+
)

fixtures/airos_liteapgps_ap_ptmp_40mhz.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@
2525
},
2626
"genuine": "/images/genuine.png",
2727
"gps": {
28+
"alt": 252.5,
29+
"dim": 3,
30+
"dop": 1.52,
2831
"fix": 1,
2932
"lat": 52.379894,
30-
"lon": 4.901608
33+
"lon": 4.901608,
34+
"sats": 8,
35+
"time_synced": null
3136
},
3237
"host": {
3338
"cpuload": 59.595959,

fixtures/airos_loco5ac_ap-ptp.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@
2525
},
2626
"genuine": "/images/genuine.png",
2727
"gps": {
28+
"alt": null,
29+
"dim": null,
30+
"dop": null,
2831
"fix": 0,
2932
"lat": 52.379894,
30-
"lon": 4.901608
33+
"lon": 4.901608,
34+
"sats": null,
35+
"time_synced": null
3136
},
3237
"host": {
3338
"cpuload": 10.10101,

fixtures/airos_loco5ac_sta-ptp.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@
2525
},
2626
"genuine": "/images/genuine.png",
2727
"gps": {
28+
"alt": null,
29+
"dim": null,
30+
"dop": null,
2831
"fix": 0,
2932
"lat": 52.379894,
30-
"lon": 4.901608
33+
"lon": 4.901608,
34+
"sats": null,
35+
"time_synced": null
3136
},
3237
"host": {
3338
"cpuload": 44.0,

fixtures/airos_nanobeam5ac_sta_ptmp_40mhz.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@
2525
},
2626
"genuine": "/images/genuine.png",
2727
"gps": {
28+
"alt": null,
29+
"dim": null,
30+
"dop": null,
2831
"fix": 0,
2932
"lat": 52.379894,
30-
"lon": 4.901608
33+
"lon": 4.901608,
34+
"sats": null,
35+
"time_synced": null
3136
},
3237
"host": {
3338
"cpuload": 32.673267,

0 commit comments

Comments
 (0)