feat: read radio1 AP state in wifi get_ap
This commit is contained in:
@@ -1646,29 +1646,41 @@ def _uci_section(section):
|
|||||||
|
|
||||||
|
|
||||||
def h_pineap_wifi_get_ap(ctx):
|
def h_pineap_wifi_get_ap(ctx):
|
||||||
open_cfg = _uci_wifi_iface('wlan0open')
|
def _iface_state(open_name, wpa_name, radio_name):
|
||||||
radio_cfg = _uci_wifi_iface('radio0')
|
open_cfg = _uci_wifi_iface(open_name)
|
||||||
wpa_cfg = _uci_wifi_iface('wlan0wpa')
|
wpa_cfg = _uci_wifi_iface(wpa_name)
|
||||||
|
radio_cfg = _uci_wifi_iface(radio_name)
|
||||||
|
|
||||||
|
def _chan(cfg):
|
||||||
|
channel = cfg.get('channel') or ''
|
||||||
|
try:
|
||||||
|
return int(channel)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
open_channel = _chan(open_cfg)
|
||||||
|
wpa_channel = _chan(wpa_cfg)
|
||||||
|
encryption = wpa_cfg.get('encryption') or ''
|
||||||
|
if encryption.startswith('psk2'):
|
||||||
|
encryption = 'psk2'
|
||||||
|
elif encryption.startswith('sae'):
|
||||||
|
encryption = 'sae'
|
||||||
|
elif encryption.startswith('owe'):
|
||||||
|
encryption = 'owe'
|
||||||
|
return open_cfg, wpa_cfg, radio_cfg, open_channel, wpa_channel, encryption
|
||||||
|
|
||||||
|
if _uci_wifi_iface('wlan1open') or _uci_wifi_iface('wlan1wpa'):
|
||||||
|
open_cfg, wpa_cfg, radio_cfg, open_channel, wpa_channel, encryption = _iface_state(
|
||||||
|
'wlan1open', 'wlan1wpa', 'radio1')
|
||||||
|
else:
|
||||||
|
open_cfg, wpa_cfg, radio_cfg, open_channel, wpa_channel, encryption = _iface_state(
|
||||||
|
'wlan0open', 'wlan0wpa', 'radio0')
|
||||||
status, data = daemon_sock_call('GET', '/api/pineap/hostapd/get_config')
|
status, data = daemon_sock_call('GET', '/api/pineap/hostapd/get_config')
|
||||||
host = data if status == 200 and isinstance(data, dict) else {}
|
host = data if status == 200 and isinstance(data, dict) else {}
|
||||||
status2, data2 = daemon_sock_call('GET', '/api/pineap/get_config')
|
status2, data2 = daemon_sock_call('GET', '/api/pineap/get_config')
|
||||||
pinecfg = data2 if status2 == 200 and isinstance(data2, dict) else {}
|
pinecfg = data2 if status2 == 200 and isinstance(data2, dict) else {}
|
||||||
pool = _uci_section('pineapd.@ssidpool[0]')
|
pool = _uci_section('pineapd.@ssidpool[0]')
|
||||||
channel = radio_cfg.get('channel') or ''
|
radio1 = _uci_wifi_iface('radio1')
|
||||||
try:
|
|
||||||
channel = int(channel)
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
channel = None
|
|
||||||
encryption = wpa_cfg.get('encryption') or ''
|
|
||||||
# OpenWrt commonly decorates the key-management value with a cipher
|
|
||||||
# (for example, "psk2+ccmp"). The UI exposes the logical modes, so
|
|
||||||
# normalize the live UCI value to an option the select can represent.
|
|
||||||
if encryption.startswith('psk2'):
|
|
||||||
encryption = 'psk2'
|
|
||||||
elif encryption.startswith('sae'):
|
|
||||||
encryption = 'sae'
|
|
||||||
elif encryption.startswith('owe'):
|
|
||||||
encryption = 'owe'
|
|
||||||
return 200, {
|
return 200, {
|
||||||
'open': {
|
'open': {
|
||||||
'enabled': open_cfg.get('disabled') == '0',
|
'enabled': open_cfg.get('disabled') == '0',
|
||||||
@@ -1676,7 +1688,7 @@ def h_pineap_wifi_get_ap(ctx):
|
|||||||
'bssid': open_cfg.get('macaddr') or '',
|
'bssid': open_cfg.get('macaddr') or '',
|
||||||
'target': pool.get('target') or None,
|
'target': pool.get('target') or None,
|
||||||
'hidden': open_cfg.get('hidden') == '1',
|
'hidden': open_cfg.get('hidden') == '1',
|
||||||
'channel': channel,
|
'channel': open_channel,
|
||||||
'country': radio_cfg.get('country') or '',
|
'country': radio_cfg.get('country') or '',
|
||||||
},
|
},
|
||||||
'wpa': {
|
'wpa': {
|
||||||
@@ -1685,9 +1697,17 @@ def h_pineap_wifi_get_ap(ctx):
|
|||||||
'enctype': encryption,
|
'enctype': encryption,
|
||||||
'hidden': wpa_cfg.get('hidden') == '1',
|
'hidden': wpa_cfg.get('hidden') == '1',
|
||||||
'enabled': wpa_cfg.get('disabled') == '0',
|
'enabled': wpa_cfg.get('disabled') == '0',
|
||||||
|
'channel': wpa_channel,
|
||||||
},
|
},
|
||||||
'enterprise': {'enabled': not host.get('pineape_disabled', True)},
|
'enterprise': {'enabled': not host.get('pineape_disabled', True)},
|
||||||
'pool': {'disabled': None, 'collecting': bool(pinecfg.get('autossidpool'))},
|
'pool': {'disabled': None, 'collecting': bool(pinecfg.get('autossidpool'))},
|
||||||
|
'radio1': {
|
||||||
|
'band': {'2g': BAND_2G, '5g': BAND_5G, '6g': BAND_6G}.get(
|
||||||
|
(radio1 or {}).get('band'), BAND_5G),
|
||||||
|
'channel': (radio1 or {}).get('channel') or 'auto',
|
||||||
|
'htmode': (radio1 or {}).get('htmode') or 'VHT80',
|
||||||
|
'country': (radio1 or {}).get('country') or '',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -71,5 +71,93 @@ class BandAuxTest(unittest.TestCase):
|
|||||||
set(range(52, 65, 4)) | set(range(100, 145, 4)))
|
set(range(52, 65, 4)) | set(range(100, 145, 4)))
|
||||||
|
|
||||||
|
|
||||||
|
def ctx(body=None):
|
||||||
|
return type('C', (), {'body': body, 'args': (), 'query': {}})()
|
||||||
|
|
||||||
|
|
||||||
|
class GetApRadio1Test(unittest.TestCase):
|
||||||
|
def _uci(self, section):
|
||||||
|
table = {
|
||||||
|
'radio0': {'type': 'wifi-device', 'band': '2g', 'channel': '11',
|
||||||
|
'htmode': 'HT20', 'country': 'US'},
|
||||||
|
'radio1': {'type': 'wifi-device', 'band': '5g', 'channel': 'auto',
|
||||||
|
'htmode': 'VHT80', 'country': 'US'},
|
||||||
|
'wlan0open': {'device': 'radio0', 'mode': 'ap', 'ssid': 'pager-open',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'none',
|
||||||
|
'channel': '11'},
|
||||||
|
'wlan0wpa': {'device': 'radio0', 'mode': 'ap', 'ssid': 'Service',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'psk2',
|
||||||
|
'channel': '1', 'key': 'testpass123'},
|
||||||
|
'wlan1open': {'device': 'radio1', 'mode': 'ap', 'ssid': 'CorpGuest',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'none',
|
||||||
|
'channel': '36'},
|
||||||
|
'wlan1wpa': {'device': 'radio1', 'mode': 'ap', 'ssid': 'Corp',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'sae',
|
||||||
|
'channel': '1', 'key': 'secret123'},
|
||||||
|
}
|
||||||
|
return dict(table.get(section, {}))
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
server._uci_wifi_iface = lambda name: self._uci(name)
|
||||||
|
server.daemon_sock_call = lambda method, path, body=None, timeout=10: (
|
||||||
|
404, {'error': 'not found'})
|
||||||
|
|
||||||
|
def test_open_reports_radio1_when_present(self):
|
||||||
|
status, payload = server.h_pineap_wifi_get_ap(ctx())
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
self.assertEqual(payload['open']['ssid'], 'CorpGuest')
|
||||||
|
self.assertEqual(payload['open']['channel'], 36)
|
||||||
|
self.assertEqual(payload['open']['country'], 'US')
|
||||||
|
|
||||||
|
def test_wpa_reports_radio1_when_present(self):
|
||||||
|
status, payload = server.h_pineap_wifi_get_ap(ctx())
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
self.assertEqual(payload['wpa']['ssid'], 'Corp')
|
||||||
|
self.assertEqual(payload['wpa']['enctype'], 'sae')
|
||||||
|
self.assertEqual(payload['wpa']['channel'], 1)
|
||||||
|
|
||||||
|
def test_radio1_info(self):
|
||||||
|
status, payload = server.h_pineap_wifi_get_ap(ctx())
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
self.assertEqual(payload['radio1']['band'], server.BAND_5G)
|
||||||
|
self.assertEqual(payload['radio1']['channel'], 'auto')
|
||||||
|
|
||||||
|
|
||||||
|
class GetApRadio1AbsentTest(unittest.TestCase):
|
||||||
|
"""Regression: no radio1 AP sections -> today's 2.4GHz behavior."""
|
||||||
|
|
||||||
|
def _uci(self, section):
|
||||||
|
table = {
|
||||||
|
'radio0': {'type': 'wifi-device', 'band': '2g', 'channel': '11',
|
||||||
|
'htmode': 'HT20', 'country': 'US'},
|
||||||
|
'radio1': {'type': 'wifi-device', 'band': '5g', 'channel': 'auto',
|
||||||
|
'htmode': 'VHT80', 'country': 'US'},
|
||||||
|
'wlan0open': {'device': 'radio0', 'mode': 'ap', 'ssid': 'pager-open',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'none',
|
||||||
|
'channel': '11'},
|
||||||
|
'wlan0wpa': {'device': 'radio0', 'mode': 'ap', 'ssid': 'Service',
|
||||||
|
'disabled': '0', 'hidden': '0', 'encryption': 'psk2',
|
||||||
|
'channel': '1', 'key': 'testpass123'},
|
||||||
|
}
|
||||||
|
return dict(table.get(section, {}))
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
server._uci_wifi_iface = lambda name: self._uci(name)
|
||||||
|
server.daemon_sock_call = lambda method, path, body=None, timeout=10: (
|
||||||
|
404, {'error': 'not found'})
|
||||||
|
|
||||||
|
def test_open_uses_wlan0open(self):
|
||||||
|
status, payload = server.h_pineap_wifi_get_ap(ctx())
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
self.assertEqual(payload['open']['ssid'], 'pager-open')
|
||||||
|
self.assertEqual(payload['open']['channel'], 11)
|
||||||
|
|
||||||
|
def test_wpa_uses_wlan0wpa(self):
|
||||||
|
status, payload = server.h_pineap_wifi_get_ap(ctx())
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
self.assertEqual(payload['wpa']['ssid'], 'Service')
|
||||||
|
self.assertEqual(payload['wpa']['channel'], 1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user