#include "server.hh" /******* Misc. very usefull functions *******/ /* Retourne la position du Point "p" dans le tableau "tab" de taille "size", ou -1 en cas d'échec. */ inline int point_tab_idx(const Point *tab, unsigned int &size, const Point &p) { for (unsigned int i = 0 ; i < size ; i++) if (tab[i] == p) return i ; return -1 ; } /* Retourne la position du Point "p" dans le vector "v", ou -1 en cas d'échec. */ inline int point_vector_idx(const vector &v, const Point &p) { for (unsigned int i = 0 ; i < v.size() ; i++) if (v[i] == p) return i ; return -1 ; } /* Explodes a string into substrings based on separator sep. Returns a string vector. */ inline vector explode(const string &input, const 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(const string &nb) { istringstream iss(nb); int tmp; iss >> tmp; return tmp; } /* Function to convert a string to an unsigned integer */ inline unsigned int string2uint(const string &nb) { istringstream iss(nb); unsigned int tmp; iss >> tmp; return tmp; } /* Function to convert a string to a float */ inline float string2float(const 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(const 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++; #ifndef FRED_CSV_FORMAT // Dans le format Fred, on n'a pas de coordonnée Z. /* z */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; #endif // FRED_CSV_FORMAT /* 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++; #ifdef FRED_CSV_FORMAT /* 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(); #else // FRED_CSV_FORMAT while (i <= buffer_in.size()) { if ((buffer_in[i] == ';' || i == buffer_in.size()) && !tmp_field.empty()) // Si on est sur un séparateur et que la valeur lue n'est pas vide, { #ifdef DEBUG_2 cout << "Ajout de la valeur lue : " << tmp_field << endl ; #endif // DEBUG_2 ret.push_back(tmp_field) ; // on met la valeur lue dans les valeurs de retour. tmp_field.clear() ; } else // Si on n'est pas sur un séparateur, tmp_field.push_back(buffer_in[i]) ; // on ajoute le caractère courant à la suite de la valeur lue. i++ ; } #endif // FRED_CSV_FORMAT /* 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(const string &ip_addr, const int &listen_port) { #ifdef DEBUG_T cout << "//--> Server::Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* 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)); makeReferencePointListFromFile(DEFAULT_REF_POINT_FILE) ; // Initialisation de "reference_point_list". makeApListFromFile(DEFAULT_AP_FILE) ; // Initialisation de "access_point_list". makeTopologyFromFile(DEFAULT_TOPOLOGY_FILE) ; // Initialisation de "area_list". makeWaypointListFromFile(DEFAULT_WAYPOINT_FILE) ; // Initialisation de "waypoint_list" et "waypoint_matrix". makeReferencePointDistances() ; // Initialisation de "reference_point_matrix". #ifdef DEBUG_T cout << "//<-- Server::Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T } Server::~Server() { #ifdef DEBUG_T cout << "//--> Server::~Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T close(sockListen); close(sockSend); reference_point_list.clear(); access_point_list.clear(); client_list.clear(); #ifdef DEBUG_T cout << "//<-- Server::~Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::send_to_client(const 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; } /* Cherche dans quelle(s) zone(s) se situe un point. * Retourne une map contenant la liste des zones auxquelles le Point "p" appartient. */ map Server::inWhichAreas(const Point &p) { #ifdef DEBUG_T cout << "//--> Server::inWhichAreas()" << endl ; fflush(stdout) ; #endif // DEBUG_T map areas ; for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) if (it->second.containsPoint(p)) areas.insert(make_pair(it->first, it->second)) ; #ifdef DEBUG_T cout << "//<-- Server::inWhichAreas()" << endl ; fflush(stdout) ; #endif // DEBUG_T return areas ; } /* Cherche les points de passage communs aux zones "z1" et "z2". * Retourne un vector contenant la liste de ces points. */ vector Server::areaConnection(const Area &z1, const Area &z2) { #ifdef DEBUG_T cout << "//--> Server::areaConnection(Area&, Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T vector points ; for (unsigned int i = 0 ; i < reference_point_list.size() ; i++) { map areas(inWhichAreas(reference_point_list[i])) ; if (areas.find(z1.getName()) != areas.end() && areas.find(z2.getName()) != areas.end()) points.push_back(reference_point_list[i]) ; } #ifdef DEBUG_T cout << "//<-- Server::areaConnection(Area&, Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points ; } /* Cherche les points de passage de la zone "z". * Retourne un vector contenant la liste de ces points. */ vector Server::areaConnection(const Area &z) { #ifdef DEBUG_T cout << "//--> Server::areaConnection(Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T vector points ; for (unsigned int i = 0 ; i < reference_point_list.size() ; i++) { map areas(inWhichAreas(reference_point_list[i])) ; if (areas.find(z.getName()) != areas.end()) points.push_back(reference_point_list[i]) ; } #ifdef DEBUG_T cout << "//<-- Server::areaConnection(Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points ; } /* Calcule la distance entre les points "p1" et "p2" en tenant compte de la topologie. */ float Server::distanceTopology(const Point &p1, const Point &p2) { #ifdef DEBUG_T cout << "//--> Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T map zones1(inWhichAreas(p1)), zones2(inWhichAreas(p2)) ; if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte. } Area z1(zones1.begin()->second), // Première zone d'appartenance du point p1. // FIXME : vérifier toutes les zones z2(zones2.begin()->second) ; vector connection ; /* *** Cas de la même zone *** */ if (z1 == z2) // Si les points sont dans la même zone, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return p1.distance(p2) ; // la distance entre eux est la distance euclidienne. } /* *** Cas de deux zones voisines *** */ if ((connection = areaConnection(z1, z2)).size() != 0) // Si les points sont dans deux zones voisines, { // la distance entre eux est la distance euclidienne de chacun jusqu'au plus proche point de passage entre les deux zones. float dist = p1.distance(connection[0]) + p2.distance(connection[0]) ; for (unsigned int i = 1 ; i < connection.size() ; i++) // Recherche du point de passage offrant la plus courte distance { float tmp_dist = p1.distance(connection[i]) + p2.distance(connection[i]) ; if (tmp_dist < dist) dist = tmp_dist ; } #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return dist ; } /* *** Les points sont dans des zones non-voisines *** */ vector // Liste des points de passage appartenant respectivement à z1 et à z2. wp_z1(areaConnection(z1)), wp_z2(areaConnection(z2)) ; int // Indices des points de passage dans la liste : wp_z1_idx, wp_z2_idx = -1 ; // z2 ne peut pas être utilisé non initialisé, contrairement à ce que dit GCC, car dans le cas où il n'est pas initialisé on quitte la fonction avant de l'utiliser (cf. "return -1" un peu plus bas); if (wp_z1.size() == 0 || wp_z2.size() == 0) // Si l'une des deux zones ne comporte aucun point de passage, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte (ceci ne devrait jamais se produire). } /* Première itération (voir explication de l'algorithme plus bas) */ unsigned int i1, i2 ; for (i1 = 0 ; i1 < wp_z1.size() ; i1++) // Recherche des premiers indices valides (où il existe un chemin entre les points de passage) { wp_z1_idx = point_vector_idx(waypoint_list, wp_z1[i1]) ; for (i2 = 0 ; i2 < wp_z2.size() ; i2++) { wp_z2_idx = point_vector_idx(waypoint_list, wp_z2[i2]) ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, break ; // on arrête le parcours. } if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, break ; // on arrête le parcours. } if (i1 >= wp_z1.size()) // Si on a parcouru tout le tableau sans trouver de chemin, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte. } float dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[i2]), tmp_dist ; for (unsigned int j = i2 + 1 ; j < wp_z2.size() ; j++) // Fin du parcours : { wp_z2_idx = point_vector_idx(waypoint_list, wp_z2[j]) ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) continue ; tmp_dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; if (tmp_dist < dist) dist = tmp_dist ; } /* Itérations suivantes */ for (unsigned int i = i1 + 1 ; i < wp_z1.size() ; i++) for (unsigned int j = 0 ; j < wp_z2.size() ; j++) { // Indice des points de passage wp_z1[i] et wp_z2[j] dans la liste des points de passage : wp_z1_idx = point_vector_idx(waypoint_list, wp_z1[i]) ; wp_z2_idx = point_vector_idx(waypoint_list, wp_z2[j]) ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) // S'il n'existe aucun chemin entre les deux points de passage continue ; /* La distance entre p1 et p2 est égale à la somme de : * - la distance entre p1 et le point de passage courant de z1 * (distance cartésienne car ils appartiennent à la même zone), * - la distance entre p2 et le point de passage courant de z2 (idem), * - la distance entre les deux points de passages suscités, qui est * donnée par la matrice des distances entre points de passage * (waypoint_matrix). * On conservera bien sûr la somme qui donne le chemin le plus court. */ tmp_dist = p1.distance(wp_z1[i]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; if (tmp_dist < dist) dist = tmp_dist ; } #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return dist ; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Recherche un point de coordonnées (x;y;z) dans la liste reference_point_list, retourne true s'il existe, false sinon. */ bool Server::pointExists(const float &x, const float &y, const float &z)const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(reference_point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Recherche un Point dans la liste reference_point_list, retourne true s'il existe, false sinon. */ bool Server::pointExists(const Point &p)const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(reference_point_list, p) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Recherche un point de coordonnées (x;y;z) dans la liste "point_list", retourne true s'il existe, false sinon. */ bool Server::pointExists(const vector &point_list, const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Recherche un Point dans la liste "point_list", retourne true s'il existe, false sinon. */ bool Server::pointExists(const vector &point_list, const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; for (i = 0 ; i < point_list.size() ; i++) if (p == point_list[i].getCoordinates()) { #ifdef DEBUG_T cout << "//<-- Server::pointExists(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return true; } #ifdef DEBUG_T cout << "//<-- Server::pointExists(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return false; } /* Do not forget to call pointExists() before this one */ unsigned int Server::pointIndex(const float &x, const float &y, const float &z)const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(reference_point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Do not forget to call pointExists() before this one */ unsigned int Server::pointIndex(const Point &p)const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(reference_point_list, p) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } unsigned int Server::pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } unsigned int Server::pointIndex(const vector &point_list, const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; for (i = 0 ; i < reference_point_list.size() ; i++) if (p == reference_point_list[i].getCoordinates()) { #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return i ; } #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return 0; // Should never happen } bool Server::apExists(const string &ap_addr)const { #ifdef DEBUG_T cout << "//--> Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T string str; for (unsigned int i = 0 ; i < access_point_list.size() ; i++) { str = access_point_list[i].getApAddr() ; const int length = str.length() ; for (int j = 0 ; j < length ; ++j) str[j] = std::tolower(str[j]) ; for (i = 0 ; i < access_point_list.size() ; i++) if (str == ap_addr) { #ifdef DEBUG_T cout << "//<-- Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T return true ; } } #ifdef DEBUG_T cout << "//<-- Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T return false ; } unsigned int Server::apIndex(const string &ap_addr)const { #ifdef DEBUG_T cout << "//--> Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; for (i = 0 ; i < access_point_list.size() ; i++) if (access_point_list[i].getApAddr() == ap_addr) { #ifdef DEBUG_T cout << "//<-- Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T return i; } #ifdef DEBUG_T cout << "//<-- Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T return 0; // Should never happen } /* Selects the "k" closest points from the measurement "m", in the SS space. * Returns an empty vector if no points are found, which should never happen. */ vector Server::getkClosestInSs(const vector &m, const unsigned int &k)const { #ifdef DEBUG_T cout << "//--> Server::getkClosestInSs(&vector, &unsigned int)" << endl ; cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T return getkClosestInSs(m, k, NULL) ; } /* Selects the "k" closest points from the measurement "m", in the SS space. * If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. * Returns an empty vector if no points are found, which should never happen. */ vector Server::getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const { #ifdef DEBUG_T cout << "//--> Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T 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 (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) { tmp_distance = reference_point_list[i].getSsSquareDistance(m); #ifdef DEBUG_2 cout << tmp_distance << " " ; #endif // DEBUG_2 /* 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) { distances_vector[j] = tmp_distance; points_vector[j] = reference_point_list[i].getCoordinates(); break; } /* Now seek the new max. distance */ dist_max = distances_vector[0]; for(j = 1 ; j < distances_vector.size() ; j++) if(distances_vector[j] > dist_max) dist_max = distances_vector[j]; } /* Else nothing needs to be done */ } } #ifdef DEBUG_2 cout << endl ; #endif // DEBUG_2 /* 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; } } #ifdef DEBUG cout << "getkClosestInSs() : Points sélectionnés :" << endl ; if (distances_vector.size() != points_vector.size()) cout << "Erreur ! distances_vector.size()=" << distances_vector.size() << " != points_vector.size()=" << points_vector.size() << endl ; else for (i = 0 ; i < distances_vector.size() - 1 ; i++) cout << distances_vector[i] << " : " << points_vector[i] << endl ; #endif // DEBUG #ifdef DEBUG_T cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points_vector; } Point Server::getkWeightedInSs(const vector &m, const unsigned int &k)const { #ifdef DEBUG_T cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret = getkWeightedInSs(m, k, NULL) ; #ifdef DEBUG_T cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. */ Point Server::getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const { #ifdef DEBUG_T cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T 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 (point_ignored == NULL || (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); #ifdef DEBUG_T cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret; } Point Server::kPointsAverage(const vector &vp)const { #ifdef DEBUG_T cout << "//--> Server::kPointsAverage()" << endl ; fflush(stdout) ; #endif // DEBUG_T 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()); #ifdef DEBUG_T cout << "//<-- Server::kPointsAverage()" << endl ; fflush(stdout) ; #endif // DEBUG_T return p; } Point Server::fbcm(const vector &m, const int &client_idx)const { #ifdef DEBUG_T cout << "//--> Server::fbcm()" << endl ; fflush(stdout) ; #endif // DEBUG_T 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(); #ifdef DEBUG_T cout << "//<-- Server::fbcm()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Return position */ return ret; } /*second version of fbcm with as parameter vector &m and a list of friis index*/ Point Server::fbcm_friis( const vector &m, const vector friis_idx_list)const { #ifdef DEBUG_T cout << "//--> Server::fbcm_friis()" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret(0, 0, 0); vector addr; vector dist_vect; vector centres; unsigned int i, j, 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++){cout<<"m[i].getMacAddr()"< 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(); cout << "RESULTAT DU FRBHM ---> " << ret << endl ; #ifdef DEBUG_T cout << "//<-- Server::fbcm_friis()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Return position */ return ret; } Point Server::interlink(const vector &m, const int &client_idx)const { #ifdef DEBUG_T cout << "//--> Server::interlink()" << endl ; fflush(stdout) ; #endif // DEBUG_T 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; #ifdef DEBUG_T cout << "//<-- Server::interlink()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Crée la liste des points de référence dans la liste reference_point_list. */ void Server::makeReferencePointListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&string)" << endl ; fflush(stdout) ; #endif // DEBUG_T makePointListFromFile(reference_point_list, filename, true) ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&string)" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::makePointListFromFile(vector &dest_point_list, const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&vector, &string)" << endl ; fflush(stdout) ; #endif // DEBUG_T makePointListFromFile(dest_point_list, filename, true) ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&vector, &string)" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit le fichier de mesures (CSV) nommé "filename", et place les informations dans la liste "dest_point_list". * Si "uniq_point" est vrai, on vérifiera l'existence d'un point avant tout ajout d'information, de manière à ne pas créer de doublon : si le point existe déjà, les informations lui seront ajoutées, sinon un nouveau point sera créé dans la liste. * Si "uniq_point" est faux, un nouveau point sera créé pour chaque ligne du fichier. */ void Server::makePointListFromFile(vector &dest_point_list, const string &filename, const bool uniq_point) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&vector, &string, bool)" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file ; // Flux d'entrée du fichier. char buffer[BUFFER_LENGTH]; // Buffer lu dans le fichier. string cpp_buffer ; // Buffer au format string. ReferencePoint rp; Point tmp_point; float x, y, z ; // Coordonnées des points. unsigned int pt_idx = 0 ; // Position du point lu dans la liste. vector infos ; // Liste des informations lues dans une ligne du fichier. input_file.open(filename.c_str()) ; if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." ; int nlines = 0 ; int npoints = 0 ; #endif // DEBUG while (!input_file.eof()) { #ifdef DEBUG if (nlines % 100 == 0) printf("\n%5d", nlines) ; cout << '.' ; nlines++ ; #endif // DEBUG input_file.getline(buffer, BUFFER_LENGTH); if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Extract fields */ cpp_buffer = buffer; if (cpp_buffer.size() == 0) // Ignorer une ligne vide continue ; infos = extractReferencePointInfoFromBuffer(cpp_buffer); x = string2float(infos[0]); y = string2float(infos[1]); #ifdef FRED_CSV_FORMAT z = DEFAULT_Z ; #else // FRED_CSV_FORMAT z = string2float(infos[2]) ; #endif // FRED_CSV_FORMAT /* Set point coordinates */ tmp_point.setX(x); tmp_point.setY(y); tmp_point.setZ(z); /* Use C++ string format */ if (!uniq_point || !pointExists(dest_point_list, tmp_point)) // Si on ne veut pas de points unique, ou que le point n'existe pas encore, { rp.setCoordinates(tmp_point); dest_point_list.push_back(rp) ; // on le crée. pt_idx = dest_point_list.size() - 1 ; // Le point que l'on vient d'ajouter est le dernier du vector. #ifdef DEBUG npoints++ ; #endif // DEBUG #ifdef DEBUG_2 cout << tmp_point << " : ajouté." << endl ; #endif // DEBUG_2 } else // Le point existe déjà : { #ifdef DEBUG_2 cout << tmp_point << " : existe déjà." << endl ; #endif // DEBUG_2 pt_idx = pointIndex(dest_point_list, tmp_point) ; // On recherche le point auquel on veut ajouter les informations. } #ifdef FRED_CSV_FORMAT vector measures_vector = extractValues(infos[4]) ; for (unsigned int i = 0 ; i < measures_vector.size() ; i++) dest_point_list[pt_idx].addMeasurement(infos[3], measures_vector[i]); measures_vector.clear(); #else // FRED_CSV_FORMAT for (unsigned int i = 4 ; i < infos.size() ; i++) { #ifdef DEBUG_2 cout << "Lecture de la valeur : " << infos[i] << "... " ; #endif // DEBUG_2 if (i + 1 < infos.size()) { dest_point_list[pt_idx].addMeasurement(infos[i], string2int(infos[i+1])) ; #ifdef DEBUG_2 cout << "Mesure ajoutée : AP = " << infos[i] << " | SS = " << string2int(infos[i+1]) << endl ; #endif // DEBUG_2 i++ ; } } #endif // FRED_CSV_FORMAT } } #ifdef DEBUG cout << '\n' << nlines << " lignes lues, " << npoints << " points différents ajoutés.\n" << endl ; #endif // DEBUG input_file.close(); infos.clear() ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&vector, &string, bool)" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::makeApListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeApListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T 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 ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH); if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. ap_infos = explode(buffer, ';'); #ifdef DEBUG cout << "AP : " << buffer ; #endif // DEBUG 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(); #ifdef DEBUG cout << " ajouté." << endl ; #endif // DEBUG } } #ifdef DEBUG cout << endl ; #endif // DEBUG input_file.close(); #ifdef DEBUG_T cout << "//<-- Server::makeApListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit la liste des zones homogènes du bâtiment (pièces) dans le fichier "filename", et place le résultat dans "area_list". */ void Server::makeTopologyFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeTopologyFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file ; char buffer[BUFFER_LENGTH] ; vector infos ; input_file.open(filename.c_str()) ; if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH) ; if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. infos = explode(buffer, ';') ; #ifdef DEBUG cout << "Pièce : " << buffer ; #endif // DEBUG if (area_list.find(infos[0]) != area_list.end()) // Si la pièce existe déjà, cerr << "Erreur ! Déclaration multiple de la zone « " << infos[0] << " »." << endl ; // on le signale ; else // sinon on l'ajoute : { area_list[infos[0]] = Area(infos[0], string2float(infos[1]), string2float(infos[2]), string2float(infos[3]), string2float(infos[4]), string2float(infos[5]), string2float(infos[6])) ; #ifdef DEBUG cout << " ajoutée." << endl ; #endif // DEBUG } infos.clear() ; } } #ifdef DEBUG cout << "--> Liste des pièces (" << area_list.size() << ") :" << endl ; for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) cout << it->first << " : " << it->second << endl ; cout << endl ; #endif // DEBUG input_file.close() ; #ifdef DEBUG_T cout << "//<-- Server::makeTopologyFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit la liste des points de passage dans le fichier "filename" et calcule les distances entre eux. Initialise waypoint_list et waypoint_matrix. * TODO : tenir compte de la topologie pour les distances entre points. */ void Server::makeWaypointListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file ; char buffer[BUFFER_LENGTH] ; vector infos ; set point_list ; // Point p_cur, p_tmp ; input_file.open(filename.c_str()); if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; #ifdef DEBUG_T cout << "//<-- Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH) ; if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. infos = explode(buffer, ';') ; #ifdef DEBUG cout << "Point de passage : " << buffer ; fflush(stdout); #endif // DEBUG /* Ajout du point lu */ Point tmp_pt(string2float(infos[0]), string2float(infos[1]), string2float(infos[2])) ; if (! point_list.insert(tmp_pt).second) cerr << "Point " << tmp_pt << " dupliqué !" << endl ; else #ifdef DEBUG cout << " traité." << endl ; fflush(stdout); #endif // DEBUG infos.clear() ; } } input_file.close() ; // Lecture du fichier terminée /* Construction de la matrice */ unsigned int nb_pts = point_list.size() ; // Nombre de points unsigned int cur_idx = 0 ; // Itérateur sur l'indice de la matrice. waypoint_list.reserve(nb_pts) ; // Vector contenant tous les points (attribut du serveur) waypoint_matrix = new float*[nb_pts] ; // Matrice (carrée) des distances entre les points de passage (attribut du serveur) for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : { waypoint_matrix[i] = new float[nb_pts] ; for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 waypoint_matrix[i][k] = -1 ; } #ifdef DEBUG cout << "--> Liste des points de passage (" << nb_pts << ") :" << endl ; fflush(stdout); #endif // DEBUG /* Calcul des distances */ for (set::iterator it = point_list.begin() ; it != point_list.end() ; it++, cur_idx++) // Pour chaque point enregistré { #ifdef DEBUG cout << *it << " :" ; #endif // DEBUG waypoint_list[cur_idx] = *it ; // Ajout du point dans waypoint_list // FIXME : utiliser plutôt push_back() ? waypoint_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent { #ifdef DEBUG cout << " / " << waypoint_list[k] ; #endif // DEBUG float dist = it->distance(waypoint_list[k]) ; // On calcule la distance waypoint_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, waypoint_matrix[k][cur_idx] = dist ; // dans les deux sens. } #ifdef DEBUG cout << " /" << endl ; #endif // DEBUG } #ifdef DEBUG /* Affichage de la matrice */ cout << "--> Matrice des distances entre points de passage :\n\t\t|" ; for (unsigned int k = 0 ; k < nb_pts ; k++) cout << ' ' << waypoint_list[k] << "\t|" ; cout << endl ; for (unsigned int k = 0 ; k < nb_pts ; k++) { cout << waypoint_list[k] << "\t|" ; for (unsigned int l = 0 ; l < nb_pts ; l++) cout << '\t' << waypoint_matrix[k][l] << "\t|" ; cout << endl ; } cout << endl ; #endif // DEBUG #ifdef DEBUG_T cout << "//<-- Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Calcule la distance entre tous les points de référence en tenant compte de la topologie (initialise reference_point_matrix). * /!\ La liste des *points de passage*, leur *matrice de distances*, ainsi que la liste des *points de référence*, DOIVENT ÊTRE INITIALISÉES avant l'appel à cette fonction. Il faut donc appeler makeWaypointListFromFile() et makeReferencePointListFromFile() avant makeReferencePointDistances(). */ void Server::makeReferencePointDistances() { #ifdef DEBUG_T cout << "//--> Server::makeReferencePointDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int nb_pts = reference_point_list.size() ; // Nombre de points à traiter. /* Construction de la matrice des distances */ reference_point_matrix = new float*[nb_pts] ; // Allocation de la première dimension. for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : { reference_point_matrix[i] = new float[nb_pts] ; for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 reference_point_matrix[i][k] = -1 ; } #ifdef DEBUG cout << "--> Liste des points de référence (" << nb_pts << ") :" << endl ; fflush(stdout); #endif // DEBUG /* Calcul des distances */ for (unsigned int cur_idx = 0 ; cur_idx < nb_pts ; cur_idx++) { #ifdef DEBUG cout << (Point) reference_point_list[cur_idx] ; #ifdef DEBUG_2 cout << " :" ; #endif // DEBUG_2 #endif // DEBUG reference_point_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent { #ifdef DEBUG_2 cout << " / " << (Point) reference_point_list[k] ; #endif // DEBUG_2 float dist = distanceTopology((Point) reference_point_list[cur_idx], (Point) reference_point_list[k]) ; // On calcule la distance reference_point_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, reference_point_matrix[k][cur_idx] = dist ; // dans les deux sens. } #ifdef DEBUG #ifdef DEBUG_2 cout << " /" ; #endif // DEBUG_2 cout << endl ; #endif // DEBUG } #ifdef DEBUG_2 /* Affichage de la matrice */ cout << "--> Matrice des distances entre points de référence :\n\t\t|" ; for (unsigned int k = 0 ; k < nb_pts ; k++) cout << ' ' << (Point) reference_point_list[k] << "\t|" ; cout << endl ; for (unsigned int k = 0 ; k < nb_pts ; k++) { cout << (Point) reference_point_list[k] << "\t|" ; for (unsigned int l = 0 ; l < nb_pts ; l++) cout << '\t' << reference_point_matrix[k][l] << "\t|" ; cout << endl ; } cout << endl ; #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::makeReferencePointDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* FONCTION POUR RÉTRO-COMPATIBILITÉ * Affiche la liste des points de référence (reference_point_list). */ void Server::printReferencePointList() { #ifdef DEBUG_T cout << "//--> Server::printReferencePointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T printPointList(reference_point_list) ; #ifdef DEBUG_T cout << "//<-- Server::printReferencePointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Affiche une liste de points (point_list). */ void Server::printPointList(vector &point_list) { #ifdef DEBUG_T cout << "//--> Server::printPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T for (unsigned int i = 0 ; i < point_list.size() ; i++) cout << point_list[i] << endl ; #ifdef DEBUG_T cout << "//<-- Server::printPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::printAccessPointList() { #ifdef DEBUG_T cout << "//--> Server::printAccessPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T for (unsigned int i = 0 ; i < access_point_list.size() ; i++) cout << access_point_list[i] << endl; #ifdef DEBUG_T cout << "//<-- Server::printAccessPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::computeFriisFromRefList() { #ifdef DEBUG_T cout << "//--> Server::computeFriisFromRefList()" << endl ; fflush(stdout) ; #endif // DEBUG_T 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 (unsigned int 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 (unsigned int 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 (unsigned int 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(); } #ifdef DEBUG_T cout << "//<-- Server::computeFriisFromRefList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /*Deuxième version de computeFriisFromRefList qui prend en entrée un point et retourne la liste d'index de friis équivalent*/ vector Server::computeFriisFromRefList(const Point &p, const vector &m) { #ifdef DEBUG_T cout << "//--> Server::computeFriisFromRefList(&Point, &vector)" << endl ; fflush(stdout) ; #endif // DEBUG_T 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; /* Compute an index for each ref point. List stored in friis_idx_list */ /* Compute an index for Point p. List stored in friis_idx_list */ for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) { pt_coords = reference_point_list[j].getCoordinates(); if (pt_coords==p) { for (unsigned int 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; if (reference_point_list[j].getPowerForAp(ap_mac, &mes_power)){ friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); } } } } for (unsigned int k=0; k < friis_idx_list.size();k++) cout<<"friis_idx_list"<< k <<": "<)" << endl ; fflush(stdout) ; #endif // DEBUG_T return friis_idx_list; } /* Ajoute un client (ClientInfo) à la liste "client_list", et renvoie une référence sur l'élément ajouté. */ ClientInfo& Server::createClient() { #ifdef DEBUG_T cout << "//--> Server::createClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T client_list.push_back(ClientInfo()) ; #ifdef DEBUG_T cout << "//<-- Server::createClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T return client_list.back() ; } /* Localise le client d'identifiant "client_id" en appliquant l'algorithme voulu. */ void Server::monitorClient(const unsigned int &client_id, const ALGORITHM &algo) { #ifdef DEBUG_T cout << "//--> Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T Point pointFastViterbi; vector friisFromList; vector &E_current = client_list[client_id].getRef_viterbi_Ecurrent(), &E_previous = client_list[client_id].getRef_viterbi_Eprevious() ; if (VITERBI_N < 2) { cerr << "monitorClient() : N ne peut être inférieur à 2 !" << endl ; #ifdef DEBUG_T cout << "//<-- Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T return ; } #ifdef TEST vector peregrination_point_list ; makePointListFromFile(peregrination_point_list, DEFAULT_TRACKING_FILE, false) ; #endif // TEST #ifdef DEBUG cout << reference_point_list.size() << " points de référence" ; #ifdef TEST cout << ", " << peregrination_point_list.size() << " points de pérégrination." << endl ; #else // TEST cout << '.' << endl ; #endif // TEST #endif // DEBUG #ifdef DEBUG_2 cout << "***** Liste des points de référence : *****" << endl ; printReferencePointList() ; #ifdef TEST cout << "***** Liste des points de pérégrination : *****" << endl ; printPointList(peregrination_point_list) ; #endif // TEST cout << "*********************************" << endl ; #endif // DEBUG_2 #ifdef TEST unsigned int pt = 0 ; while (pt < peregrination_point_list.size()) #else // TEST while (true) #endif // TEST { vector vm ; #ifdef TEST /* Get point measurements */ //vm.clear(); vm = peregrination_point_list[pt].getMeasurementList(); #else // TEST vm = récupère_mesure() ; // FIXME ! #endif // TEST E_previous = E_current ; E_current = getkClosestInSs(vm, VITERBI_K) ; // Création de l'ensemble des K points les plus proches dans l'espace des puissances. #ifdef DEBUG cout << "Point courant : " << peregrination_point_list[pt] ; #endif // DEBUG switch (algo) { case ALGO_VLI : /* Application de l'algorithme Viterbi */ fastViterbiLike(client_id, NULL) ; break ; case ALGO_BASIC_FRBHM : /* Application de l'algorithme FRBHM basique */ cout << "-------FRBHM---------" << endl ; computeFriisFromRefList() ; pointFastViterbi = fastViterbiLike(client_id, NULL) ; friisFromList = computeFriisFromRefList(pointFastViterbi, vm) ; fbcm_friis(vm, friisFromList) ; break ; default : cerr << "Erreur ! Algorithme inconnu." << endl ; } #ifdef TEST pt++ ; #endif // TEST } #ifdef DEBUG_T cout << "//<-- Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* * Computes new cumulative distances for the viterbi instance of the client nb "client_id". * Returns the solution (Point) of the last ended viterbi. * Distances are grouped by line corresponding to an instance. */ Point Server::fastViterbiLike(const unsigned int &client_id, float **distance_matrix) { #ifdef DEBUG_T cout << "//--> Server::fastViterbiLike()" << endl ; fflush(stdout) ; #endif // DEBUG_T float_array &V = client_list[client_id].getRef_viterbi_V() ; vector &E_current = client_list[client_id].getRef_viterbi_Ecurrent(), &E_previous = client_list[client_id].getRef_viterbi_Eprevious() ; unsigned int &i = client_list[client_id].getRef_viterbi_iteration() ; int N = VITERBI_N, K = VITERBI_K ; unsigned int V0_min_k = 0 ; // Indice du point sélectionné à chaque itération if (i > 1) // Si on n'est plus à la première itération { /* Recalcul des plus courtes distances */ for (float_index n = N-1-i ; n < N-2 ; n++) // Pour chaque historique existant (sauf le dernier), for (float_index k = 0 ; k < K ; k++) // pour chaque point de l'historique, { // on met à jour le chemin minimum entre l'historique précédent et le point : V[n][k] = V[n+1][0] + E_previous[0].distance(E_current[k]) ; for (float_index l = 1 ; l < K ; l++) { float f = V[n+1][l] + E_previous[l].distance(E_current[k]) ; if (f < V[n][k]) V[n][k] = f ; } } /* Traitement du dernier historique */ for (float_index k = 0 ; k < K ; k++) // Pour chaque point, { // on récupère le chemin minimum entre l'historique précédent et le point : V[N-2][k] = E_previous[0].distance(E_current[k]) ; for (float_index l = 1 ; l < K ; l++) { float f = E_previous[l].distance(E_current[k]) ; if (f < V[N-2][k]) V[N-2][k] = f ; } } /* Choix du point à renvoyer */ V0_min_k = 0 ; // Indice du point correspondant au V0 minimal. Si le tableau n'est pas plein, la plus petite valeur a l'indice 0 (car getkClosestInSs() renvoit un résultat trié). if (N-1-i == 0) { #ifdef DEBUG float V0_min = V[0][0] ; cout << "V[0][0]=" << V[0][0] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; #endif // DEBUG for (float_index k=1 ; k < K ; k++) { if (V[0][k] < V0_min) { V0_min_k = k ; #ifdef DEBUG V0_min = V[0][k] ; #endif // DEBUG } #ifdef DEBUG cout << "V[0][" << k << "]=" << V[0][k] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; #endif // DEBUG } #ifdef DEBUG cout << "V0_min = " << V0_min << " ; V0_min_k=" << V0_min_k << endl ; #endif // DEBUG } } #ifdef DEBUG cout << "V :" << endl ; for (float_index n=0 ; n < N-1 ; n++) { for (float_index k=0 ; k < K ; k++) cout << "[" << V[n][k] << "]" ; cout << endl ; } cout << "Point sélectionné : " << E_current[V0_min_k] << endl ; cout << "--------------------------" << endl ; #endif // DEBUG if (i < N-1) i++ ; #ifdef DEBUG_T cout << "//<-- Server::fastViterbiLike()" << endl ; fflush(stdout) ; #endif // DEBUG_T return E_current[V0_min_k] ; } /* For experimentation purpose only */ void Server::radar_exp() { ofstream logfile; vector solutions; Point solution, solution_kw, ref_coords; unsigned int i; vector vm; // 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, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 3, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 4, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 5, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; /* Nearest in SS */ solutions = getkClosestInSs(vm, 1, &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(); }