Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3.4 |
| 2 | # |
| 3 | # Copyright 2018 - The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | |
| 17 | import json |
| 18 | import logging |
| 19 | import math |
| 20 | import os |
| 21 | import re |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 22 | import statistics |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 23 | import time |
| 24 | from acts import asserts |
| 25 | from acts import base_test |
| 26 | from acts import utils |
| 27 | from acts.test_decorators import test_tracker_info |
| 28 | from acts.test_utils.wifi import wifi_power_test_utils as wputils |
| 29 | from acts.test_utils.wifi import wifi_retail_ap as retail_ap |
| 30 | from acts.test_utils.wifi import wifi_test_utils as wutils |
| 31 | |
| 32 | SHORT_SLEEP = 1 |
| 33 | MED_SLEEP = 6 |
| 34 | STATION_DUMP = "iw wlan0 station dump" |
| 35 | SCAN = "wpa_cli scan" |
| 36 | SCAN_RESULTS = "wpa_cli scan_results" |
| 37 | SIGNAL_POLL = "wpa_cli signal_poll" |
| 38 | CONST_3dB = 3.01029995664 |
| 39 | RSSI_ERROR_VAL = float("nan") |
| 40 | |
| 41 | |
| 42 | class WifiRssiTest(base_test.BaseTestClass): |
| 43 | def __init__(self, controllers): |
| 44 | base_test.BaseTestClass.__init__(self, controllers) |
| 45 | |
| 46 | def setup_class(self): |
| 47 | self.dut = self.android_devices[0] |
| 48 | req_params = ["test_params", "main_network"] |
| 49 | opt_params = ["RetailAccessPoints"] |
| 50 | self.unpack_userparams(req_params, opt_params) |
| 51 | self.num_atten = self.attenuators[0].instrument.num_atten |
| 52 | self.iperf_server = self.iperf_servers[0] |
| 53 | self.access_points = retail_ap.create(self.RetailAccessPoints) |
| 54 | self.access_point = self.access_points[0] |
| 55 | self.log_path = os.path.join(logging.log_path, "results") |
| 56 | utils.create_dir(self.log_path) |
| 57 | self.log.info("Access Point Configuration: {}".format( |
| 58 | self.access_point.ap_settings)) |
| 59 | self.testclass_results = [] |
| 60 | |
| 61 | def teardown_test(self): |
| 62 | self.iperf_server.stop() |
| 63 | |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 64 | def pass_fail_check_rssi_stability(self, rssi_result): |
| 65 | """Check the test result and decide if it passed or failed. |
| 66 | |
| 67 | Checks the RSSI test result and fails the test if the standard |
| 68 | deviation of signal_poll_rssi is beyond the threshold defined in the |
| 69 | config file. |
| 70 | |
| 71 | Args: |
| 72 | rssi_result: dict containing attenuation, rssi, and other meta |
| 73 | data. This dict is the output of self.post_process_results |
| 74 | """ |
| 75 | # Save output as text file |
| 76 | test_name = self.current_test_name |
| 77 | results_file_path = "{}/{}.json".format(self.log_path, |
| 78 | self.current_test_name) |
| 79 | with open(results_file_path, 'w') as results_file: |
| 80 | json.dump(rssi_result, results_file, indent=4) |
| 81 | |
| 82 | x_data = [] |
| 83 | y_data = [] |
| 84 | legends = [] |
| 85 | std_deviations = { |
| 86 | "signal_poll_rssi": [], |
| 87 | "signal_poll_avg_rssi": [], |
| 88 | "chain_0_rssi": [], |
| 89 | "chain_1_rssi": [], |
| 90 | } |
| 91 | for data_point in rssi_result["rssi_result"]: |
| 92 | for key, val in data_point["connected_rssi"].items(): |
| 93 | if type(val) == list: |
| 94 | x_data.append([ |
| 95 | x * self.test_params["polling_frequency"] |
| 96 | for x in range(len(val)) |
| 97 | ]) |
| 98 | y_data.append(val) |
| 99 | legends.append(key) |
| 100 | std_deviations[key].append( |
| 101 | data_point["connected_rssi"]["stdev_" + key]) |
| 102 | data_sets = [x_data, y_data] |
| 103 | x_label = 'Time (s)' |
| 104 | y_label = 'RSSI (dBm)' |
| 105 | fig_property = { |
| 106 | "title": test_name, |
| 107 | "x_label": x_label, |
| 108 | "y_label": y_label, |
| 109 | "linewidth": 3, |
| 110 | "markersize": 0 |
| 111 | } |
| 112 | output_file_path = "{}/{}.html".format(self.log_path, test_name) |
| 113 | wputils.bokeh_plot( |
| 114 | data_sets, |
| 115 | legends, |
| 116 | fig_property, |
| 117 | shaded_region=None, |
| 118 | output_file_path=output_file_path) |
| 119 | |
| 120 | test_failed = any([ |
| 121 | stdev > self.test_params["stdev_tolerance"] |
| 122 | for stdev in std_deviations["signal_poll_rssi"] |
| 123 | ]) |
| 124 | if test_failed: |
| 125 | asserts.fail( |
| 126 | "RSSI stability failed. Standard deviations were {0} dB " |
| 127 | "(limit {1}), per chain standard deviation [{2}, {3}] dB". |
| 128 | format([ |
| 129 | float("{:.2f}".format(x)) |
| 130 | for x in std_deviations["signal_poll_rssi"] |
| 131 | ], self.test_params["stdev_tolerance"], [ |
| 132 | float("{:.2f}".format(x)) |
| 133 | for x in std_deviations["chain_0_rssi"] |
| 134 | ], [ |
| 135 | float("{:.2f}".format(x)) |
| 136 | for x in std_deviations["chain_1_rssi"] |
| 137 | ])) |
| 138 | asserts.explicit_pass( |
| 139 | "RSSI stability passed. Standard deviations were {0} dB " |
| 140 | "(limit {1}), per chain standard deviation [{2}, {3}] dB".format([ |
| 141 | float("{:.2f}".format(x)) |
| 142 | for x in std_deviations["signal_poll_rssi"] |
| 143 | ], self.test_params["stdev_tolerance"], [ |
| 144 | float("{:.2f}".format(x)) |
| 145 | for x in std_deviations["chain_0_rssi"] |
| 146 | ], [ |
| 147 | float("{:.2f}".format(x)) |
| 148 | for x in std_deviations["chain_1_rssi"] |
| 149 | ])) |
| 150 | |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 151 | def pass_fail_check_rssi_vs_attenuation(self, postprocessed_results): |
| 152 | """Check the test result and decide if it passed or failed. |
| 153 | |
| 154 | Checks the RSSI test result and compares and compute its deviation from |
| 155 | the predicted RSSI. This computation is done for all reported RSSI |
| 156 | values. The test fails if any of the RSSI values specified in |
| 157 | rssi_under_test have an average error beyond what is specified in the |
| 158 | configuration file. |
| 159 | |
| 160 | Args: |
| 161 | result: dict containing attenuation, rssi, and other meta |
| 162 | data. This dict is the output of self.post_process_results |
| 163 | """ |
| 164 | |
| 165 | error_data = { |
| 166 | "signal_poll_rssi": [ |
| 167 | postprocessed_results["mean_signal_poll_rssi"][idx] - |
| 168 | postprocessed_results["predicted_rssi"][idx] |
| 169 | for idx in range(len(postprocessed_results["predicted_rssi"])) |
| 170 | ], |
| 171 | "signal_poll_avg_rssi": [ |
| 172 | postprocessed_results["mean_signal_poll_avg_rssi"][idx] - |
| 173 | postprocessed_results["predicted_rssi"][idx] |
| 174 | for idx in range(len(postprocessed_results["predicted_rssi"])) |
| 175 | ], |
| 176 | "scan_rssi": [ |
| 177 | postprocessed_results["mean_scan_rssi"][idx] - |
| 178 | postprocessed_results["predicted_rssi"][idx] |
| 179 | for idx in range(len(postprocessed_results["predicted_rssi"])) |
| 180 | ], |
| 181 | "chain_0_rssi": [ |
| 182 | postprocessed_results["mean_chain_0_rssi"][idx] + CONST_3dB - |
| 183 | postprocessed_results["predicted_rssi"][idx] |
| 184 | for idx in range(len(postprocessed_results["predicted_rssi"])) |
| 185 | ], |
| 186 | "chain_1_rssi": [ |
| 187 | postprocessed_results["mean_chain_1_rssi"][idx] + CONST_3dB - |
| 188 | postprocessed_results["predicted_rssi"][idx] |
| 189 | for idx in range(len(postprocessed_results["predicted_rssi"])) |
| 190 | ] |
| 191 | } |
| 192 | |
| 193 | test_failed = False |
| 194 | test_message = "" |
| 195 | for key, val in error_data.items(): |
| 196 | # Compute the error metrics ignoring invalid RSSI readings |
| 197 | # If all readings invalid, set error to RSSI_ERROR_VAL |
| 198 | filtered_errors = [x for x in val if not math.isnan(x)] |
| 199 | if filtered_errors: |
| 200 | avg_error = sum([abs(x) for x in filtered_errors |
| 201 | ]) / len(filtered_errors) |
| 202 | avg_shift = sum(filtered_errors) / len(filtered_errors) |
| 203 | else: |
| 204 | avg_error = RSSI_ERROR_VAL |
| 205 | rssi_failure = (avg_error > self.test_params["abs_tolerance"] |
| 206 | ) or math.isnan(avg_error) |
| 207 | if rssi_failure and key in self.test_params["rssi_under_test"]: |
| 208 | test_message = test_message + ( |
| 209 | "{} failed. Average error is {:.2f} dB. " |
| 210 | "Average shift is {:.2f} dB.\n").format( |
| 211 | key, avg_error, avg_shift) |
| 212 | test_failed = True |
| 213 | elif rssi_failure: |
| 214 | test_message = test_message + ( |
| 215 | "{} failed (ignored). Average error is {:.2f} dB. " |
| 216 | "Average shift is {:.2f} dB.\n").format( |
| 217 | key, avg_error, avg_shift) |
| 218 | else: |
| 219 | test_message = test_message + ( |
| 220 | "{} passed. Average error is {:.2f} dB. " |
| 221 | "Average shift is {:.2f} dB.\n").format( |
| 222 | key, avg_error, avg_shift) |
| 223 | |
| 224 | if test_failed: |
| 225 | asserts.fail(test_message) |
| 226 | asserts.explicit_pass(test_message) |
| 227 | |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 228 | def post_process_rssi_vs_attenuation(self, rssi_result): |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 229 | """Saves plots and JSON formatted results. |
| 230 | |
| 231 | Args: |
| 232 | rssi_result: dict containing attenuation, rssi and other meta |
| 233 | data |
| 234 | Returns: |
| 235 | postprocessed_results: compiled arrays of RSSI measurements used in |
| 236 | pass/fail check |
| 237 | """ |
| 238 | # Save output as text file |
| 239 | test_name = self.current_test_name |
| 240 | results_file_path = "{}/{}.json".format(self.log_path, |
| 241 | self.current_test_name) |
| 242 | with open(results_file_path, 'w') as results_file: |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 243 | json.dump(rssi_result, results_file, indent=4) |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 244 | # Plot and save |
| 245 | total_attenuation = [ |
| 246 | att + rssi_result["fixed_attenuation"] |
| 247 | for att in rssi_result["attenuation"] |
| 248 | ] |
| 249 | # Compile results into arrays of RSSIs suitable for plotting |
| 250 | postprocessed_results = { |
| 251 | "total_attenuation": |
| 252 | total_attenuation, |
| 253 | "mean_signal_poll_rssi": [ |
| 254 | x["connected_rssi"]["mean_signal_poll_rssi"] |
| 255 | for x in rssi_result["rssi_result"] |
| 256 | ], |
| 257 | "mean_signal_poll_avg_rssi": [ |
| 258 | x["connected_rssi"]["mean_signal_poll_avg_rssi"] |
| 259 | for x in rssi_result["rssi_result"] |
| 260 | ], |
| 261 | "mean_scan_rssi": [ |
| 262 | x["scan_rssi"][rssi_result["connected_bssid"]]["avg_rssi"] |
| 263 | for x in rssi_result["rssi_result"] |
| 264 | ], |
| 265 | "mean_chain_0_rssi": [ |
| 266 | x["connected_rssi"]["mean_chain_0_rssi"] |
| 267 | for x in rssi_result["rssi_result"] |
| 268 | ], |
| 269 | "mean_chain_1_rssi": [ |
| 270 | x["connected_rssi"]["mean_chain_1_rssi"] |
| 271 | for x in rssi_result["rssi_result"] |
| 272 | ], |
| 273 | "predicted_rssi": |
| 274 | [rssi_result["ap_tx_power"] - att for att in total_attenuation] |
| 275 | } |
| 276 | data_sets = [[ |
| 277 | total_attenuation, total_attenuation, total_attenuation, |
| 278 | total_attenuation, total_attenuation, total_attenuation |
| 279 | ], [ |
| 280 | postprocessed_results["mean_signal_poll_rssi"], |
| 281 | postprocessed_results["mean_signal_poll_avg_rssi"], |
| 282 | postprocessed_results["mean_scan_rssi"], |
| 283 | postprocessed_results["mean_chain_0_rssi"], |
| 284 | postprocessed_results["mean_chain_1_rssi"], |
| 285 | postprocessed_results["predicted_rssi"] |
| 286 | ]] |
| 287 | legends = [ |
| 288 | "Signal Poll RSSI", "Signal Poll AVG_RSSI", "Scan RSSI", |
| 289 | "Chain 0 RSSI", "Chain 1 RSSI", "Predicted RSSI" |
| 290 | ] |
| 291 | x_label = 'Attenuation (dB)' |
| 292 | y_label = 'RSSI (dBm)' |
| 293 | fig_property = { |
| 294 | "title": test_name, |
| 295 | "x_label": x_label, |
| 296 | "y_label": y_label, |
| 297 | "linewidth": 3, |
| 298 | "markersize": 10 |
| 299 | } |
| 300 | output_file_path = "{}/{}.html".format(self.log_path, test_name) |
| 301 | wputils.bokeh_plot( |
| 302 | data_sets, |
| 303 | legends, |
| 304 | fig_property, |
| 305 | shaded_region=None, |
| 306 | output_file_path=output_file_path) |
| 307 | return postprocessed_results |
| 308 | |
| 309 | def get_scan_rssi(self, tracked_bssids, num_measurements=1): |
| 310 | """Gets scan RSSI for specified BSSIDs. |
| 311 | |
| 312 | Args: |
| 313 | tracked_bssids: array of BSSIDs to gather RSSI data for |
| 314 | num_measurements: number of scans done, and RSSIs collected |
| 315 | Returns: |
| 316 | scan_rssi: dict containing the measurement results as well as the |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 317 | statistics of the scan RSSI for all BSSIDs in tracked_bssids |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 318 | """ |
| 319 | scan_rssi = {} |
| 320 | for bssid in tracked_bssids: |
| 321 | scan_rssi[bssid] = {"rssi": [], "avg_rssi": None} |
| 322 | for idx in range(num_measurements): |
| 323 | scan_output = self.dut.adb.shell(SCAN) |
| 324 | time.sleep(MED_SLEEP) |
| 325 | scan_output = self.dut.adb.shell(SCAN_RESULTS) |
| 326 | for bssid in tracked_bssids: |
| 327 | bssid_result = re.search( |
| 328 | bssid + ".*", scan_output, flags=re.IGNORECASE) |
| 329 | if bssid_result: |
| 330 | bssid_result = bssid_result.group(0).split("\t") |
| 331 | scan_rssi[bssid]["rssi"].append(int(bssid_result[2])) |
| 332 | else: |
| 333 | scan_rssi[bssid]["rssi"].append(RSSI_ERROR_VAL) |
| 334 | # Compute mean RSSIs. Only average valid readings. |
| 335 | # Output RSSI_ERROR_VAL if no readings found. |
| 336 | for key, val in scan_rssi.items(): |
| 337 | filtered_rssi_values = [ |
| 338 | x for x in val["rssi"] if not math.isnan(x) |
| 339 | ] |
| 340 | if filtered_rssi_values: |
| 341 | scan_rssi[key]["avg_rssi"] = sum(filtered_rssi_values) / len( |
| 342 | filtered_rssi_values) |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 343 | if len(filtered_rssi_values) > 1: |
| 344 | scan_rssi[key]["stdev"] = statistics.stdev( |
| 345 | filtered_rssi_values) |
| 346 | else: |
| 347 | scan_rssi[key]["stdev"] = 0 |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 348 | else: |
| 349 | scan_rssi[key]["avg_rssi"] = RSSI_ERROR_VAL |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 350 | scan_rssi[key]["stdev"] = RSSI_ERROR_VAL |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 351 | return scan_rssi |
| 352 | |
| 353 | def get_connected_rssi(self, |
| 354 | num_measurements=1, |
| 355 | polling_frequency=SHORT_SLEEP): |
| 356 | """Gets all RSSI values reported for the connected access point/BSSID. |
| 357 | |
| 358 | Args: |
| 359 | num_measurements: number of scans done, and RSSIs collected |
| 360 | polling_frequency: time to wait between RSSI measurements |
| 361 | Returns: |
| 362 | connected_rssi: dict containing the measurements results for |
| 363 | all reported RSSI values (signal_poll, per chain, etc.) and their |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 364 | statistics |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 365 | """ |
| 366 | connected_rssi = { |
| 367 | "signal_poll_rssi": [], |
| 368 | "signal_poll_avg_rssi": [], |
| 369 | "chain_0_rssi": [], |
| 370 | "chain_1_rssi": [] |
| 371 | } |
| 372 | for idx in range(num_measurements): |
| 373 | # Get signal poll RSSI |
| 374 | signal_poll_output = self.dut.adb.shell(SIGNAL_POLL) |
| 375 | match = re.search("RSSI=.*", signal_poll_output) |
| 376 | if match: |
| 377 | temp_rssi = int(match.group(0).split("=")[1]) |
| 378 | if temp_rssi == -9999: |
| 379 | connected_rssi["signal_poll_rssi"].append(RSSI_ERROR_VAL) |
| 380 | else: |
| 381 | connected_rssi["signal_poll_rssi"].append(temp_rssi) |
| 382 | else: |
| 383 | connected_rssi["signal_poll_rssi"].append(RSSI_ERROR_VAL) |
| 384 | match = re.search("AVG_RSSI=.*", signal_poll_output) |
| 385 | if match: |
| 386 | connected_rssi["signal_poll_avg_rssi"].append( |
| 387 | int(match.group(0).split("=")[1])) |
| 388 | else: |
| 389 | connected_rssi["signal_poll_avg_rssi"].append(RSSI_ERROR_VAL) |
| 390 | # Get per chain RSSI |
| 391 | per_chain_rssi = self.dut.adb.shell(STATION_DUMP) |
| 392 | match = re.search(".*signal avg:.*", per_chain_rssi) |
| 393 | if match: |
| 394 | per_chain_rssi = per_chain_rssi[per_chain_rssi.find("[") + 1: |
| 395 | per_chain_rssi.find("]")] |
| 396 | per_chain_rssi = per_chain_rssi.split(", ") |
| 397 | connected_rssi["chain_0_rssi"].append(int(per_chain_rssi[0])) |
| 398 | connected_rssi["chain_1_rssi"].append(int(per_chain_rssi[1])) |
| 399 | else: |
| 400 | connected_rssi["chain_0_rssi"].append(RSSI_ERROR_VAL) |
| 401 | connected_rssi["chain_1_rssi"].append(RSSI_ERROR_VAL) |
| 402 | time.sleep(polling_frequency) |
| 403 | # Compute mean RSSIs. Only average valid readings. |
| 404 | # Output RSSI_ERROR_VAL if no valid connected readings found. |
| 405 | for key, val in connected_rssi.copy().items(): |
| 406 | filtered_rssi_values = [x for x in val if not math.isnan(x)] |
| 407 | if filtered_rssi_values: |
| 408 | connected_rssi["mean_{}".format(key)] = sum( |
| 409 | filtered_rssi_values) / len(filtered_rssi_values) |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 410 | if len(filtered_rssi_values) > 1: |
| 411 | connected_rssi["stdev_{}".format(key)] = statistics.stdev( |
| 412 | filtered_rssi_values) |
| 413 | else: |
| 414 | connected_rssi["stdev_{}".format(key)] = 0 |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 415 | else: |
| 416 | connected_rssi["mean_{}".format(key)] = RSSI_ERROR_VAL |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 417 | connected_rssi["stdev_{}".format(key)] = RSSI_ERROR_VAL |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 418 | return connected_rssi |
| 419 | |
| 420 | def rssi_test(self, iperf_traffic, connected_measurements, |
| 421 | scan_measurements, bssids, polling_frequency): |
| 422 | """Test function to run RSSI tests. |
| 423 | |
| 424 | The function runs an RSSI test in the current device/AP configuration. |
| 425 | Function is called from another wrapper function that sets up the |
| 426 | testbed for the RvR test |
| 427 | |
| 428 | Args: |
| 429 | iperf_traffic: boolean specifying whether or not to run traffic |
| 430 | during RSSI tests |
| 431 | connected_measurements: number of RSSI measurements to make for the |
| 432 | connected AP per attenuation point |
| 433 | scan_measurements: number of scans and scan RSSIs to make per |
| 434 | attenuation point |
| 435 | bssids: list of BSSIDs to monitor in scans |
| 436 | polling_frequency: time between connected AP measurements |
| 437 | Returns: |
| 438 | rssi_result: dict containing rssi_result and meta data |
| 439 | """ |
| 440 | self.log.info("Start running RSSI test.") |
| 441 | rssi_result = [] |
| 442 | # Start iperf traffic if required by test |
| 443 | if self.iperf_traffic: |
| 444 | self.iperf_server.start(tag=0) |
| 445 | self.dut.run_iperf_client_nb( |
| 446 | self.test_params["iperf_server_address"], |
| 447 | self.iperf_args, |
| 448 | timeout=3600) |
| 449 | for atten in self.rssi_atten_range: |
| 450 | # Set Attenuation |
| 451 | self.log.info("Setting attenuation to {} dB".format(atten)) |
| 452 | [ |
| 453 | self.attenuators[i].set_atten(atten) |
| 454 | for i in range(self.num_atten) |
| 455 | ] |
| 456 | time.sleep(MED_SLEEP) |
| 457 | current_rssi = {} |
| 458 | current_rssi["connected_rssi"] = self.get_connected_rssi( |
| 459 | connected_measurements, polling_frequency) |
| 460 | current_rssi["scan_rssi"] = self.get_scan_rssi( |
| 461 | bssids, scan_measurements) |
| 462 | rssi_result.append(current_rssi) |
| 463 | self.log.info("Connected RSSI at {0:.2f} dB is {1:.2f} dB".format( |
| 464 | atten, current_rssi["connected_rssi"][ |
| 465 | "mean_signal_poll_rssi"])) |
| 466 | # Stop iperf traffic if needed |
| 467 | if self.iperf_traffic: |
| 468 | self.iperf_server.stop() |
| 469 | self.dut.adb.shell("pkill iperf3") |
| 470 | [self.attenuators[i].set_atten(0) for i in range(self.num_atten)] |
| 471 | return rssi_result |
| 472 | |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 473 | def rssi_test_func(self, iperf_traffic, connected_measurements, |
| 474 | scan_measurements, bssids, polling_frequency): |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 475 | """Main function to test RSSI. |
| 476 | |
| 477 | The function sets up the AP in the correct channel and mode |
| 478 | configuration and called rssi_test to sweep attenuation and measure |
| 479 | RSSI |
| 480 | |
| 481 | Returns: |
| 482 | rssi_result: dict containing rssi_results and meta data |
| 483 | """ |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 484 | #Initialize test settings |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 485 | rssi_result = {} |
| 486 | # Configure AP |
| 487 | band = self.access_point.band_lookup_by_channel(self.channel) |
| 488 | self.access_point.set_channel(band, self.channel) |
| 489 | self.access_point.set_bandwidth(band, self.mode) |
| 490 | self.log.info("Access Point Configuration: {}".format( |
| 491 | self.access_point.ap_settings)) |
| 492 | # Set attenuator to starting attenuation |
| 493 | [ |
| 494 | self.attenuators[i].set_atten(self.rssi_atten_range[0]) |
| 495 | for i in range(self.num_atten) |
| 496 | ] |
| 497 | # Connect DUT to Network |
| 498 | wutils.wifi_toggle_state(self.dut, True) |
| 499 | wutils.reset_wifi(self.dut) |
| 500 | self.main_network[band]["channel"] = self.channel |
| 501 | wutils.wifi_connect(self.dut, self.main_network[band], num_of_tries=5) |
| 502 | time.sleep(5) |
| 503 | # Run RvR and log result |
| 504 | rssi_result["test_name"] = self.current_test_name |
| 505 | rssi_result["ap_settings"] = self.access_point.ap_settings.copy() |
| 506 | rssi_result["attenuation"] = list(self.rssi_atten_range) |
| 507 | rssi_result["connected_bssid"] = self.main_network[band]["BSSID"] |
| 508 | rssi_result["ap_tx_power"] = self.test_params["ap_tx_power"][str( |
| 509 | self.channel)] |
| 510 | rssi_result["fixed_attenuation"] = self.test_params[ |
| 511 | "fixed_attenuation"][str(self.channel)] |
| 512 | rssi_result["rssi_result"] = self.rssi_test( |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 513 | iperf_traffic, connected_measurements, scan_measurements, bssids, |
| 514 | polling_frequency) |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 515 | self.testclass_results.append(rssi_result) |
| 516 | return rssi_result |
| 517 | |
| 518 | def _test_rssi_vs_atten(self): |
| 519 | """ Function that gets called for each test case of rssi_vs_atten |
| 520 | |
| 521 | The function gets called in each rvr test case. The function customizes |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 522 | the test based on the test name of the test that called it |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 523 | """ |
| 524 | test_params = self.current_test_name.split("_") |
| 525 | self.channel = int(test_params[4][2:]) |
| 526 | self.mode = test_params[5] |
| 527 | self.iperf_traffic = "ActiveTraffic" in test_params[6] |
| 528 | self.iperf_args = '-i 1 -t 3600 -J -R' |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 529 | band = self.access_point.band_lookup_by_channel(self.channel) |
| 530 | num_atten_steps = int((self.test_params["rssi_atten_stop"] - |
| 531 | self.test_params["rssi_atten_start"]) / |
| 532 | self.test_params["rssi_atten_step"]) |
| 533 | self.rssi_atten_range = [ |
| 534 | self.test_params["rssi_atten_start"] + |
| 535 | x * self.test_params["rssi_atten_step"] |
| 536 | for x in range(0, num_atten_steps) |
| 537 | ] |
| 538 | rssi_result = self.rssi_test_func( |
| 539 | self.iperf_traffic, self.test_params["connected_measurements"], |
| 540 | self.test_params["scan_measurements"], [ |
| 541 | self.main_network[band]["BSSID"] |
| 542 | ], self.test_params["polling_frequency"]) |
| 543 | postprocessed_results = self.post_process_rssi_vs_attenuation( |
| 544 | rssi_result) |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 545 | self.pass_fail_check_rssi_vs_attenuation(postprocessed_results) |
| 546 | |
| 547 | def _test_rssi_stability(self): |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 548 | """ Function that gets called for each test case of rssi_stability |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 549 | |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 550 | The function gets called in each stability test case. The function |
| 551 | customizes test based on the test name of the test that called it |
| 552 | """ |
| 553 | test_params = self.current_test_name.split("_") |
| 554 | self.channel = int(test_params[3][2:]) |
| 555 | self.mode = test_params[4] |
| 556 | self.iperf_traffic = "ActiveTraffic" in test_params[5] |
| 557 | self.iperf_args = '-i 1 -t 3600 -J -R' |
| 558 | band = self.access_point.band_lookup_by_channel(self.channel) |
| 559 | self.rssi_atten_range = self.test_params["stability_test_atten"] |
| 560 | connected_measurements = int( |
| 561 | self.test_params["stability_test_duration"] / |
| 562 | self.test_params["polling_frequency"]) |
| 563 | rssi_result = self.rssi_test_func( |
| 564 | self.iperf_traffic, connected_measurements, 0, [ |
| 565 | self.main_network[band]["BSSID"] |
| 566 | ], self.test_params["polling_frequency"]) |
| 567 | self.pass_fail_check_rssi_stability(rssi_result) |
Omar El Ayach | 19a5567 | 2018-03-09 00:53:12 +0000 | [diff] [blame] | 568 | |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 569 | @test_tracker_info(uuid='519689b8-0a3c-4fd9-9227-fd7962d0f1a0') |
| 570 | def test_rssi_stability_ch1_VHT20_ActiveTraffic(self): |
| 571 | self._test_rssi_stability() |
| 572 | |
| 573 | @test_tracker_info(uuid='23eca2ab-d0b4-4730-9f32-ec2d901ae493') |
| 574 | def test_rssi_stability_ch2_VHT20_ActiveTraffic(self): |
| 575 | self._test_rssi_stability() |
| 576 | |
| 577 | @test_tracker_info(uuid='63d340c0-dcf9-4e14-87bd-a068a59836b2') |
| 578 | def test_rssi_stability_ch3_VHT20_ActiveTraffic(self): |
| 579 | self._test_rssi_stability() |
| 580 | |
| 581 | @test_tracker_info(uuid='ddbe88d8-be20-40eb-8f29-55049e3fef28') |
| 582 | def test_rssi_stability_ch4_VHT20_ActiveTraffic(self): |
| 583 | self._test_rssi_stability() |
| 584 | |
| 585 | @test_tracker_info(uuid='9c06304e-2b60-4619-8fb3-73fd2cb4b854') |
| 586 | def test_rssi_stability_ch5_VHT20_ActiveTraffic(self): |
| 587 | self._test_rssi_stability() |
| 588 | |
| 589 | @test_tracker_info(uuid='74b656ca-132e-4d66-9584-560287081607') |
| 590 | def test_rssi_stability_ch6_VHT20_ActiveTraffic(self): |
| 591 | self._test_rssi_stability() |
| 592 | |
| 593 | @test_tracker_info(uuid='23b5f19a-539b-4908-a197-06ce505d3d23') |
| 594 | def test_rssi_stability_ch7_VHT20_ActiveTraffic(self): |
| 595 | self._test_rssi_stability() |
| 596 | |
| 597 | @test_tracker_info(uuid='e7b85167-f4c4-4adb-a111-04d8a5f10e1a') |
| 598 | def test_rssi_stability_ch8_VHT20_ActiveTraffic(self): |
| 599 | self._test_rssi_stability() |
| 600 | |
| 601 | @test_tracker_info(uuid='2a0a9393-4b68-4c08-8787-3f35d1a8458b') |
| 602 | def test_rssi_stability_ch9_VHT20_ActiveTraffic(self): |
| 603 | self._test_rssi_stability() |
| 604 | |
| 605 | @test_tracker_info(uuid='069c7acf-3e7e-4298-91cb-d292c6025ae1') |
| 606 | def test_rssi_stability_ch10_VHT20_ActiveTraffic(self): |
| 607 | self._test_rssi_stability() |
| 608 | |
| 609 | @test_tracker_info(uuid='95c5a27c-1dea-47a4-a1c5-edf955545f12') |
| 610 | def test_rssi_stability_ch11_VHT20_ActiveTraffic(self): |
| 611 | self._test_rssi_stability() |
| 612 | |
| 613 | @test_tracker_info(uuid='8aeab023-a096-4fbe-80dd-fd01466f9fac') |
| 614 | def test_rssi_stability_ch36_VHT20_ActiveTraffic(self): |
| 615 | self._test_rssi_stability() |
| 616 | |
| 617 | @test_tracker_info(uuid='872fed9f-d0bb-4a7b-a2a7-bf8df7740b2d') |
| 618 | def test_rssi_stability_ch36_VHT40_ActiveTraffic(self): |
| 619 | self._test_rssi_stability() |
| 620 | |
| 621 | @test_tracker_info(uuid='27395fd1-e286-473a-b98e-5a50db2a598a') |
| 622 | def test_rssi_stability_ch36_VHT80_ActiveTraffic(self): |
| 623 | self._test_rssi_stability() |
| 624 | |
| 625 | @test_tracker_info(uuid='6f6b25e3-1a1e-4a61-930a-1d0aa25ba900') |
| 626 | def test_rssi_stability_ch40_VHT20_ActiveTraffic(self): |
| 627 | self._test_rssi_stability() |
| 628 | |
| 629 | @test_tracker_info(uuid='c6717da7-855c-4c6e-a6e2-ee42b8feaaab') |
| 630 | def test_rssi_stability_ch44_VHT20_ActiveTraffic(self): |
| 631 | self._test_rssi_stability() |
| 632 | |
| 633 | @test_tracker_info(uuid='2e34f735-079c-4619-9e74-b96dc8d0597f') |
| 634 | def test_rssi_stability_ch44_VHT40_ActiveTraffic(self): |
| 635 | self._test_rssi_stability() |
| 636 | |
| 637 | @test_tracker_info(uuid='d543c019-1ff5-41d4-9b37-ccdc593f3edd') |
| 638 | def test_rssi_stability_ch48_VHT20_ActiveTraffic(self): |
| 639 | self._test_rssi_stability() |
| 640 | |
| 641 | @test_tracker_info(uuid='2bb08914-36b2-4f58-9b3e-c3f3f4fac8ab') |
| 642 | def test_rssi_stability_ch149_VHT20_ActiveTraffic(self): |
| 643 | self._test_rssi_stability() |
| 644 | |
| 645 | @test_tracker_info(uuid='e2f585f5-7811-4570-b987-23da301eb75d') |
| 646 | def test_rssi_stability_ch149_VHT40_ActiveTraffic(self): |
| 647 | self._test_rssi_stability() |
| 648 | |
| 649 | @test_tracker_info(uuid='f3e74d5b-73f6-4723-abf3-c9c147db08e3') |
| 650 | def test_rssi_stability_ch149_VHT80_ActiveTraffic(self): |
| 651 | self._test_rssi_stability() |
| 652 | |
| 653 | @test_tracker_info(uuid='06503ed0-baf3-4cd1-ac5e-4124e3c7f52f') |
| 654 | def test_rssi_stability_ch153_VHT20_ActiveTraffic(self): |
| 655 | self._test_rssi_stability() |
| 656 | |
| 657 | @test_tracker_info(uuid='0cf8286f-a919-4e29-a9f2-e7738a4afe8f') |
| 658 | def test_rssi_stability_ch157_VHT20_ActiveTraffic(self): |
| 659 | self._test_rssi_stability() |
| 660 | |
| 661 | @test_tracker_info(uuid='f9a0165c-468b-4096-8f4b-cc80bae564a0') |
| 662 | def test_rssi_stability_ch157_VHT40_ActiveTraffic(self): |
| 663 | self._test_rssi_stability() |
| 664 | |
| 665 | @test_tracker_info(uuid='4b74dd46-4190-4556-8ad8-c55808e9e847') |
| 666 | def test_rssi_stability_ch161_VHT20_ActiveTraffic(self): |
| 667 | self._test_rssi_vs_atten() |
Omar El Ayach | 19a5567 | 2018-03-09 00:53:12 +0000 | [diff] [blame] | 668 | |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 669 | @test_tracker_info(uuid='ae54b7cc-d76d-4460-8dcc-2c439265c7c9') |
| 670 | def test_rssi_vs_atten_ch1_VHT20_ActiveTraffic(self): |
| 671 | self._test_rssi_vs_atten() |
| 672 | |
| 673 | @test_tracker_info(uuid='07fe7899-886d-45ba-9c1d-7daaf9844c9c') |
| 674 | def test_rssi_vs_atten_ch2_VHT20_ActiveTraffic(self): |
| 675 | self._test_rssi_vs_atten() |
| 676 | |
| 677 | @test_tracker_info(uuid='9e86578b-a6cd-4de9-a79d-eabac5bd5f4e') |
| 678 | def test_rssi_vs_atten_ch3_VHT20_ActiveTraffic(self): |
| 679 | self._test_rssi_vs_atten() |
| 680 | |
| 681 | @test_tracker_info(uuid='e9d258ca-8e70-408e-b704-782fce7a07c5') |
| 682 | def test_rssi_vs_atten_ch4_VHT20_ActiveTraffic(self): |
| 683 | self._test_rssi_vs_atten() |
| 684 | |
| 685 | @test_tracker_info(uuid='1c5d71a0-7532-49e4-98a9-1c2d9d8d58d2') |
| 686 | def test_rssi_vs_atten_ch5_VHT20_ActiveTraffic(self): |
| 687 | self._test_rssi_vs_atten() |
| 688 | |
| 689 | @test_tracker_info(uuid='107f01f3-b6b9-470b-9895-6345edfc9599') |
| 690 | def test_rssi_vs_atten_ch6_VHT20_ActiveTraffic(self): |
| 691 | self._test_rssi_vs_atten() |
| 692 | |
| 693 | @test_tracker_info(uuid='88cb18b2-30bf-4c01-ac28-15451289e7cd') |
| 694 | def test_rssi_vs_atten_ch7_VHT20_ActiveTraffic(self): |
| 695 | self._test_rssi_vs_atten() |
| 696 | |
| 697 | @test_tracker_info(uuid='c07a7442-bd1d-40c7-80ed-167e30b8cfaf') |
| 698 | def test_rssi_vs_atten_ch8_VHT20_ActiveTraffic(self): |
| 699 | self._test_rssi_vs_atten() |
| 700 | |
| 701 | @test_tracker_info(uuid='b8946280-88d5-400d-a417-2bdc9d7e054a') |
| 702 | def test_rssi_vs_atten_ch9_VHT20_ActiveTraffic(self): |
| 703 | self._test_rssi_vs_atten() |
| 704 | |
| 705 | @test_tracker_info(uuid='a05db91b-740d-4984-a447-79ab438034f0') |
| 706 | def test_rssi_vs_atten_ch10_VHT20_ActiveTraffic(self): |
| 707 | self._test_rssi_vs_atten() |
| 708 | |
| 709 | @test_tracker_info(uuid='f4d565f8-f060-462c-9b3c-cd1f7d27b3ea') |
| 710 | def test_rssi_vs_atten_ch11_VHT20_ActiveTraffic(self): |
| 711 | self._test_rssi_vs_atten() |
| 712 | |
Omar El Ayach | b880808 | 2018-03-04 01:05:39 +0000 | [diff] [blame] | 713 | @test_tracker_info(uuid='a33a93ac-604a-414f-ae96-42dffbe59a93') |
| 714 | def test_rssi_vs_atten_ch36_VHT20_ActiveTraffic(self): |
| 715 | self._test_rssi_vs_atten() |
| 716 | |
| 717 | @test_tracker_info(uuid='39875ab0-e0e9-464b-8a47-4dedd65f066e') |
| 718 | def test_rssi_vs_atten_ch36_VHT40_ActiveTraffic(self): |
| 719 | self._test_rssi_vs_atten() |
| 720 | |
| 721 | @test_tracker_info(uuid='c6ff8768-f124-4190-baf2-bbf14b612de3') |
| 722 | def test_rssi_vs_atten_ch36_VHT80_ActiveTraffic(self): |
| 723 | self._test_rssi_vs_atten() |
| 724 | |
| 725 | @test_tracker_info(uuid='ed4705af-e202-4737-b410-8bab0515e79f') |
| 726 | def test_rssi_vs_atten_ch40_VHT20_ActiveTraffic(self): |
| 727 | self._test_rssi_vs_atten() |
| 728 | |
| 729 | @test_tracker_info(uuid='1388df99-ecbf-4412-9ded-d66552f37ec5') |
| 730 | def test_rssi_vs_atten_ch44_VHT20_ActiveTraffic(self): |
| 731 | self._test_rssi_vs_atten() |
| 732 | |
| 733 | @test_tracker_info(uuid='06868677-ad3c-4f50-9b9e-ae8d9455ae4d') |
| 734 | def test_rssi_vs_atten_ch44_VHT40_ActiveTraffic(self): |
| 735 | self._test_rssi_vs_atten() |
| 736 | |
| 737 | @test_tracker_info(uuid='9b6676de-c736-4603-a9b3-97670bea8f25') |
| 738 | def test_rssi_vs_atten_ch48_VHT20_ActiveTraffic(self): |
| 739 | self._test_rssi_vs_atten() |
| 740 | |
| 741 | @test_tracker_info(uuid='2641c4b8-0092-4e29-9139-fdb3b3f04d05') |
| 742 | def test_rssi_vs_atten_ch149_VHT20_ActiveTraffic(self): |
| 743 | self._test_rssi_vs_atten() |
| 744 | |
| 745 | @test_tracker_info(uuid='c8bc3f7d-b459-4e40-9c73-b0bf534c6c08') |
| 746 | def test_rssi_vs_atten_ch149_VHT40_ActiveTraffic(self): |
| 747 | self._test_rssi_vs_atten() |
| 748 | |
| 749 | @test_tracker_info(uuid='3e08f5b6-9f3c-4905-8b10-82e1ca830cc9') |
| 750 | def test_rssi_vs_atten_ch149_VHT80_ActiveTraffic(self): |
| 751 | self._test_rssi_vs_atten() |
| 752 | |
| 753 | @test_tracker_info(uuid='2343efe3-fdda-4180-add7-4786d35e29bb') |
| 754 | def test_rssi_vs_atten_ch153_VHT20_ActiveTraffic(self): |
| 755 | self._test_rssi_vs_atten() |
| 756 | |
| 757 | @test_tracker_info(uuid='89a16974-2399-4356-b720-17b765ff1c3a') |
| 758 | def test_rssi_vs_atten_ch157_VHT20_ActiveTraffic(self): |
| 759 | self._test_rssi_vs_atten() |
| 760 | |
| 761 | @test_tracker_info(uuid='c8e0e44a-b962-4e71-ba8f-068f268c8823') |
| 762 | def test_rssi_vs_atten_ch157_VHT40_ActiveTraffic(self): |
| 763 | self._test_rssi_vs_atten() |
| 764 | |
| 765 | @test_tracker_info(uuid='581b5794-239e-4d1c-b0ce-7c6dc5bd373f') |
| 766 | def test_rssi_vs_atten_ch161_VHT20_ActiveTraffic(self): |
| 767 | self._test_rssi_vs_atten() |
Omar El Ayach | 432f461 | 2018-03-22 02:33:00 +0000 | [diff] [blame^] | 768 | |
| 769 | |
| 770 | class WifiRssi_2GHz_ActiveTraffic_Test(WifiRssiTest): |
| 771 | def __init__(self, controllers): |
| 772 | base_test.BaseTestClass.__init__(self, controllers) |
| 773 | self.tests = ("test_rssi_stability_ch1_VHT20_ActiveTraffic", |
| 774 | "test_rssi_stability_ch2_VHT20_ActiveTraffic", |
| 775 | "test_rssi_stability_ch3_VHT20_ActiveTraffic", |
| 776 | "test_rssi_stability_ch4_VHT20_ActiveTraffic", |
| 777 | "test_rssi_stability_ch5_VHT20_ActiveTraffic", |
| 778 | "test_rssi_stability_ch6_VHT20_ActiveTraffic", |
| 779 | "test_rssi_stability_ch7_VHT20_ActiveTraffic", |
| 780 | "test_rssi_stability_ch8_VHT20_ActiveTraffic", |
| 781 | "test_rssi_stability_ch9_VHT20_ActiveTraffic", |
| 782 | "test_rssi_stability_ch10_VHT20_ActiveTraffic", |
| 783 | "test_rssi_stability_ch11_VHT20_ActiveTraffic", |
| 784 | "test_rssi_vs_atten_ch1_VHT20_ActiveTraffic", |
| 785 | "test_rssi_vs_atten_ch2_VHT20_ActiveTraffic", |
| 786 | "test_rssi_vs_atten_ch3_VHT20_ActiveTraffic", |
| 787 | "test_rssi_vs_atten_ch4_VHT20_ActiveTraffic", |
| 788 | "test_rssi_vs_atten_ch5_VHT20_ActiveTraffic", |
| 789 | "test_rssi_vs_atten_ch6_VHT20_ActiveTraffic", |
| 790 | "test_rssi_vs_atten_ch7_VHT20_ActiveTraffic", |
| 791 | "test_rssi_vs_atten_ch8_VHT20_ActiveTraffic", |
| 792 | "test_rssi_vs_atten_ch9_VHT20_ActiveTraffic", |
| 793 | "test_rssi_vs_atten_ch10_VHT20_ActiveTraffic", |
| 794 | "test_rssi_vs_atten_ch11_VHT20_ActiveTraffic") |
| 795 | |
| 796 | |
| 797 | class WifiRssi_5GHz_ActiveTraffic_Test(WifiRssiTest): |
| 798 | def __init__(self, controllers): |
| 799 | base_test.BaseTestClass.__init__(self, controllers) |
| 800 | self.tests = ("test_rssi_stability_ch36_VHT20_ActiveTraffic", |
| 801 | "test_rssi_stability_ch36_VHT40_ActiveTraffic", |
| 802 | "test_rssi_stability_ch36_VHT80_ActiveTraffic", |
| 803 | "test_rssi_stability_ch40_VHT20_ActiveTraffic", |
| 804 | "test_rssi_stability_ch44_VHT20_ActiveTraffic", |
| 805 | "test_rssi_stability_ch44_VHT40_ActiveTraffic", |
| 806 | "test_rssi_stability_ch48_VHT20_ActiveTraffic", |
| 807 | "test_rssi_stability_ch149_VHT20_ActiveTraffic", |
| 808 | "test_rssi_stability_ch149_VHT40_ActiveTraffic", |
| 809 | "test_rssi_stability_ch149_VHT80_ActiveTraffic", |
| 810 | "test_rssi_stability_ch153_VHT20_ActiveTraffic", |
| 811 | "test_rssi_stability_ch157_VHT20_ActiveTraffic", |
| 812 | "test_rssi_stability_ch157_VHT40_ActiveTraffic", |
| 813 | "test_rssi_stability_ch161_VHT20_ActiveTraffic", |
| 814 | "test_rssi_vs_atten_ch36_VHT20_ActiveTraffic", |
| 815 | "test_rssi_vs_atten_ch36_VHT40_ActiveTraffic", |
| 816 | "test_rssi_vs_atten_ch36_VHT80_ActiveTraffic", |
| 817 | "test_rssi_vs_atten_ch40_VHT20_ActiveTraffic", |
| 818 | "test_rssi_vs_atten_ch44_VHT20_ActiveTraffic", |
| 819 | "test_rssi_vs_atten_ch44_VHT40_ActiveTraffic", |
| 820 | "test_rssi_vs_atten_ch48_VHT20_ActiveTraffic", |
| 821 | "test_rssi_vs_atten_ch149_VHT20_ActiveTraffic", |
| 822 | "test_rssi_vs_atten_ch149_VHT40_ActiveTraffic", |
| 823 | "test_rssi_vs_atten_ch149_VHT80_ActiveTraffic", |
| 824 | "test_rssi_vs_atten_ch153_VHT20_ActiveTraffic", |
| 825 | "test_rssi_vs_atten_ch157_VHT20_ActiveTraffic", |
| 826 | "test_rssi_vs_atten_ch157_VHT40_ActiveTraffic", |
| 827 | "test_rssi_vs_atten_ch161_VHT20_ActiveTraffic") |