GDP group 24 node core

Dependencies:   EthernetInterface SDFileSystem mbed-rtos mbed snail MbedJSONValue

main.cpp

Committer:
Trumple
Date:
2015-01-28
Revision:
31:9cf3f1e5ad68
Parent:
29:564b1eaf5b99

File content as of revision 31:9cf3f1e5ad68:

#include "mbed.h"
#include "snail.h"
#include "sensorinterface.h"
#include "sdcard.h"
#include "http.h"
#include "MbedJSONValue.h"
#include <map>

#define DEBUG
#define API_IP "178.62.84.55"
#define API_PORT 8888
#define API_TIME_IP "81.4.121.72"
#define API_TIME_PORT 80

time_t lastPollTime = 0;
time_t pollInterval = 30;

bool isBasenode = false;

http h = http();
sensorinterface* sif;

char localAddress[8];
char baseNodeAddress[8];
bool networkParametersUpdated = false;
bool networkParametersTimedOut = false;
 
Serial pc(USBTX, USBRX);
snail xbee = snail();
Ticker networkParametersTimeout;

queue<snail::sensordata> messageQueue;

//commissioning button
DigitalOut commissioningOutput(p30);
InterruptIn commissioningInput(p16);

string addressToString(char address[8])
{
    string address_str;
    for(int i = 0; i < 8; i++)
    {
        char addressBuffer[2];
        sprintf(addressBuffer, "%.2X", address[i]);
        address_str += string(addressBuffer, 2);
    }
    
    return address_str;
}

void handleJoinNetworkReply(snail::message& message)
{
    pc.printf("[MAIN] Got join network reply...\r\n");
    snail::joinnetworkreply& reply = static_cast<snail::joinnetworkreply&>(message);
    set_time(reply.timestamp);
    memcpy(baseNodeAddress, reply.baseNodeAddress, sizeof(baseNodeAddress));
    
    networkParametersUpdated = true;
}

void handleJoinNetworkRequest(snail::message& message)
{
    pc.printf("[MAIN] Got join network request...\r\n");
    if (isBasenode)
    {
        snail::joinnetworkrequest& request = static_cast<snail::joinnetworkrequest&>(message);
        
        //report connected sensors to server
        MbedJSONValue j;
        j["sensors"];
        for (int i = 0; i < request.sensorCount; i++)
        {
            char sensorIDBuffer[3];
            sprintf(sensorIDBuffer, "%i", request.sensors[i].id);
            char typeBuffer[3];
            sprintf(typeBuffer, "%i", request.sensors[i].type);
            j["sensors"][i]["sensorID"] = string(sensorIDBuffer);
            j["sensors"][i]["sensortype"] = string(typeBuffer);
        }
        
        string address = addressToString(request.source);
        #ifdef DEBUG
            pc.printf( ("[MAIN] POSTing startup information: " + j.serialize() + "\r\n").c_str() );
        #endif
        h.post(API_IP, API_PORT, "/field/" + string(localAddress) + "/" + address + "/startup/", j.serialize()).c_str();
        
        snail::joinnetworkreply reply(request.source, time(NULL), localAddress);
        xbee.send(reply, sizeof(reply));
    }
}

void handleSensorData(snail::message& message)
{
    pc.printf("[MAIN] Got sensor data...\r\n");
    snail::sensordata& d = static_cast<snail::sensordata&>(message);
    
    char sensorID[3];
    sprintf(sensorID, "%i", d.i2cAddress);
    
    MbedJSONValue j;
    j["timestamp"] = (int)time(NULL);
    
    for (int i = 0; i < d.payloadSize; i++)
        j["value"][i] = d.payload[i];
    
    #ifdef DEBUG
        pc.printf( ("[MAIN] POSTing sensor reading: " + j.serialize() + "\r\n").c_str() );
    #endif
    
    h.post(API_IP, API_PORT, "/field/" + string(localAddress) + "/" + addressToString(d.source) + "/" + sensorID + "/", j.serialize()).c_str();
}

void handleNetworkParametersTimeout()
{
    networkParametersTimedOut = true;
}

void getLocalAddress()
{
    pc.printf("[MAIN] Requesting lower address bits...\r\n");
    xbee.ATCommand("SL");
    
    while (!xbee.isATCommandResponseWaiting())
        xbee.processIncomingData();
        
    snail::atcommandresponse SLr = xbee.getATCommandResponse();
    
    pc.printf("[MAIN] Requesting upper address bits...\r\n");
    xbee.ATCommand("SH");
    
    while (!xbee.isATCommandResponseWaiting())
        xbee.processIncomingData();
        
    snail::atcommandresponse SHr = xbee.getATCommandResponse();
    
    string address(SHr.response);
    address += SLr.response;
    
    pc.printf("[MAIN] Got local address: ");
    
    for (int i = 0; i < address.size(); i++)
        pc.printf("%.2X", address[i]);
    
    pc.printf("\r\n");
    
    memcpy(localAddress, address.c_str(), sizeof(localAddress));
}

void getNetworkParameters()
{
    #ifdef DEBUG
        pc.printf("[MAIN] Requesting to join network...\r\n");
    #endif
    
    //prepare for response from basenode
    xbee.registerMessageCallback(MESSAGE_JOIN_NETWORK_REPLY, handleJoinNetworkReply);
    
    //handle retrying after timeout
    networkParametersTimeout.attach(&handleNetworkParametersTimeout, 30.0);
    
    //generate list of sensors attached
    snail::joinnetworkrequest::sensor localSensors[32];
    map<char, sensor>::iterator cs = sif->sensors.begin();
    int i = 0;
    
    //either loop until we reach the end of the sensors or until we hit the max
    while (cs != sif->sensors.end() && i < 32)
    {
        localSensors[i].type = cs->second.type;
        localSensors[i].id = cs->second.type;
        i++;
        cs++;
    }
    
    #ifdef DEBUG
        pc.printf("[MAIN] Informing basenode of %i attached devices\r\n", i);
    #endif
    
    //construct joinnetworkrequest, including the number of sensors attached
    snail::joinnetworkrequest request(localSensors, i);
    
    xbee.send(request, sizeof(request));
    
    while(!networkParametersUpdated)
    {
        if (networkParametersTimedOut)
        {
            #ifdef DEBUG
                pc.printf("[MAIN] Timed out, retrying...\r\n");
            #endif
            xbee.send(request, sizeof(request));
            networkParametersTimedOut = false;
        }
        xbee.processIncomingData();
    }
    
    #ifdef DEBUG
        pc.printf("[MAIN] Got network parameters. Time: %i, base node address: ", time(NULL));
        
        for (int i = 0; i < sizeof(baseNodeAddress); i++)
            pc.printf("%.2X", baseNodeAddress[i]);
        pc.printf("\r\n");
    #endif
    //no longer need to handle timeout
    networkParametersTimeout.detach();
}

void commissioningFall()
{
    commissioningOutput = 0;
}

void commissioningRise()
{
    commissioningOutput = 1;
}

int main()
{
    #ifdef DEBUG
        pc.printf("[MAIN] Starting up...\r\n");
        pc.printf("                         .       .\r\n");
        pc.printf("                        / `.   .' \\\r\n");
        pc.printf("                .---.  <    > <    >  .---.\r\n");
        pc.printf("                |    \\  \\ - ~ ~ - /  /    |\r\n");
        pc.printf("                 ~-..-~             ~-..-~\r\n");
        pc.printf("             \\~~~\\.'                    `./~~~/\r\n");
        pc.printf("   .-~~^-.    \\__/                        \\__/\r\n");
        pc.printf(" .'  O    \\     /               /       \\  \\\r\n");
        pc.printf("(_____,    `._.'               |         }  \\/~~~/\r\n");
        pc.printf(" `----.          /       }     |        /    \\__/\r\n");
        pc.printf("       `-.      |       /      |       /      `. ,~~|\r\n");
        pc.printf("           ~-.__|      /_ - ~ ^|      /- _      `..-'   f: f:\r\n");
        pc.printf("                |     /        |     /     ~-.     `-. _||_||_\r\n");
        pc.printf("                |_____|        |_____|         ~ - . _ _ _ _ _>\r\n");
        pc.printf("\r\n");
        pc.printf("\r\n");
        pc.printf("         Sensorsaurus | Team 24 GDP | Southampton | 2015\r\n");
        pc.printf("\r\n");
        pc.printf("\r\n");
    #endif
    sdcard sd = sdcard();
    h.connect();
    
    //commissioning button
    commissioningInput.fall(commissioningFall);
    commissioningInput.rise(commissioningRise);
    
    //check if local node is basenode
    isBasenode = h.isEthernetConnected();
    #ifdef DEBUG
        pc.printf("[MAIN] Basenode status: %i\r\n", isBasenode);
    #endif
    
    getLocalAddress();
    
    if (isBasenode)
    {   
        string timestampStr = h.get(API_TIME_IP, API_TIME_PORT, "/");
        time_t timestamp = atoi(timestampStr.c_str());
        
        set_time(timestamp);
        
        pc.printf("[MAIN] Got time: %i\r\n", timestamp);
        
        xbee.registerMessageCallback(MESSAGE_JOIN_NETWORK_REQUEST, handleJoinNetworkRequest);
        xbee.registerMessageCallback(MESSAGE_SENSOR_DATA, handleSensorData);
        
        while(1)
        {
            #ifdef DEBUG
                pc.printf("[MAIN] Basenode is idle\r\n");
            #endif
            
            wait(1);
            xbee.processIncomingData();
        }
    }
    else
    {
        sensorinterface sensors = sensorinterface();
        sif = &sensors;
        getNetworkParameters();
        
        while(1)
        {
            xbee.processIncomingData();
            
            //if xbee is awake send contents of message queue
            if (xbee.isCTS())
            {
                while(!messageQueue.empty())
                {
                    snail::sensordata message = messageQueue.front();
                    xbee.send(message, sizeof(message));
                    messageQueue.pop();
                }
            }
            
            //check if it's time to poll
            if (time(NULL) - lastPollTime > pollInterval)
            {
                #ifdef DEBUG
                    pc.printf("[MAIN] Requesting data...\r\n");
                #endif
                sensors.requestData();
                lastPollTime = time(NULL);
            }
            
            //if there is data waiting for us...
            if (sensors.isDataWaiting())
            {
                #ifdef DEBUG
                    pc.printf("[MAIN] Data waiting, reading data...\r\n");
                #endif
                
                d_reply data = sensors.readData();
                
                #ifdef DEBUG
                    pc.printf("[MAIN] Got data: ");
                    for (int i = 0; i < data.readings.size(); i++)
                        pc.printf("0x%.4X|", data.readings[i]);
                    pc.printf("\r\n");
                #endif
                
                int readings[16];
                for (int i = 0; i < data.readings.size(); i++)
                    readings[i] = data.readings[i];
                
                snail::sensordata message(baseNodeAddress, data.type, data.type, time(NULL), readings, data.readings.size());
                
                messageQueue.push(message);
                
                //log
                sd.write(static_cast<long int>(time(NULL)), data);
            }
        }
    }
}