owlps/GuiNuMo-server/server.cc

748 lines
20 KiB
C++

#include "server.hh"
/* Misc. very usefull functions */
/* Explodes a string into substrings based on separator sep. Returns a string vector. */
inline vector<string> explode(string input, char sep)
{
vector<string> vs;
string tmp;
unsigned int i;
for (i = 0 ; i < input.size() ; i++)
if (input[i] == sep)
{
vs.push_back(tmp);
tmp.clear();
}
else
{
tmp.push_back(input[i]);
}
//Last entry, did not encounter a separator.
vs.push_back(tmp);
tmp.clear();
return vs;
}
/* Function to convert a string to an integer */
inline int string2int(string nb)
{
istringstream iss(nb);
int tmp;
iss >> tmp;
return tmp;
}
/* Function to convert a string to an unsigned integer */
inline unsigned int string2uint(string nb)
{
istringstream iss(nb);
unsigned int tmp;
iss >> tmp;
return tmp;
}
/* Function to convert a string to a float */
inline float string2float(string nb)
{
istringstream iss(nb);
float tmp;
iss >> tmp;
return tmp;
}
/* Function extracts ints from string */
inline vector<int> extractValues(string buff)
{
unsigned int ptr = 0;
vector<int> ret;
string tmp_field;
if (buff[buff.size()-1] != ';')
buff.push_back(';');
while (ptr < buff.size())
{
if (buff[ptr] != ';')
tmp_field.push_back(buff[ptr]);
else
{
ret.push_back(string2int(tmp_field));
tmp_field.clear();
}
ptr++;
}
return ret;
}
inline vector<string> extractReferencePointInfoFromBuffer(string buffer_in)
{
unsigned int i = 0;
string tmp_field;
vector<string> ret;
/* Extract coordinates */
/* x */
while (buffer_in[i] != ';')
{
tmp_field.push_back(buffer_in[i]);
i++;
}
ret.push_back(tmp_field);
tmp_field.clear();
i++; //go after the ';'
/* y */
while (buffer_in[i] != ';')
{
tmp_field.push_back(buffer_in[i]);
i++;
}
ret.push_back(tmp_field);
tmp_field.clear();
i++;
/* Extract direction (not used now) */
while (buffer_in[i] != ';')
{
tmp_field.push_back(buffer_in[i]);
i++;
}
ret.push_back(tmp_field);
tmp_field.clear();
i++;
/* Extract mac address */
while (buffer_in[i] != ';')
{
tmp_field.push_back(buffer_in[i]);
i++;
}
ret.push_back(tmp_field);
tmp_field.clear();
i++;
/* Extract scan list */
while (i < buffer_in.size())
{
tmp_field.push_back(buffer_in[i]);
i++;
}
ret.push_back(tmp_field);
tmp_field.clear();
/* Return the vector with each data */
return ret;
}
/* ***************************************************************** */
//Server::Server(string ip_addr, int listen_port, int send_port) // FIXME : paramètre send_port inutilisé
Server::Server(string ip_addr, int listen_port)
{
/* Open socket */
sockListen = socket(PF_INET, SOCK_DGRAM, 0);
sockSend = socket(PF_INET, SOCK_DGRAM, 0);
/* Set addr */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(listen_port);
server_addr.sin_addr.s_addr = inet_addr(ip_addr.c_str());
memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
/* Bind */
bind(sockListen, (struct sockaddr *)&server_addr, sizeof(server_addr));
}
Server::~Server()
{
client_list.clear();
reference_point_list.clear();
access_point_list.clear();
close(sockListen);
close(sockSend);
}
void Server::send_to_client(int cl)
{
/* Do not forget to implement later: usefull for a demo */
}
int Server::receive_data()
{
/* Do not forget to implement later: usefull for a demo */
return 0;
}
bool Server::pointExists(float x, float y, float z)const
{
Point p(x, y, z);
unsigned int i;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (p == reference_point_list[i].getCoordinates())
return true;
return false;
}
/* Do not forget to call pointExists() before this one */
unsigned int Server::pointIndex(float x, float y, float z)const
{
Point p(x, y, z);
unsigned int i;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (p == reference_point_list[i].getCoordinates())
return i;
return 0; // Should never happen
}
bool Server::pointExists(Point p)const
{
unsigned int i;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (p == reference_point_list[i].getCoordinates())
return true;
return false;
}
bool Server::apExists(string ap_addr)const
{
unsigned int i;
for (i = 0 ; i < access_point_list.size() ; i++)
if (access_point_list[i].getApAddr() == ap_addr)
return true;
return false;
}
unsigned int Server::apIndex(string ap_addr)const
{
unsigned int i;
for (i = 0 ; i < access_point_list.size() ; i++)
if (access_point_list[i].getApAddr() == ap_addr)
return i;
return 0; // Should never happen
}
/* Do not forget to call pointExists() before this one */
unsigned int Server::pointIndex(Point p)const
{
unsigned int i;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (p == reference_point_list[i].getCoordinates())
return i;
return 0; // Should never happen
}
/* return -1 if point does not exist, which should never happen */
vector<Point> Server::getkClosestInSs(vector<Measurement> m, unsigned int k, bool ignore_point, Point point_ignored)const
{
unsigned int i, j, min_idx;
vector<float> distances_vector;
vector<Point> points_vector;
Point tmp_pt;
float tmp_distance = 0, dist_max = 10000000, tmp_min;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (!ignore_point||(reference_point_list[i].getCoordinates() != point_ignored))
{
tmp_distance = reference_point_list[i].getSsSquareDistance(m);
/* if not k points, add it */
if(distances_vector.size() < k)
{
distances_vector.push_back(tmp_distance);
points_vector.push_back(reference_point_list[i].getCoordinates());
dist_max = (dist_max > tmp_distance)?tmp_distance:dist_max;
}
else
{
/* if tmp_dst < dist_max, should add it and remove previous greatest dist. */
if(dist_max > tmp_distance)
{
/* remove old max */
for (j = 0 ; j < distances_vector.size() ; j++)
if (distances_vector[j] == dist_max)
{
dist_max = tmp_distance;
distances_vector.erase(distances_vector.begin() + j);
points_vector.erase(points_vector.begin() + j);
distances_vector.push_back(tmp_distance);
points_vector.push_back(reference_point_list[i].getCoordinates());
break;
}
}
/* Else nothing needs to be done */
}
}
/* Sorts the vector */
for (i = 0 ; i < distances_vector.size() - 1 ; i++)
{
tmp_min = distances_vector[i];
min_idx = i;
for (j = i+1 ; j < distances_vector.size() ; j++)
if (tmp_min > distances_vector[j])
{
tmp_min = distances_vector[j];
min_idx = j;
}
if (min_idx != i)
{
/* Swap points */
tmp_pt = points_vector[i];
points_vector[i] = points_vector[min_idx];
points_vector[min_idx] = tmp_pt;
/* Swap distances */
distances_vector[min_idx] = distances_vector[i];
distances_vector[i] = tmp_min;
}
}
return points_vector;
}
Point Server::getkWeightedInSs(vector<Measurement> m, unsigned int k, bool ignore_point, Point point_ignored)const
{
unsigned int i, j;
vector<float> distances_vector;
vector<Point> points_vector;
float tmp_distance = 0, dist_max = 10000000;
Point ret;
float total = 0, x = 0, y = 0, z = 0;
for (i = 0 ; i < reference_point_list.size() ; i++)
if (!ignore_point || (reference_point_list[i].getCoordinates() != point_ignored))
{
tmp_distance = reference_point_list[i].getSsSquareDistance(m);
/* if not k points, add it */
if (distances_vector.size() < k)
{
distances_vector.push_back(tmp_distance);
points_vector.push_back(reference_point_list[i].getCoordinates());
dist_max = (dist_max > tmp_distance) ? tmp_distance : dist_max;
}
else
{
/* if tmp_dst < dist_max, should add it and remove previous greatest dist. */
if (dist_max > tmp_distance)
{
/* remove old max */
for (j = 0 ; j < distances_vector.size() ; j++)
if(distances_vector[j] == dist_max)
{
dist_max = tmp_distance;
distances_vector.erase(distances_vector.begin() + j);
points_vector.erase(points_vector.begin() + j);
distances_vector.push_back(tmp_distance);
points_vector.push_back(reference_point_list[i].getCoordinates());
break;
}
}
/* Else nothing needs to be done */
}
}
for (i = 0 ; i < distances_vector.size() ; i++)
total += distances_vector[i];
for (i = 0 ; i < distances_vector.size() ; i++)
{
x += points_vector[i].getX() * distances_vector[i] / total;
y += points_vector[i].getY() * distances_vector[i] / total;
z += points_vector[i].getZ() * distances_vector[i] / total;
}
ret.setX(x);
ret.setY(y);
ret.setZ(z);
return ret;
}
Point Server::kPointsAverage(vector<Point> vp)const
{
unsigned int i;
float x=0, y=0, z=0;
Point p;
for (i = 0 ; i < vp.size() ; i++)
{
x += vp[i].getX();
y += vp[i].getY();
z += vp[i].getZ();
}
p.setX(x / (float) vp.size());
p.setY(y / (float) vp.size());
p.setZ(z / (float) vp.size());
return p;
}
Point Server::fbcm(vector<Measurement> m, int client_idx)const
{
Point ret(0, 0, 0);
vector<string> addr;
vector<float> dist_vect;
vector<Point> centres;
unsigned int i, ap_idx;
float constant_term, minmax_res, minmax_max;
float x = MINMAX_X_START, y = MINMAX_Y_START;
i = 0;
//cout << "FBCM: ";
for (i = 0 ; i < m.size() ; i++)
if (apExists(m[i].getMacAddr()))
{
ap_idx = apIndex(m[i].getMacAddr());
//cout << "AP idx: " << ap_idx << " ";
centres.push_back(access_point_list[ap_idx].getCoordinates());
addr.push_back(m[i].getMacAddr());
constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2;
constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI));
//end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2.
//cout << "20log(" << (300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI) << ") = ";
//cout << constant_term << " ";
dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / (10 * access_point_list[ap_idx].getFriisIndex())));
//cout << endl;
}
/* Then: min-max */
minmax_res = 1000000;
for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP)
for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP)
{
minmax_max = 0;
for (i = 0 ; i < centres.size() ; i++)
if ((centres[i].squareDistance(x, y, 3) - (dist_vect[i]*dist_vect[i])) > minmax_max)
minmax_max = centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i]);
if (minmax_max < minmax_res)
{
ret.setX(x);
ret.setY(y);
minmax_res = minmax_max;
}
}
/* Clear all vectors */
addr.clear();
dist_vect.clear();
centres.clear();
/* Return position */
return ret;
}
Point Server::interlink(vector<Measurement> m, int client_idx)const
{
Point ret(0, 0, 0);
vector<string> addr;
vector<float> dist_vect;
vector<Point> centres;
unsigned int i, ap_idx;
float constant_term, minmax_res, minmax_max;
float x = MINMAX_X_START, y = MINMAX_Y_START;
i = 0;
for (i = 0 ; i < m.size() ; i++)
if (apExists(m[i].getMacAddr()))
{
ap_idx = apIndex(m[i].getMacAddr());
centres.push_back(access_point_list[ap_idx].getCoordinates());
addr.push_back(m[i].getMacAddr());
constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain();
constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)) + 2;
//end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2.
dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / 35));
}
/* Then: min-max */
minmax_res = 1000000;
for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP)
for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP)
{
minmax_max = 0;
for (i = 0 ; i < centres.size() ; i++)
if ((centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i])) > minmax_max)
minmax_max = centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i]) ;
if (minmax_max < minmax_res)
{
ret.setX(x);
ret.setY(y);
minmax_res = minmax_max;
}
}
/* Clear all vectors */
addr.clear();
dist_vect.clear();
centres.clear();
/* Return position */
return ret;
}
void Server::makeReferencePointListFromFile(string filename)
{
ifstream input_file;
char buffer[BUFFER_LENGTH];
string lecture_fichier;
ReferencePoint rp;
Point tmp_point;
float x, y;
unsigned int i, pt_idx;
string cpp_buffer, tmp_mes;
vector<int> measures_vector;
vector<string> infos;
input_file.open(filename.c_str()) ;
if (input_file.fail())
{
cerr << "Error opening input file « " << filename << " » !" << endl ;
return ;
}
while (!input_file.eof())
{
input_file.getline(buffer, BUFFER_LENGTH);
if ((input_file.rdstate() & ifstream::eofbit) == 0)
{
/* Extract fields */
cpp_buffer = buffer;
infos = extractReferencePointInfoFromBuffer(cpp_buffer);
x = string2float(infos[0]);
y = string2float(infos[1]);
/* Set point coordinates */
tmp_point.setX(x);
tmp_point.setY(y);
tmp_point.setZ(DEFAULT_Z);
/* Use C++ string format */
if (!pointExists(tmp_point))
{
rp.setCoordinates(tmp_point);
reference_point_list.push_back(rp);
}
pt_idx = pointIndex(tmp_point);
measures_vector = extractValues(infos[4]);
for (i = 0 ; i < measures_vector.size() ; i++)
reference_point_list[pt_idx].addMeasurement(infos[3], measures_vector[i]);
}
}
input_file.close();
measures_vector.clear();
}
void Server::makeApListFromFile(string filename)
{
ifstream input_file;
char buffer[BUFFER_LENGTH];
vector<string> ap_infos;
AccessPoint tmp_ap;
input_file.open(filename.c_str());
if (input_file.fail())
{
cerr << "Error opening input file « " << filename << " » !" << endl ;
return ;
}
while (!input_file.eof())
{
input_file.getline(buffer, BUFFER_LENGTH);
if ((input_file.rdstate() & ifstream::eofbit) == 0)
{
ap_infos = explode(buffer, ';');
cout << buffer << endl;
for (unsigned int i=0 ; i < ap_infos.size() ; i++)
cout << ap_infos[i] << endl;
tmp_ap.setApAddr(ap_infos[0]);
tmp_ap.setCoordinates(string2float(ap_infos[1]), string2float(ap_infos[2]), string2float(ap_infos[3]));
tmp_ap.setFrequency(string2uint(ap_infos[4]));
tmp_ap.setAntennaGain(string2float(ap_infos[5]));
tmp_ap.setOutputPower(string2float(ap_infos[6]));
access_point_list.push_back(tmp_ap);
ap_infos.clear();
}
}
input_file.close();
}
void Server::printReferencePointList()
{
unsigned int i;
for (i = 0 ; i < reference_point_list.size() ; i++)
cout << reference_point_list[i] << endl;
}
void Server::printAccessPointList()
{
unsigned int i;
for (i = 0 ; i < access_point_list.size() ; i++)
cout << access_point_list[i] << endl;
}
void Server::computeFriisFromRefList()
{
unsigned int i, j;
vector<float> friis_idx_list;
Point pt_coords, ap_coords;
float ap_power, ap_gain, calib_gain = 2, const_term, mes_power, friis_sum;
unsigned int ap_freq;
string ap_mac;
for (i = 0 ; i < access_point_list.size() ; i++)
{
ap_power = access_point_list[i].getOutputPower();
ap_coords = access_point_list[i].getCoordinates();
ap_freq = access_point_list[i].getFrequency();
ap_gain = access_point_list[i].getAntennaGain();
ap_mac = access_point_list[i].getApAddr();
/* Compute main general term, independant from scans */
const_term = calib_gain + ap_gain;
const_term -= 20 * log10(4 * M_PI);
const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power;
/* Compute an index for each ref point. List stored in friis_idx_list */
for (j = 0 ; j < reference_point_list.size() ; j++)
{
pt_coords = reference_point_list[j].getCoordinates();
if (reference_point_list[i].getPowerForAp(ap_mac, &mes_power))
friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords))));
}
/* Now, compute avg value */
friis_sum = 0;
for (j = 0 ; j < friis_idx_list.size() ; j++)
friis_sum += friis_idx_list[j];
access_point_list[i].setFriisIndex(friis_sum / friis_idx_list.size());
cout << access_point_list[i].getApAddr() << " -> " << (friis_sum / friis_idx_list.size()) << endl;
friis_idx_list.clear();
}
}
/*
* Function computes new cumulative distances for each running viterbi instance,
* Returns the solution (type: Point) of the last ended viterbi.
* Distances are grouped by line corresponding to an instance.
* vk MUST be the same as last.size() and current.size() !
*/
/*
Point Server::viterbiLike(float ** dists, unsigned short vk, unsigned short vn, vector<Point> last, vector<Point> current)
{
unsigned int i, j, k;
float min;
vector<float> last_dists;
Point position;
// Compute the ending viterbi: line 0
for (i = 0 ; i < current.size() ; i++)
{
min = dists[0][0] + last[0].distance(current[i]);
for (j = 1 ; j < last.size() ; j++)
if ((dists[0][j] + last[j].distance(current[i])) < min)
min = dists[0][j] + last[j].distance(current[i]);
last_dists.push_back(min);
}
// Find shortest dist
min = last_dists[0];
j = 0;
for (i = 1 ; i < last_dists.size() ; i++)
if (last_dists[i] < min)
{
min = last_dists[i];
j = i;
}
// Shortest distance determines the true point
position = current[j];
// Now, compute the remaining of the distance matrix
}
*/
/* For experimentation purpose only */
void Server::radar_exp()
{
ofstream logfile;
vector<Point> solutions;
Point solution, solution_kw, ref_coords;
unsigned int i;
vector<Measurement> vm;
makeReferencePointListFromFile(DEFAULT_REF_POINT_FILE);
makeApListFromFile(DEFAULT_AP_FILE);
computeFriisFromRefList();
/* Open a log file */
logfile.open(DEFAULT_LOGFILE);
if (logfile.fail())
{
cerr << "Error opening output file « " << logfile << " » !" << endl ;
return ;
}
/* Column names */
logfile << "Coordinates\t2-kss\t(Error)\t3-kss\t(Error)\t4-kss\t(Error)\t5-kss\t(Error)\tnss\t(Error)\tInterlink\t(Error)\tFBCM\t(Error)" << endl;
cout << reference_point_list.size() << " reference points." << endl ;
for (i = 0 ; i < reference_point_list.size() ; i++)
{
/* Get point measurements */
vm.clear();
vm = reference_point_list[i].getMeasurementList();
ref_coords = reference_point_list[i].getCoordinates();
/* Print point coordinates */
logfile << ref_coords << "\t";
/* From 2 to 5 K-weighted-SS */
solution = getkWeightedInSs(vm, 2, true, ref_coords);
logfile << solution << "\t" << solution.distance(ref_coords) << "\t";
solution = getkWeightedInSs(vm, 3, true, ref_coords);
logfile << solution << "\t" << solution.distance(ref_coords) << "\t";
solution = getkWeightedInSs(vm, 4, true, ref_coords);
logfile << solution << "\t" << solution.distance(ref_coords) << "\t";
solution = getkWeightedInSs(vm, 5, true, ref_coords);
logfile << solution << "\t" << solution.distance(ref_coords) << "\t";
/* Nearest in SS */
solutions = getkClosestInSs(vm, 1, true, ref_coords);
logfile << solutions[0] << "\t" << solutions[0].distance(ref_coords) << "\t";
/* Interlink Networks */
solution = interlink(vm, 0);
logfile << solution << "\t" << solution.distance(ref_coords) << "\t";
/* FBCM */
solution = fbcm(vm, 0);
logfile << solution << "\t" << solution.distance(ref_coords) << endl;
solutions.clear();
}
logfile.close();
}