/************************** * Plane * *************************** * Designed & Developed by * * Adrien Marquès * * * *************************** * doowap31@gmail.com * **************************/ #include "plane.h" // numéro de vol de l'plane : code sur 5 caractères char numero_vol[6]; struct coord crd; struct control ctrl; int mcast_socket = -1; int commu_socket = -1; char buffer[MAX_BUF_LEN] = {0}; struct sockaddr_in sgca; int open_communication(){ /* 0. Initialisation des variables */ struct sockaddr_in udp; // données des sockets char buffer[MAX_BUF_LEN] = {0}; // buffer int status; struct bind_header request; struct in_addr ip; // pour afficher l'ip en dot notation /* [1] Socket Multicast UDP =========================================================*/ /* (1) Création socket multicast client* (écoute) ---------------------------------------------------------*/ if( DROP_MULTICAST_SERVER(MCST_HOST, MCST_PORT, &mcast_socket, &udp) < 0 ) return 0; // *un client multicast est en fait un serveur UDP, mais le terme persiste car le service est délivré par le CLIENT UDP /* (2) Attente réponse SGCA -> adresse+port TCP ---------------------------------------------------------*/ /* 1. Attente réponse */ status = recv(mcast_socket, buffer, MAX_BUF_LEN, 0); /* 2. Gestion erreur */ if( status < 0 ){ close(mcast_socket); return 0; } /* 3. Vérification taille */ if( status < BINDHDR_LEN ){ close(mcast_socket); return 0; } /* 4. On récupère les données */ bzero(&request, sizeof(struct bind_header)); memcpy(&request.flags, buffer, sizeof(char) ); memcpy(&request.addr, buffer+sizeof(char), sizeof(in_addr_t) ); memcpy(&request.port, buffer+sizeof(char)+sizeof(in_addr_t), sizeof(unsigned short) ); // on indian-switch request.addr = ntohl(request.addr); request.port = ntohs(request.port); ip.s_addr = request.addr; /* 5. On vérifie les flags */ if( !(request.flags&BINDHEAD_TCP) || request.flags&BINDHEAD_UDP ){ close(mcast_socket); return 0; } // printf("* hex("); for( int i = 0 ; i < BINDHDR_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n"); printf("* received bind_header{flags = %d; addr = %x/'%s'; port = %d;}\n\n", request.flags, request.addr, inet_ntoa(ip), request.port); /* [2] Socket communication TCP =========================================================*/ /* (1) Création socket TCP + connection ---------------------------------------------------------*/ /* 1. Création socket TCP + connection serveur */ if( TCP_CONNECT(&commu_socket, request.addr, request.port, PAUSE, &sgca) < 0 ) return 0; return 1; } void close_communication(){ // fonction à implémenter qui permet de fermer la communication // avec le gestionnaire de vols } void send_data(){ /* [0] Initialisation des variables =========================================================*/ char buffer[MAX_BUF_LEN] = {0}; struct plane_data request; int read; /* [1] Envoi des caractéristiques =========================================================*/ /* 1. Vérification socket */ if( commu_socket < 0 ) return; /* 2. création objet */ strcpy(request.code, numero_vol); request.x = htonl( crd.x ); request.y = htonl( crd.y ); request.z = htonl( crd.z ); request.cap = htonl( ctrl.cap ); request.spd = htonl( ctrl.speed ); /* 3. Copie buffer */ memcpy(buffer+sizeof(char)*0+sizeof(int)*0, &request.code, sizeof(char)*6 ); memcpy(buffer+sizeof(char)*6+sizeof(int)*0, &request.x, sizeof(int) ); memcpy(buffer+sizeof(char)*6+sizeof(int)*1, &request.y, sizeof(int) ); memcpy(buffer+sizeof(char)*6+sizeof(int)*2, &request.z, sizeof(int) ); memcpy(buffer+sizeof(char)*6+sizeof(int)*3, &request.cap, sizeof(int) ); memcpy(buffer+sizeof(char)*6+sizeof(int)*4, &request.spd, sizeof(int) ); read = send(commu_socket, buffer, PLANE_DATA_LEN/sizeof(char), 0); if( read <= 0 ){ printf("Cannot send\n"); return; } // printf("* hex("); for( int i = 0 ; i < PLANE_DATA_LEN/sizeof(char) ; i++ ) printf("\\x%02X", buffer[i]); printf(")\n"); } /******************************** *** Fonctions gérant le déplacement de l'plane : ne pas modifier ********************************/ // initialise aléatoirement les paramètres initiaux de l'plane void init_plane(){ // initialisation aléatoire du compteur aléatoire time_t seed; time( &seed); srandom(seed); // intialisation des paramètres de l'plane crd.x = 1000 + random() % 1000; crd.y = 1000 + random() % 1000; crd.z = 900 + random() % 100; ctrl.cap = random() % 360; ctrl.speed = 600 + random() % 200; // initialisation du numero de l'plane : chaine de 5 caractères // formée de 2 lettres puis 3 chiffres numero_vol[0] = (random() % 26) + 'A'; numero_vol[1] = (random() % 26) + 'A'; numero_vol[2] = (random() % 10) + '0'; numero_vol[3] = (random() % 10) + '0'; numero_vol[4] = (random() % 10) + '0'; numero_vol[5] = 0; } // modifie la valeur de l'plane avec la valeur passée en paramètre int update_speed(int speed){ if( speed < 0 ) return -1; if( speed > VITMAX ) return -1; ctrl.speed = speed; return 0; } // modifie le cap de l'plane avec la valeur passée en paramètre int update_cap(int cap){ if( cap < 0 || cap >= 360 ) return -1; ctrl.cap = cap; return 0; } // modifie l'z de l'plane avec la valeur passée en paramètre int update_z(int alt){ if( alt < 0 ) return 01; crd.z = alt; return 0; } // affiche les caractéristiques courantes de l'plane void display_data(){ printf("| Plane %s |\n * position(%d,%d, %d)\n * speed: %d\n * cap: %d\n\n", numero_vol, crd.x, crd.y, crd.z, ctrl.speed, ctrl.cap); } // recalcule la localisation de l'plane en fonction de sa speed et de son cap void calc_ctrl(){ float ctrl_x, ctrl_y; if (ctrl.speed < VITMIN){ close_communication(); exit(2); } if (crd.z == 0){ close_communication(); exit(3); } ctrl_x = cos(ctrl.cap * 2 * M_PI / 360) * ctrl.speed * 10 / VITMIN; ctrl_y = sin(ctrl.cap * 2 * M_PI / 360) * ctrl.speed * 10 / VITMIN; // on se déplace d'au moins une case quels que soient le cap et la speed // sauf si cap est un des angles droit if ((ctrl_x > 0) && (ctrl_x < 1)) ctrl_x = 1; if ((ctrl_x < 0) && (ctrl_x > -1)) ctrl_x = -1; if ((ctrl_y > 0) && (ctrl_y < 1)) ctrl_y = 1; if ((ctrl_y < 0) && (ctrl_y > -1)) ctrl_y = -1; crd.x = crd.x + (int)ctrl_x; crd.y = crd.y + (int)ctrl_y; display_data(); } // fonction principale : gère l'exécution de l'plane au fil du temps void update(){ int received; struct sgca_req request; char buffer[MAX_BUF_LEN] = {0}; while( 1 ){ calc_ctrl(); send_data(); /* [1] Gestion réception avec timeout =========================================================*/ /* 1. Attente de message */ received = recv(commu_socket, buffer, MAX_BUF_LEN, 0); /* 2. Si rien -> on reboucle */ if( received != (sizeof(char)+3*sizeof(int)) ) continue; printf("** Received update request **\n"); /* [2] Gestion de requête de mise à jour =========================================================*/ /* 1. On parse la requête */ memcpy(&request.flags, buffer, sizeof(char) ); memcpy(&request.z, buffer+sizeof(char), sizeof(int) ); memcpy(&request.cap, buffer+sizeof(char)+sizeof(int), sizeof(int) ); memcpy(&request.spd, buffer+sizeof(char)+sizeof(int)*2, sizeof(int) ); /* 2. On indian-switch */ request.z = ntohl(request.z); request.cap = ntohl(request.cap); request.spd = ntohl(request.spd); printf("Request received { flags = %d; z = %d; cap = %d; speed = %d }\n", request.flags, request.z, request.cap, request.spd); /* 3. On essaie de mettre à jour en fonction des flags */ if( request.flags&REQ_ALT ) if( update_z(request.z) == -1 ) request.flags -= REQ_ALT; if( request.flags&REQ_SPD ) if( update_speed(request.spd) == -1 ) request.flags -= REQ_SPD; if( request.flags&REQ_CAP ) if( update_cap(request.cap) == -1 ) request.flags -= REQ_CAP; /* [3] Gestion de la réponse =========================================================*/ /* 1. On prépare la réponse */ buffer[0] = request.flags; printf("Response flags : %d\n", request.flags); /* 2. Envoi de la réponse */ if( send(commu_socket, buffer, sizeof(char), 0) <= 0 ){ printf("Cannot send response\n"); } } } int main(){ // on initialise le plane init_plane(); display_data(); // on quitte si on arrive à pas contacter le gestionnaire de vols if( !open_communication() ){ printf("Cannot connect to SGCA.\n"); exit(1); } // on se déplace une fois toutes les initialisations faites update(); }