1# Copyright (c) 2016 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Class to control the Buffalo WSR1166DD router.""" 6 7import logging 8import urlparse 9 10import dynamic_ap_configurator 11import ap_spec 12import time 13 14 15class BuffaloWSR1166DDAPConfigurator( 16 dynamic_ap_configurator.DynamicAPConfigurator): 17 """Configurator for Buffalo WSR1166DD router.""" 18 BAND_IDS = { 19 ap_spec.BAND_2GHZ: 'ra0Form', 20 ap_spec.BAND_5GHZ: 'ra00_0Form' 21 } 22 IFACE_IDS = { 23 ap_spec.BAND_2GHZ: 'ra0aForm', 24 ap_spec.BAND_5GHZ: 'ra00_0aForm' 25 } 26 27 28 def get_number_of_pages(self): 29 """Returns the number of available pages.""" 30 return 1 31 32 33 def is_update_interval_supported(self): 34 """Returns True if setting the PSK refresh interval is supported. 35 36 @return True is supported; False otherwise 37 """ 38 return False 39 40 41 def get_supported_modes(self): 42 """Returns a list of dictionaries with supported bands and modes.""" 43 return [{'band': ap_spec.BAND_2GHZ, 44 'modes': [ap_spec.MODE_N, ap_spec.MODE_G]}, 45 {'band': ap_spec.BAND_5GHZ, 46 'modes': [ap_spec.MODE_AC, ap_spec.MODE_N, ap_spec.MODE_A]}] 47 48 49 def get_supported_bands(self): 50 """Returns a list of dictionaries with supported channels per band.""" 51 return [{'band': ap_spec.BAND_2GHZ, 52 'channels': [1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11]}, 53 {'band': ap_spec.BAND_5GHZ, 54 'channels': [36, 40, 44, 48, 149, 153, 55 157, 161, 165]}] 56 57 58 def is_security_mode_supported(self, security_mode): 59 """Returns if a given security_type is supported. 60 61 @param security_mode: one security modes defined in the APSpec 62 63 @return True if the security mode is supported; False otherwise. 64 """ 65 return security_mode in (ap_spec.SECURITY_TYPE_DISABLED, 66 ap_spec.SECURITY_TYPE_MIXED) 67 68 69 def navigate_to_page(self, page_number): 70 """Navigates to the page corresponding to the given page number. 71 72 This method performs the translation between a page number and a url 73 to load. This is used internally by apply_settings. 74 75 @param page_number: page number of the page to load 76 77 """ 78 self.get_url(self.admin_interface_url) 79 if self.admin_login_needed(self.admin_interface_url): 80 self.ap_login() 81 self.click_button_by_xpath('//li[@id="network"]') 82 self.wait_for_object_by_id('menuSub') 83 self.click_button_by_xpath('//div[@id="menuSub"]/li[2]') 84 self.wait_for_object_by_id('ra0Container') 85 86 87 def save_page(self, page_number): 88 """Saves the given page. 89 90 @param page_number: Page number of the page to save. 91 """ 92 xpath = '//fieldset[@id="ra0Container"]/center/input' 93 if self.current_band == ap_spec.BAND_5GHZ: 94 xpath = '//fieldset[@id="ra00_0Container"]/center/input' 95 self.click_button_by_xpath(xpath) 96 confirmation_xpath = ( 97 '//div[@id="uiPopup" and contains(., "Settings Applied")]') 98 self.wait_for_object_by_xpath(confirmation_xpath) 99 100 101 def set_mode(self, mode, band=None): 102 """Sets the mode. 103 104 @param mode: must be one of the modes listed in __init__(). 105 @param band: the band to select. 106 107 """ 108 self.add_item_to_command_list(self._set_mode, (mode, band), 1, 800) 109 110 111 def _set_mode(self, mode, band=None): 112 """Sets the mode. 113 114 @param mode: must be one of the modes listed in __init__(). 115 @param band: the band to select. 116 117 """ 118 modes = { 119 ap_spec.BAND_5GHZ: { 120 ap_spec.MODE_N: '802.11n 20 MHz', 121 ap_spec.MODE_A: '802.11a', 122 ap_spec.MODE_AC: '802.11ac 40 MHz' 123 }, 124 ap_spec.BAND_2GHZ: { 125 ap_spec.MODE_N: '802.11n 20 MHz', 126 ap_spec.MODE_G: '802.11g' 127 } 128 } 129 item_value = modes.get(self.current_band).get(mode) 130 if not item_value: 131 raise RuntimeError('Mode not supported %s' % mode) 132 xpath = ( 133 '//form[@id="%s"]/.//select[@id="htmode"]' % 134 self.BAND_IDS.get(self.current_band)) 135 self.select_item_from_popup_by_xpath(item_value, xpath) 136 137 138 def set_radio(self, enabled=True): 139 """Turns the radio on and off. 140 141 @param enabled: True to turn on the radio; False otherwise. 142 """ 143 self.add_item_to_command_list(self._set_radio, (enabled,), 1, 1) 144 145 146 def _set_radio(self, enabled=True): 147 """Turns the radio on and off. 148 149 @param enabled: True to turn on the radio; False otherwise. 150 """ 151 value = 'Disabled' 152 if enabled: 153 value = 'Enabled' 154 xpath = ( 155 '//form[@id="%s"]/.//select[@id="disabled"]' % 156 self.BAND_IDS.get(self.current_band)) 157 self.select_item_from_popup_by_xpath(value, xpath) 158 159 160 def set_ssid(self, ssid): 161 """Sets the SSID of the wireless network. 162 163 @param ssid: name of the wireless network. 164 """ 165 self.add_item_to_command_list(self._set_ssid, (ssid,), 1, 900) 166 167 168 def _set_ssid(self, ssid): 169 """Sets the SSID of the wireless network. 170 171 @param ssid: name of the wireless network. 172 """ 173 xpath = '//form[@id="ra0aForm"]/div[3]/div[@class="uiField"]/input' 174 if self.current_band == ap_spec.BAND_5GHZ: 175 xpath = ( 176 '//form[@id="ra00_0aForm"]/div[3]/div[@class="uiField"]/input') 177 self.set_content_of_text_field_by_xpath(ssid, xpath) 178 self._ssid = ssid 179 180 181 def set_channel(self, channel): 182 """Sets the channel of the wireless network. 183 184 @param channel: integer value of the channel. 185 """ 186 self.add_item_to_command_list(self._set_channel, (channel,), 1, 900) 187 188 189 def _set_channel(self, channel): 190 """Sets the channel of the wireless network. 191 192 @param channel: integer value of the channel. 193 """ 194 xpath = ( 195 '//form[@id="%s"]/.//select[@id="channel"]' % 196 self.BAND_IDS.get(self.current_band)) 197 self.select_item_from_popup_by_xpath(str(channel), xpath) 198 199 200 def set_ch_width(self, width): 201 """Adjusts the channel width. 202 203 @param width: the channel width. 204 """ 205 self.add_item_to_command_list(self._set_ch_width,(width,), 1, 900) 206 207 208 def _set_ch_width(self, width): 209 """Adjusts the channel width. 210 211 @param width: the channel width. 212 """ 213 channel_width_choice = { 214 ap_spec.BAND_2GHZ: ['802.11n 40 MHz', 215 '802.11n 20 MHz'], 216 ap_spec.BAND_5GHZ: ['802.11ac 80 MHz', 217 '802.11ac 40 MHz', 218 '802.11n 20 MHz'] 219 } 220 xpath = ( 221 '//form[@id="%s"]/.//select[@id="htmode"]' % 222 self.BAND_IDS.get(self.current_band)) 223 self.select_item_from_popup_by_xpath( 224 channel_width_choice.get(self.current_band)[width], 225 xpath) 226 227 228 def set_band(self, band): 229 """Sets the band of the wireless network. 230 231 @param band: Constant describing the band type. 232 """ 233 if band == ap_spec.BAND_5GHZ: 234 self.current_band = ap_spec.BAND_5GHZ 235 elif band == ap_spec.BAND_2GHZ: 236 self.current_band = ap_spec.BAND_2GHZ 237 else: 238 raise RuntimeError('Invalid band sent %s' % band) 239 240 241 def set_security_disabled(self): 242 """Disables the security of the wireless network.""" 243 self.add_item_to_command_list(self._set_security_disabled, (), 1, 900) 244 245 246 def _set_security_disabled(self): 247 """Disables the security of the wireless network.""" 248 xpath = ( 249 '//form[@id="%s"]/.//select[@id="encryption"]' % 250 self.IFACE_IDS.get(self.current_band)) 251 self.select_item_from_popup_by_xpath('None', xpath) 252 253 254 def set_security_wep(self, key_value, authentication): 255 """Enables WEP security for the wireless network. 256 257 @param key_value: encryption key to use. 258 @param authentication: one of two supported WEP authentication types: 259 open or shared. 260 """ 261 logging.debug('wep security not supported by this router') 262 263 264 def set_security_wpapsk(self, security, shared_key, update_interval=None): 265 """Enables WPA using a private security key for the wireless network. 266 267 @param security: Required security for AP configuration. 268 @param shared_key: shared encryption key to use. 269 @param update_interval: number of seconds to wait before updating. 270 """ 271 self.add_item_to_command_list(self._set_security_wpapsk, 272 (security, shared_key,), 1, 900) 273 274 275 def _set_security_wpapsk(self, security, shared_key, update_interval=None): 276 """Enables WPA/WPA2 using a psk for the wireless network. 277 278 @param security: Required security for AP configuration. 279 @param shared_key: shared encryption key to use. 280 @param update_interval: number of seconds to wait before updating. 281 """ 282 xpath = ( 283 '//form[@id="%s"]/.//select[@id="encryption"]' % 284 self.IFACE_IDS.get(self.current_band)) 285 self.select_item_from_popup_by_xpath('WPA/WPA2 PSK', xpath) 286 xpath = ( 287 '//form[@id="%s"]/.//input[@id="key"]' % 288 self.IFACE_IDS.get(self.current_band)) 289 self.set_content_of_text_field_by_xpath(shared_key, xpath) 290 291 292 def is_visibility_supported(self): 293 """Returns True if AP supports setting SSID broadcast. 294 295 @return True if supported; False otherwise. 296 """ 297 return False 298 299 300 def admin_login_needed(self, page_url): 301 """Check if we are on the admin login page. 302 303 @param page_url: string, the page to open. 304 305 @return True if login needed False otherwise. 306 """ 307 login_element = '//input[@id="pass"]' 308 apply_element = '//input[@value="Submit"]' 309 login_displayed = self.wait_for_objects_by_xpath([login_element, 310 apply_element]) 311 if login_displayed == login_element: 312 return True 313 elif login_displayed == apply_element: 314 return False 315 else: 316 raise Exception('The page %s did not load' % page_url) 317 318 319 def ap_login(self): 320 """Login as admin before configuring settings.""" 321 self.set_content_of_text_field_by_id('password', 'pass', 322 abort_check=True) 323 self.click_button_by_xpath('//input[@value="Submit"]') 324 self.wait_for_object_by_id('uiContent') 325