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);
}
}
}
}
