Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ConfigFile EthernetInterface mbed-rtos mbed
Fork of S05APP3 by
main.cpp
- Committer:
- benjaminroy
- Date:
- 2017-02-14
- Revision:
- 21:37a11c3659cc
- Parent:
- 20:e96c9acfd2ea
File content as of revision 21:37a11c3659cc:
// Titre: S05APP3 // Auteurs: Benjamin Roy et Marc-Antoine Beaudoin // Date: 14 février 2017 // ======================================================= // ===================== COORDINATOR ===================== // ======================================================= #include "EthernetInterface.h" #include "ConfigFile.h" #include "mbed.h" #include "rtos.h" AnalogOut errorLed(p18); DigitalOut reset(p8); EthernetInterface eth; Mutex mutex; Serial xbee(p13, p14); // tx, rx Serial pc(USBTX, USBRX); // tx, rx TCPSocketConnection socket; Ticker ticker1; Thread *t1; /* Boîte aux lettres */ typedef struct { uint8_t type; char strAccelerationX[15]; char strAccelerationY[15]; char strAccelerationZ[15]; char strDryContact[15]; } mail_t; Mail<mail_t, 20> mail_box; uint8_t routerAddress[8] = { 0 }; // Should be 00 13 A2 00 40 8B 41 6E uint8_t startDelimiter = 0x7E; uint16_t portNumber = 0; uint16_t panId = 0; char serverAddress[32]; char panIdChar[5]; char portNbr[5]; /* * Imprime le buffer à l'écran pour des fins de déboguage: */ void printBuffer(uint8_t bufferSize, uint8_t* buffer) { for(uint8_t k = 0; k <= bufferSize; k++) { pc.printf("%X-", buffer[k]); } printf("\n"); } /* * Envoyer et recevoir des données via le protocole Xbee: */ uint8_t* readDataFromXbee(uint8_t bufferSize) { mutex.lock(); uint8_t buffer[104] = { 0 }; for (uint8_t i = 0; i <= bufferSize;) { if (xbee.readable()) { buffer[i] = xbee.getc(); i++; } } mutex.unlock(); return buffer; } void sendDataToXbee(uint8_t bufferSize, uint8_t* buffer) { for (uint8_t i = 0; i < bufferSize;) { if (xbee.writeable()) { xbee.putc(buffer[i]); i++; } } } /* * Lecture du fichier de configuration: */ void readConfigFile() { LocalFileSystem local("local"); ConfigFile cfg; char *serverAddressStr = "serverAddr"; char *portNumberStr = "portNb"; char *panIdStr = "panID"; if (!cfg.read("/local/input.cfg")) { error("Erreur dans la lecture du fichier de configuration...\n"); } else { cfg.getValue(panIdStr, &panIdChar[0], sizeof(panIdChar)); cfg.getValue(serverAddressStr, &serverAddress[0], sizeof(serverAddress)); cfg.getValue(portNumberStr, &portNbr[0], sizeof(portNbr)); portNumber = (uint16_t)strtol(portNbr, NULL, 10); panId = (uint16_t)strtol(panIdChar, NULL, 10); // printf("The server address is %s\n", serverAddress); // printf("The port number is %i\n", portNumber); // printf("The PAN ID is %i\n", panId); } } /* * Détection et gestion des erreurs (allumer une LED pendant 1 seconde lorsqu'une erreur est détectée): */ void printError(char* buffer) { pc.printf(buffer); errorLed.write(3.3); wait(1); errorLed.write(0); } void readATCommandResponse(uint8_t* buffer) { if (buffer[4] == 0x01) printError("AT Command Response: Error.\n"); else if (buffer[4] == 0x02) printError("AT Command Response: Invalid Command.\n"); else if (buffer[4] == 0x03) printError("AT Command Response: Invalid Parameter.\n"); else if (buffer[4] == 0x04) printError("AT Command Response: Tx Failure.\n"); } void readRemoteATCommandResponse(uint8_t* buffer) { if (buffer[14] == 0x01) printError("Remote AT Command Response: Error.\n"); else if (buffer[14] == 0x02) printError("Remote AT Command Response: Invalid Command.\n"); else if (buffer[14] == 0x03) printError("Remote AT Command Response: Invalid Parameter.\n"); else if (buffer[14] == 0x04) printError("Remote AT Command Response: Tx Failure.\n"); } void readTransmitStatus(uint8_t* buffer) { if (buffer[5] == 0x01) pc.printf("Transmit Status: An expedted MAC acknowledgement never occured. \n"); else if (buffer[5] == 0x02) pc.printf("Transmit Status: CCA failure. \n"); else if (buffer[5] == 0x03) pc.printf("Transmit Status: Packet was purgedwithoutbeing transmitted. \n"); else if (buffer[5] == 0x04) pc.printf("Transmit Status: Physical error on the interface with the WiFi transceiver. \n"); else if (buffer[5] == 0x18) pc.printf("Transmit Status: No buffers. \n"); else if (buffer[5] == 0x21) pc.printf("Transmit Status: Expected networkacknowledgement never occured. \n"); else if (buffer[5] == 0x22) pc.printf("Transmit Status: Not joined to network. \n"); else if (buffer[5] == 0x23) pc.printf("Transmit Status: Self-addressed. \n"); else if (buffer[5] == 0x24) pc.printf("Transmit Status: Address not found. \n"); else if (buffer[5] == 0x25) pc.printf("Transmit Status: Route not found. \n"); else if (buffer[5] == 0x26) pc.printf("Transmit Status: Broadcast relay was not heard. \n"); else if (buffer[5] == 0x2B) pc.printf("Transmit Status: Invalid binding table index. \n"); else if (buffer[5] == 0x2C) pc.printf("Transmit Status: Invalid Endpoint. \n"); else if (buffer[5] == 0x31) pc.printf("Transmit Status: A software error occurred. \n"); else if (buffer[5] == 0x32) pc.printf("Transmit Status: Resource Error. \n"); else if (buffer[5] == 0x74) pc.printf("Transmit Status: Data payload too large. \n"); else if (buffer[5] == 0x76) pc.printf("Transmit Status: Client socket creationat attempt failed. \n"); } void readModemStatus(uint8_t* buffer) { if (buffer[1] == 0x00) pc.printf("Modem status: Hardware reset.\n"); else if (buffer[1] == 0x01) printError("Modem status: Watchdog timer reset.\n"); else if (buffer[1] == 0x02) printError("Modem status: Joined network.\n"); else if (buffer[1] == 0x03) printError("Modem status: Disassociated.\n"); else if (buffer[1] == 0x04) printError("Modem status: Configuration error/synchronization.\n"); else if (buffer[1] == 0x05) printError("Modem status: Coordinator realignment.\n"); else if (buffer[1] == 0x06) pc.printf("Modem status: Coordinator started.\n"); else if (buffer[1] == 0x07) printError("Modem status: Network security key updated.\n"); else if (buffer[1] == 0x08) printError("Modem status: Network woke up.\n"); else if (buffer[1] == 0x0C) printError("Modem status: Network went to sleep.\n"); else if (buffer[1] == 0x0E) printError("Modem status: Device cloud connected.\n"); else if (buffer[1] == 0x0F) printError("Modem status: Device cloud disconnected.\n"); else if (buffer[1] == 0x11) printError("Modem status: Modem configurationchanged while join in progress.\n"); else if (buffer[1] == 0x80) printError("Modem status: Stack error (80+).\n"); else if (buffer[1] == 0x82) printError("Modem status: Send/join command issuedwithout connecting from AP.\n"); else if (buffer[1] == 0x83) printError("Modem status: Access point not found.\n"); else if (buffer[1] == 0x84) printError("Modem status: PSK not configured.\n"); } /* * Calculer et vérifier le checksum des trames reçues: */ uint8_t calculateChecksum(uint8_t frameTypeIndex, uint8_t frameSize, uint8_t* buffer) { char checksum = 0; for (int i = frameTypeIndex; i < frameSize - 1; i++) { checksum += buffer[i]; } return (0xFF - checksum); } bool checksumIsValid(uint8_t bufferSize, uint8_t* buffer) { uint32_t checkSum = 0; for (int i = 0; i < bufferSize; i++) { checkSum += buffer[i]; } if ((0xFF - (checkSum & 0xFF)) != buffer[bufferSize]) { pc.printf("Erreur dans la transmission de la trame --> "); printBuffer(bufferSize, buffer); return false; } return true; } /* * Faire allumer une DEL, reliée à un des ports du XBEE (DIO) du Routeur, en utilisant une commande de configuration à distance provenant du Coordinateur * HIGH: {0x7E, 0x00, 0x10, 0x17, 0x01, 0x00, 0x13, 0xA2, 0x00, 0x40, 0x8B, 0x41, 0x6E, 0xFF, 0xFE, 0x02, 0x44, 0x34, 0x05, 0x3C}; * LOW: {0x7E, 0x00, 0x10, 0x17, 0x02, 0x00, 0x13, 0xA2, 0x00, 0x40, 0x8B, 0x41, 0x6E, 0xFF, 0xFE, 0x02, 0x44, 0x34, 0x04, 0x3C}; */ void toggleRouterLed() { bool led = false; uint8_t command[20] = { 0 }; Thread::signal_wait(0x2); // Attendre que l'adresse du noeud rooteur soit connue command[0] = startDelimiter; command[1] = 0x00; command[2] = 0x10; command[3] = 0x17; for (uint8_t i = 0; i < sizeof(routerAddress); i++) { command[i + 5] = routerAddress[i]; } command[13] = 0xFF; command[14] = 0xFE; command[15] = 0x02; command[16] = 0x44; command[17] = 0x34; while(1) { Thread::signal_wait(0x1); // Période: 1 Hz if (led) { command[4] = 0x01; command[18] = 0x05; } else { command[4] = 0x02; command[18] = 0x04; } command[19] = calculateChecksum(3, sizeof(command), command); sendDataToXbee(sizeof(command), command); led = !led; } } void sendDataToServer() { while(1) { osEvent evt = mail_box.get(); if (evt.status == osEventMail) { mail_t *mail = (mail_t*)evt.value.p; int responseSize = 0; char buffer[50] = { 0 }; if (mail->type == 0) { sprintf(buffer, "%s, %s, %s\0", mail->strAccelerationX, mail->strAccelerationY, mail->strAccelerationZ); } else { sprintf(buffer, "%s\0", mail->strDryContact); } printf("Envoye des serveurs: "); printBuffer(buffer, sizeof(buffer)-1); socket.send_all(buffer, sizeof(buffer)-1); responseSize = socket.receive(buffer, sizeof(buffer)-1); buffer[responseSize] = '\0'; pc.printf("Server: %s\n", buffer); mail_box.free(mail); } } } /* * Lire et décomposer les trames reçues (adresse, données, status): */ void readRouterAddress(uint8_t* buffer) { for (uint8_t i = 0; i < 8; i++) { routerAddress[i] = buffer[i + 1]; } t1->signal_set(0x02); } void readRouterData(uint8_t bufferSize, uint8_t* buffer) { uint16_t acc[3] = {0}; if (buffer[0] == 0x90 && bufferSize == 18) { // Ajouter les données reçues par l'accéléromètre à la boîte aux lettres: for (uint8_t i = 12; i < bufferSize; i += 2) { acc[(i/2)-6] = (buffer[i+1] << 8 ) | (buffer[i] & 0xff); } mail_t *mail = mail_box.alloc(); mail->type = 0; sprintf(mail->strAccelerationX, "X:%i\0", acc[0]); sprintf(mail->strAccelerationY, "Y:%i\0", acc[1]); sprintf(mail->strAccelerationZ, "Z:%i\0", acc[2]); mail_box.put(mail); } else if (buffer[0] == 0x90 && bufferSize == 13) { // Ajouter les données reçues par le contact sec à la boîte aux lettres: mail_t *mail = mail_box.alloc(); mail->type = 1; sprintf(mail->strDryContact, "Contact: %i\0", buffer[12]); mail_box.put(mail); } } void readDataFromRouter(){ while(1) { if (xbee.readable() && xbee.getc() == startDelimiter) { uint8_t buffer[104] = { 0 }; uint8_t bufferSize = (xbee.getc() << 8 ) | (xbee.getc() & 0xff); memcpy(buffer, readDataFromXbee(bufferSize), bufferSize + 1); if (checksumIsValid(bufferSize, buffer)) { if (buffer[0] == 0x90) { // Frame Type: printBuffer(bufferSize, buffer); readRouterAddress(buffer); readRouterData(bufferSize, buffer); } else if (buffer[0] == 0x8A) { // Frame Type: Modem Status readModemStatus(buffer); } else if (buffer[0] == 0x8B) { // Frame Type: Transmit Status } else if (buffer[0] == 0x97) { // Frame Type: Remote AT Command Response readRemoteATCommandResponse(buffer); } else if (buffer[0] == 0x09) { // Frame Type: AT Command Response readATCommandResponse(buffer); } } } } } /* * Poser le ID du réseau PAN à rejoindre: */ void setCoordinatorPanId(uint16_t panId) { char _8bitsPanId[2] = { (panId >> 8) & 0xFF, panId & 0xFF }; uint8_t setPanIdBuffer[] = { startDelimiter, 0x00, 0x06, 0x09, 0x01, 0x49, 0x44, _8bitsPanId[0], _8bitsPanId[1], 0x00 }; uint8_t saveChangesBuffer[] = { startDelimiter, 0x00, 0x04, 0x09, 0x02, 0x57, 0x52, 0x4B }; uint8_t applyChangesBuffer[] = { startDelimiter, 0x00, 0x04, 0x09, 0x03, 0x41, 0x43, 0x6F }; setPanIdBuffer[sizeof(setPanIdBuffer) - 1] = calculateChecksum(0, sizeof(setPanIdBuffer), setPanIdBuffer); // Calculate the checksum sendDataToXbee(sizeof(setPanIdBuffer), setPanIdBuffer); // Set the 64-bit PAN ID sendDataToXbee(sizeof(saveChangesBuffer), saveChangesBuffer); // Save the changes sendDataToXbee(sizeof(applyChangesBuffer), applyChangesBuffer); // Apply changes by sending the CN command } /* * Envoyer un signal au thread qui fait clignoter la DEL du noeud routeur: */ void isr() { t1->signal_set(0x1); } // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- int main() { pc.printf("Starting a coordinator... \n"); reset = 0; wait_ms(1); reset = 1; wait_ms(1); readConfigFile(); setCoordinatorPanId(panId); if (eth.init() != 0) { // Use DHCP pc.printf("Erreur d'initialisation du RJ45.\n"); } if (eth.connect() != 0) { pc.printf("Erreur de connection du RJ45\n"); } else { pc.printf("IP Address is %s\n", eth.getIPAddress()); } int numberOfRetries = 0; while (socket.connect(serverAddress, portNumber) != 0) { if (numberOfRetries == 5) { error("Erreur dans la connection au socket.\n"); } numberOfRetries++; } // Démarrage des tâches: Thread _readDataFromRouter(readDataFromRouter); Thread _toggleRouterLed(toggleRouterLed); Thread _sendDataToServer(sendDataToServer); t1 = &_toggleRouterLed; ticker1.attach(&isr, 1); while(1) {} }