GDP group 24 node core

Dependencies:   EthernetInterface SDFileSystem mbed-rtos mbed snail MbedJSONValue

main.cpp

Committer:
Trumple
Date:
2015-01-13
Revision:
15:1d98f45717bc
Parent:
10:13176e7bd4c8
Child:
21:a32666afce7a

File content as of revision 15:1d98f45717bc:

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

#define DEBUG

time_t lastPollTime = 0;
time_t pollInterval = 30;


bool isBasenode = true;
string fieldID = "testfield";

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;

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 fBuffer[3];
            sprintf(fBuffer, "%i", request.sensors[i].type);
            j["sensors"][i]["sensorID"] = string(sensorIDBuffer);
            j["sensors"][i]["sensortype"] = string(fBuffer);
        }
        
        string address = addressToString(request.source);
        #ifdef DEBUG
            pc.printf( ("[MAIN] POSTing startup information: " + j.serialize() + "\r\n").c_str() );
        #endif
        h.post("178.62.84.55", 8888, "/field/" + fieldID + "/" + 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);
    
    int value = 0;
    value += d.payload[0];
    value = value << 8;
    value += d.payload[1];
    
    char sensorID[3];
    sprintf(sensorID, "%i", d.i2cAddress);
    
    MbedJSONValue j;
    j["timestamp"] = (int)time(NULL);
    j["value"] = value;
    
    #ifdef DEBUG
        pc.printf( ("[MAIN] POSTing sensor reading: " + j.serialize() + "\r\n").c_str() );
    #endif
    
    h.post("178.62.84.55", 8888, "/field/" + fieldID + "/" + 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->first;
        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();
}

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 | 2014\r\n");
        pc.printf("\r\n");
        pc.printf("\r\n");
    #endif
    //sdcard sd = sdcard();
    
    //TODO: read basenode pin
    #ifdef DEBUG
        pc.printf("[MAIN] Basenode switch: %i\r\n", isBasenode);
    #endif
    
    //TODO: load configuration from SD
    
    getLocalAddress();
    
    if (isBasenode)
    {
        h.connect();
        
        string timestampStr = h.get("time.bitnode.co.uk", 80, "/");
        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();
            
            //TODO: if message queue exceeds MAX_QUEUE SIZE, write older readings to SD card.
            
            //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%.2X|", data.readings[i]);
                    pc.printf("\r\n");
                #endif
                
                string readings_str(data.readings.begin(), data.readings.end());
                char readings[sizeof(snail::sensordata().payload)];
                memcpy(readings, readings_str.c_str(), sizeof(readings));
                
                //TODO: Get real I2C address
                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);
            }
        }
    }
}