blob: 42473442162db86ab2b889004206d447d88edb65 [file] [log] [blame]
#!/usr/bin/env python3.4
#
# Copyright 2018 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import logging
import math
import os
import re
import statistics
import time
from acts import asserts
from acts import base_test
from acts import utils
from acts.test_decorators import test_tracker_info
from acts.test_utils.wifi import wifi_power_test_utils as wputils
from acts.test_utils.wifi import wifi_retail_ap as retail_ap
from acts.test_utils.wifi import wifi_test_utils as wutils
SHORT_SLEEP = 1
MED_SLEEP = 6
STATION_DUMP = "iw wlan0 station dump"
SCAN = "wpa_cli scan"
SCAN_RESULTS = "wpa_cli scan_results"
SIGNAL_POLL = "wpa_cli signal_poll"
CONST_3dB = 3.01029995664
RSSI_ERROR_VAL = float("nan")
class WifiRssiTest(base_test.BaseTestClass):
def __init__(self, controllers):
base_test.BaseTestClass.__init__(self, controllers)
def setup_class(self):
self.dut = self.android_devices[0]
req_params = ["rssi_test_params", "testbed_params", "main_network"]
opt_params = ["RetailAccessPoints"]
self.unpack_userparams(req_params, opt_params)
self.test_params = self.rssi_test_params
self.num_atten = self.attenuators[0].instrument.num_atten
self.iperf_server = self.iperf_servers[0]
self.access_points = retail_ap.create(self.RetailAccessPoints)
self.access_point = self.access_points[0]
self.log_path = os.path.join(logging.log_path, "results")
utils.create_dir(self.log_path)
self.log.info("Access Point Configuration: {}".format(
self.access_point.ap_settings))
self.testclass_results = []
def teardown_test(self):
self.iperf_server.stop()
def pass_fail_check_rssi_stability(self, postprocessed_results):
"""Check the test result and decide if it passed or failed.
Checks the RSSI test result and fails the test if the standard
deviation of signal_poll_rssi is beyond the threshold defined in the
config file.
Args:
postprocessed_results: compiled arrays of RSSI measurements
"""
test_failed = any([
stdev > self.test_params["stdev_tolerance"]
for stdev in postprocessed_results["signal_poll_rssi"]["stdev"]
])
test_message = (
"RSSI stability {0}. Standard deviation was {1} dB "
"(limit {2}), per chain standard deviation [{3}, {4}] dB".format(
"failed" * test_failed + "passed" * (not test_failed), [
float("{:.2f}".format(x))
for x in postprocessed_results["signal_poll_rssi"]["stdev"]
], self.test_params["stdev_tolerance"], [
float("{:.2f}".format(x))
for x in postprocessed_results["chain_0_rssi"]["stdev"]
], [
float("{:.2f}".format(x))
for x in postprocessed_results["chain_1_rssi"]["stdev"]
]))
if test_failed:
asserts.fail(test_message)
asserts.explicit_pass(test_message)
def pass_fail_check_rssi_accuracy(self, postprocessed_results,
rssi_under_test, absolute_accuracy):
"""Check the test result and decide if it passed or failed.
Checks the RSSI test result and compares and compute its deviation from
the predicted RSSI. This computation is done for all reported RSSI
values. The test fails if any of the RSSI values specified in
rssi_under_test have an average error beyond what is specified in the
configuration file.
Args:
postprocessed_results: compiled arrays of RSSI measurements
rssi_under_test: list of RSSIs under test, i.e., can cause test to
fail
absolute_accuracy: boolean indicating whether to look at absolute
RSSI accuracy, or centered RSSI accuracy. Centered accuracy is
computed after systematic RSSI shifts are removed.
"""
test_failed = False
test_message = ""
if absolute_accuracy:
error_type = "absolute"
else:
error_type = "centered"
for key, val in postprocessed_results.items():
# Compute the error metrics ignoring invalid RSSI readings
# If all readings invalid, set error to RSSI_ERROR_VAL
if "rssi" in key and "predicted" not in key:
filtered_error = [x for x in val["error"] if not math.isnan(x)]
if filtered_error:
avg_shift = statistics.mean(filtered_error)
if absolute_accuracy:
avg_error = statistics.mean(
[abs(x) for x in filtered_error])
else:
avg_error = statistics.mean(
[abs(x - avg_shift) for x in filtered_error])
else:
avg_error = RSSI_ERROR_VAL
avg_shift = RSSI_ERROR_VAL
rssi_failure = (avg_error > self.test_params["abs_tolerance"]
) or math.isnan(avg_error)
if rssi_failure and key in rssi_under_test:
test_message = test_message + (
"{} failed. Average {} error is {:.2f} dB. "
"Average shift is {:.2f} dB.\n").format(
key, error_type, avg_error, avg_shift)
test_failed = True
elif rssi_failure:
test_message = test_message + (
"{} failed (ignored). Average {} error is {:.2f} dB. "
"Average shift is {:.2f} dB.\n").format(
key, error_type, avg_error, avg_shift)
else:
test_message = test_message + (
"{} passed. Average {} error is {:.2f} dB. "
"Average shift is {:.2f} dB.\n").format(
key, error_type, avg_error, avg_shift)
if test_failed:
asserts.fail(test_message)
asserts.explicit_pass(test_message)
def post_process_rssi_sweep(self, rssi_result):
"""Postprocesses and saves JSON formatted results.
Args:
rssi_result: dict containing attenuation, rssi and other meta
data
Returns:
postprocessed_results: compiled arrays of RSSI data used in
pass/fail check
"""
# Save output as text file
results_file_path = "{}/{}.json".format(self.log_path,
self.current_test_name)
with open(results_file_path, 'w') as results_file:
json.dump(rssi_result, results_file, indent=4)
# Compile results into arrays of RSSIs suitable for plotting
postprocessed_results = {
"signal_poll_rssi": {},
"signal_poll_avg_rssi": {},
"scan_rssi": {},
"chain_0_rssi": {},
"chain_1_rssi": {},
"total_attenuation": [],
"predicted_rssi": []
}
for key, val in postprocessed_results.items():
if "scan_rssi" in key:
postprocessed_results[key]["data"] = [
x for data_point in rssi_result["rssi_result"] for x in
data_point[key][rssi_result["connected_bssid"]]["data"]
]
postprocessed_results[key]["mean"] = [
x[key][rssi_result["connected_bssid"]]["mean"]
for x in rssi_result["rssi_result"]
]
postprocessed_results[key]["stdev"] = [
x[key][rssi_result["connected_bssid"]]["stdev"]
for x in rssi_result["rssi_result"]
]
elif "predicted_rssi" in key:
postprocessed_results["total_attenuation"] = [
att + rssi_result["fixed_attenuation"] +
rssi_result["dut_front_end_loss"]
for att in rssi_result["attenuation"]
]
postprocessed_results["predicted_rssi"] = [
rssi_result["ap_tx_power"] - att
for att in postprocessed_results["total_attenuation"]
]
elif "rssi" in key:
postprocessed_results[key]["data"] = [
x for data_point in rssi_result["rssi_result"]
for x in data_point[key]["data"]
]
postprocessed_results[key]["mean"] = [
x[key]["mean"] for x in rssi_result["rssi_result"]
]
postprocessed_results[key]["stdev"] = [
x[key]["stdev"] for x in rssi_result["rssi_result"]
]
# Compute RSSI errors
for key, val in postprocessed_results.items():
if "chain" in key:
postprocessed_results[key]["error"] = [
postprocessed_results[key]["mean"][idx] + CONST_3dB -
postprocessed_results["predicted_rssi"][idx]
for idx in range(
len(postprocessed_results["predicted_rssi"]))
]
elif "rssi" in key and "predicted" not in key:
postprocessed_results[key]["error"] = [
postprocessed_results[key]["mean"][idx] -
postprocessed_results["predicted_rssi"][idx]
for idx in range(
len(postprocessed_results["predicted_rssi"]))
]
return postprocessed_results
def plot_rssi_vs_attenuation(self, postprocessed_results):
"""Function to plot RSSI vs attenuation sweeps
Args:
postprocessed_results: compiled arrays of RSSI data.
"""
data_sets = [[
postprocessed_results["total_attenuation"],
postprocessed_results["total_attenuation"],
postprocessed_results["total_attenuation"],
postprocessed_results["total_attenuation"],
postprocessed_results["total_attenuation"],
postprocessed_results["total_attenuation"]
], [
postprocessed_results["signal_poll_rssi"]["mean"],
postprocessed_results["signal_poll_avg_rssi"]["mean"],
postprocessed_results["scan_rssi"]["mean"],
postprocessed_results["chain_0_rssi"]["mean"],
postprocessed_results["chain_1_rssi"]["mean"],
postprocessed_results["predicted_rssi"]
]]
legends = [
"Signal Poll RSSI", "Signal Poll AVG_RSSI", "Scan RSSI",
"Chain 0 RSSI", "Chain 1 RSSI", "Predicted RSSI"
]
fig_property = {
"title": self.current_test_name,
"x_label": 'Attenuation (dB)',
"y_label": 'RSSI (dBm)',
"linewidth": 3,
"markersize": 10
}
output_file_path = "{}/{}.html".format(self.log_path,
self.current_test_name)
wputils.bokeh_plot(
data_sets,
legends,
fig_property,
shaded_region=None,
output_file_path=output_file_path)
def plot_rssi_vs_time(self, rssi_result, postprocessed_results,
center_curves):
"""Function to plot RSSI vs time.
Args:
rssi_result: dict containing raw RSSI data
postprocessed_results: compiled arrays of RSSI data
center_curvers: boolean indicating whether to shift curves to align
them with predicted RSSIs
"""
x_data = []
y_data = []
legends = []
rssi_time_series = {
"signal_poll_rssi": [],
"signal_poll_avg_rssi": [],
"scan_rssi": [],
"chain_0_rssi": [],
"chain_1_rssi": [],
"predicted_rssi": []
}
for key, val in rssi_time_series.items():
if "predicted_rssi" in key:
rssi_time_series[key] = [
x for x in postprocessed_results[key] for copies in range(
len(rssi_result["rssi_result"][0]["signal_poll_rssi"][
"data"]))
]
elif "rssi" in key:
if center_curves:
filtered_error = [
x for x in postprocessed_results[key]["error"]
if not math.isnan(x)
]
if filtered_error:
avg_shift = statistics.mean(filtered_error)
else:
avg_shift = 0
rssi_time_series[key] = [
x - avg_shift
for x in postprocessed_results[key]["data"]
]
else:
rssi_time_series[key] = postprocessed_results[key]["data"]
time = [
self.test_params["polling_frequency"] * x
for x in range(len(rssi_time_series[key]))
]
if len(rssi_time_series[key]) > 0:
x_data.append(time)
y_data.append(rssi_time_series[key])
legends.append(key)
data_sets = [x_data, y_data]
fig_property = {
"title": self.current_test_name,
"x_label": 'Time (s)',
"y_label": center_curves * 'Centered' + 'RSSI (dBm)',
"linewidth": 3,
"markersize": 0
}
output_file_path = "{}/{}.html".format(self.log_path,
self.current_test_name)
wputils.bokeh_plot(
data_sets,
legends,
fig_property,
shaded_region=None,
output_file_path=output_file_path)
def get_scan_rssi(self, tracked_bssids, num_measurements=1):
"""Gets scan RSSI for specified BSSIDs.
Args:
tracked_bssids: array of BSSIDs to gather RSSI data for
num_measurements: number of scans done, and RSSIs collected
Returns:
scan_rssi: dict containing the measurement results as well as the
statistics of the scan RSSI for all BSSIDs in tracked_bssids
"""
scan_rssi = {}
for bssid in tracked_bssids:
scan_rssi[bssid] = {"data": [], "mean": None, "stdev": None}
for idx in range(num_measurements):
scan_output = self.dut.adb.shell(SCAN)
time.sleep(MED_SLEEP)
scan_output = self.dut.adb.shell(SCAN_RESULTS)
for bssid in tracked_bssids:
bssid_result = re.search(
bssid + ".*", scan_output, flags=re.IGNORECASE)
if bssid_result:
bssid_result = bssid_result.group(0).split("\t")
scan_rssi[bssid]["data"].append(int(bssid_result[2]))
else:
scan_rssi[bssid]["data"].append(RSSI_ERROR_VAL)
# Compute mean RSSIs. Only average valid readings.
# Output RSSI_ERROR_VAL if no readings found.
for key, val in scan_rssi.items():
filtered_rssi_values = [
x for x in val["data"] if not math.isnan(x)
]
if filtered_rssi_values:
scan_rssi[key]["mean"] = statistics.mean(filtered_rssi_values)
if len(filtered_rssi_values) > 1:
scan_rssi[key]["stdev"] = statistics.stdev(
filtered_rssi_values)
else:
scan_rssi[key]["stdev"] = 0
else:
scan_rssi[key]["mean"] = RSSI_ERROR_VAL
scan_rssi[key]["stdev"] = RSSI_ERROR_VAL
return scan_rssi
def get_connected_rssi(self,
num_measurements=1,
polling_frequency=SHORT_SLEEP):
"""Gets all RSSI values reported for the connected access point/BSSID.
Args:
num_measurements: number of scans done, and RSSIs collected
polling_frequency: time to wait between RSSI measurements
Returns:
connected_rssi: dict containing the measurements results for
all reported RSSI values (signal_poll, per chain, etc.) and their
statistics
"""
connected_rssi = {
"signal_poll_rssi": {
"data": [],
"mean": None,
"stdev": None
},
"signal_poll_avg_rssi": {
"data": [],
"mean": None,
"stdev": None
},
"chain_0_rssi": {
"data": [],
"mean": None,
"stdev": None
},
"chain_1_rssi": {
"data": [],
"mean": None,
"stdev": None
}
}
for idx in range(num_measurements):
measurement_start_time = time.time()
# Get signal poll RSSI
signal_poll_output = self.dut.adb.shell(SIGNAL_POLL)
match = re.search("RSSI=.*", signal_poll_output)
if match:
temp_rssi = int(match.group(0).split("=")[1])
if temp_rssi == -9999:
connected_rssi["signal_poll_rssi"]["data"].append(
RSSI_ERROR_VAL)
else:
connected_rssi["signal_poll_rssi"]["data"].append(
temp_rssi)
else:
connected_rssi["signal_poll_rssi"]["data"].append(
RSSI_ERROR_VAL)
match = re.search("AVG_RSSI=.*", signal_poll_output)
if match:
connected_rssi["signal_poll_avg_rssi"]["data"].append(
int(match.group(0).split("=")[1]))
else:
connected_rssi["signal_poll_avg_rssi"]["data"].append(
RSSI_ERROR_VAL)
# Get per chain RSSI
per_chain_rssi = self.dut.adb.shell(STATION_DUMP)
match = re.search(".*signal avg:.*", per_chain_rssi)
if match:
per_chain_rssi = per_chain_rssi[per_chain_rssi.find("[") + 1:
per_chain_rssi.find("]")]
per_chain_rssi = per_chain_rssi.split(", ")
connected_rssi["chain_0_rssi"]["data"].append(
int(per_chain_rssi[0]))
connected_rssi["chain_1_rssi"]["data"].append(
int(per_chain_rssi[1]))
else:
connected_rssi["chain_0_rssi"]["data"].append(RSSI_ERROR_VAL)
connected_rssi["chain_1_rssi"]["data"].append(RSSI_ERROR_VAL)
measurement_elapsed_time = time.time() - measurement_start_time
time.sleep(max(0, polling_frequency - measurement_elapsed_time))
# Compute mean RSSIs. Only average valid readings.
# Output RSSI_ERROR_VAL if no valid connected readings found.
for key, val in connected_rssi.copy().items():
filtered_rssi_values = [
x for x in val["data"] if not math.isnan(x)
]
if filtered_rssi_values:
connected_rssi[key]["mean"] = statistics.mean(
filtered_rssi_values)
if len(filtered_rssi_values) > 1:
connected_rssi[key]["stdev"] = statistics.stdev(
filtered_rssi_values)
else:
connected_rssi[key]["stdev"] = 0
else:
connected_rssi[key]["mean"] = RSSI_ERROR_VAL
connected_rssi[key]["stdev"] = RSSI_ERROR_VAL
return connected_rssi
def rssi_test(self, iperf_traffic, connected_measurements,
scan_measurements, bssids, polling_frequency,
first_measurement_delay):
"""Test function to run RSSI tests.
The function runs an RSSI test in the current device/AP configuration.
Function is called from another wrapper function that sets up the
testbed for the RvR test
Args:
iperf_traffic: boolean specifying whether or not to run traffic
during RSSI tests
connected_measurements: number of RSSI measurements to make for the
connected AP per attenuation point
scan_measurements: number of scans and scan RSSIs to make per
attenuation point
bssids: list of BSSIDs to monitor in scans
polling_frequency: time between connected AP measurements
Returns:
rssi_result: dict containing rssi_result and meta data
"""
self.log.info("Start running RSSI test.")
rssi_result = []
# Start iperf traffic if required by test
if self.iperf_traffic:
self.iperf_server.start(tag=0)
self.dut.run_iperf_client_nb(
self.testbed_params["iperf_server_address"],
self.iperf_args,
timeout=3600)
for atten in self.rssi_atten_range:
# Set Attenuation
self.log.info("Setting attenuation to {} dB".format(atten))
[
self.attenuators[i].set_atten(atten)
for i in range(self.num_atten)
]
time.sleep(first_measurement_delay)
current_rssi = {}
current_rssi = self.get_connected_rssi(connected_measurements,
polling_frequency)
current_rssi["scan_rssi"] = self.get_scan_rssi(
bssids, scan_measurements)
rssi_result.append(current_rssi)
self.log.info("Connected RSSI at {0:.2f} dB is {1:.2f} dB".format(
atten, current_rssi["signal_poll_rssi"]["mean"]))
# Stop iperf traffic if needed
if self.iperf_traffic:
self.iperf_server.stop()
self.dut.adb.shell("pkill iperf3")
[self.attenuators[i].set_atten(0) for i in range(self.num_atten)]
return rssi_result
def rssi_test_func(self, iperf_traffic, connected_measurements,
scan_measurements, bssids, polling_frequency,
first_measurement_delay):
"""Main function to test RSSI.
The function sets up the AP in the correct channel and mode
configuration and called rssi_test to sweep attenuation and measure
RSSI
Returns:
rssi_result: dict containing rssi_results and meta data
"""
#Initialize test settings
rssi_result = {}
# Configure AP
band = self.access_point.band_lookup_by_channel(self.channel)
if "2G" in band:
frequency = wutils.WifiEnums.channel_2G_to_freq[self.channel]
else:
frequency = wutils.WifiEnums.channel_5G_to_freq[self.channel]
if frequency in wutils.WifiEnums.DFS_5G_FREQUENCIES:
self.access_point.set_region(self.testbed_params["DFS_region"])
else:
self.access_point.set_region(self.testbed_params["default_region"])
self.access_point.set_channel(band, self.channel)
self.access_point.set_bandwidth(band, self.mode)
self.log.info("Access Point Configuration: {}".format(
self.access_point.ap_settings))
# Set attenuator to starting attenuation
[
self.attenuators[i].set_atten(self.rssi_atten_range[0])
for i in range(self.num_atten)
]
# Connect DUT to Network
wutils.wifi_toggle_state(self.dut, True)
wutils.reset_wifi(self.dut)
self.main_network[band]["channel"] = self.channel
wutils.wifi_connect(self.dut, self.main_network[band], num_of_tries=5)
time.sleep(MED_SLEEP)
# Run RvR and log result
rssi_result["test_name"] = self.current_test_name
rssi_result["ap_settings"] = self.access_point.ap_settings.copy()
rssi_result["attenuation"] = list(self.rssi_atten_range)
rssi_result["connected_bssid"] = self.main_network[band]["BSSID"]
if "{}_{}".format(str(self.channel),
self.mode) in self.testbed_params["ap_tx_power"]:
rssi_result["ap_tx_power"] = self.testbed_params["ap_tx_power"][
"{}_{}".format(str(self.channel), self.mode)]
else:
rssi_result["ap_tx_power"] = self.testbed_params["ap_tx_power"][
str(self.channel)]
rssi_result["fixed_attenuation"] = self.testbed_params[
"fixed_attenuation"][str(self.channel)]
rssi_result["dut_front_end_loss"] = self.testbed_params[
"dut_front_end_loss"][str(self.channel)]
rssi_result["rssi_result"] = self.rssi_test(
iperf_traffic, connected_measurements, scan_measurements, bssids,
polling_frequency, first_measurement_delay)
self.testclass_results.append(rssi_result)
return rssi_result
def _test_rssi_vs_atten(self):
""" Function that gets called for each test case of rssi_vs_atten
The function gets called in each rssi test case. The function
customizes the test based on the test name of the test that called it
"""
test_params = self.current_test_name.split("_")
self.channel = int(test_params[4][2:])
self.mode = test_params[5]
self.iperf_traffic = "ActiveTraffic" in test_params[6]
self.iperf_args = '-i 1 -t 3600 -J -R'
band = self.access_point.band_lookup_by_channel(self.channel)
num_atten_steps = int((self.test_params["rssi_vs_atten_stop"] -
self.test_params["rssi_vs_atten_start"]) /
self.test_params["rssi_vs_atten_step"])
self.rssi_atten_range = [
self.test_params["rssi_vs_atten_start"] +
x * self.test_params["rssi_vs_atten_step"]
for x in range(0, num_atten_steps)
]
rssi_result = self.rssi_test_func(
self.iperf_traffic,
self.test_params["rssi_vs_atten_connected_measurements"],
self.test_params["rssi_vs_atten_scan_measurements"],
[self.main_network[band]["BSSID"]],
self.test_params["polling_frequency"], MED_SLEEP)
postprocessed_results = self.post_process_rssi_sweep(rssi_result)
self.plot_rssi_vs_attenuation(postprocessed_results)
self.pass_fail_check_rssi_accuracy(
postprocessed_results, self.test_params["rssi_vs_atten_metrics"],
1)
def _test_rssi_stability(self):
""" Function that gets called for each test case of rssi_stability
The function gets called in each stability test case. The function
customizes test based on the test name of the test that called it
"""
test_params = self.current_test_name.split("_")
self.channel = int(test_params[3][2:])
self.mode = test_params[4]
self.iperf_traffic = "ActiveTraffic" in test_params[5]
self.iperf_args = '-i 1 -t 3600 -J -R'
band = self.access_point.band_lookup_by_channel(self.channel)
self.rssi_atten_range = self.test_params["rssi_stability_atten"]
connected_measurements = int(
self.test_params["rssi_stability_duration"] /
self.test_params["polling_frequency"])
rssi_result = self.rssi_test_func(
self.iperf_traffic, connected_measurements, 0,
[self.main_network[band]["BSSID"]],
self.test_params["polling_frequency"], MED_SLEEP)
postprocessed_results = self.post_process_rssi_sweep(rssi_result)
self.plot_rssi_vs_time(rssi_result, postprocessed_results, 1)
self.pass_fail_check_rssi_stability(postprocessed_results)
def _test_rssi_tracking(self):
""" Function that gets called for each test case of rssi_tracking
The function gets called in each rssi test case. The function
customizes the test based on the test name of the test that called it
"""
test_params = self.current_test_name.split("_")
self.channel = int(test_params[3][2:])
self.mode = test_params[4]
self.iperf_traffic = "ActiveTraffic" in test_params[5]
self.iperf_args = '-i 1 -t 3600 -J -R'
band = self.access_point.band_lookup_by_channel(self.channel)
self.rssi_atten_range = []
for waveform in self.test_params["rssi_tracking_waveforms"]:
waveform_vector = []
for section in range(len(waveform["atten_levels"]) - 1):
section_limits = waveform["atten_levels"][section:section + 2]
if section_limits[0] < section_limits[1]:
waveform_vector = waveform_vector + sorted(
list(
range(section_limits[0], section_limits[1],
waveform["step_size"])) *
waveform["step_duration"])
else:
waveform_vector = waveform_vector + list(
reversed(
sorted(
list(
range(section_limits[1], section_limits[0],
waveform["step_size"])) *
waveform["step_duration"])))
waveform_vector = waveform_vector * waveform["repetitions"]
self.rssi_atten_range = self.rssi_atten_range + waveform_vector
connected_measurements = int(1 / self.test_params["polling_frequency"])
rssi_result = self.rssi_test_func(
self.iperf_traffic, connected_measurements, 0,
[self.main_network[band]["BSSID"]],
self.test_params["polling_frequency"], 0)
postprocessed_results = self.post_process_rssi_sweep(rssi_result)
self.plot_rssi_vs_time(rssi_result, postprocessed_results, 1)
self.pass_fail_check_rssi_accuracy(postprocessed_results,
["signal_poll_rssi"], 0)
@test_tracker_info(uuid='519689b8-0a3c-4fd9-9227-fd7962d0f1a0')
def test_rssi_stability_ch1_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='23eca2ab-d0b4-4730-9f32-ec2d901ae493')
def test_rssi_stability_ch2_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='63d340c0-dcf9-4e14-87bd-a068a59836b2')
def test_rssi_stability_ch3_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='ddbe88d8-be20-40eb-8f29-55049e3fef28')
def test_rssi_stability_ch4_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='9c06304e-2b60-4619-8fb3-73fd2cb4b854')
def test_rssi_stability_ch5_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='74b656ca-132e-4d66-9584-560287081607')
def test_rssi_stability_ch6_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='23b5f19a-539b-4908-a197-06ce505d3d23')
def test_rssi_stability_ch7_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='e7b85167-f4c4-4adb-a111-04d8a5f10e1a')
def test_rssi_stability_ch8_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='2a0a9393-4b68-4c08-8787-3f35d1a8458b')
def test_rssi_stability_ch9_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='069c7acf-3e7e-4298-91cb-d292c6025ae1')
def test_rssi_stability_ch10_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='95c5a27c-1dea-47a4-a1c5-edf955545f12')
def test_rssi_stability_ch11_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='8aeab023-a096-4fbe-80dd-fd01466f9fac')
def test_rssi_stability_ch36_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='872fed9f-d0bb-4a7b-a2a7-bf8df7740b2d')
def test_rssi_stability_ch36_VHT40_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='27395fd1-e286-473a-b98e-5a50db2a598a')
def test_rssi_stability_ch36_VHT80_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='6f6b25e3-1a1e-4a61-930a-1d0aa25ba900')
def test_rssi_stability_ch40_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='c6717da7-855c-4c6e-a6e2-ee42b8feaaab')
def test_rssi_stability_ch44_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='2e34f735-079c-4619-9e74-b96dc8d0597f')
def test_rssi_stability_ch44_VHT40_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='d543c019-1ff5-41d4-9b37-ccdc593f3edd')
def test_rssi_stability_ch48_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='2bb08914-36b2-4f58-9b3e-c3f3f4fac8ab')
def test_rssi_stability_ch149_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='e2f585f5-7811-4570-b987-23da301eb75d')
def test_rssi_stability_ch149_VHT40_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='f3e74d5b-73f6-4723-abf3-c9c147db08e3')
def test_rssi_stability_ch149_VHT80_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='06503ed0-baf3-4cd1-ac5e-4124e3c7f52f')
def test_rssi_stability_ch153_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='0cf8286f-a919-4e29-a9f2-e7738a4afe8f')
def test_rssi_stability_ch157_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='f9a0165c-468b-4096-8f4b-cc80bae564a0')
def test_rssi_stability_ch157_VHT40_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='4b74dd46-4190-4556-8ad8-c55808e9e847')
def test_rssi_stability_ch161_VHT20_ActiveTraffic(self):
self._test_rssi_stability()
@test_tracker_info(uuid='ae54b7cc-d76d-4460-8dcc-2c439265c7c9')
def test_rssi_vs_atten_ch1_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='07fe7899-886d-45ba-9c1d-7daaf9844c9c')
def test_rssi_vs_atten_ch2_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='9e86578b-a6cd-4de9-a79d-eabac5bd5f4e')
def test_rssi_vs_atten_ch3_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='e9d258ca-8e70-408e-b704-782fce7a07c5')
def test_rssi_vs_atten_ch4_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='1c5d71a0-7532-49e4-98a9-1c2d9d8d58d2')
def test_rssi_vs_atten_ch5_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='107f01f3-b6b9-470b-9895-6345edfc9599')
def test_rssi_vs_atten_ch6_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='88cb18b2-30bf-4c01-ac28-15451289e7cd')
def test_rssi_vs_atten_ch7_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='c07a7442-bd1d-40c7-80ed-167e30b8cfaf')
def test_rssi_vs_atten_ch8_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='b8946280-88d5-400d-a417-2bdc9d7e054a')
def test_rssi_vs_atten_ch9_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='a05db91b-740d-4984-a447-79ab438034f0')
def test_rssi_vs_atten_ch10_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='f4d565f8-f060-462c-9b3c-cd1f7d27b3ea')
def test_rssi_vs_atten_ch11_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='a33a93ac-604a-414f-ae96-42dffbe59a93')
def test_rssi_vs_atten_ch36_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='39875ab0-e0e9-464b-8a47-4dedd65f066e')
def test_rssi_vs_atten_ch36_VHT40_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='c6ff8768-f124-4190-baf2-bbf14b612de3')
def test_rssi_vs_atten_ch36_VHT80_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='ed4705af-e202-4737-b410-8bab0515e79f')
def test_rssi_vs_atten_ch40_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='1388df99-ecbf-4412-9ded-d66552f37ec5')
def test_rssi_vs_atten_ch44_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='06868677-ad3c-4f50-9b9e-ae8d9455ae4d')
def test_rssi_vs_atten_ch44_VHT40_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='9b6676de-c736-4603-a9b3-97670bea8f25')
def test_rssi_vs_atten_ch48_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='2641c4b8-0092-4e29-9139-fdb3b3f04d05')
def test_rssi_vs_atten_ch149_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='c8bc3f7d-b459-4e40-9c73-b0bf534c6c08')
def test_rssi_vs_atten_ch149_VHT40_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='3e08f5b6-9f3c-4905-8b10-82e1ca830cc9')
def test_rssi_vs_atten_ch149_VHT80_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='2343efe3-fdda-4180-add7-4786d35e29bb')
def test_rssi_vs_atten_ch153_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='89a16974-2399-4356-b720-17b765ff1c3a')
def test_rssi_vs_atten_ch157_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='c8e0e44a-b962-4e71-ba8f-068f268c8823')
def test_rssi_vs_atten_ch157_VHT40_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='581b5794-239e-4d1c-b0ce-7c6dc5bd373f')
def test_rssi_vs_atten_ch161_VHT20_ActiveTraffic(self):
self._test_rssi_vs_atten()
@test_tracker_info(uuid='')
def test_rssi_tracking_ch161_VHT20_ActiveTraffic(self):
self._test_rssi_tracking()
@test_tracker_info(uuid='')
def test_rssi_tracking_ch161_VHT20_NoTraffic(self):
self._test_rssi_tracking()
class WifiRssi_2GHz_ActiveTraffic_Test(WifiRssiTest):
def __init__(self, controllers):
base_test.BaseTestClass.__init__(self, controllers)
self.tests = ("test_rssi_stability_ch1_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch1_VHT20_ActiveTraffic",
"test_rssi_stability_ch2_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch2_VHT20_ActiveTraffic",
"test_rssi_stability_ch3_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch3_VHT20_ActiveTraffic",
"test_rssi_stability_ch4_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch4_VHT20_ActiveTraffic",
"test_rssi_stability_ch5_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch5_VHT20_ActiveTraffic",
"test_rssi_stability_ch6_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch6_VHT20_ActiveTraffic",
"test_rssi_stability_ch7_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch7_VHT20_ActiveTraffic",
"test_rssi_stability_ch8_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch8_VHT20_ActiveTraffic",
"test_rssi_stability_ch9_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch9_VHT20_ActiveTraffic",
"test_rssi_stability_ch10_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch10_VHT20_ActiveTraffic",
"test_rssi_stability_ch11_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch11_VHT20_ActiveTraffic")
class WifiRssi_5GHz_ActiveTraffic_Test(WifiRssiTest):
def __init__(self, controllers):
base_test.BaseTestClass.__init__(self, controllers)
self.tests = ("test_rssi_stability_ch36_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch36_VHT20_ActiveTraffic",
"test_rssi_stability_ch36_VHT40_ActiveTraffic",
"test_rssi_vs_atten_ch36_VHT40_ActiveTraffic",
"test_rssi_stability_ch36_VHT80_ActiveTraffic",
"test_rssi_vs_atten_ch36_VHT80_ActiveTraffic",
"test_rssi_stability_ch40_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch40_VHT20_ActiveTraffic",
"test_rssi_stability_ch44_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch44_VHT20_ActiveTraffic",
"test_rssi_stability_ch44_VHT40_ActiveTraffic",
"test_rssi_vs_atten_ch44_VHT40_ActiveTraffic",
"test_rssi_stability_ch48_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch48_VHT20_ActiveTraffic",
"test_rssi_stability_ch149_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch149_VHT20_ActiveTraffic",
"test_rssi_stability_ch149_VHT40_ActiveTraffic",
"test_rssi_vs_atten_ch149_VHT40_ActiveTraffic",
"test_rssi_stability_ch149_VHT80_ActiveTraffic",
"test_rssi_vs_atten_ch149_VHT80_ActiveTraffic",
"test_rssi_stability_ch153_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch153_VHT20_ActiveTraffic",
"test_rssi_stability_ch157_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch157_VHT20_ActiveTraffic",
"test_rssi_stability_ch157_VHT40_ActiveTraffic",
"test_rssi_vs_atten_ch157_VHT40_ActiveTraffic",
"test_rssi_stability_ch161_VHT20_ActiveTraffic",
"test_rssi_vs_atten_ch161_VHT20_ActiveTraffic")