Takes in sensor readings from NRF24 connected nodes and publises the data over MQTT

Dependencies:   EthernetInterface MQTT mbed-rtos mbed nRF24L01P

Revision:
0:cec410958705
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 03 18:46:47 2015 +0000
@@ -0,0 +1,285 @@
+#include "mbed.h"
+#include "MQTTEthernet.h"
+#include "MQTTClient.h"
+#include "nRF24L01P.h"
+
+#define TRANSFER_SIZE 8 
+const uint8_t NodeID = 1;
+const uint8_t Nodes = 19;
+
+Serial pc(USBTX, USBRX); // tx, rx
+nRF24L01P my_nrf24l01p(p5, p6, p7, p8, p9, p10);    // mosi, miso, sck, csn, ce, irq
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);   
+
+float brightness = 0.0f;
+char txData[TRANSFER_SIZE], rxData[TRANSFER_SIZE], oldRxData[TRANSFER_SIZE];
+int arrivedcount = 0;
+time_t seconds;
+
+struct MQTTmessage {
+    char topic[50];
+    char value[50];
+    bool isNumeric;
+};
+
+struct lastHeard {
+    uint8_t address;
+    time_t seconds;
+};
+
+
+struct lastHeard lastHeardArray[Nodes];
+
+const struct MQTTtoNRF24map {
+    uint8_t address;
+    char topic[50];
+} maps[Nodes] = {
+    {100, "temperature/study"},
+    {101, "temperature/entrance"},
+    {102, "temperature/hall"},
+    {103, "temperature/lounge"},
+    {104, "temperature/utility"},
+    {105, "temperature/kitchen"},
+    {106, "temperature/toilet"},
+    {107, "temperature/landing"},
+    {108, "temperature/mainBedroom"},
+    {109, "temperature/samBedroom"},
+    {110, "temperature/meganBedroom"},
+    {111, "temperature/spareBedroom"},
+    {112, "temperature/bathroom"},
+    {113, "temperature/outside"},
+    {114, "temperature/garage"},
+    {120, "door/garage"},
+    {121, "door/garageBig"},
+    {122, "door/study"},
+    {150, "power/house"},
+    };
+
+struct MQTTmessage makeMessage(char topic[50], char value[50], bool isNumeric) {
+    struct MQTTmessage returnMessage;
+    strncpy(returnMessage.topic, topic, 50);
+    strncpy(returnMessage.value, value, 50);
+    returnMessage.isNumeric = isNumeric;
+    return returnMessage;
+}
+
+int checkDuplicates(char inRx[TRANSFER_SIZE], char inOldRx[TRANSFER_SIZE]) {
+    int i;
+    for (i = 0; i < TRANSFER_SIZE; i++) {
+        if (inRx[i] != inOldRx[i]) {return 1;}      // And if it's not the same as the last one recieved
+    }
+    return 0;
+}
+
+void sendMessage(MQTT::Client<MQTTEthernet, Countdown> client, struct MQTTmessage inMessage) {
+    MQTT::Message message;
+    message.qos = MQTT::QOS0;
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)inMessage.value;
+    if (inMessage.isNumeric) {
+        message.payloadlen = strlen(inMessage.value);
+    } else {
+        message.payloadlen = strlen(inMessage.value) + 1;
+    }client.publish(inMessage.topic, message);
+    while (arrivedcount < 1)
+        client.yield(100);
+    seconds = time(NULL);
+    pc.printf("%d : Sent message to %s : %s\r\n", seconds, inMessage.topic, inMessage.value);
+}
+
+char* decodeTemperatures(uint8_t inTemp) {
+    char tempStr[50];
+    sprintf(tempStr, "%4.2f", ((float)inTemp - 20) / 2);
+    return tempStr;
+}
+
+struct MQTTmessage useRadioData(){
+    struct MQTTmessage returnMessage;   
+    bool foundMap = false;
+    for (int i=0; i<Nodes; i++) {
+        if (maps[i].address == rxData[0]) {
+            lastHeardArray[i].seconds = seconds;
+            if (strncmp(maps[i].topic, "temp", 4) == 0) {
+                strncpy(returnMessage.topic, maps[i].topic, 50);
+                strncpy(returnMessage.value, decodeTemperatures(rxData[7]), 50);
+                returnMessage.isNumeric = true;
+            } else if (strncmp(maps[i].topic, "door", 4) == 0) {
+                strncpy(returnMessage.topic, maps[i].topic, 50);
+                if (rxData[7] == 255) {
+                    strncpy(returnMessage.value, "ON", 8);
+                } else if (rxData[7] == 0) {
+                    strncpy(returnMessage.value, "OFF", 8);
+                } else {
+                    strncpy(returnMessage.value, "Unknown", 8);
+                }
+                returnMessage.isNumeric = false;
+            } else {
+                strncpy(returnMessage.topic, maps[i].topic, 50);
+                strncpy(returnMessage.value, decodeTemperatures(rxData[7]), 50);
+                returnMessage.isNumeric = false;
+            }
+            foundMap = true;
+            break;
+        }
+    } 
+    if (!foundMap){
+        strncpy(returnMessage.topic, "mBed/UnknownMessage", 50);
+        strncpy(returnMessage.value, rxData, 8);
+    }
+    return returnMessage;
+}
+
+void messageArrived(MQTT::MessageData& md) {
+    MQTT::Message &message = md.message;
+    pc.printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
+    pc.printf("Payload %.*s\r\n", message.payloadlen, (char*)message.payload);
+    ++arrivedcount;
+    pc.puts((char*)message.payload);
+}
+
+int main() {
+    set_time(0);
+    seconds = time(NULL);
+    pc.printf("%d : mBed started\r\n", seconds);
+    
+    for (int i=0; i<Nodes; i++) {
+        lastHeardArray[i].address = maps[i].address;
+    }
+    
+    //MQTT init
+    MQTTEthernet ipstack = MQTTEthernet();
+    MQTT::Client<MQTTEthernet, Countdown> client = MQTT::Client<MQTTEthernet, Countdown>(ipstack);
+
+    char* hostname = "172.16.0.1";
+    int port = 1883;
+    char* topic = "mBed";
+    seconds = time(NULL);
+    pc.printf("%d : Connecting to %s:%d\r\n", seconds, hostname, port);
+    int rc = ipstack.connect(hostname, port);
+    if (rc != 0) {
+        seconds = time(NULL);
+        pc.printf("%d : rc from TCP connect is %d\r\n", seconds, rc);
+    }
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+    data.MQTTVersion = 3;
+    data.clientID.cstring = "mbed-sample";
+    data.username.cstring = "testuser";
+    data.password.cstring = "testpassword";
+    if ((rc = client.connect(data)) != 0){
+        seconds = time(NULL);
+        pc.printf("%d : rc from MQTT connect is %d\r\n", seconds, rc);
+    }
+    if ((rc = client.subscribe(topic, MQTT::QOS1, messageArrived)) != 0) {
+        seconds = time(NULL);    
+        pc.printf("%d : rc from MQTT subscribe is %d\r\n", seconds, rc);    
+    }
+    sendMessage(client, makeMessage("mBed", "mBed powered up", false));
+    //End MQTT init
+    
+    
+    //Start NRF24 Init
+    //int txDataCnt = 0;
+    //int rxDataCnt = 0;
+    
+    my_nrf24l01p.powerUp();
+    my_nrf24l01p.setRfFrequency(2525);
+    my_nrf24l01p.setTransferSize( TRANSFER_SIZE );
+    my_nrf24l01p.setCrcWidth(16);
+    my_nrf24l01p.setAirDataRate(250);
+    my_nrf24l01p.disableAutoAcknowledge();
+    my_nrf24l01p.setRxAddress(0xe7e7e7e7e8);
+    my_nrf24l01p.setTxAddress(0xe7e7e7e7e7);
+    my_nrf24l01p.disableAutoRetransmit();
+    
+    pc.printf( "nRF24L01+ Frequency    : %d MHz\r\n",  my_nrf24l01p.getRfFrequency() );
+    pc.printf( "nRF24L01+ Output power : %d dBm\r\n",  my_nrf24l01p.getRfOutputPower() );
+    pc.printf( "nRF24L01+ Data Rate    : %d kbps\r\n", my_nrf24l01p.getAirDataRate() );
+    pc.printf( "nRF24L01+ TX Address   : 0x%010llX\r\n", my_nrf24l01p.getTxAddress() );
+    pc.printf( "nRF24L01+ RX Address   : 0x%010llX\r\n", my_nrf24l01p.getRxAddress() );
+    pc.printf( "nRF24L01+ CRC Width    : %d bits\r\n", my_nrf24l01p.getCrcWidth() );
+    pc.printf( "nRF24L01+ TransferSize : %d bytes\r\n", my_nrf24l01p.getTransferSize() );
+    
+    my_nrf24l01p.setReceiveMode();
+    my_nrf24l01p.enable();
+    //End NRF24 init
+    
+    while (1) {
+        if ( my_nrf24l01p.readable() ) {
+            //rxDataCnt = 
+            my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, TRANSFER_SIZE );
+            myled1 = 1;
+            int notDuplicate = checkDuplicates(rxData, oldRxData);
+            if ( rxData[1]==NodeID ) {             // Addressed to this node, and not the same as the last one
+                seconds = time(NULL);
+                pc.printf("%d : New NRF Data: ", seconds);
+
+                //int i;
+                for (int i = 0; i < TRANSFER_SIZE; i++) {
+                    oldRxData[i] = rxData[i];
+                    if (i > 0) printf(":");
+                    printf("%d", rxData[i]);
+                }
+                printf(" - ");
+                txData[0] = rxData[1];                      // Send response back to source
+                txData[1] = NodeID;                         // From this host
+                txData[2] = 2;                              // as an Ack...
+                txData[3] = rxData[3];                      // ...to the packet ID that was recieved
+                txData[4] = 0;                              // with an empty payload
+                txData[5] = 0;
+                txData[6] = 0;
+                txData[7] = 0;                              
+                
+                my_nrf24l01p.setTransmitMode();
+                for (int i = 0; i < 8; i++) {
+                    //txDataCnt = 
+                    my_nrf24l01p.write( NRF24L01P_PIPE_P1, txData, TRANSFER_SIZE );
+                    wait_us(500);
+                }
+                my_nrf24l01p.setReceiveMode();
+                                
+                for (int i = 0; i < TRANSFER_SIZE; i++) {
+                    if (i > 0) pc.printf(":");
+                    pc.printf("%d", txData[i]);
+                }
+                printf("\r\n");
+                
+                seconds = time(NULL);
+                pc.printf("%d : Sending NRF data \r\n", seconds);            
+                if (notDuplicate) {
+                    if(!client.isConnected()) {
+                        myled4 = 1;
+                        pc.printf("%d : Connecting to %s:%d\r\n", seconds, hostname, port);
+                        rc = ipstack.connect(hostname, port);
+                        if (rc != 0) {
+                            seconds = time(NULL);
+                            pc.printf("%d : rc from TCP connect is %d\r\n", seconds, rc);
+                        }
+                        /*
+                        data = MQTTPacket_connectData_initializer;       
+                        data.MQTTVersion = 3;
+                        data.clientID.cstring = "mbed-sample";
+                        data.username.cstring = "testuser";
+                        data.password.cstring = "testpassword";
+                        */
+                        if ((rc = client.connect(data)) != 0){
+                            seconds = time(NULL);
+                            pc.printf("%d : rc from MQTT connect is %d\r\n", seconds, rc);
+                        }
+                        if ((rc = client.subscribe(topic, MQTT::QOS1, messageArrived)) != 0) {
+                            seconds = time(NULL);    
+                            pc.printf("%d : rc from MQTT subscribe is %d\r\n", seconds, rc);    
+                        }
+                        sendMessage(client, makeMessage("mBed", "session died, restarting", false));
+                    }
+                    sendMessage(client, useRadioData());
+                }    
+            }
+            myled1 = 0;
+        }
+        // insert mqtt poller here...
+    }
+}
\ No newline at end of file