/// <summary> /// A client calls this method to start a new sniffer measurement at the specified location (with the specified start time). /// </summary> /// <param name="clientMac">The client requesting the sniffer measurement</param> /// <param name="vertexId">The id of the vertex where the user is located</param> /// <param name="startMeasTime">The start time of the measurement (as specified by the user)</param> private bool StartMeasuring(string clientMac, Vertex vertex) { if (clientMac == null || vertex == null) { return(false); } if (context == null || LoadedBuildings == null) { LoadRadioMap(); //Ja, eller bare opdater det lokale radio map hver gang en bruger foretager en maaling return(false); } //Create new sniffer measurement SnifferWifiMeasurement newMeas = new SnifferWifiMeasurement(); newMeas.meas_time_start = DateTime.Now; //Add sniffer-meas to vertex vertex.SnifferWifiMeasurements.Add(newMeas); newMeas.Vertex = vertex; //Add measurement to 'currently building' datastructures. currentOfflineMeasurements.TryAdd(clientMac, newMeas); currentMeasuringClients.TryAdd(clientMac, vertex); return(true); }
private static Building getNearestAPMatchBuilding(SnifferWifiMeasurement meas) { if (LoadedBuildings == null) { return(null); } if (meas == null) { return(null); } Building bestMatch = null; //find best match by matching number of common APs int maxCommonAPs = 0; foreach (Building curBuilding in LoadedBuildings) { int commonAPs = getNumberOfIdenticalMacs(meas.getMACs(), curBuilding); if (commonAPs > maxCommonAPs) { maxCommonAPs = commonAPs; bestMatch = curBuilding; } } return(bestMatch); }
public static bool containsMac(this SnifferWifiMeasurement source, string mac) { foreach (SnifferHistogram h in source.SnifferHistograms) { if (h.Mac.Equals(mac)) { return(true); } } return(false); }
public static List <string> getMACs(this SnifferWifiMeasurement source) { List <String> result = new List <string>(); foreach (SnifferHistogram h in source.SnifferHistograms) { if (!result.Contains(h.Mac)) { result.Add(h.Mac); } } return(result); }
/// <summary> /// A sniffer entry (sniffer-mac, client-mac, rssi, and time) is added to currently built measurements. /// The procedures is the same for online and offline measurements - the only difference is that we do not track changes to /// online measurements as we are not interested in saving them persistently (at least not at the present time) /// </summary> /// <param name="snifferMac">The sniffer's mac address</param> /// <param name="clientMac">The client's mac adress</param> /// <param name="rssi">The client's rssi as measured by the sniffer</param> /// <param name="mode">'Offline' or 'Online' to help distinguish whether we want to save the data persistently</param> /// <param name="time">The time the sniffer entry was made. </param> private static void addToMeasurement(string snifferMac, string clientMac, int rssi, DateTime time) { Mode mode; //First, determine the mode. if (currentOfflineMeasurements.ContainsKey(clientMac)) { mode = Mode.Offline; } else if (currentOnlineMeasurements.ContainsKey(clientMac)) { mode = Mode.Online; } else { return; //Unknown client mac } ConcurrentDictionary <string, SnifferWifiMeasurement> dic = getMeasurementDictionary(mode); SnifferWifiMeasurement curWifiMeasurement = dic[clientMac]; //Update end meas time (even more may come..) curWifiMeasurement.meas_time_end = time; //Add or update histogram with snifferMac, rssi value SnifferHistogram curHist = curWifiMeasurement.SnifferHistograms.FirstOrDefault(h => h.Mac == snifferMac && h.value == rssi); if (curHist == null) //insert new histogram { curHist = new SnifferHistogram(); curHist.Mac = snifferMac; curHist.value = rssi; curHist.count = 0; curWifiMeasurement.SnifferHistograms.Add(curHist); curHist.SnifferWifiMeasurement = curWifiMeasurement; if (mode == Mode.Offline) { context.AddRelatedObject(curWifiMeasurement, "SnifferHistograms", curHist); } } curHist.count++; //yet another count for this rssi value //In the offline mode we actually save the data. if (mode == Mode.Offline) { context.UpdateObject(curWifiMeasurement); context.UpdateObject(curHist); } }
//We are not too concerned with decimal numbers, so we return the avg as an int //(Moreover, this is a legacy from the WinMobile client and the Streamspin server) public static double getAvgDbM(this SnifferWifiMeasurement source, string mac) { int totalVal = 0; int totalCount = 0; //the total number of distinct values //calculate the total foreach (SnifferHistogram sniff in source.SnifferHistograms) { if (sniff.Mac == mac) { totalVal += sniff.value * sniff.count; totalCount += sniff.count; } } return(totalVal / totalCount); }
public EstimateResult compare(IEnumerable <Vertex> vertices, SnifferWifiMeasurement measurement) { measurement = getNStrongestAPMeasurement(measurement, 7); if (vertices == null || measurement == null) { return(null); } bcs = WifiPosEngine.BestCandidateSet; //new BCS(5); //bcs.clear(); double curDist; //distance of current vertice in search space EstimateResult result = new EstimateResult(null, double.MaxValue); foreach (Vertex curVertex in vertices) //sammenlign med hver Vertex { foreach (SnifferWifiMeasurement curFP in curVertex.SnifferWifiMeasurements) //sammenlign med hvert fingerprint (usually only one - otherwise use more intelligent approach) { curDist = 0; foreach (String mac in measurement.getMACs()) //all APs in sample { if (curFP.containsMac(mac)) { curDist += Math.Pow((measurement.getAvgDbM(mac) - curFP.getAvgDbM(mac)), 2); } else { curDist += Math.Pow((measurement.getAvgDbM(mac) - MISSING_MAC_PENALTY), 2); } } curDist = Math.Sqrt(curDist); if (curDist < result.getDistance()) { result.setDistance(curDist); result.setVertex(curVertex); } bcs.add(curVertex, curDist); //add to best candidate set - which will take care of only using the best estimates. } } //The following only yields a local error estimate within the primary- or secondary //vertices and may thus not be appropriate result.setErrorEstimate(Math.Ceiling(bcs.getMaxDistance())); return(result); }
//Public visibility so we can test it (directly) via unit tests public static SnifferWifiMeasurement getNStrongestAPMeasurement(SnifferWifiMeasurement measurement, int n) { if (measurement.getMACs().Count < n) { return(measurement); } SortedDictionary <double, String> strongestAPs = new SortedDictionary <double, String>(); //Find the n strongest macs // foreach (String mac in measurement.getMACs()) //all APs in sample { double curMacVal = measurement.getAvgDbM(mac); while (strongestAPs.ContainsKey(curMacVal)) { curMacVal += 0.0001; } strongestAPs.Add(curMacVal, mac); //NB: TreeMap sorts members in ascending order! //Thus, we remove from the head to keep the strongest values if (strongestAPs.Count > n) { strongestAPs.Remove(strongestAPs.First().Key); } } //Create new measurement containing n strongest macs SnifferWifiMeasurement result = new SnifferWifiMeasurement(); foreach (double d in strongestAPs.Keys) { SnifferHistogram h = new SnifferHistogram(); h.Mac = strongestAPs[d]; h.value = (int)d; h.count = 1; result.SnifferHistograms.Add(h); //result.addValue(strongestAPs.get(d), (int)d); } return(result); }
public bool StartWifiPositioning(string clientMac) { if (clientMac == null) { return(false); } //Create new sniffer measurement DateTime time = DateTime.Now; SnifferWifiMeasurement newMeas = new SnifferWifiMeasurement(); newMeas.meas_time_start = DateTime.Now; //Add measurement to 'currently building' datastructures. currentOnlineMeasurements.TryAdd(clientMac, newMeas); //add client to 'currently positioning' and set initial location = null. currentPositioningClients.TryAdd(clientMac, null); //no 'last position' //add engine for user currentWifiPosEngines.TryAdd(clientMac, new WifiPosEngine(null)); //unknown building return(true); }
public void AddToSnifferWifiMeasurements(SnifferWifiMeasurement snifferWifiMeasurement) { base.AddObject("SnifferWifiMeasurements", snifferWifiMeasurement); }
public static SnifferWifiMeasurement CreateSnifferWifiMeasurement(int ID, int vertex_ID) { SnifferWifiMeasurement snifferWifiMeasurement = new SnifferWifiMeasurement(); snifferWifiMeasurement.ID = ID; snifferWifiMeasurement.Vertex_ID = vertex_ID; return snifferWifiMeasurement; }
public int SaveMeasurement(string clientMac) { const int error = -1; int result = error; //change if success if (clientMac == null) { return(error); } if (!(savedMeasuringClients.ContainsKey(clientMac) && savedOfflineMeasurements.ContainsKey(clientMac))) { return(error); } //Remove the measurement from from the 'current' list. SnifferWifiMeasurement curWifi = savedOfflineMeasurements[clientMac]; Vertex curVertex = savedMeasuringClients[clientMac]; savedOfflineMeasurements.Remove(clientMac); savedMeasuringClients.Remove(clientMac); Building curBuilding = LoadedBuildings.First(b => b.ID == curVertex.Building_ID); //save changes persistently try { //Notify context about changes radiomapEntities localContext = new radiomapEntities(radiomapUri); if (curVertex.ID <= UNBOUND_ID_STARTVALUE) //unbound location { AbsoluteLocation absLoc = curVertex.AbsoluteLocations.First(); localContext.AttachTo("Buildings", curBuilding); localContext.AddRelatedObject(curBuilding, "Vertices", curVertex); localContext.AddRelatedObject(curVertex, "AbsoluteLocations", absLoc); } else { localContext.AttachTo("Vertices", curVertex); result = curVertex.ID; } localContext.AddRelatedObject(curVertex, "SnifferWifiMeasurements", curWifi); foreach (SnifferHistogram curHist in curWifi.SnifferHistograms) { localContext.AddRelatedObject(curWifi, "SnifferHistograms", curHist); } //save to database DataServiceResponse response = localContext.SaveChanges(SaveChangesOptions.Batch); // Enumerate the returned responses. If a new vertex, add it to the current building and return its id. foreach (ChangeOperationResponse change in response) { // Get the descriptor for the entity. EntityDescriptor descriptor = change.Descriptor as EntityDescriptor; if (descriptor != null) { if (descriptor.Entity is SnifferWifiMeasurement) { //Yes, the measurement got saved Console.WriteLine("Measurement saved."); //dummy statement } else if (descriptor.Entity is Vertex) { Vertex newVertex = descriptor.Entity as Vertex; curBuilding.Vertices.Add(newVertex); result = newVertex.ID; } } } return(result); } catch (DataServiceRequestException) { return(error); } }
private static Building getCorrectBuilding(SnifferWifiMeasurement meas) { //consider strategy pattern return(getNearestAPMatchBuilding(meas)); }
public EstimateResult getEstimate(SnifferWifiMeasurement currentMeasurement) { //Check ready state if (mCurrentBuilding == null) { return(null); } //Maintain primary and secondary search space //Cf OfflineClientPocketPCUF if (secondarySearchSpace == null) { secondarySearchSpace = mCurrentBuilding.Vertices; // mGraph.getVertices(); } EstimateResult primaryEstimate = new EstimateResult(null, Double.MaxValue); EstimateResult secondaryEstimate = new EstimateResult(null, Double.MaxValue); BestCandidateSet = new BCS(5); //candidates are added in the compare methods below //measurement is compared with primary search space (adjacent vertices to previous estimated vertex) //and secondary search space (non-connected nodes or the full graph) if (prevBestEstimateVertex != null) { primaryEstimate = mPosAlgorithm.compare(prevBestEstimateVertex.adjacentVertices(), currentMeasurement); } secondaryEstimate = mPosAlgorithm.compare(secondarySearchSpace, currentMeasurement); //Changed to accomodate hyper, where we return null if online meas only has one mac //Vertex best = null; EstimateResult bestEstimate = null; if (primaryEstimate != null) { bestEstimate = primaryEstimate; } if (secondaryEstimate != null) { //The primary estimate may be overriden by a secondary if it is better for the second time in a row if (secondaryEstimate.getDistance() < primaryEstimate.getDistance()) { numSecondaryBest++; if (numSecondaryBest >= 2 || prevBestEstimateVertex == null) { numSecondaryBest = 0; bestEstimate = secondaryEstimate; //.getVertex(); } } else { numSecondaryBest = 0; } } prevBestEstimateVertex = bestEstimate.getVertex(); //Currently, the error estimate is also calculated in the compare methods, //but we override that logic here since this implementation considers the global //candidates - not just the local primary- or secondary candidates. //We throw in an extra 5 meters to account for movement double error = Math.Ceiling(BestCandidateSet.getMaxDistance()); // + 5; bestEstimate.setErrorEstimate(error); return(bestEstimate); }