1"""Controller for Asus AXE11000 access point.""" 2 3import time 4from acts import logger 5from selenium import webdriver 6from selenium.common.exceptions import NoSuchElementException 7from selenium.webdriver.chrome.options import Options 8from selenium.webdriver.support.ui import Select 9 10MOBLY_CONTROLLER_CONFIG_NAME = "AsusAXE11000AP" 11ACTS_CONTROLLER_REFERENCE_NAME = "access_points" 12 13# Access point UI parameters 14USERNAME = "login_username" 15PASSWORD = "login_passwd" 16SIGN_IN_ID = "button" 17APPLY_BUTTON = "apply_btn" 18APPLY_BUTTON_ID = "applyButton" 19WIRELESS_SETTINGS = "Advanced_Wireless_Content_menu" 20GENERAL_TAB = "Advanced_Wireless_Content_tab" 21PROFESSIONAL_TAB = "Advanced_WAdvanced_Content_tab" 22HE_MODE_ID = "he_mode_field" 23WL_UNIT = "wl_unit" 24WL_11AX = "wl_11ax" 25WL_RADIO = "wl_radio" 26WL_CLOSED = "wl_closed" 27RADIO = "radio" 28BAND_2G_CHANNEL = "band0_channel" 29BAND_5G_CHANNEL = "band1_channel" 30BAND_6G_CHANNEL = "band2_channel" 31BAND_2G_AUTH = "band0_auth_mode_x" 32BAND_5G_AUTH = "band1_auth_mode_x" 33BAND_6G_AUTH = "band2_auth_mode_x" 34BAND_2G_SSID = "band0_ssid" 35BAND_5G_SSID = "band1_ssid" 36BAND_6G_SSID = "band2_ssid" 37BAND_2G_PSK = "band0_wpa_psk" 38BAND_5G_PSK = "band1_wpa_psk" 39BAND_6G_PSK = "band2_wpa_psk" 40BAND_2G_RAD_IP = "band0_radius_ipaddr" 41BAND_5G_RAD_IP = "band1_radius_ipaddr" 42BAND_2G_RAD_PORT = "band0_radius_port" 43BAND_5G_RAD_PORT = "band1_radius_port" 44BAND_2G_RAD_KEY = "band0_radius_key" 45BAND_5G_RAD_KEY = "band1_radius_key" 46SMART_CONNECT = "smartcon_enable_field" 47BROWSER_WAIT_SHORT_TIMEOUT = 6 48BROWSER_WAIT_TIMEOUT = 15 49BROWSER_WAIT_LONG_TIMEOUT = 90 50BROWSER_WAIT_VERY_LONG_TIMEOUT = 180 51 52# Access point supported modes, channels 53VALID_BANDS = ["2g", "5g", "6g"] 54WL_BAND_VALUE = {"2g": "0", "5g": "1", "6g": "2"} 55CHANNELS_2G = { 56 0: "0", 57 1: "1", 58 2: "2", 59 3: "3", 60 4: "4", 61 5: "5", 62 6: "6", 63 7: "7", 64 8: "8", 65 9: "9", 66 10: "10", 67 11: "11" 68} 69CHANNELS_5G = { 70 0: "0", 71 36: "36/160", 72 40: "40/160", 73 44: "44/160", 74 48: "48/160", 75 52: "52/160", 76 56: "56/160", 77 60: "60/160", 78 64: "64/160", 79 100: "100/160", 80 104: "104/160", 81 108: "108/160", 82 112: "112/160", 83 116: "116/160", 84 120: "120/160", 85 124: "124/160", 86 128: "128/160", 87 132: "132/80", 88 136: "136/80", 89 140: "140/80", 90 144: "144/80", 91 149: "149/80", 92 153: "153/80", 93 157: "157/80", 94 161: "161/80", 95 165: "165" 96} 97CHANNELS_6G = { 98 0: "0", 99 37: "6g37/160", 100 53: "6g53/160", 101 69: "6g69/160", 102 85: "6g85/160", 103 101: "6g101/160", 104 117: "6g117/160", 105 133: "6g133/160", 106 149: "6g149/160", 107 165: "6g165/160", 108 181: "6g181/160", 109 197: "6g197/160", 110 213: "6g213/160" 111} 112 113 114def create(configs): 115 """Creates ap controllers from a json config.""" 116 return [AsusAXE11000AP(c) for c in configs] 117 118 119def destroy(aps): 120 """Destroys a list of ap controllers.""" 121 for ap in aps: 122 ap.reset_to_default_ap_settings() 123 ap.driver.quit() 124 125 126class AsusAXE11000AP(object): 127 """Asus AXE11000 AccessPoint controller. 128 129 Controller class for Asus AXE11000 6GHz AP. This class provides methods to 130 configure the AP with different settings required for 11ax and 6GHz testing. 131 The controller uses chrome webdriver to communicate with the AP. 132 133 The controller object is initiated in the test class. The ACTS test runner 134 calls this controller using the 'AsusAXE11000AP' keyword in the ACTS config 135 file. The AP is reset to default settings and this is handled during the 136 test teardown. 137 138 Attributes: 139 ip: IP address to reach the AP. 140 port: Port numnber to reach the AP. 141 protocol: Protcol to reach the AP (http/https). 142 username: Username to login to the AP. 143 password: Password to login to the AP. 144 config_page: web url to login to the AP. 145 ap_settings: AP settings configured at any given point. 146 default_ap_settings: Default AP settings before running the tests. 147 driver: chrome webdriver object to update the settings. 148 """ 149 150 def __init__(self, config): 151 """Initialize AP. 152 153 Creates a chrome webdriver object based on the router parameters. 154 The webdriver will login to the router and goes to the wireless settings 155 page. This object will be used to change the router settings required for 156 the test cases. Required parameters are <ip_address>, <port>, <protocol>, 157 <admin_username> and <admin_password>. 158 159 Url: <procotol>://<ip_address>:<port>/Main_Login.asp 160 Login: <admin_username>/<admin_password> 161 162 Args: 163 config: dict, dictionary of router parameters required for webdriver. 164 """ 165 self.ip = config["ip_address"] 166 self.port = config["port"] 167 self.protocol = config["protocol"] 168 self.username = config["admin_username"] 169 self.password = config["admin_password"] 170 lambda_msg = lambda msg: "[AsusAXE11000AP|%s] %s" % (self.ip, msg) 171 self.log = logger.create_logger(lambda_msg) 172 self.ap_settings = {"2g": {}, "5g": {}, "6g": {},} 173 self.config_page = ( 174 "{protocol}://{ip_address}:{port}/Main_Login.asp").format( 175 protocol=self.protocol, ip_address=self.ip, port=self.port) 176 self.chrome_options = Options() 177 self.chrome_options.add_argument("--headless") 178 self.chrome_options.add_argument("--no-sandbox") 179 self.driver = webdriver.Chrome(options=self.chrome_options) 180 self.driver.implicitly_wait(BROWSER_WAIT_TIMEOUT*2) 181 self.driver.get(self.config_page) 182 self.driver.find_element_by_name(USERNAME).send_keys(self.username) 183 self.driver.find_element_by_name(PASSWORD).send_keys(self.password) 184 self.driver.find_element_by_id(SIGN_IN_ID).click() 185 self._wait_for_web_element(self.driver.find_element_by_id, 186 WIRELESS_SETTINGS) 187 self.driver.find_element_by_id(WIRELESS_SETTINGS).click() 188 self._wait_for_web_element(self.driver.find_element_by_id, SMART_CONNECT) 189 self._update_ap_settings() 190 self.default_ap_settings = self.ap_settings.copy() 191 192 ### Helper methods ### 193 194 def _wait_for_web_element(self, 195 find_element, 196 element, 197 attribute=None, 198 value=None): 199 """Verifies click actions/selections work. 200 201 Args: 202 find_element: func(), webdriver method to call 203 element: str, web element to look for. Ex: id, class, name 204 attribute: str, attribute to get from a webelement 205 value: str, verify attribute is set to the correct value 206 207 Raises: 208 ValueError: An error occurred if expected attribute not found. 209 """ 210 curr_time = time.time() 211 while time.time() < curr_time + BROWSER_WAIT_TIMEOUT*4: 212 time.sleep(2) 213 try: 214 x = find_element(element) 215 if attribute and str(value) not in x.get_attribute(attribute): 216 raise ValueError("Attribute is not set to the right value") 217 return 218 except NoSuchElementException: 219 pass 220 raise ValueError("Failed to find web element: %s" % element) 221 222 def _update_ap_settings_2g_band(self): 223 """Read settings configured on 2g band. 224 225 Parameters Updated: 226 security type: open, wpa2-psk, wpa3-sae or wpa2-ent. 227 ssid: SSID of the wifi network. 228 password: password of the wifi network (if psk or sae network). 229 radius server ip: Radius server IP addr (if ent network). 230 radius server port: Radius server Port number (if ent network). 231 radius server secret: Radius server secret (if ent network). 232 channel: 2G band channel. 233 """ 234 dict_2g = {} 235 dict_2g["security"] = self.driver.find_element_by_name( 236 BAND_2G_AUTH).get_attribute("value") 237 dict_2g["SSID"] = self.driver.find_element_by_name( 238 BAND_2G_SSID).get_attribute("value") 239 if dict_2g["security"] == "psk2" or dict_2g["security"] == "sae": 240 dict_2g["password"] = self.driver.find_element_by_name( 241 BAND_2G_PSK).get_attribute("value") 242 elif dict_2g["security"] == "wpa2": 243 dict_2g["radius_ip_addr"] = self.driver.find_element_by_name( 244 BAND_2G_RAD_IP).get_attribute("value") 245 dict_2g["radius_port"] = self.driver.find_element_by_name( 246 BAND_2G_RAD_PORT).get_attribute("value") 247 dict_2g["radius_secret"] = self.driver.find_element_by_name( 248 BAND_2G_RAD_KEY).get_attribute("value") 249 channel_field = self._get_webdriver_elements_for_channels(band) 250 ch_val = self.driver.find_element_by_name(channel_field).get_attribute( 251 "value") 252 channel = 0 253 for key, val in CHANNELS_2G.items(): 254 if val == ch_val: 255 channel = key 256 break 257 self.ap_settings["2g"] = dict_2g.copy() 258 self.ap_settings["2g"]["channel"] = channel 259 260 def _update_ap_settings_5g_band(self): 261 """Read settings configured on 5g band. 262 263 Parameters Updated: 264 security type: open, wpa2-psk, wpa3-sae or wpa2-ent. 265 ssid: SSID of the wifi network. 266 password: password of the wifi network (if psk or sae network). 267 radius server ip: Radius server IP addr (if ent network). 268 radius server port: Radius server Port number (if ent network). 269 radius server secret: Radius server secret (if ent network). 270 channel: 5G band channel. 271 """ 272 dict_5g = {} 273 dict_5g["security"] = self.driver.find_element_by_name( 274 BAND_5G_AUTH).get_attribute("value") 275 dict_5g["SSID"] = self.driver.find_element_by_name( 276 BAND_5G_SSID).get_attribute("value") 277 if dict_5g["security"] == "psk2" or dict_5g["security"] == "sae": 278 dict_5g["password"] = self.driver.find_element_by_name( 279 BAND_5G_PSK).get_attribute("value") 280 elif dict_5g["security"] == "wpa2": 281 dict_5g["radius_ip_addr"] = self.driver.find_element_by_name( 282 BAND_5G_RAD_IP).get_attribute("value") 283 dict_5g["radius_port"] = self.driver.find_element_by_name( 284 BAND_5G_RAD_PORT).get_attribute("value") 285 dict_2g["radius_secret"] = self.driver.find_element_by_name( 286 BAND_5G_RAD_KEY).get_attribute("value") 287 channel_field = self._get_webdriver_elements_for_channels(band) 288 ch_val = self.driver.find_element_by_name(channel_field).get_attribute( 289 "value") 290 channel = 0 291 for key, val in CHANNELS_5G.items(): 292 if val == ch_val: 293 channel = key 294 break 295 self.ap_settings["5g"] = dict_5g.copy() 296 self.ap_settings["5g"]["channel"] = channel 297 298 def _update_ap_settings_6g_band(self): 299 """Read settings configured on 6g band. 300 301 Parameters Updated: 302 security type: wpa3-owe, wpa3-sae. 303 ssid: SSID of the wifi network. 304 password: password of the wifi network (if sae network). 305 channel: 6G band channel. 306 """ 307 dict_6g = {} 308 dict_6g["security"] = self.driver.find_element_by_name( 309 BAND_6G_AUTH).get_attribute("value") 310 dict_6g["SSID"] = self.driver.find_element_by_name( 311 BAND_6G_SSID).get_attribute("value") 312 if dict_6g["security"] == "sae": 313 dict_6g["password"] = self.driver.find_element_by_name( 314 BAND_6G_PSK).get_attribute("value") 315 channel_field = self._get_webdriver_elements_for_channels(band) 316 ch_val = self.driver.find_element_by_name(channel_field).get_attribute( 317 "value") 318 channel = 0 319 for key, val in CHANNELS_6G.items(): 320 if val == ch_val: 321 channel = key 322 break 323 self.ap_settings["6g"] = dict_6g.copy() 324 self.ap_settings["6g"]["channel"] = channel 325 326 def _update_ap_settings(self): 327 """Read AP settings of 2G, 5G and 6G bands. 328 329 This method reads the wifi network currently configured on any particular 330 band. The settings are updated to self.ap_settings object. 331 """ 332 self.driver.refresh() 333 self._update_ap_settings_2g_band() 334 self._update_ap_settings_5g_band() 335 self._update_ap_settings_6g_band() 336 337 def _get_webdriver_elements_for_channels(self, band): 338 """Return webdriver elements for the band to configure channel. 339 340 Args: 341 band: str, Wifi band to configure. Ex: 2g, 5g, 6g. 342 343 Returns: 344 channel field for the specific band. 345 """ 346 channel_field = BAND_2G_CHANNEL 347 if band == "5g": 348 channel_field = BAND_5G_CHANNEL 349 elif band == "6g": 350 channel_field = BAND_6G_CHANNEL 351 return channel_field 352 353 def _set_channel(self, band, channel): 354 """Configure channel on a specific band. 355 356 Args: 357 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 358 channel: int, Channel to set. 359 360 Raises: 361 ValueError: An error occurred due to invalid band or configuration. 362 """ 363 band = band.lower() 364 if band not in VALID_BANDS: 365 raise ValueError("Band %s is not valid" % band) 366 if (band == "2g" and channel not in CHANNELS_2G) or ( 367 band == "5g" and 368 channel not in CHANNELS_5G) or (band == "6g" and 369 channel not in CHANNELS_6G): 370 raise ValueError("Channel %s is not supported in band %s" % 371 (channel, band)) 372 channel_field = self._get_webdriver_elements_for_channels(band) 373 channels_val_dict = CHANNELS_6G 374 if band == "2g": 375 channels_val_dict = CHANNELS_2G 376 elif band == "5g": 377 channels_val_dict = CHANNELS_5G 378 channel = channels_val_dict[channel] 379 380 # Set channel 381 if self.driver.find_element_by_name(channel_field).get_attribute( 382 "value") != channel: 383 css_selector = "select[name=%s]" % channel_field 384 Select(self.driver.find_element_by_css_selector( 385 css_selector)).select_by_value(channel) 386 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 387 388 def _configure_personal_network(self, band, auth, ssid=None, password=None): 389 """Configure wpa3 sae/wpa2 psk network on a specific band. 390 391 Args: 392 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 393 auth: str, WPA2 PSK or WPA3 SAE security. 394 ssid: str, ssid of the wifi network. 395 password: str, password of the wifi network. 396 397 Raises: 398 ValueError: An error occurred due to invalid band or configuration. 399 """ 400 band = band.lower() 401 if band not in VALID_BANDS: 402 raise ValueError("Band %s is not valid" % band) 403 if band == "6g" and auth == "psk2": 404 raise ValueError("AP doesn't support WPA2 PSK on 6g band.") 405 (auth_field, ssid_field, 406 psk_field) = self._get_webdriver_elements_for_personal_auth(band) 407 408 # configure personal network 409 css_selector = "select[name=%s]" % auth_field 410 Select(self.driver.find_element_by_css_selector( 411 css_selector)).select_by_value(auth) 412 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 413 if ssid: 414 self.driver.find_element_by_name(ssid_field).clear() 415 self.driver.find_element_by_name(ssid_field).send_keys(ssid) 416 if password: 417 self.driver.find_element_by_name(psk_field).clear() 418 self.driver.find_element_by_name(psk_field).send_keys(password) 419 420 def _configure_open_owe_network(self, band, auth, ssid=None): 421 """Configure wpa3 owe/open network on a specific band. 422 423 Args: 424 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 425 auth: str, WPA2 PSK or WPA3 SAE security. 426 ssid: str, ssid of the wifi network. 427 428 Raises: 429 ValueError: An error occurred due to invalid band or configuration. 430 """ 431 band = band.lower() 432 if band not in VALID_BANDS: 433 raise ValueError("Band %s is not valid" % band) 434 if band == "6g" and auth == "open": 435 raise ValueError("AP doesn't support open network on 6g band.") 436 if (band == "2g" or band == "5g") and auth == "owe": 437 raise ValueError("AP doesn't support OWE on 2g and 5g bands.") 438 (auth_field, ssid_field, 439 _) = self._get_webdriver_elements_for_personal_auth(band) 440 441 # Configure wifi network 442 css_selector = "select[name=%s]" % auth_field 443 Select(self.driver.find_element_by_css_selector( 444 css_selector)).select_by_value(auth) 445 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 446 if ssid: 447 self.driver.find_element_by_name(ssid_field).clear() 448 self.driver.find_element_by_name(ssid_field).send_keys(ssid) 449 450 def _configure_wpa2_ent_network(self, band, radius_ip, radius_port, 451 radius_secret, ssid=None): 452 """Configure wpa2 ent network on a specific band. 453 454 Args: 455 band: str, Wifi band to check. Ex: 2g, 5g. 456 radius_ip: str, radius server ip addr. 457 radius_port: str, radius server port number. 458 radius_secret: str, radius server secret. 459 ssid: str, ssid of the wifi network. 460 461 Raises: 462 ValueError: An error occurred due to invalid band or configuration. 463 """ 464 band = band.lower() 465 if band not in VALID_BANDS: 466 raise ValueError("Band %s is not valid" % band) 467 if band == "6g": 468 raise ValueError("6GHz doesn't support enterprise network on this AP.") 469 (auth_field, ssid_field, 470 _) = self._get_webdriver_elements_for_personal_auth(band) 471 (rad_ip_field, rad_port_field, 472 rad_key_field) = self._get_webdriver_elements_for_ent_auth(band) 473 474 # Set enterprise network 475 css_selector = "select[name=%s]" % auth_field 476 Select(self.driver.find_element_by_css_selector( 477 css_selector)).select_by_value("wpa2") 478 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 479 if ssid: 480 self.driver.find_element_by_name(ssid_field).clear() 481 self.driver.find_element_by_name(ssid_field).send_keys(ssid) 482 self.driver.find_element_by_name(rad_ip_field).clear() 483 self.driver.find_element_by_name(rad_ip_field).send_keys(radius_ip) 484 self.driver.find_element_by_name(rad_port_field).clear() 485 self.driver.find_element_by_name(rad_port_field).send_keys(radius_port) 486 self.driver.find_element_by_name(rad_key_field).clear() 487 self.driver.find_element_by_name(rad_key_field).send_keys(radius_secret) 488 489 def _get_webdriver_elements_for_personal_auth(self, band): 490 """Return webdriver elements for the band to configure personal auth. 491 492 Args: 493 band: str, Wifi band to configure. Ex: 2g, 5g, 6g. 494 495 Returns: 496 tuple of auth, ssid, psk field for the band. 497 """ 498 auth_field = BAND_2G_AUTH 499 ssid_field = BAND_2G_SSID 500 psk_field = BAND_2G_PSK 501 if band == "5g": 502 auth_field = BAND_5G_AUTH 503 ssid_field = BAND_5G_SSID 504 psk_field = BAND_5G_PSK 505 elif band == "6g": 506 auth_field = BAND_6G_AUTH 507 ssid_field = BAND_6G_SSID 508 psk_field = BAND_6G_PSK 509 return (auth_field, ssid_field, psk_field) 510 511 def _get_webdriver_elements_for_ent_auth(self, band): 512 """Return webdriver elements for the band to configure ent auth. 513 514 Args: 515 band: str, Wifi band to configure. Ex: 2g, 5g, 6g. 516 517 Returns: 518 tuple of radius server IP, port, secret for the band. 519 """ 520 rad_ip_field = BAND_2G_RAD_IP 521 rad_port_field = BAND_2G_RAD_PORT 522 rad_key_field = BAND_2G_RAD_KEY 523 if band == "5g": 524 rad_ip_field = BAND_5G_RAD_IP 525 rad_port_field = BAND_5G_RAD_PORT 526 rad_key_field = BAND_5G_RAD_KEY 527 return (rad_ip_field, rad_port_field, rad_key_field) 528 529 ### Methods to configure AP ### 530 531 def set_channel_and_apply(self, band, channel): 532 """Set channel for specific band. 533 534 Args: 535 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 536 channel: int, Channel to set. 537 """ 538 # Go back to General tab in advanced settings 539 self.driver.find_element_by_id(GENERAL_TAB).click() 540 self._wait_for_web_element(self.driver.find_element_by_id, SMART_CONNECT) 541 542 channel_field = self._get_webdriver_elements_for_channels(band) 543 self._set_channel(band, channel) 544 self.driver.find_element_by_id(APPLY_BUTTON_ID).click() 545 time.sleep(BROWSER_WAIT_LONG_TIMEOUT) 546 self._wait_for_web_element(self.driver.find_element_by_name, 547 channel_field, "value", channel) 548 self._update_ap_settings() 549 550 def get_configured_channel(self, band): 551 """Get the channel configured on specific band. 552 553 Args: 554 band: str, Wifi band to check. Ex: eg, 5g, 6g. 555 556 Returns: 557 Channel configured on the band. 558 559 Raises: 560 ValueError: An error occurred due to invalid band. 561 """ 562 band = band.lower() 563 if band not in VALID_BANDS: 564 raise ValueError("Band %s is not valid" % band) 565 return self.ap_settings[band]["channel"] 566 567 def configure_ap(self, network_dict): 568 """Configure AP with settings for different bands. 569 570 Args: 571 network_dict: dict, dictionary that holds configuration for each band. 572 """ 573 # Go back to General tab in advanced settings 574 self.driver.refresh() 575 self.driver.find_element_by_id(GENERAL_TAB).click() 576 self._wait_for_web_element(self.driver.find_element_by_id, SMART_CONNECT) 577 578 # configure wireless settings 579 self.log.info("Network dictionary: %s" % network_dict) 580 for band in network_dict: 581 security = network_dict[band]["security"] 582 ssid = network_dict[band]["SSID"] if "SSID" in network_dict[ 583 band] else None 584 password = network_dict[band]["password"] if "password" in network_dict[ 585 band] else None 586 if security == "open" or security == "owe": 587 self._configure_open_owe_network(band, security, ssid) 588 elif security == "psk2" or security == "sae": 589 self._configure_personal_network(band, security, ssid, password) 590 elif network_dict[band]["security"] == "wpa2": 591 self._configure_wpa2_ent_network( 592 band, 593 network_dict[band]["radius_server_ip"], 594 network_dict[band]["radius_server_port"], 595 network_dict[band]["radius_server_secret"], 596 ssid) 597 598 for band in network_dict: 599 if "channel" in network_dict[band]: 600 self._set_channel(band, network_dict[band]["channel"]) 601 self.driver.find_element_by_id(APPLY_BUTTON_ID).click() 602 time.sleep(BROWSER_WAIT_LONG_TIMEOUT) 603 604 # update ap settings 605 self._update_ap_settings() 606 607 # configure hidden or 11ax mode 608 for band in network_dict: 609 apply_settings = False 610 if "hidden" in network_dict[band]: 611 res = self._configure_hidden_network(band, network_dict[band]["hidden"]) 612 apply_settings = apply_settings or res 613 if "11ax" in network_dict[band]: 614 res = self._configure_11ax_mode(band, network_dict[band]["11ax"]) 615 apply_settings = apply_settings or res 616 if apply_settings: 617 self.driver.find_element_by_id(APPLY_BUTTON).click() 618 time.sleep(BROWSER_WAIT_VERY_LONG_TIMEOUT) 619 620 def get_wifi_network(self, band): 621 """Get wifi network configured on the AP for the specific band. 622 623 Args: 624 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 625 626 Returns: 627 Wifi network as a dictionary. 628 629 Raises: 630 ValueError: An error occurred due to invalid band. 631 """ 632 band = band.lower() 633 if band not in VALID_BANDS: 634 raise ValueError("Band %s is not valid" % band) 635 wifi_network = {} 636 wifi_network["SSID"] = self.ap_settings[band]["SSID"] 637 if "password" in self.ap_settings[band]: 638 wifi_network["password"] = self.ap_settings[band]["password"] 639 security = self.ap_settings[band]["security"] 640 if security == "sae" or security == "owe": 641 wifi_network["security"] = security 642 return wifi_network 643 644 def _configure_hidden_network(self, band, val): 645 """Configure hidden network for a specific band. 646 647 Args: 648 band: str, Wifi band to configure hidden network. 649 val: str, String value to configure. 650 651 Returns: 652 True if settings applied, False if not. 653 654 Raises: 655 ValueError: An error occurred due to invalid band. 656 """ 657 band = band.lower() 658 if band not in VALID_BANDS: 659 raise ValueError("Band %s is not valid" % band) 660 661 # Go to Professional tab in advanced settings 662 self.driver.find_element_by_id(PROFESSIONAL_TAB).click() 663 self._wait_for_web_element(self.driver.find_element_by_id, HE_MODE_ID) 664 665 # Select the requested band from the drop down menu 666 css_selector = "select[name=%s]" % WL_UNIT 667 Select( 668 self.driver.find_element_by_css_selector(css_selector)).select_by_value( 669 WL_BAND_VALUE[band]) # (TODO: gmoturu@) find if selection worked 670 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 671 672 # Configure hidden network 673 state = True if val == "1" else False 674 return_result = False 675 if self.driver.find_element_by_name(WL_CLOSED).is_selected() != state: 676 css_selector = "input[name='%s'][value='%s']" % (WL_CLOSED, val) 677 self.driver.find_element_by_css_selector(css_selector).click() 678 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 679 return_result = True 680 681 return return_result 682 683 def configure_hidden_network_and_apply(self, band, state=True): 684 """Configure hidden network for a specific band. 685 686 Args: 687 band: str, Wifi band to configure hidden network. 688 state: bool, Set the wifi network as hidden if True, False if not. 689 """ 690 val = "1" if state else "0" 691 if self._configure_hidden_network(band, val): 692 self.driver.find_element_by_id(APPLY_BUTTON).click() 693 time.sleep(BROWSER_WAIT_VERY_LONG_TIMEOUT) 694 if self.driver.find_element_by_name(WL_CLOSED).is_selected() != state: 695 raise ValueError("Failed to configure hidden network on band: %s" % band) 696 697 # Go back to General tab in advanced settings 698 self.driver.find_element_by_id(GENERAL_TAB).click() 699 self._wait_for_web_element(self.driver.find_element_by_id, SMART_CONNECT) 700 701 def _configure_11ax_mode(self, band, val): 702 """Configure 11ax mode on a specific band. 703 704 Args: 705 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 706 val: str, String value to configure. 707 708 Returns: 709 True if settings are applied, False if not. 710 711 Raises: 712 ValueError: An error occurred due to invalid band. 713 """ 714 band = band.lower() 715 if band not in VALID_BANDS: 716 raise ValueError("Band %s is not valid" % band) 717 718 # Go to Professional tab in advanced settings 719 self.driver.find_element_by_id(PROFESSIONAL_TAB).click() 720 self._wait_for_web_element(self.driver.find_element_by_id, HE_MODE_ID) 721 722 # Select the requested band from the drop down menu 723 css_selector = "select[name=%s]" % WL_UNIT 724 Select( 725 self.driver.find_element_by_css_selector(css_selector)).select_by_value( 726 WL_BAND_VALUE[band]) # (TODO: gmoturu@) find if selection worked 727 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 728 729 # Configure 11ax 730 return_result = False 731 if self.driver.find_element_by_name(WL_11AX).get_attribute( 732 "value") != val: 733 css_selector = "select[name=%s]" % WL_11AX 734 Select(self.driver.find_element_by_css_selector( 735 css_selector)).select_by_value(val) 736 time.sleep(BROWSER_WAIT_SHORT_TIMEOUT) 737 return_result = True 738 739 return return_result 740 741 def configure_11ax_mode_and_apply(self, band, state=True): 742 """Configure 11ax mode on a specific band. 743 744 Args: 745 band: str, Wifi band to check. Ex: 2g, 5g, 6g. 746 state: bool, Enable 11ax if True, disable if False 747 """ 748 val = "1" if state else "0" 749 if self._configure_11ax_mode(band, val): 750 self.driver.find_element_by_id(APPLY_BUTTON).click() 751 time.sleep(BROWSER_WAIT_VERY_LONG_TIMEOUT) 752 self._wait_for_web_element(self.driver.find_element_by_name, WL_11AX, 753 "value", val) 754 755 # Go back to General tab in advanced settings 756 self.driver.find_element_by_id(GENERAL_TAB).click() 757 self._wait_for_web_element(self.driver.find_element_by_id, SMART_CONNECT) 758 759 def reset_to_default_ap_settings(self): 760 """Reset AP to the default settings.""" 761 if self.default_ap_settings != self.ap_settings: 762 self.configure_ap(self.default_ap_settings) 763 764