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

Dependencies:   EthernetInterface MQTT mbed-rtos mbed nRF24L01P

main.cpp

Committer:
Mephi
Date:
2015-06-03
Revision:
0:cec410958705

File content as of revision 0:cec410958705:

#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...
    }
}