#include "server.hh" /* Misc. very usefull functions */ /* Explodes a string into substrings based on separator sep. Returns a string vector. */ inline vector explode(string input, char sep) { vector 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 extractValues(string buff) { unsigned int ptr = 0; vector 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 extractReferencePointInfoFromBuffer(string buffer_in) { unsigned int i = 0; string tmp_field; vector 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 Server::getkClosestInSs(vector m, unsigned int k, bool ignore_point, Point point_ignored)const { unsigned int i, j, min_idx; vector distances_vector; vector 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 m, unsigned int k, bool ignore_point, Point point_ignored)const { unsigned int i, j; vector distances_vector; vector 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 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 m, int client_idx)const { Point ret(0, 0, 0); vector addr; vector dist_vect; vector 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 m, int client_idx)const { Point ret(0, 0, 0); vector addr; vector dist_vect; vector 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 measures_vector; vector 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 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 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 last, vector current) { unsigned int i, j, k; float min; vector 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 solutions; Point solution, solution_kw, ref_coords; unsigned int i; vector 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(); }