mirror of
https://github.com/Telecominfraproject/wlan-cloud-rrm.git
synced 2025-10-29 17:52:24 +00:00
States aggregation (#82)
* initial Signed-off-by: zhiqiand <zhiqian@fb.com> * fix some comments Signed-off-by: zhiqiand <zhiqian@fb.com> * fix comments on AggregatedState and ModelerUtils Signed-off-by: zhiqiand <zhiqian@fb.com> * reformat and thread-safe Signed-off-by: zhiqiand <zhiqian@fb.com> * add buffer size for state Signed-off-by: zhiqiand <zhiqian@fb.com> * fix some comments Signed-off-by: zhiqiand <zhiqian@fb.com> * add javadoc Signed-off-by: zhiqiand <zhiqian@fb.com> * fix comments in TestUtils Signed-off-by: zhiqiand <zhiqian@fb.com> * fix some comments Signed-off-by: zhiqiand <zhiqian@fb.com> * fix some comments Signed-off-by: zhiqiand <zhiqian@fb.com> * fix some comments Signed-off-by: zhiqiand <zhiqian@fb.com> * fix tx_power Signed-off-by: zhiqiand <zhiqian@fb.com> * fix channel number Signed-off-by: zhiqiand <zhiqian@fb.com> * fix long type Signed-off-by: zhiqiand <zhiqian@fb.com> Signed-off-by: zhiqiand <zhiqian@fb.com>
This commit is contained in:
@@ -309,6 +309,12 @@ public class RRMConfig {
|
||||
* ({@code MODELERPARAMS_WIFISCANBUFFERSIZE})
|
||||
*/
|
||||
public int wifiScanBufferSize = 10;
|
||||
|
||||
/**
|
||||
* Maximum rounds of States to store per device
|
||||
* ({@code MODELERPARAMS_STATEBUFFERSIZE})
|
||||
*/
|
||||
public int stateBufferSize = 10;
|
||||
}
|
||||
|
||||
/** Modeler parameters. */
|
||||
@@ -532,6 +538,9 @@ public class RRMConfig {
|
||||
if ((v = env.get("MODELERPARAMS_WIFISCANBUFFERSIZE")) != null) {
|
||||
modelerParams.wifiScanBufferSize = Integer.parseInt(v);
|
||||
}
|
||||
if ((v = env.get("MODELERPARAMS_STATEBUFFERSIZE")) != null) {
|
||||
modelerParams.stateBufferSize = Integer.parseInt(v);
|
||||
}
|
||||
ModuleConfig.ApiServerParams apiServerParams =
|
||||
config.moduleConfig.apiServerParams;
|
||||
if ((v = env.get("APISERVERPARAMS_HTTPPORT")) != null) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.facebook.openwifirrm.modules;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -93,8 +94,9 @@ public class Modeler implements Runnable {
|
||||
public Map<String, List<List<WifiScanEntry>>> latestWifiScans =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/** List of latest state per device. */
|
||||
public Map<String, State> latestState = new ConcurrentHashMap<>();
|
||||
/** List of latest states per device. */
|
||||
public Map<String, List<State>> latestStates =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/** List of radio info per device. */
|
||||
public Map<String, JsonArray> latestDeviceStatusRadios =
|
||||
@@ -267,7 +269,10 @@ public class Modeler implements Runnable {
|
||||
if (state != null) {
|
||||
try {
|
||||
State stateModel = gson.fromJson(state, State.class);
|
||||
dataModel.latestState.put(device.serialNumber, stateModel);
|
||||
dataModel.latestStates.computeIfAbsent(
|
||||
device.serialNumber,
|
||||
k -> Collections.synchronizedList(new LinkedList<>())
|
||||
).add(stateModel);
|
||||
logger.debug(
|
||||
"Device {}: added initial state from uCentralGw",
|
||||
device.serialNumber
|
||||
@@ -299,8 +304,18 @@ public class Modeler implements Runnable {
|
||||
if (state != null) {
|
||||
try {
|
||||
State stateModel = gson.fromJson(state, State.class);
|
||||
dataModel.latestState
|
||||
.put(record.serialNumber, stateModel);
|
||||
List<State> latestStatesList = dataModel.latestStates
|
||||
.computeIfAbsent(
|
||||
record.serialNumber,
|
||||
k -> Collections
|
||||
.synchronizedList(new LinkedList<>())
|
||||
);
|
||||
if (latestStatesList.size() >= params.stateBufferSize) {
|
||||
latestStatesList.remove(0);
|
||||
}
|
||||
latestStatesList.add(stateModel);
|
||||
dataModel.latestStates
|
||||
.put(record.serialNumber, latestStatesList);
|
||||
stateUpdates.add(record.serialNumber);
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.error(
|
||||
@@ -423,7 +438,7 @@ public class Modeler implements Runnable {
|
||||
logger.debug("Removed some wifi scan entries from data model");
|
||||
}
|
||||
if (
|
||||
dataModel.latestState.entrySet()
|
||||
dataModel.latestStates.entrySet()
|
||||
.removeIf(e -> !isRRMEnabled(e.getKey()))
|
||||
) {
|
||||
logger.debug("Removed some state entries from data model");
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -24,6 +25,11 @@ import com.facebook.openwifirrm.modules.Modeler.DataModel;
|
||||
import com.facebook.openwifirrm.ucentral.WifiScanEntry;
|
||||
import com.facebook.openwifirrm.ucentral.informationelement.HTOperation;
|
||||
import com.facebook.openwifirrm.ucentral.informationelement.VHTOperation;
|
||||
import com.facebook.openwifirrm.ucentral.models.AggregatedState;
|
||||
import com.facebook.openwifirrm.ucentral.models.State;
|
||||
import com.facebook.openwifirrm.ucentral.models.State.Interface;
|
||||
import com.facebook.openwifirrm.ucentral.models.State.Interface.SSID;
|
||||
import com.facebook.openwifirrm.ucentral.models.State.Interface.SSID.Association;
|
||||
|
||||
/**
|
||||
* Modeler utilities.
|
||||
@@ -381,4 +387,173 @@ public class ModelerUtils {
|
||||
}
|
||||
return aggregatedWifiScans;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts the input State info to an AggregatedState
|
||||
* and adds it to the bssidToAggregatedStates map. If the bssid&station
|
||||
* of the input State does not exist in the map, create a new
|
||||
* AggregatedState list. If the bssid&station of the input State exists,
|
||||
* then convert State to AggregatedState and check if there exits an
|
||||
* AggregatedState of the same radio. If there does, append the value
|
||||
* of aggregation field to the existing AggregatedState, if not, create
|
||||
* a new AggregatedState and add it to the list.
|
||||
*
|
||||
* @param bssidToAggregatedStates map from bssid&station to a list of AggregatedState.
|
||||
* @param state the state that is to be added.
|
||||
*/
|
||||
static void addStateToAggregation(
|
||||
Map<String, List<AggregatedState>> bssidToAggregatedStates,
|
||||
State state
|
||||
) {
|
||||
for (Interface stateInterface : state.interfaces) {
|
||||
if (stateInterface.ssids == null) {
|
||||
continue;
|
||||
}
|
||||
for (SSID ssid : stateInterface.ssids) {
|
||||
Map<String, Integer> radioInfo = new HashMap<>();
|
||||
radioInfo.put("channel", ssid.radio.get("channel").getAsInt());
|
||||
radioInfo.put(
|
||||
"channel_width",
|
||||
ssid.radio.get("channel_width").getAsInt()
|
||||
);
|
||||
radioInfo
|
||||
.put("tx_power", ssid.radio.get("tx_power").getAsInt());
|
||||
|
||||
for (Association association : ssid.associations) {
|
||||
if (association == null) {
|
||||
continue;
|
||||
}
|
||||
String key = getBssidStationKeyPair(
|
||||
association.bssid,
|
||||
association.station
|
||||
);
|
||||
List<AggregatedState> aggregatedStates =
|
||||
bssidToAggregatedStates
|
||||
.computeIfAbsent(key, k -> new ArrayList<>());
|
||||
AggregatedState aggState =
|
||||
new AggregatedState(association, radioInfo);
|
||||
|
||||
/**
|
||||
* Indicate if the aggState can be merged into some old AggregatedState.
|
||||
* If true, it will be merged by appending its mcs/rssi field to the old one.
|
||||
* If false, it will be added to the list aggregatedStates.
|
||||
*/
|
||||
boolean canBeMergedToOldAggregatedState = false;
|
||||
for (
|
||||
AggregatedState oldAggregatedState : aggregatedStates
|
||||
) {
|
||||
if (oldAggregatedState.add(aggState)) {
|
||||
canBeMergedToOldAggregatedState = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!canBeMergedToOldAggregatedState) {
|
||||
aggregatedStates.add(aggState);
|
||||
}
|
||||
bssidToAggregatedStates.put(key, aggregatedStates);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method aggregates States by bssid&station key pair and radio info.
|
||||
* if two States of the same bssid&station match in channel, channel width and tx_power
|
||||
* need to be aggregated to one {@code AggregatedState}. Currently only mcs and
|
||||
* rssi fields are being aggregated. They are of List<Integer> type in AggregatedState,
|
||||
* which list all the values over the time.
|
||||
*
|
||||
* @param dataModel the data model which includes the latest recorded States.
|
||||
* @param obsoletionPeriodMs the maximum amount of time (in milliseconds) it
|
||||
* is worth aggregating over, starting from the
|
||||
* most recent States and working backwards in time.
|
||||
* A State exactly {@code obsoletionPeriodMs} ms earlier
|
||||
* than the most recent State is considered non-obsolete
|
||||
* (i.e., the "non-obsolete" window is inclusive).
|
||||
* Must be non-negative.
|
||||
* @param refTimeMs the reference time were passed to make testing easier
|
||||
* @return Map<String, Map<String, List<AggregatedState>>> A map from serial number to
|
||||
* a map from bssid_station String pair to a list of AggregatedState.
|
||||
*/
|
||||
public static Map<String, Map<String, List<AggregatedState>>> getAggregatedStates(
|
||||
Modeler.DataModel dataModel,
|
||||
long obsoletionPeriodMs,
|
||||
long refTimeMs
|
||||
) {
|
||||
if (obsoletionPeriodMs < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"obsoletionPeriodMs must be non-negative."
|
||||
);
|
||||
}
|
||||
Map<String, Map<String, List<AggregatedState>>> aggregatedStates =
|
||||
new HashMap<>();
|
||||
|
||||
for (
|
||||
Map.Entry<String, List<State>> deviceToStateList : dataModel.latestStates
|
||||
.entrySet()
|
||||
) {
|
||||
String serialNumber = deviceToStateList.getKey();
|
||||
List<State> states = deviceToStateList.getValue();
|
||||
|
||||
if (states.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort in reverse chronological order. Sorting is done just in case the
|
||||
* States in the original list are not chronological already - although
|
||||
* they are inserted chronologically, perhaps latency, synchronization, etc.
|
||||
*/
|
||||
states.sort(
|
||||
(state1, state2) -> -Long.compare(state1.unit.localtime, state2.unit.localtime)
|
||||
);
|
||||
|
||||
Map<String, List<AggregatedState>> bssidToAggregatedStates =
|
||||
aggregatedStates
|
||||
.computeIfAbsent(serialNumber, k -> new HashMap<>());
|
||||
|
||||
for (State state : states) {
|
||||
if (refTimeMs - state.unit.localtime > obsoletionPeriodMs) {
|
||||
// discard obsolete entries
|
||||
break;
|
||||
}
|
||||
|
||||
addStateToAggregation(bssidToAggregatedStates, state);
|
||||
}
|
||||
}
|
||||
return aggregatedStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets the most recent State from latestStates per device.
|
||||
*
|
||||
* @param latestStates list of latest States per device.
|
||||
* @return Map<String, State> a map from device String to latest State.
|
||||
*/
|
||||
public static Map<String, State> getLatestState(
|
||||
Map<String, List<State>> latestStates
|
||||
) {
|
||||
Map<String, State> latestState = new ConcurrentHashMap<>();
|
||||
for (
|
||||
Map.Entry<String, List<State>> stateEntry : latestStates.entrySet()
|
||||
) {
|
||||
String key = stateEntry.getKey();
|
||||
List<State> value = stateEntry.getValue();
|
||||
if (value.isEmpty()) {
|
||||
latestState.put(key, null);
|
||||
} else {
|
||||
latestState.put(key, value.get(value.size() - 1));
|
||||
}
|
||||
}
|
||||
return latestState;
|
||||
}
|
||||
|
||||
/** Create a key pair consisted of bssid and station string */
|
||||
public static String getBssidStationKeyPair(String bssid, String station) {
|
||||
return String.format(
|
||||
"bssid: %s, station: %s",
|
||||
bssid,
|
||||
station
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public abstract class ChannelOptimizer {
|
||||
// Remove model entries not in the given zone
|
||||
this.model.latestWifiScans.keySet()
|
||||
.removeIf(serialNumber -> !deviceConfigs.containsKey(serialNumber));
|
||||
this.model.latestState.keySet()
|
||||
this.model.latestStates.keySet()
|
||||
.removeIf(serialNumber -> !deviceConfigs.containsKey(serialNumber));
|
||||
this.model.latestDeviceStatusRadios.keySet()
|
||||
.removeIf(serialNumber -> !deviceConfigs.containsKey(serialNumber));
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.facebook.openwifirrm.DeviceDataManager;
|
||||
import com.facebook.openwifirrm.modules.ModelerUtils;
|
||||
import com.facebook.openwifirrm.modules.Modeler.DataModel;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralConstants;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralUtils;
|
||||
@@ -340,8 +341,10 @@ public class LeastUsedChannelOptimizer extends ChannelOptimizer {
|
||||
AVAILABLE_CHANNELS_BAND
|
||||
);
|
||||
|
||||
Map<String, State> latestState =
|
||||
ModelerUtils.getLatestState(model.latestStates);
|
||||
Map<String, String> bssidsMap =
|
||||
UCentralUtils.getBssidsMap(model.latestState);
|
||||
UCentralUtils.getBssidsMap(latestState);
|
||||
|
||||
for (String band : bandsMap.keySet()) {
|
||||
// Performance metrics
|
||||
@@ -373,7 +376,7 @@ public class LeastUsedChannelOptimizer extends ChannelOptimizer {
|
||||
}
|
||||
|
||||
// Get current channel of the device
|
||||
State state = model.latestState.get(serialNumber);
|
||||
State state = latestState.get(serialNumber);
|
||||
if (state == null) {
|
||||
logger.debug(
|
||||
"Device {}: No state found, skipping...",
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.facebook.openwifirrm.DeviceDataManager;
|
||||
import com.facebook.openwifirrm.modules.ModelerUtils;
|
||||
import com.facebook.openwifirrm.modules.Modeler.DataModel;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralUtils;
|
||||
import com.facebook.openwifirrm.ucentral.WifiScanEntry;
|
||||
@@ -128,8 +129,10 @@ public class RandomChannelInitializer extends ChannelOptimizer {
|
||||
AVAILABLE_CHANNELS_BAND
|
||||
);
|
||||
|
||||
Map<String, State> latestState =
|
||||
ModelerUtils.getLatestState(model.latestStates);
|
||||
Map<String, String> bssidsMap =
|
||||
UCentralUtils.getBssidsMap(model.latestState);
|
||||
UCentralUtils.getBssidsMap(latestState);
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : bandsMap.entrySet()) {
|
||||
// Performance metrics
|
||||
@@ -183,7 +186,7 @@ public class RandomChannelInitializer extends ChannelOptimizer {
|
||||
? rng.nextInt(availableChannelsList.size()) : defaultChannelIndex
|
||||
);
|
||||
|
||||
State state = model.latestState.get(serialNumber);
|
||||
State state = latestState.get(serialNumber);
|
||||
if (state == null) {
|
||||
logger.debug(
|
||||
"Device {}: No state found, skipping...",
|
||||
|
||||
@@ -175,7 +175,8 @@ public class LocationBasedOptimalTPC extends TPC {
|
||||
// Filter out the invalid APs (e.g., no radio, no location data)
|
||||
// Update txPowerChoices, boundary, apLocX, apLocY for the optimization
|
||||
for (String serialNumber : serialNumbers) {
|
||||
State state = model.latestState.get(serialNumber);
|
||||
List<State> states = model.latestStates.get(serialNumber);
|
||||
State state = states.get(states.size() - 1);
|
||||
|
||||
// Ignore the device if its radio is not active
|
||||
if (state.radios == null || state.radios.length == 0) {
|
||||
|
||||
@@ -154,8 +154,9 @@ public class MeasurementBasedApApTPC extends TPC {
|
||||
*/
|
||||
protected static Set<String> getManagedBSSIDs(DataModel model) {
|
||||
Set<String> managedBSSIDs = new HashSet<>();
|
||||
for (Map.Entry<String, State> e : model.latestState.entrySet()) {
|
||||
State state = e.getValue();
|
||||
for (Map.Entry<String, List<State>> e : model.latestStates.entrySet()) {
|
||||
List<State> states = e.getValue();
|
||||
State state = states.get(states.size() - 1);
|
||||
if (state.interfaces == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -311,7 +312,8 @@ public class MeasurementBasedApApTPC extends TPC {
|
||||
buildRssiMap(managedBSSIDs, model.latestWifiScans, band);
|
||||
logger.debug("Starting TPC for the {} band", band);
|
||||
for (String serialNumber : serialNumbers) {
|
||||
State state = model.latestState.get(serialNumber);
|
||||
List<State> states = model.latestStates.get(serialNumber);
|
||||
State state = states.get(states.size() - 1);
|
||||
if (
|
||||
state == null || state.radios == null ||
|
||||
state.radios.length == 0
|
||||
|
||||
@@ -291,10 +291,10 @@ public class MeasurementBasedApClientTPC extends TPC {
|
||||
public Map<String, Map<String, Integer>> computeTxPowerMap() {
|
||||
Map<String, Map<String, Integer>> txPowerMap = new TreeMap<>();
|
||||
|
||||
for (Map.Entry<String, State> e : model.latestState.entrySet()) {
|
||||
for (Map.Entry<String, List<State>> e : model.latestStates.entrySet()) {
|
||||
String serialNumber = e.getKey();
|
||||
State state = e.getValue();
|
||||
|
||||
List<State> states = e.getValue();
|
||||
State state = states.get(states.size() - 1);
|
||||
if (state.radios == null || state.radios.length == 0) {
|
||||
logger.debug(
|
||||
"Device {}: No radios found, skipping...",
|
||||
|
||||
@@ -122,7 +122,7 @@ public class RandomTxPowerInitializer extends TPC {
|
||||
if (!setDifferentTxPowerPerAp) {
|
||||
List<Integer> txPowerChoices =
|
||||
new ArrayList<>(DEFAULT_TX_POWER_CHOICES);
|
||||
for (String serialNumber : model.latestState.keySet()) {
|
||||
for (String serialNumber : model.latestStates.keySet()) {
|
||||
for (String band : UCentralConstants.BANDS) {
|
||||
txPowerChoices = updateTxPowerChoices(
|
||||
band,
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract class TPC {
|
||||
this.model.latestWifiScans.keySet()
|
||||
.removeIf(serialNumber -> !deviceConfigs.containsKey(serialNumber)
|
||||
);
|
||||
this.model.latestState.keySet()
|
||||
this.model.latestStates.keySet()
|
||||
.removeIf(serialNumber -> !deviceConfigs.containsKey(serialNumber)
|
||||
);
|
||||
this.model.latestDeviceStatusRadios.keySet()
|
||||
@@ -184,9 +184,10 @@ public abstract class TPC {
|
||||
*/
|
||||
protected Map<Integer, List<String>> getApsPerChannel() {
|
||||
Map<Integer, List<String>> apsPerChannel = new TreeMap<>();
|
||||
for (Map.Entry<String, State> e : model.latestState.entrySet()) {
|
||||
for (Map.Entry<String, List<State>> e : model.latestStates.entrySet()) {
|
||||
String serialNumber = e.getKey();
|
||||
State state = e.getValue();
|
||||
List<State> states = e.getValue();
|
||||
State state = states.get(states.size() - 1);
|
||||
|
||||
if (state.radios == null || state.radios.length == 0) {
|
||||
logger.debug(
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.openwifirrm.ucentral.models;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.facebook.openwifirrm.ucentral.models.State.Interface.SSID.Association;
|
||||
import com.facebook.openwifirrm.ucentral.models.State.Interface.SSID.Association.Rate;
|
||||
|
||||
/**
|
||||
* Aggregation model for State aggregation. Only contains info useful for
|
||||
* analysis.
|
||||
*/
|
||||
public class AggregatedState {
|
||||
|
||||
/** Rate information with aggregated fields. */
|
||||
public static class AggregatedRate {
|
||||
/**
|
||||
* This is the common bitRate for all the aggregated fields.
|
||||
*/
|
||||
public long bitRate;
|
||||
|
||||
/**
|
||||
* This is the common channel width for all the aggregated fields.
|
||||
*/
|
||||
public int chWidth;
|
||||
|
||||
/**
|
||||
* Aggregated fields mcs
|
||||
*/
|
||||
public List<Integer> mcs = new ArrayList<>();
|
||||
|
||||
/** Constructor with no args */
|
||||
private AggregatedRate() {}
|
||||
|
||||
/** Add a Rate to the AggregatedRate */
|
||||
private void add(Rate rate) {
|
||||
if (rate == null) {
|
||||
return;
|
||||
}
|
||||
if (mcs.isEmpty()) {
|
||||
bitRate = rate.bitrate;
|
||||
chWidth = rate.chwidth;
|
||||
}
|
||||
mcs.add(rate.mcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an AggregatedRate with the same channel_width to the
|
||||
* AggregatedRate
|
||||
*/
|
||||
private void add(AggregatedRate rate) {
|
||||
if (rate == null || rate.chWidth != chWidth) {
|
||||
return;
|
||||
}
|
||||
if (mcs.isEmpty()) {
|
||||
bitRate = rate.bitRate;
|
||||
chWidth = rate.chWidth;
|
||||
}
|
||||
mcs.addAll(rate.mcs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Radio information with channel, channel_width and tx_power.
|
||||
*/
|
||||
public static class Radio {
|
||||
public int channel;
|
||||
public int channelWidth;
|
||||
public int txPower;
|
||||
|
||||
private Radio() {}
|
||||
|
||||
public Radio(int channel, int channelWidth, int txPower) {
|
||||
this.channel = channel;
|
||||
this.channelWidth = channelWidth;
|
||||
this.txPower = txPower;
|
||||
}
|
||||
|
||||
private Radio(Map<String, Integer> radioInfo) {
|
||||
channel = radioInfo.getOrDefault("channel", -1);
|
||||
channelWidth = radioInfo.getOrDefault("channel_width", -1);
|
||||
txPower = radioInfo.getOrDefault("tx_power", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(channel, channelWidth, txPower);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Radio other = (Radio) obj;
|
||||
return channel == other.channel &&
|
||||
channelWidth == other.channelWidth && txPower == other.txPower;
|
||||
}
|
||||
}
|
||||
|
||||
public String bssid;
|
||||
public String station;
|
||||
public long connected;
|
||||
public long inactive;
|
||||
public List<Integer> rssi;
|
||||
public long rxBytes;
|
||||
public long rxPackets;
|
||||
public AggregatedRate rxRate;
|
||||
public long txBytes;
|
||||
public long txDuration;
|
||||
public long txFailed;
|
||||
public long txPackets;
|
||||
public AggregatedRate txRate;
|
||||
public long txRetries;
|
||||
public int ackSignal;
|
||||
public int ackSignalAvg;
|
||||
public Radio radio;
|
||||
|
||||
/** Constructor with no args */
|
||||
public AggregatedState() {
|
||||
this.rxRate = new AggregatedRate();
|
||||
this.txRate = new AggregatedRate();
|
||||
this.rssi = new ArrayList<>();
|
||||
this.radio = new Radio();
|
||||
}
|
||||
|
||||
/** Construct from Association and radio */
|
||||
public AggregatedState(
|
||||
Association association,
|
||||
Map<String, Integer> radioInfo
|
||||
) {
|
||||
this.rxRate = new AggregatedRate();
|
||||
this.txRate = new AggregatedRate();
|
||||
this.rssi = new ArrayList<>();
|
||||
|
||||
this.bssid = association.bssid;
|
||||
this.station = association.station;
|
||||
this.connected = association.connected;
|
||||
this.inactive = association.inactive;
|
||||
this.rssi.add(association.rssi);
|
||||
this.rxBytes = association.rx_bytes;
|
||||
this.rxPackets = association.rx_packets;
|
||||
this.rxRate.add(association.rx_rate);
|
||||
this.txBytes = association.tx_bytes;
|
||||
this.txDuration = association.tx_duration;
|
||||
this.txFailed = association.tx_failed;
|
||||
this.txPackets = association.tx_packets;
|
||||
this.txRate.add(association.tx_rate);
|
||||
this.txRetries = association.tx_retries;
|
||||
this.ackSignal = association.ack_signal;
|
||||
this.ackSignalAvg = association.ack_signal_avg;
|
||||
this.radio = new Radio(radioInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bssid, station, radio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AggregatedState other = (AggregatedState) obj;
|
||||
|
||||
return bssid == other.bssid && station == other.station &&
|
||||
connected == other.connected && inactive == other.inactive && rssi
|
||||
.equals(other.rssi) &&
|
||||
rxBytes == other.rxBytes && rxBytes == other.rxPackets &&
|
||||
Objects.equals(rxRate, other.rxRate) &&
|
||||
txBytes == other.txBytes && txDuration == other.txDuration &&
|
||||
txFailed == other.txFailed && txPackets == other.txPackets &&
|
||||
Objects.equals(txRate, other.txRate) &&
|
||||
txRetries == other.txRetries && ackSignal == other.ackSignal &&
|
||||
ackSignalAvg == other.ackSignalAvg &&
|
||||
Objects.equals(radio, other.radio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an AggregatedState to this AggregatedState. Succeed only when the two
|
||||
* matches in hashCode.
|
||||
*
|
||||
* @param state input AggregatedState
|
||||
* @return boolean true if the two matches in bssid, station, channel,
|
||||
* channel_width and tx_power
|
||||
*/
|
||||
public boolean add(AggregatedState state) {
|
||||
if (hashCode() == state.hashCode()) {
|
||||
this.rssi.addAll(state.rssi);
|
||||
this.rxRate.add(state.rxRate);
|
||||
this.txRate.add(state.txRate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -24,6 +26,8 @@ import com.facebook.openwifirrm.aggregators.MeanAggregator;
|
||||
import com.facebook.openwifirrm.modules.Modeler.DataModel;
|
||||
import com.facebook.openwifirrm.optimizers.TestUtils;
|
||||
import com.facebook.openwifirrm.ucentral.WifiScanEntry;
|
||||
import com.facebook.openwifirrm.ucentral.models.AggregatedState;
|
||||
import com.facebook.openwifirrm.ucentral.models.State;
|
||||
|
||||
public class ModelerUtilsTest {
|
||||
@Test
|
||||
@@ -32,9 +36,9 @@ public class ModelerUtilsTest {
|
||||
double[][][] rxPower = ModelerUtils.generateRxPower(
|
||||
500,
|
||||
4,
|
||||
new ArrayList<>(Arrays.asList(408.0, 507.0, 64.0, 457.0)),
|
||||
new ArrayList<>(Arrays.asList(317.0, 49.0, 140.0, 274.0)),
|
||||
new ArrayList<>(Arrays.asList(20.0, 20.0, 20.0, 20.0))
|
||||
Arrays.asList(408.0, 507.0, 64.0, 457.0),
|
||||
Arrays.asList(317.0, 49.0, 140.0, 274.0),
|
||||
Arrays.asList(20.0, 20.0, 20.0, 20.0)
|
||||
);
|
||||
assertNull(rxPower);
|
||||
}
|
||||
@@ -44,9 +48,9 @@ public class ModelerUtilsTest {
|
||||
double[][][] rxPower = ModelerUtils.generateRxPower(
|
||||
500,
|
||||
4,
|
||||
new ArrayList<>(Arrays.asList(408.0, 453.0, 64.0, 457.0)),
|
||||
new ArrayList<>(Arrays.asList(317.0, 49.0, 140.0, 274.0)),
|
||||
new ArrayList<>(Arrays.asList(20.0, 20.0, 20.0, 20.0))
|
||||
Arrays.asList(408.0, 453.0, 64.0, 457.0),
|
||||
Arrays.asList(317.0, 49.0, 140.0, 274.0),
|
||||
Arrays.asList(20.0, 20.0, 20.0, 20.0)
|
||||
);
|
||||
assertEquals(-108.529, rxPower[0][0][0], 0.001);
|
||||
double[][] heatMap = ModelerUtils.generateHeatMap(
|
||||
@@ -74,9 +78,9 @@ public class ModelerUtilsTest {
|
||||
double[][][] rxPower = ModelerUtils.generateRxPower(
|
||||
500,
|
||||
4,
|
||||
new ArrayList<>(Arrays.asList(408.0, 453.0, 64.0, 457.0)),
|
||||
new ArrayList<>(Arrays.asList(317.0, 49.0, 140.0, 274.0)),
|
||||
new ArrayList<>(Arrays.asList(30.0, 30.0, 30.0, 30.0))
|
||||
Arrays.asList(408.0, 453.0, 64.0, 457.0),
|
||||
Arrays.asList(317.0, 49.0, 140.0, 274.0),
|
||||
Arrays.asList(30.0, 30.0, 30.0, 30.0)
|
||||
);
|
||||
assertEquals(-98.529, rxPower[0][0][0], 0.001);
|
||||
double[][] heatMap = ModelerUtils.generateHeatMap(
|
||||
@@ -547,4 +551,295 @@ public class ModelerUtilsTest {
|
||||
aggregateMap.get(apB).get(bssidA)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddStateToAggregation() {
|
||||
final String bssidA = "aa:aa:aa:aa:aa:a";
|
||||
final String stationA1 = "stationA1";
|
||||
final String stationA2 = "stationA2";
|
||||
final String bssidB = "bb:bb:bb:bb:bb:bb";
|
||||
final String stationB = "stationB";
|
||||
final String stationC = "stationC";
|
||||
final String bssidC = "cc:cc:cc:cc:cc:cc";
|
||||
|
||||
AggregatedState aggStateA1 = TestUtils.createAggregatedState(
|
||||
1,
|
||||
20,
|
||||
10,
|
||||
bssidA,
|
||||
stationA1,
|
||||
new int[] { 10, 20, 30 }
|
||||
);
|
||||
AggregatedState aggStateA2 = TestUtils.createAggregatedState(
|
||||
6,
|
||||
20,
|
||||
10,
|
||||
bssidA,
|
||||
stationA2,
|
||||
new int[] { 20, 30, 40 }
|
||||
);
|
||||
AggregatedState aggStateB = TestUtils.createAggregatedState(
|
||||
11,
|
||||
20,
|
||||
20,
|
||||
bssidB,
|
||||
stationB,
|
||||
new int[] { 10, 20, 30 }
|
||||
);
|
||||
AggregatedState aggStateC = TestUtils.createAggregatedState(
|
||||
1,
|
||||
20,
|
||||
10,
|
||||
bssidC,
|
||||
stationC,
|
||||
new int[] { 100, 200, 300 }
|
||||
);
|
||||
|
||||
Map<String, List<AggregatedState>> bssidToAggregatedStates =
|
||||
new HashMap<>();
|
||||
bssidToAggregatedStates.put(
|
||||
ModelerUtils.getBssidStationKeyPair(bssidA, stationA1),
|
||||
new ArrayList<>(Arrays.asList(aggStateA1))
|
||||
);
|
||||
|
||||
bssidToAggregatedStates.put(
|
||||
ModelerUtils.getBssidStationKeyPair(bssidA, stationA2),
|
||||
new ArrayList<>(Arrays.asList(aggStateA2))
|
||||
);
|
||||
bssidToAggregatedStates.put(
|
||||
ModelerUtils.getBssidStationKeyPair(bssidB, stationB),
|
||||
new ArrayList<>(Arrays.asList(aggStateB))
|
||||
);
|
||||
bssidToAggregatedStates.put(
|
||||
ModelerUtils.getBssidStationKeyPair(bssidC, stationC),
|
||||
new ArrayList<>(Arrays.asList(aggStateC))
|
||||
);
|
||||
|
||||
State toBeAggregated1 = TestUtils.createState(
|
||||
6,
|
||||
20,
|
||||
10,
|
||||
bssidA,
|
||||
new String[] { stationA1, stationA1, stationA2 },
|
||||
new int[] { 40, 50, 60 },
|
||||
1
|
||||
);
|
||||
|
||||
ModelerUtils
|
||||
.addStateToAggregation(bssidToAggregatedStates, toBeAggregated1);
|
||||
|
||||
assertEquals(
|
||||
bssidToAggregatedStates
|
||||
.get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1))
|
||||
.get(0).rssi,
|
||||
Arrays.asList(10, 20, 30)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
bssidToAggregatedStates
|
||||
.get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1))
|
||||
.get(1).rssi,
|
||||
Arrays.asList(40, 50)
|
||||
);
|
||||
assertEquals(
|
||||
bssidToAggregatedStates
|
||||
.get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA2))
|
||||
.get(0).rssi,
|
||||
Arrays.asList(20, 30, 40, 60)
|
||||
);
|
||||
|
||||
State toBeAggregated2 = TestUtils.createState(
|
||||
11,
|
||||
20,
|
||||
20,
|
||||
bssidB,
|
||||
new String[] { stationB },
|
||||
new int[] { 40 },
|
||||
1
|
||||
);
|
||||
ModelerUtils
|
||||
.addStateToAggregation(bssidToAggregatedStates, toBeAggregated2);
|
||||
assertEquals(
|
||||
bssidToAggregatedStates
|
||||
.get(ModelerUtils.getBssidStationKeyPair(bssidB, stationB))
|
||||
.get(0).rssi,
|
||||
Arrays.asList(10, 20, 30, 40)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAggregatedStates() {
|
||||
final long obsoletionPeriodMs = 60000000;
|
||||
final String serialNumberA = "aaaaaaaaaaaa";
|
||||
final String bssidA = "aa:aa:aa:aa:aa:a";
|
||||
final String serialNumberB = "bbbbbbbbbbbb";
|
||||
final String bssidB = "bb:bb:bb:bb:bb:bb";
|
||||
final String serialNumberC = "cccccccccccc";
|
||||
final String bssidC = "cc:cc:cc:cc:cc:cc";
|
||||
final String stationA1 = "stationA1";
|
||||
final String stationA2 = "stationA2";
|
||||
final String stationA3 = "stationA3";
|
||||
final String stationA4 = "stationA4";
|
||||
final String stationB = "stationB";
|
||||
final String stationC = "stationC";
|
||||
|
||||
final long refTimeMs = TestUtils.DEFAULT_LOCAL_TIME;
|
||||
|
||||
DataModel dataModel = new DataModel();
|
||||
|
||||
// This serie of StateA is used to test a valid input states.
|
||||
State time1StateA = TestUtils.createState(
|
||||
1,
|
||||
80,
|
||||
10,
|
||||
bssidA,
|
||||
new String[] { stationA1, stationA2, stationA2, stationA3 },
|
||||
new int[] { -84, -67, -67, 10 },
|
||||
6,
|
||||
40,
|
||||
20,
|
||||
bssidA,
|
||||
new String[] { stationA1 },
|
||||
new int[] { -80 },
|
||||
TestUtils.DEFAULT_LOCAL_TIME
|
||||
);
|
||||
|
||||
State time2StateA = TestUtils.createState(
|
||||
1,
|
||||
80,
|
||||
10,
|
||||
bssidA,
|
||||
new String[] { stationA1, stationA3 },
|
||||
new int[] { 27, 100 },
|
||||
6,
|
||||
40,
|
||||
20,
|
||||
bssidA,
|
||||
new String[] { stationA2, stationA2 },
|
||||
new int[] { 180, 67 },
|
||||
TestUtils.DEFAULT_LOCAL_TIME - 800
|
||||
);
|
||||
|
||||
//As State time3StateA is obsolete, it should not be aggregated.
|
||||
State time3StateA = TestUtils.createState(
|
||||
1,
|
||||
80,
|
||||
10,
|
||||
bssidA,
|
||||
new String[] { stationA1, stationA2, stationA4 },
|
||||
new int[] { 24, 27, 1000 },
|
||||
6,
|
||||
40,
|
||||
20,
|
||||
bssidA,
|
||||
new String[] { stationA1, stationA2 },
|
||||
new int[] { 180, 180 },
|
||||
// Set the localtime exactly obsolete
|
||||
TestUtils.DEFAULT_LOCAL_TIME - obsoletionPeriodMs - 1
|
||||
);
|
||||
|
||||
dataModel.latestStates.put(
|
||||
serialNumberA,
|
||||
new ArrayList<>(
|
||||
Arrays.asList(
|
||||
time1StateA,
|
||||
time2StateA,
|
||||
time3StateA
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Map<String, Map<String, List<AggregatedState>>> aggregatedMap =
|
||||
ModelerUtils
|
||||
.getAggregatedStates(dataModel, obsoletionPeriodMs, refTimeMs);
|
||||
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).size(),
|
||||
2
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).get(0).radio,
|
||||
new AggregatedState.Radio(1, 80, 10)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).get(0).rssi,
|
||||
Arrays.asList(-84, 27)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).get(1).radio,
|
||||
new AggregatedState.Radio(6, 40, 20)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).get(1).rssi,
|
||||
Arrays.asList(-80)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA2)).get(0).radio,
|
||||
new AggregatedState.Radio(1, 80, 10)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA2)).get(0).rssi,
|
||||
Arrays.asList(-67, -67)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA2)).get(1).radio,
|
||||
new AggregatedState.Radio(6, 40, 20)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA2)).get(1).rssi,
|
||||
Arrays.asList(180, 67)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA3)).get(0).radio,
|
||||
new AggregatedState.Radio(1, 80, 10)
|
||||
);
|
||||
assertEquals(
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA3)).get(0).rssi,
|
||||
Arrays.asList(10, 100)
|
||||
);
|
||||
|
||||
// Test more clients operate on the same channel (stationB and stationA)
|
||||
State time1StateB = TestUtils.createState(
|
||||
1,
|
||||
80,
|
||||
10,
|
||||
bssidB,
|
||||
new String[] { stationB },
|
||||
new int[] { -30 },
|
||||
TestUtils.DEFAULT_LOCAL_TIME
|
||||
);
|
||||
dataModel.latestStates
|
||||
.computeIfAbsent(serialNumberB, k -> new ArrayList<>())
|
||||
.add(time1StateB);
|
||||
|
||||
State time1StateC = TestUtils.createState(
|
||||
6,
|
||||
40,
|
||||
20,
|
||||
bssidC,
|
||||
new String[] { stationC },
|
||||
new int[] { -100 },
|
||||
TestUtils.DEFAULT_LOCAL_TIME
|
||||
);
|
||||
dataModel.latestStates
|
||||
.computeIfAbsent(serialNumberC, k -> new ArrayList<>())
|
||||
.add(time1StateC);
|
||||
|
||||
Map<String, Map<String, List<AggregatedState>>> aggregatedMap2 =
|
||||
ModelerUtils
|
||||
.getAggregatedStates(dataModel, obsoletionPeriodMs, refTimeMs);
|
||||
|
||||
assertEquals(
|
||||
aggregatedMap2.get(serialNumberB).get(ModelerUtils.getBssidStationKeyPair(bssidB, stationB)).get(0).rssi, Arrays.asList(-30)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
aggregatedMap2.get(serialNumberC).get(ModelerUtils.getBssidStationKeyPair(bssidC, stationC)).get(0).rssi, Arrays.asList(-100)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
aggregatedMap2.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).size(),
|
||||
aggregatedMap.get(serialNumberA).get(ModelerUtils.getBssidStationKeyPair(bssidA, stationA1)).size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.facebook.openwifirrm.DeviceTopology;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralConstants;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralUtils;
|
||||
import com.facebook.openwifirrm.ucentral.WifiScanEntry;
|
||||
import com.facebook.openwifirrm.ucentral.models.AggregatedState;
|
||||
import com.facebook.openwifirrm.ucentral.models.State;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
@@ -39,6 +40,12 @@ public class TestUtils {
|
||||
/** Default tx power in dBm */
|
||||
public static final int DEFAULT_TX_POWER = 20;
|
||||
|
||||
/**
|
||||
* Default local time in unix timestamps in seconds
|
||||
* GMT: Fri Sep 24 2021 23:47:55 GMT+0000
|
||||
*/
|
||||
public static final long DEFAULT_LOCAL_TIME = 1632527275;
|
||||
|
||||
/** Create a topology from the given devices in a single zone. */
|
||||
public static DeviceTopology createTopology(
|
||||
String zone,
|
||||
@@ -428,26 +435,28 @@ public class TestUtils {
|
||||
return radio;
|
||||
}
|
||||
|
||||
/** Create a {@code State.Unit}. */
|
||||
private static State.Unit createStateUnit() {
|
||||
/** Create a {@code State.Unit} with specifying localtime in unix timestamp in seconds. */
|
||||
private static State.Unit createStateUnit(long localtime) {
|
||||
// @formatter:off
|
||||
String jsonStr = String.format(
|
||||
" {\n" +
|
||||
" \"load\": [\n" +
|
||||
" 0,\n" +
|
||||
" 0,\n" +
|
||||
" 0\n" +
|
||||
" ],\n" +
|
||||
" \"localtime\": %d,\n" +
|
||||
" \"memory\": {\n" +
|
||||
" \"free\": 788930560,\n" +
|
||||
" \"total\": 973561856\n" +
|
||||
" },\n" +
|
||||
" \"uptime\": 684456\n" +
|
||||
" }\n", localtime);
|
||||
// @formatter:on
|
||||
return gson.fromJson(
|
||||
" {\n" +
|
||||
" \"load\": [\n" +
|
||||
" 0,\n" +
|
||||
" 0,\n" +
|
||||
" 0\n" +
|
||||
" ],\n" +
|
||||
" \"localtime\": 1632527275,\n" +
|
||||
" \"memory\": {\n" +
|
||||
" \"free\": 788930560,\n" +
|
||||
" \"total\": 973561856\n" +
|
||||
" },\n" +
|
||||
" \"uptime\": 684456\n" +
|
||||
" }\n",
|
||||
jsonStr,
|
||||
State.Unit.class
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,7 +472,9 @@ public class TestUtils {
|
||||
* @param channelWidths array of channel widths (MHz)
|
||||
* @param txPowers array of tx powers (dBm)
|
||||
* @param bssids array of BSSIDs
|
||||
* @param stations 2-D array of client station codes
|
||||
* @param clientRssis 2-D array of client RSSIs
|
||||
* @param localtime unix timestamp in seconds.
|
||||
* @return the state of an AP with radios described by the given parameters
|
||||
*/
|
||||
public static State createState(
|
||||
@@ -471,15 +482,19 @@ public class TestUtils {
|
||||
int[] channelWidths,
|
||||
int[] txPowers,
|
||||
String[] bssids,
|
||||
int[][] clientRssis
|
||||
String[][] stations,
|
||||
int[][] clientRssis,
|
||||
long localtime
|
||||
) {
|
||||
if (
|
||||
!(channels.length == channelWidths.length &&
|
||||
channelWidths.length == txPowers.length &&
|
||||
txPowers.length == bssids.length)
|
||||
txPowers.length == bssids.length &&
|
||||
bssids.length == stations.length &&
|
||||
stations.length == clientRssis.length)
|
||||
) {
|
||||
throw new IllegalArgumentException(
|
||||
"All arguments must have the same length."
|
||||
"All array-type arguments must have the same length."
|
||||
);
|
||||
}
|
||||
final int numRadios = channels.length;
|
||||
@@ -503,12 +518,49 @@ public class TestUtils {
|
||||
new State.Interface.SSID.Association();
|
||||
state.interfaces[i].ssids[0].associations[j].rssi =
|
||||
clientRssis[i][j];
|
||||
state.interfaces[i].ssids[0].associations[j].station =
|
||||
stations[i][j];
|
||||
state.interfaces[i].ssids[0].associations[j].bssid = bssids[i];
|
||||
state.interfaces[i].ssids[0].radio = gson
|
||||
.fromJson(gson.toJson(state.radios[i]), JsonObject.class);
|
||||
}
|
||||
}
|
||||
state.unit = createStateUnit();
|
||||
state.unit = createStateUnit(localtime);
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a device state object with one radio.
|
||||
*
|
||||
* @param channel channel number
|
||||
* @param channelWidth channel width in MHz
|
||||
* @param txPower tx power in dBm
|
||||
* @param bssid bssid
|
||||
* @param stations array of station codes
|
||||
* @param clientRssis array of client RSSIs
|
||||
* @param localtime unix timestamp in seconds.
|
||||
* @return the state of an AP with one radio
|
||||
*/
|
||||
public static State createState(
|
||||
int channel,
|
||||
int channelWidth,
|
||||
int txPower,
|
||||
String bssid,
|
||||
String[] stations,
|
||||
int[] clientRssis,
|
||||
long localtime
|
||||
) {
|
||||
return createState(
|
||||
new int[] { channel },
|
||||
new int[] { channelWidth },
|
||||
new int[] { txPower },
|
||||
new String[] { bssid },
|
||||
new String[][] { stations },
|
||||
new int[][] { clientRssis },
|
||||
localtime
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a device state object with one radio.
|
||||
*
|
||||
@@ -571,7 +623,9 @@ public class TestUtils {
|
||||
new int[] { channelWidth },
|
||||
new int[] { txPower },
|
||||
new String[] { bssid },
|
||||
new int[][] { clientRssis }
|
||||
new String[][] { new String[clientRssis.length] },
|
||||
new int[][] { clientRssis },
|
||||
DEFAULT_LOCAL_TIME
|
||||
);
|
||||
}
|
||||
|
||||
@@ -599,52 +653,84 @@ public class TestUtils {
|
||||
String bssidB
|
||||
) {
|
||||
return createState(
|
||||
channelA,
|
||||
channelWidthA,
|
||||
txPowerA,
|
||||
bssidA,
|
||||
new int[] {},
|
||||
channelB,
|
||||
channelWidthB,
|
||||
txPowerB,
|
||||
bssidB,
|
||||
new int[] {}
|
||||
new int[] { channelA, channelB },
|
||||
new int[] { channelWidthA, channelWidthB },
|
||||
new int[] { txPowerA, txPowerB },
|
||||
new String[] { bssidA, bssidB },
|
||||
new String[][] { new String[] {}, new String[] {} },
|
||||
new int[][] { new int[] {}, new int[] {} },
|
||||
DEFAULT_LOCAL_TIME
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a device state object with two radios.
|
||||
*
|
||||
* @param channelA channel number
|
||||
* @param channelWidthA channel width (MHz) of channelA
|
||||
* @param txPowerA tx power for channelA
|
||||
* @param bssidA bssid for radio on channelA
|
||||
* @param clientRssisA array of client RSSIs for channelA
|
||||
* @param channelB channel number
|
||||
* @param channelWidthB channel width (MHz) of channelB
|
||||
* @param txPowerB tx power for channelB
|
||||
* @param bssidB bssid for radio on channelB
|
||||
* @param clientRssisB array of client RSSIs for channelB
|
||||
* @return the state of an AP with two radios
|
||||
*/
|
||||
* Create a device state object with two radios.
|
||||
*
|
||||
* @param channelA channel number
|
||||
* @param channelWidthA channel width (MHz) of channelA
|
||||
* @param txPowerA tx power (dB) for channelA
|
||||
* @param bssidA bssid for radio on channelA
|
||||
* @param clientRssisA array of client RSSIs for channelA
|
||||
* @param channelB channel number
|
||||
* @param channelWidthB channel width (MHz) of channelB
|
||||
* @param txPowerB tx power (dB) for channelB
|
||||
* @param bssidB bssid for radio on channelB
|
||||
* @param clientRssisB array of client RSSIs for channelB
|
||||
* @param localtime local time for the State
|
||||
* @return the state of an AP with two radios
|
||||
*/
|
||||
public static State createState(
|
||||
int channelA,
|
||||
int channelWidthA,
|
||||
int txPowerA,
|
||||
String bssidA,
|
||||
String[] stationsA,
|
||||
int[] clientRssisA,
|
||||
int channelB,
|
||||
int channelWidthB,
|
||||
int txPowerB,
|
||||
String bssidB,
|
||||
int[] clientRssisB
|
||||
String[] stationsB,
|
||||
int[] clientRssisB,
|
||||
long localtime
|
||||
) {
|
||||
return createState(
|
||||
new int[] { channelA, channelB },
|
||||
new int[] { channelWidthA, channelWidthB },
|
||||
new int[] { txPowerA, txPowerB },
|
||||
new String[] { bssidA, bssidB },
|
||||
new int[][] { clientRssisA, clientRssisB }
|
||||
new String[][] { stationsA, stationsB },
|
||||
new int[][] { clientRssisA, clientRssisB },
|
||||
localtime
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AggregatedState from given radio info.
|
||||
*
|
||||
* @param channel channel number
|
||||
* @param channelWidth channel width (MHz) of channelA
|
||||
* @param txPower tx power (db) for this channel
|
||||
* @param bssid bssid for radio on this channel
|
||||
* @param station station string for radio on this channel
|
||||
* @param clientRssi array of client RSSIs.
|
||||
* @return AggregatedState creating from the given radio.
|
||||
*/
|
||||
public static AggregatedState createAggregatedState(
|
||||
int channel,
|
||||
int channelWidth,
|
||||
int txPower,
|
||||
String bssid,
|
||||
String station,
|
||||
int[] clientRssi
|
||||
) {
|
||||
AggregatedState state = new AggregatedState();
|
||||
state.radio = new AggregatedState.Radio(channel, channelWidth, txPower);
|
||||
state.bssid = bssid;
|
||||
state.station = station;
|
||||
for (int rssi : clientRssi) {
|
||||
state.rssi.add(rssi);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -77,9 +80,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(40, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -98,9 +101,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -142,9 +147,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -164,9 +172,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 6)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(6, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(6, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -182,9 +190,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 6)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(6, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(6, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -235,9 +243,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -256,9 +267,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(40, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -276,9 +287,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -328,9 +341,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -351,9 +367,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(40, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -372,9 +388,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -418,9 +436,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -442,9 +463,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(40, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -463,9 +484,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -483,9 +506,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceD,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceD,
|
||||
TestUtils.createState(40, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceD,
|
||||
@@ -536,9 +559,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -558,9 +584,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 36)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(36, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(36, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -579,9 +605,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -601,9 +629,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceD,
|
||||
TestUtils.createDeviceStatus(band, 36)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceD,
|
||||
TestUtils.createState(36, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(36, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceD,
|
||||
@@ -626,9 +654,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceE,
|
||||
TestUtils.createDeviceStatus(band, eExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceE,
|
||||
TestUtils.createState(eExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceE,
|
||||
@@ -672,9 +703,12 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -693,9 +727,9 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 48)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(48, channelWidth, dummyBssid)
|
||||
Arrays.asList(TestUtils.createState(48, channelWidth, dummyBssid))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -725,9 +759,11 @@ public class LeastUsedChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(149, channelWidth, dummyBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.facebook.openwifirrm.optimizers.channel;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -46,13 +47,17 @@ public class RandomChannelInitializerTest {
|
||||
|
||||
// A and B will be assigned to the same channel
|
||||
DataModel dataModel = new DataModel();
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(6, channelWidth, deviceABssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(6, channelWidth, deviceABssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(11, channelWidth, deviceBBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(11, channelWidth, deviceBBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestDeviceStatusRadios.put(
|
||||
deviceA,
|
||||
@@ -91,13 +96,17 @@ public class RandomChannelInitializerTest {
|
||||
|
||||
// A and B will be assigned to the same channel
|
||||
DataModel dataModel = new DataModel();
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(6, channelWidth, deviceABssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(6, channelWidth, deviceABssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(11, channelWidth, deviceBBssid)
|
||||
Arrays.asList(
|
||||
TestUtils.createState(11, channelWidth, deviceBBssid)
|
||||
)
|
||||
);
|
||||
dataModel.latestDeviceStatusRadios.put(
|
||||
deviceA,
|
||||
|
||||
@@ -56,9 +56,13 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, bssidA)
|
||||
Arrays
|
||||
.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, bssidA)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -80,9 +84,9 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 40)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(40, channelWidth, bssidB)
|
||||
Arrays.asList(TestUtils.createState(40, channelWidth, bssidB))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -114,9 +118,9 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 149)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(149, channelWidth, bssidC)
|
||||
Arrays.asList(TestUtils.createState(149, channelWidth, bssidC))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
@@ -160,9 +164,13 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceA,
|
||||
TestUtils.createDeviceStatus(band, aExpectedChannel)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(aExpectedChannel, channelWidth, bssidA)
|
||||
Arrays
|
||||
.asList(
|
||||
TestUtils
|
||||
.createState(aExpectedChannel, channelWidth, bssidA)
|
||||
)
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceA,
|
||||
@@ -182,9 +190,9 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceB,
|
||||
TestUtils.createDeviceStatus(band, 6)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(6, channelWidth, bssidB)
|
||||
Arrays.asList(TestUtils.createState(6, channelWidth, bssidB))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceB,
|
||||
@@ -200,9 +208,9 @@ public class UnmanagedApAwareChannelOptimizerTest {
|
||||
deviceC,
|
||||
TestUtils.createDeviceStatus(band, 6)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(6, channelWidth, bssidC)
|
||||
Arrays.asList(TestUtils.createState(6, channelWidth, bssidC))
|
||||
);
|
||||
dataModel.latestWifiScans.put(
|
||||
deviceC,
|
||||
|
||||
@@ -132,17 +132,19 @@ public class LocationBasedOptimalTPCTest {
|
||||
device,
|
||||
TestUtils.createDeviceStatus(UCentralConstants.BANDS)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -199,17 +201,19 @@ public class LocationBasedOptimalTPCTest {
|
||||
device,
|
||||
TestUtils.createDeviceStatus(UCentralConstants.BANDS)
|
||||
);
|
||||
dataModel2.latestState.put(
|
||||
dataModel2.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -220,13 +224,15 @@ public class LocationBasedOptimalTPCTest {
|
||||
Arrays.asList(UCentralConstants.BAND_5G)
|
||||
)
|
||||
);
|
||||
dataModel2.latestState.put(
|
||||
dataModel2.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -308,17 +314,19 @@ public class LocationBasedOptimalTPCTest {
|
||||
device,
|
||||
TestUtils.createDeviceStatus(UCentralConstants.BANDS)
|
||||
);
|
||||
dataModel2.latestState.put(
|
||||
dataModel2.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -367,17 +375,19 @@ public class LocationBasedOptimalTPCTest {
|
||||
device,
|
||||
TestUtils.createDeviceStatus(UCentralConstants.BANDS)
|
||||
);
|
||||
dataModel3.latestState.put(
|
||||
dataModel3.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -416,17 +426,19 @@ public class LocationBasedOptimalTPCTest {
|
||||
device,
|
||||
TestUtils.createDeviceStatus(UCentralConstants.BANDS)
|
||||
);
|
||||
dataModel4.latestState.put(
|
||||
dataModel4.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid,
|
||||
DEFAULT_CHANNEL_2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
dummyBssid
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,13 +92,15 @@ public class MeasurementBasedApApTPCTest {
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
String device = devices.get(i);
|
||||
String bssid = bssids.get(i);
|
||||
model.latestState.put(
|
||||
model.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
channel,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
channel,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid
|
||||
)
|
||||
)
|
||||
);
|
||||
model.latestDeviceStatusRadios.put(
|
||||
@@ -130,17 +132,19 @@ public class MeasurementBasedApApTPCTest {
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
String device = devices.get(i);
|
||||
String bssid = bssids.get(i);
|
||||
model.latestState.put(
|
||||
model.latestStates.put(
|
||||
device,
|
||||
TestUtils.createState(
|
||||
channel2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid,
|
||||
channel5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
channel2G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid,
|
||||
channel5G,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
bssid
|
||||
)
|
||||
)
|
||||
);
|
||||
model.latestDeviceStatusRadios.put(
|
||||
@@ -569,13 +573,15 @@ public class MeasurementBasedApApTPCTest {
|
||||
);
|
||||
|
||||
// now test when device C does not have a 5G radio
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
DEVICE_C,
|
||||
TestUtils.createState(
|
||||
1,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
BSSID_C
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
1,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
MAX_TX_POWER,
|
||||
BSSID_C
|
||||
)
|
||||
)
|
||||
);
|
||||
dataModel.latestDeviceStatusRadios.put(
|
||||
|
||||
@@ -55,25 +55,41 @@ public class MeasurementBasedApClientTPCTest {
|
||||
);
|
||||
|
||||
DataModel dataModel = new DataModel();
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(36, 20, 20, "", new int[] { -65 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 20, "", new int[] { -65 })
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(36, 40, 21, null, new int[] { -65, -73, -58 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
36,
|
||||
40,
|
||||
21,
|
||||
null,
|
||||
new int[] { -65, -73, -58 }
|
||||
)
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceD,
|
||||
TestUtils.createState(36, 20, 22, null, new int[] { -80 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 22, null, new int[] { -80 })
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceE,
|
||||
TestUtils.createState(36, 20, 23, null, new int[] { -45 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 23, null, new int[] { -45 })
|
||||
)
|
||||
);
|
||||
|
||||
TPC optimizer = new MeasurementBasedApClientTPC(
|
||||
@@ -136,35 +152,41 @@ public class MeasurementBasedApClientTPCTest {
|
||||
|
||||
DataModel dataModel = new DataModel();
|
||||
// 2G only
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(1, 20, 20, null, new int[] {})
|
||||
Arrays.asList(
|
||||
TestUtils.createState(1, 20, 20, null, new int[] {})
|
||||
)
|
||||
);
|
||||
// 5G only
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
)
|
||||
);
|
||||
// 2G and 5G
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(
|
||||
1,
|
||||
20,
|
||||
20,
|
||||
null,
|
||||
new int[] {},
|
||||
36,
|
||||
20,
|
||||
20,
|
||||
null,
|
||||
new int[] {}
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
1,
|
||||
20,
|
||||
20,
|
||||
null,
|
||||
36,
|
||||
20,
|
||||
20,
|
||||
null
|
||||
)
|
||||
)
|
||||
);
|
||||
// No valid bands in 2G or 5G
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceD,
|
||||
TestUtils.createState(25, 20, 20, null, new int[] {})
|
||||
Arrays.asList(
|
||||
TestUtils.createState(25, 20, 20, null, new int[] {})
|
||||
)
|
||||
);
|
||||
|
||||
TPC optimizer = new MeasurementBasedApClientTPC(
|
||||
@@ -220,17 +242,29 @@ public class MeasurementBasedApClientTPCTest {
|
||||
deviceDataManager.setDeviceLayeredConfig(deviceLayeredConfig);
|
||||
|
||||
DataModel dataModel = new DataModel();
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceA,
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 20, null, new int[] {})
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceB,
|
||||
TestUtils.createState(36, 20, 20, "", new int[] { -65 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(36, 20, 20, "", new int[] { -65 })
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
deviceC,
|
||||
TestUtils.createState(36, 40, 21, null, new int[] { -65, -73, -58 })
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
36,
|
||||
40,
|
||||
21,
|
||||
null,
|
||||
new int[] { -65, -73, -58 }
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
TPC optimizer = new MeasurementBasedApClientTPC(
|
||||
|
||||
@@ -63,26 +63,30 @@ public class RandomTxPowerInitializerTest {
|
||||
*/
|
||||
private static DataModel createModel() {
|
||||
DataModel dataModel = new DataModel();
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
DEVICE_A,
|
||||
TestUtils.createState(
|
||||
36,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_A,
|
||||
2,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_A
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
36,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_A,
|
||||
2,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_A
|
||||
)
|
||||
)
|
||||
);
|
||||
dataModel.latestState.put(
|
||||
dataModel.latestStates.put(
|
||||
DEVICE_B,
|
||||
TestUtils.createState(
|
||||
2,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_B
|
||||
Arrays.asList(
|
||||
TestUtils.createState(
|
||||
2,
|
||||
DEFAULT_CHANNEL_WIDTH,
|
||||
DEFAULT_TX_POWER,
|
||||
BSSID_B
|
||||
)
|
||||
)
|
||||
);
|
||||
return dataModel;
|
||||
|
||||
Reference in New Issue
Block a user