* Routeur
Dependencies: ConfigFile mbed MMA8452 mbed-rtos
Fork of S05APP3_routeur by
main.cpp
- Committer:
- benjaminroy
- Date:
- 2017-02-14
- Revision:
- 15:42879340d625
- Parent:
- 14:ef95f6bce079
File content as of revision 15:42879340d625:
// Titre: S05APP3 // Auteurs: Benjamin Roy et Marc-Antoine Beaudoin // Date: 14 février 2017 // ================================================== // ===================== ROUTER ===================== // ================================================== #include "ConfigFile.h" #include "MMA8452.h" #include "mbed.h" #include "rtos.h" #define MMA8452_CTRL_REG_1 0x2A #define MMA8452_ADDRESS1 0x3A #define MMA8452_OUT_X_MSB 0x01 #define MMA8452_OUT_Y_MSB 0x03 #define MMA8452_OUT_Z_MSB 0x05 #define MMA8452_WHO_AM_I 0x0D Accelerometer_MMA8452 mma8452(p28, p27, 100); AnalogOut errorLed(p18); DigitalOut reset(p8); DigitalIn btn(p15); I2C i2c(p28, p27); // SDA, SCL Mutex mutex; Mutex mutex2; Mutex mutex3; Serial xbee(p13, p14); // tx, rx Serial pc(USBTX, USBRX); // tx, rx Ticker ticker1; Ticker ticker2; Thread *t1; Thread *t2; /* Boîte aux lettres */ typedef struct { uint8_t data[40]; } mail_t; Mail<mail_t, 50> mail_box; int16_t (*functionPointers[4])(); uint16_t panId = 0; uint16_t dryContactPeriod = 0; uint16_t accelerometerPeriod = 0; uint8_t coordinatorAddress[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t startDelimiter = 0x7E; uint8_t accFrameId = 0x01; uint8_t dryContactFrameId = 0x02; char panIdChar[5]; char dryContactPeriodChar[5]; char accelerometerPeriodChar[5]; /* * Imprimer 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]); } pc.printf("\n"); } /* * Envoyer et recevoir des données via le protocole Xbee: */ uint8_t* readDataFromXbee(uint8_t bufferSize) { uint8_t buffer[104] = { 0 }; for (uint8_t i = 0; i <= bufferSize;) { if (xbee.readable()) { buffer[i] = xbee.getc(); i++; } } 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 *panIdStr = "panID"; char *accPeriodStr = "accelerometerPeriod"; char *dryContactStr = "dryContactPeriod"; 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(dryContactStr, &dryContactPeriodChar[0], sizeof(dryContactPeriodChar)); cfg.getValue(accPeriodStr, &accelerometerPeriodChar[0], sizeof(accelerometerPeriodChar)); panId = (uint16_t)strtol(panIdChar, NULL, 10); dryContactPeriod = (uint16_t)strtol(dryContactPeriodChar, NULL, 10); accelerometerPeriod = (uint16_t)strtol(accelerometerPeriodChar, NULL, 10); // printf("The PAN ID is %i\n", panId); // printf("Period of accelerometer: %i\n", accelerometerPeriod); // printf("Period of the dry contact: %i\n", dryContactPeriod); } } /* * 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"); } uint8_t* split16bitsData(uint16_t acc) { union { uint16_t u16_value; uint8_t u8_value[2]; } data; data.u16_value = acc; return data.u8_value; } /* * Lecture des données transmises par l'accéléromètre et le contact sec: */ int16_t readXAcceleration() { int16_t temp; char addr[1] = { MMA8452_OUT_X_MSB }; char XAcceleration[2] = { 0 }; i2c.write(MMA8452_ADDRESS1, addr, 1, true); i2c.read(MMA8452_ADDRESS1, &XAcceleration[0], 2); ((char*)&temp)[0] = XAcceleration[1]; ((char*)&temp)[1] = XAcceleration[0]; return (temp >> 4); } int16_t readYAcceleration() { int16_t temp; char addr[1] = { MMA8452_OUT_Y_MSB }; char YAcceleration[2] = { 0 }; i2c.write(MMA8452_ADDRESS1, addr, 1, true); i2c.read(MMA8452_ADDRESS1, &YAcceleration[0], 2); ((char*)&temp)[0] = YAcceleration[1]; ((char*)&temp)[1] = YAcceleration[0]; return (temp >> 4); } int16_t readZAcceleration() { int16_t temp; char addr[1] = { MMA8452_OUT_Z_MSB }; char ZAcceleration[2] = { 0 }; i2c.write(MMA8452_ADDRESS1, addr, 1, true); i2c.read(MMA8452_ADDRESS1, &ZAcceleration[0], 2); ((char*)&temp)[0] = ZAcceleration[1]; ((char*)&temp)[1] = ZAcceleration[0]; return (temp >> 4); } int16_t readDryContact() { return btn; } /* * Calculer et vérifier le checksum des trames reçues: */ uint8_t calculateChecksum(uint8_t frameTypeIndex, uint8_t bufferSize, uint8_t* buffer) { uint32_t checksum = 0; for (uint8_t i = frameTypeIndex; i < bufferSize - 1; i++) { checksum += buffer[i]; } return (uint8_t)(0xFF - (checksum & 0xFF)); } bool checksumIsValid(uint8_t bufferSize, uint8_t* buffer) { uint32_t checkSum = 0; for (uint8_t 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; } void sendDataToCoordinator() { while (true) { osEvent evt = mail_box.get(); if (evt.status == osEventMail) { mail_t *mail = (mail_t*)evt.value.p; sendDataToXbee(sizeof(mail->data), mail->data); mail_box.free(mail); } } } void addDataToMemPool(uint8_t bufferSize, uint8_t* buffer, uint8_t frameId) { printBuffer(bufferSize, buffer); mail_t *mail = mail_box.alloc(); for (uint8_t i = 0; i < bufferSize; i++) { mail->data[i] = buffer[i]; } mail_box.put(mail); } void sendDryContactToMemPool() { while(true) { Thread::signal_wait(0x1); mutex2.lock(); int16_t dryContact = functionPointers[0] (); uint8_t buffer[19] = { 0 }; buffer[0] = startDelimiter; // Start Delimiter buffer[1] = 0x00; // Length buffer[2] = 0x0F; // Length buffer[3] = 0x10; // Frame Type buffer[4] = dryContactFrameId; // Frame ID buffer[5] = coordinatorAddress[0]; // 64 bit adress buffer[6] = coordinatorAddress[1]; // 64 bit adress buffer[7] = coordinatorAddress[2]; // 64 bit adress buffer[8] = coordinatorAddress[3]; // 64 bit adress buffer[9] = coordinatorAddress[4]; // 64 bit adress buffer[10] = coordinatorAddress[5]; // 64 bit adress buffer[11] = coordinatorAddress[6]; // 64 bit adress buffer[12] = coordinatorAddress[7]; // 64 bit adress buffer[13] = 0xFF; // 16 bit adress buffer[14] = 0xFE; // 16 bit adress buffer[15] = 0x00; // Broadcast radius buffer[16] = 0x00; // Options buffer[17] = dryContact; // RF Data... buffer[18] = calculateChecksum(3, sizeof(buffer), buffer); // Checksum mutex.lock(); addDataToMemPool(sizeof(buffer), buffer, buffer[4]); mutex.unlock(); mutex2.unlock(); } } void sendXYZAccelerationsToMemPool() { while (true) { Thread::signal_wait(0x1); mutex3.lock(); int16_t accX = std::abs(functionPointers[1]()); int16_t accY = std::abs(functionPointers[2]()); int16_t accZ = std::abs(functionPointers[3]()); //printf("Acceleration X: %i\n", accX); //printf("Acceleration Y: %i\n", accY); //printf("Acceleration Z: %i\n", accZ); uint8_t buffer[24] = { 0 }; uint8_t* XAcceleration = split16bitsData(accX); uint8_t* YAcceleration = split16bitsData(accY); uint8_t* ZAcceleration = split16bitsData(accZ); buffer[0] = startDelimiter; // Start Delimiter buffer[1] = 0x00; // Length buffer[2] = 0x14; // Length buffer[3] = 0x10; // Frame Type buffer[4] = accFrameId; // Frame ID buffer[5] = coordinatorAddress[0]; // 64 bit adress buffer[6] = coordinatorAddress[1]; // 64 bit adress buffer[7] = coordinatorAddress[2]; // 64 bit adress buffer[8] = coordinatorAddress[3]; // 64 bit adress buffer[9] = coordinatorAddress[4]; // 64 bit adress buffer[10] = coordinatorAddress[5]; // 64 bit adress buffer[11] = coordinatorAddress[6]; // 64 bit adress buffer[12] = coordinatorAddress[7]; // 64 bit adress buffer[13] = 0xFF; // 16 bit adress buffer[14] = 0xFE; // 16 bit adress buffer[15] = 0x00; // Broadcast radius buffer[16] = 0x00; // Options buffer[17] = XAcceleration[0]; // RF Data... buffer[18] = XAcceleration[1]; // RF Data... buffer[19] = YAcceleration[0]; // RF Data... buffer[20] = YAcceleration[1]; // RF Data... buffer[21] = ZAcceleration[0]; // RF Data... buffer[22] = ZAcceleration[1]; // RF Data... buffer[23] = calculateChecksum(3, sizeof(buffer), buffer); // Checksum mutex.lock(); addDataToMemPool(sizeof(buffer), buffer, buffer[4]); mutex.unlock(); mutex3.unlock(); } } /* * Lire et décomposer les trames reçues: */ void readDataFromCoordinator(){ while(1) { uint8_t buffer[104] = { 0 }; if (xbee.readable() && xbee.getc() == startDelimiter) { 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: } else if (buffer[0] == 0x8A) { // Frame Type: Modem Status readModemStatus(buffer); } else if (buffer[0] == 0x8B) { // Frame Type: Transmit Status readTransmitStatus(buffer); } else if (buffer[0] == 0x97) { // Frame Type: Remote AT Command Response } else if (buffer[0] == 0x09) { // Frame Type: AT Command Response readATCommandResponse(buffer); } } } } } /* * Poser le ID du réseau PAN à rejoindre: */ void setRouterPanId(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 } /* * */ void wakeupThread1() { t1->signal_set(0x1); } void wakeupThread2() { t2->signal_set(0x1); } // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- int main() { printf("Starting a router...\n"); reset = 0; wait_ms(1); reset = 1; wait_ms(1); mma8452.init(); mma8452.activate(); readConfigFile(); setRouterPanId(panId); functionPointers[0] = readDryContact; functionPointers[1] = readXAcceleration; functionPointers[2] = readYAcceleration; functionPointers[3] = readZAcceleration; // Démarrage des tâches... Thread _readDryContact(sendDryContactToMemPool); Thread _readAccelerations(sendXYZAccelerationsToMemPool); Thread _sendDataToCoordinator(sendDataToCoordinator); Thread _readDataFromCoordinator(readDataFromCoordinator); t1 = &_readDryContact; t2 = &_readAccelerations; ticker1.attach(&wakeupThread1, dryContactPeriod); ticker2.attach(&wakeupThread2, accelerometerPeriod); while (1) {} }