Skip to content

Commit 51d053e

Browse files
committed
Add improvents and more v6 mapping
1 parent c705360 commit 51d053e

13 files changed

+74
-27
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ All notable changes to this project will be documented in this file.
1010
- Calculated cpuload on v6 if values available (to prevent reporting close to 100%)
1111
- Fix frequency on v6 firmware (if value is cast as a string ending in MHz)
1212
- Added tx/rx rates for v6
13+
- Fixed ieeemode (v8) vs opmode (v6) mapped back to IeeeMode enum
14+
- Derived antenna_gain (v8) from antenna (v6 string)
15+
- Improved internal workings
1316

1417
## [0.5.6] - 2025-10-11
1518

airos/airos6.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __init__(
3636
)
3737

3838
@staticmethod
39-
def derived_wireless_data(
39+
def _derived_wireless_data(
4040
derived: dict[str, Any], response: dict[str, Any]
4141
) -> dict[str, Any]:
4242
"""Add derived wireless data to the device response."""

airos/base.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(
9595
self._login_urls = [self._login_url, self._v6_xm_login_url]
9696

9797
@staticmethod
98-
def derived_wireless_data(
98+
def _derived_wireless_data(
9999
derived: dict[str, Any], response: dict[str, Any]
100100
) -> dict[str, Any]:
101101
"""Add derived wireless data to the device response."""
@@ -190,9 +190,10 @@ def _derived_data_helper(
190190

191191
return response
192192

193-
def derived_data(self, response: dict[str, Any]) -> dict[str, Any]:
193+
@classmethod
194+
def derived_data(cls, response: dict[str, Any]) -> dict[str, Any]:
194195
"""Add derived data to the device response (instance method for polymorphism)."""
195-
return self._derived_data_helper(response, self.derived_wireless_data)
196+
return cls._derived_data_helper(response, cls._derived_wireless_data)
196197

197198
def _get_authenticated_headers(
198199
self,

airos/data.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,12 @@ class IeeeMode(Enum):
145145

146146
AUTO = "AUTO"
147147
_11ACVHT80 = "11ACVHT80" # On a NanoStation
148+
_11ACVHT60 = "11ACVHT60"
149+
_11ACVHT50 = "11ACVHT50"
148150
_11ACVHT40 = "11ACVHT40"
149151
_11ACVHT20 = "11ACVHT20" # On a LiteBeam
152+
_11NAHT40MINUS = "11NAHT40MINUS" # On a v6 XM
153+
_11NAHT40PLUS = "11NAHT40PLUS" # On a v6 XW
150154
# More to be added when known
151155

152156

@@ -552,13 +556,19 @@ class Wireless(AirOSDataClass):
552556
@classmethod
553557
def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
554558
"""Pre-deserialize hook for Wireless."""
559+
555560
_check_and_log_unknown_enum_value(d, "mode", WirelessMode, "Wireless", "mode")
561+
556562
_check_and_log_unknown_enum_value(
557-
d, "ieeemode", IeeeMode, "Wireless", "ieeemode"
563+
d, "security", Security, "Wireless", "security"
558564
)
565+
566+
# Ensure ieeemode/opmode are in uppercase and map opmode back into ieeemode
567+
d["ieeemode"] = d["ieeemode"].upper() or None
559568
_check_and_log_unknown_enum_value(
560-
d, "security", Security, "Wireless", "security"
569+
d, "ieeemode", IeeeMode, "Wireless", "ieeemode"
561570
)
571+
562572
return d
563573

564574

@@ -583,8 +593,8 @@ class Wireless6(AirOSDataClass):
583593
ack: int
584594
distance: int # In meters
585595
ccq: int
586-
txrate: int
587-
rxrate: int
596+
txrate: str
597+
rxrate: str
588598
security: Security
589599
qos: str
590600
rstatus: int
@@ -594,7 +604,9 @@ class Wireless6(AirOSDataClass):
594604
aprepeater: int # Not bool as v8
595605
chanbw: int
596606
throughput: Throughput
607+
ieeemode: IeeeMode # Virtual to match base/v8
597608
mode: Wireless6Mode | None = None
609+
antenna_gain: int | None = None # Virtual to match base/v8
598610

599611
@classmethod
600612
def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
@@ -615,6 +627,13 @@ def __pre_deserialize__(cls, d: dict[str, Any]) -> dict[str, Any]:
615627
"tx": int(float(txrate)) if txrate else 0,
616628
}
617629

630+
d["ieeemode"] = d["opmode"].upper() or None
631+
_check_and_log_unknown_enum_value(
632+
d, "ieeemode", IeeeMode, "Wireless", "ieeemode"
633+
)
634+
match = re.search(r"(\d+)\s*dBi", d["antenna"])
635+
d["antenna_gain"] = int(match.group(1)) if match else None
636+
618637
return d
619638

620639

airos/helpers.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ async def async_get_firmware_data(
4747

4848
if fw_major == 6:
4949
derived_data = AirOS6._derived_data_helper( # noqa: SLF001
50-
raw_status, AirOS6.derived_wireless_data
50+
raw_status,
51+
AirOS6._derived_wireless_data, # noqa: SLF001
5152
)
5253
else: # Assume AirOS 8 for all other versions
5354
derived_data = AirOS8._derived_data_helper( # noqa: SLF001
54-
raw_status, AirOS8.derived_wireless_data
55+
raw_status,
56+
AirOS8._derived_wireless_data, # noqa: SLF001
5557
)
5658

5759
# Extract MAC address and hostname from the derived data

fixtures/airos_NanoStation_M5_sta_v6.3.16.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
"wireless": {
132132
"ack": 5,
133133
"antenna": "Built in - 16 dBi",
134+
"antenna_gain": 16,
134135
"apmac": "xxxxxxxx",
135136
"aprepeater": 0,
136137
"cac_nol": 0,
@@ -144,22 +145,23 @@
144145
"essid": "Nano",
145146
"frequency": 5180,
146147
"hide_essid": 0,
148+
"ieeemode": "11NAHT40PLUS",
147149
"mode": "sta",
148150
"noisef": -99,
149151
"nol_chans": 0,
150152
"opmode": "11NAHT40PLUS",
151153
"qos": "No QoS",
152154
"rssi": 32,
153155
"rstatus": 5,
154-
"rxrate": 216,
156+
"rxrate": "216",
155157
"security": "WPA2",
156158
"signal": -64,
157159
"throughput": {
158160
"rx": 216,
159161
"tx": 270
160162
},
161163
"txpower": 24,
162-
"txrate": 270,
164+
"txrate": "270",
163165
"wds": 1
164166
}
165167
}

fixtures/airos_NanoStation_loco_M5_v6.3.16_XM_ap.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"wireless": {
118118
"ack": 28,
119119
"antenna": "Built in - 13 dBi",
120+
"antenna_gain": 13,
120121
"apmac": "XX:XX:XX:XX:XX:XX",
121122
"aprepeater": 0,
122123
"cac_nol": 0,
@@ -130,22 +131,23 @@
130131
"essid": "SOMETHING",
131132
"frequency": 5700,
132133
"hide_essid": 1,
134+
"ieeemode": "11NAHT40MINUS",
133135
"mode": "ap",
134136
"noisef": -91,
135137
"nol_chans": 0,
136138
"opmode": "11naht40minus",
137139
"qos": "No QoS",
138140
"rssi": 51,
139141
"rstatus": 5,
140-
"rxrate": 300,
142+
"rxrate": "300",
141143
"security": "WPA2",
142144
"signal": -45,
143145
"throughput": {
144146
"rx": 300,
145147
"tx": 270
146148
},
147149
"txpower": 2,
148-
"txrate": 270,
150+
"txrate": "270",
149151
"wds": 1
150152
}
151153
}

fixtures/airos_NanoStation_loco_M5_v6.3.16_XM_sta.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"wireless": {
118118
"ack": 28,
119119
"antenna": "Built in - 13 dBi",
120+
"antenna_gain": 13,
120121
"apmac": "XX:XX:XX:XX:XX:XX",
121122
"aprepeater": 0,
122123
"cac_nol": 0,
@@ -130,22 +131,23 @@
130131
"essid": "SOMETHING",
131132
"frequency": 5700,
132133
"hide_essid": 0,
134+
"ieeemode": "11NAHT40MINUS",
133135
"mode": "sta",
134136
"noisef": -89,
135137
"nol_chans": 0,
136138
"opmode": "11naht40minus",
137139
"qos": "No QoS",
138140
"rssi": 50,
139141
"rstatus": 5,
140-
"rxrate": 180,
142+
"rxrate": "180",
141143
"security": "WPA2",
142144
"signal": -46,
143145
"throughput": {
144146
"rx": 180,
145147
"tx": 243
146148
},
147149
"txpower": 2,
148-
"txrate": 243,
150+
"txrate": "243",
149151
"wds": 1
150152
}
151153
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "airos"
7-
version = "0.5.7a11"
7+
version = "0.5.7a12"
88
license = "MIT"
99
description = "Ubiquiti airOS module(s) for Python 3."
1010
readme = "README.md"

script/generate_ha_fixture.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,10 @@ def generate_airos_fixtures() -> None:
6767
new_data: AirOS6Data | AirOS8Data
6868

6969
if fw_major == 6:
70-
derived_data = AirOS6._derived_data_helper( # noqa: SLF001
71-
source_data, AirOS6.derived_wireless_data
72-
)
70+
derived_data = AirOS6.derived_data(source_data)
7371
new_data = AirOS6Data.from_dict(derived_data)
7472
else:
75-
derived_data = AirOS8._derived_data_helper( # noqa: SLF001
76-
source_data, AirOS8.derived_wireless_data
77-
)
73+
derived_data = AirOS8.derived_data(source_data)
7874
new_data = AirOS8Data.from_dict(derived_data)
7975

8076
with open(new_fixture_path, "w", encoding="utf-8") as new: # noqa: PTH123

0 commit comments

Comments
 (0)