GDP group 24 node core

Dependencies:   EthernetInterface SDFileSystem mbed-rtos mbed snail MbedJSONValue

Committer:
Trumple
Date:
Tue Dec 23 21:28:40 2014 +0000
Revision:
10:13176e7bd4c8
Parent:
9:f0030295ae9b
Child:
15:1d98f45717bc
POST connected sensors to web API when a node requests to join the network, POST sensor data readings to web API using appropriate node and sensor IDs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Trumple 0:fcab3b154e49 1 #include "mbed.h"
Trumple 0:fcab3b154e49 2 #include "snail.h"
Trumple 0:fcab3b154e49 3 #include "sensorinterface.h"
Trumple 0:fcab3b154e49 4 #include "sdcard.h"
Trumple 1:27b35752c5d0 5 #include "http.h"
Trumple 2:1cbb20dd1733 6 #include "MbedJSONValue.h"
Trumple 8:fd531fe7637b 7 #include <map>
Trumple 0:fcab3b154e49 8
Trumple 0:fcab3b154e49 9 #define DEBUG
Trumple 0:fcab3b154e49 10
Trumple 0:fcab3b154e49 11 time_t lastPollTime = 0;
Trumple 0:fcab3b154e49 12 time_t pollInterval = 30;
Trumple 2:1cbb20dd1733 13
Trumple 0:fcab3b154e49 14
Trumple 0:fcab3b154e49 15 bool isBasenode = false;
Trumple 10:13176e7bd4c8 16 string fieldID = "testfield";
Trumple 10:13176e7bd4c8 17
Trumple 2:1cbb20dd1733 18 http h = http();
Trumple 8:fd531fe7637b 19 sensorinterface* sif;
Trumple 8:fd531fe7637b 20
Trumple 1:27b35752c5d0 21 char localAddress[8];
Trumple 2:1cbb20dd1733 22 char baseNodeAddress[8];
Trumple 1:27b35752c5d0 23 bool networkParametersUpdated = false;
Trumple 1:27b35752c5d0 24 bool networkParametersTimedOut = false;
Trumple 0:fcab3b154e49 25
Trumple 0:fcab3b154e49 26 Serial pc(USBTX, USBRX);
Trumple 1:27b35752c5d0 27 snail xbee = snail();
Trumple 1:27b35752c5d0 28 Ticker networkParametersTimeout;
Trumple 0:fcab3b154e49 29
jakehodges 6:92ddc620a78f 30 queue<snail::sensordata> messageQueue;
jakehodges 6:92ddc620a78f 31
Trumple 10:13176e7bd4c8 32 string addressToString(char address[8])
Trumple 10:13176e7bd4c8 33 {
Trumple 10:13176e7bd4c8 34 string address_str;
Trumple 10:13176e7bd4c8 35 for(int i = 0; i < 8; i++)
Trumple 10:13176e7bd4c8 36 {
Trumple 10:13176e7bd4c8 37 char addressBuffer[2];
Trumple 10:13176e7bd4c8 38 sprintf(addressBuffer, "%.2X", address[i]);
Trumple 10:13176e7bd4c8 39 address_str += string(addressBuffer, 2);
Trumple 10:13176e7bd4c8 40 }
Trumple 10:13176e7bd4c8 41
Trumple 10:13176e7bd4c8 42 return address_str;
Trumple 10:13176e7bd4c8 43 }
Trumple 10:13176e7bd4c8 44
Trumple 2:1cbb20dd1733 45 void handleJoinNetworkReply(snail::message& message)
Trumple 1:27b35752c5d0 46 {
Trumple 2:1cbb20dd1733 47 pc.printf("[MAIN] Got join network reply...\r\n");
Trumple 2:1cbb20dd1733 48 snail::joinnetworkreply& reply = static_cast<snail::joinnetworkreply&>(message);
Trumple 2:1cbb20dd1733 49 set_time(reply.timestamp);
Trumple 2:1cbb20dd1733 50 memcpy(baseNodeAddress, reply.baseNodeAddress, sizeof(baseNodeAddress));
Trumple 2:1cbb20dd1733 51
Trumple 1:27b35752c5d0 52 networkParametersUpdated = true;
Trumple 1:27b35752c5d0 53 }
Trumple 1:27b35752c5d0 54
Trumple 2:1cbb20dd1733 55 void handleJoinNetworkRequest(snail::message& message)
Trumple 0:fcab3b154e49 56 {
Trumple 2:1cbb20dd1733 57 pc.printf("[MAIN] Got join network request...\r\n");
Trumple 1:27b35752c5d0 58 if (isBasenode)
Trumple 1:27b35752c5d0 59 {
Trumple 2:1cbb20dd1733 60 snail::joinnetworkrequest& request = static_cast<snail::joinnetworkrequest&>(message);
Trumple 2:1cbb20dd1733 61
Trumple 10:13176e7bd4c8 62 //report connected sensors to server
Trumple 10:13176e7bd4c8 63 MbedJSONValue j;
Trumple 10:13176e7bd4c8 64 j["sensors"];
Trumple 10:13176e7bd4c8 65 for (int i = 0; i < request.sensorCount; i++)
Trumple 10:13176e7bd4c8 66 {
Trumple 10:13176e7bd4c8 67 char sensorIDBuffer[3];
Trumple 10:13176e7bd4c8 68 sprintf(sensorIDBuffer, "%i", request.sensors[i].id);
Trumple 10:13176e7bd4c8 69 char fBuffer[3];
Trumple 10:13176e7bd4c8 70 sprintf(fBuffer, "%i", request.sensors[i].type);
Trumple 10:13176e7bd4c8 71 j["sensors"][i]["sensorID"] = string(sensorIDBuffer);
Trumple 10:13176e7bd4c8 72 j["sensors"][i]["sensortype"] = string(fBuffer);
Trumple 10:13176e7bd4c8 73 }
Trumple 10:13176e7bd4c8 74
Trumple 10:13176e7bd4c8 75 string address = addressToString(request.source);
Trumple 10:13176e7bd4c8 76 #ifdef DEBUG
Trumple 10:13176e7bd4c8 77 pc.printf( ("[MAIN] POSTing startup information: " + j.serialize() + "\r\n").c_str() );
Trumple 10:13176e7bd4c8 78 #endif
Trumple 10:13176e7bd4c8 79 h.post("178.62.84.55", 8888, "/field/" + fieldID + "/" + address + "/startup/", j.serialize()).c_str();
Trumple 10:13176e7bd4c8 80
Trumple 2:1cbb20dd1733 81 snail::joinnetworkreply reply(request.source, time(NULL), localAddress);
Trumple 1:27b35752c5d0 82 xbee.send(reply, sizeof(reply));
Trumple 1:27b35752c5d0 83 }
Trumple 1:27b35752c5d0 84 }
Trumple 1:27b35752c5d0 85
Trumple 2:1cbb20dd1733 86 void handleSensorData(snail::message& message)
Trumple 2:1cbb20dd1733 87 {
Trumple 2:1cbb20dd1733 88 pc.printf("[MAIN] Got sensor data...\r\n");
Trumple 2:1cbb20dd1733 89 snail::sensordata& d = static_cast<snail::sensordata&>(message);
Trumple 2:1cbb20dd1733 90
Trumple 4:0bab12a0cc9a 91 int value = 0;
Trumple 4:0bab12a0cc9a 92 value += d.payload[0];
Trumple 4:0bab12a0cc9a 93 value = value << 8;
Trumple 4:0bab12a0cc9a 94 value += d.payload[1];
Trumple 4:0bab12a0cc9a 95
Trumple 10:13176e7bd4c8 96 char sensorID[3];
Trumple 10:13176e7bd4c8 97 sprintf(sensorID, "%i", d.i2cAddress);
Trumple 10:13176e7bd4c8 98
Trumple 4:0bab12a0cc9a 99 MbedJSONValue j;
Trumple 4:0bab12a0cc9a 100 j["timestamp"] = (int)time(NULL);
Trumple 4:0bab12a0cc9a 101 j["value"] = value;
Trumple 10:13176e7bd4c8 102
Trumple 10:13176e7bd4c8 103 #ifdef DEBUG
Trumple 10:13176e7bd4c8 104 pc.printf( ("[MAIN] POSTing sensor reading: " + j.serialize() + "\r\n").c_str() );
Trumple 10:13176e7bd4c8 105 #endif
Trumple 10:13176e7bd4c8 106
Trumple 10:13176e7bd4c8 107 h.post("178.62.84.55", 8888, "/field/" + fieldID + "/" + addressToString(d.source) + "/" + sensorID + "/", j.serialize()).c_str();
Trumple 2:1cbb20dd1733 108 }
Trumple 2:1cbb20dd1733 109
Trumple 1:27b35752c5d0 110 void handleNetworkParametersTimeout()
Trumple 1:27b35752c5d0 111 {
Trumple 1:27b35752c5d0 112 networkParametersTimedOut = true;
Trumple 1:27b35752c5d0 113 }
Trumple 1:27b35752c5d0 114
Trumple 1:27b35752c5d0 115 void getLocalAddress()
Trumple 1:27b35752c5d0 116 {
Trumple 2:1cbb20dd1733 117 pc.printf("[MAIN] Requesting lower address bits...\r\n");
Trumple 2:1cbb20dd1733 118 xbee.ATCommand("SL");
Trumple 2:1cbb20dd1733 119
Trumple 2:1cbb20dd1733 120 while (!xbee.isATCommandResponseWaiting())
Trumple 2:1cbb20dd1733 121 xbee.processIncomingData();
Trumple 2:1cbb20dd1733 122
Trumple 2:1cbb20dd1733 123 snail::atcommandresponse SLr = xbee.getATCommandResponse();
Trumple 2:1cbb20dd1733 124
Trumple 2:1cbb20dd1733 125 pc.printf("[MAIN] Requesting upper address bits...\r\n");
Trumple 2:1cbb20dd1733 126 xbee.ATCommand("SH");
Trumple 2:1cbb20dd1733 127
Trumple 2:1cbb20dd1733 128 while (!xbee.isATCommandResponseWaiting())
Trumple 2:1cbb20dd1733 129 xbee.processIncomingData();
Trumple 2:1cbb20dd1733 130
Trumple 2:1cbb20dd1733 131 snail::atcommandresponse SHr = xbee.getATCommandResponse();
Trumple 2:1cbb20dd1733 132
Trumple 2:1cbb20dd1733 133 string address(SHr.response);
Trumple 2:1cbb20dd1733 134 address += SLr.response;
Trumple 2:1cbb20dd1733 135
Trumple 2:1cbb20dd1733 136 pc.printf("[MAIN] Got local address: ");
Trumple 2:1cbb20dd1733 137
Trumple 2:1cbb20dd1733 138 for (int i = 0; i < address.size(); i++)
Trumple 2:1cbb20dd1733 139 pc.printf("%.2X", address[i]);
Trumple 2:1cbb20dd1733 140
Trumple 2:1cbb20dd1733 141 pc.printf("\r\n");
Trumple 2:1cbb20dd1733 142
Trumple 2:1cbb20dd1733 143 memcpy(localAddress, address.c_str(), sizeof(localAddress));
Trumple 1:27b35752c5d0 144 }
Trumple 1:27b35752c5d0 145
Trumple 1:27b35752c5d0 146 void getNetworkParameters()
Trumple 1:27b35752c5d0 147 {
Trumple 1:27b35752c5d0 148 #ifdef DEBUG
Trumple 2:1cbb20dd1733 149 pc.printf("[MAIN] Requesting to join network...\r\n");
Trumple 1:27b35752c5d0 150 #endif
Trumple 0:fcab3b154e49 151
Trumple 8:fd531fe7637b 152 //prepare for response from basenode
Trumple 2:1cbb20dd1733 153 xbee.registerMessageCallback(MESSAGE_JOIN_NETWORK_REPLY, handleJoinNetworkReply);
Trumple 2:1cbb20dd1733 154
Trumple 8:fd531fe7637b 155 //handle retrying after timeout
Trumple 2:1cbb20dd1733 156 networkParametersTimeout.attach(&handleNetworkParametersTimeout, 30.0);
Trumple 1:27b35752c5d0 157
Trumple 8:fd531fe7637b 158 //generate list of sensors attached
Trumple 8:fd531fe7637b 159 snail::joinnetworkrequest::sensor localSensors[32];
Trumple 8:fd531fe7637b 160 map<char, sensor>::iterator cs = sif->sensors.begin();
Trumple 8:fd531fe7637b 161 int i = 0;
Trumple 8:fd531fe7637b 162
Trumple 8:fd531fe7637b 163 //either loop until we reach the end of the sensors or until we hit the max
Trumple 8:fd531fe7637b 164 while (cs != sif->sensors.end() && i < 32)
Trumple 8:fd531fe7637b 165 {
Trumple 8:fd531fe7637b 166 localSensors[i].type = cs->second.type;
Trumple 8:fd531fe7637b 167 localSensors[i].id = cs->first;
Trumple 8:fd531fe7637b 168 i++;
Trumple 8:fd531fe7637b 169 cs++;
Trumple 8:fd531fe7637b 170 }
Trumple 8:fd531fe7637b 171
Trumple 8:fd531fe7637b 172 #ifdef DEBUG
Trumple 8:fd531fe7637b 173 pc.printf("[MAIN] Informing basenode of %i attached devices\r\n", i);
Trumple 8:fd531fe7637b 174 #endif
Trumple 8:fd531fe7637b 175
Trumple 8:fd531fe7637b 176 //construct joinnetworkrequest, including the number of sensors attached
Trumple 8:fd531fe7637b 177 snail::joinnetworkrequest request(localSensors, i);
Trumple 1:27b35752c5d0 178
Trumple 1:27b35752c5d0 179 xbee.send(request, sizeof(request));
Trumple 0:fcab3b154e49 180
Trumple 1:27b35752c5d0 181 while(!networkParametersUpdated)
Trumple 1:27b35752c5d0 182 {
Trumple 1:27b35752c5d0 183 if (networkParametersTimedOut)
Trumple 1:27b35752c5d0 184 {
Trumple 1:27b35752c5d0 185 #ifdef DEBUG
Trumple 1:27b35752c5d0 186 pc.printf("[MAIN] Timed out, retrying...\r\n");
Trumple 1:27b35752c5d0 187 #endif
Trumple 1:27b35752c5d0 188 xbee.send(request, sizeof(request));
Trumple 1:27b35752c5d0 189 networkParametersTimedOut = false;
Trumple 1:27b35752c5d0 190 }
Trumple 2:1cbb20dd1733 191 xbee.processIncomingData();
Trumple 1:27b35752c5d0 192 }
Trumple 0:fcab3b154e49 193
Trumple 1:27b35752c5d0 194 #ifdef DEBUG
Trumple 2:1cbb20dd1733 195 pc.printf("[MAIN] Got network parameters. Time: %i, base node address: ", time(NULL));
Trumple 2:1cbb20dd1733 196
Trumple 2:1cbb20dd1733 197 for (int i = 0; i < sizeof(baseNodeAddress); i++)
Trumple 2:1cbb20dd1733 198 pc.printf("%.2X", baseNodeAddress[i]);
Trumple 2:1cbb20dd1733 199 pc.printf("\r\n");
Trumple 1:27b35752c5d0 200 #endif
Trumple 8:fd531fe7637b 201 //no longer need to handle timeout
Trumple 1:27b35752c5d0 202 networkParametersTimeout.detach();
Trumple 0:fcab3b154e49 203 }
Trumple 0:fcab3b154e49 204
Trumple 0:fcab3b154e49 205 int main()
Trumple 0:fcab3b154e49 206 {
Trumple 0:fcab3b154e49 207 #ifdef DEBUG
Trumple 0:fcab3b154e49 208 pc.printf("[MAIN] Starting up...\r\n");
Trumple 2:1cbb20dd1733 209 pc.printf(" . .\r\n");
Trumple 2:1cbb20dd1733 210 pc.printf(" / `. .' \\\r\n");
Trumple 2:1cbb20dd1733 211 pc.printf(" .---. < > < > .---.\r\n");
Trumple 2:1cbb20dd1733 212 pc.printf(" | \\ \\ - ~ ~ - / / |\r\n");
Trumple 2:1cbb20dd1733 213 pc.printf(" ~-..-~ ~-..-~\r\n");
Trumple 2:1cbb20dd1733 214 pc.printf(" \\~~~\\.' `./~~~/\r\n");
Trumple 2:1cbb20dd1733 215 pc.printf(" .-~~^-. \\__/ \\__/\r\n");
Trumple 2:1cbb20dd1733 216 pc.printf(" .' O \\ / / \\ \\\r\n");
Trumple 2:1cbb20dd1733 217 pc.printf("(_____, `._.' | } \\/~~~/\r\n");
Trumple 2:1cbb20dd1733 218 pc.printf(" `----. / } | / \\__/\r\n");
Trumple 2:1cbb20dd1733 219 pc.printf(" `-. | / | / `. ,~~|\r\n");
Trumple 2:1cbb20dd1733 220 pc.printf(" ~-.__| /_ - ~ ^| /- _ `..-' f: f:\r\n");
Trumple 2:1cbb20dd1733 221 pc.printf(" | / | / ~-. `-. _||_||_\r\n");
Trumple 2:1cbb20dd1733 222 pc.printf(" |_____| |_____| ~ - . _ _ _ _ _>\r\n");
Trumple 2:1cbb20dd1733 223 pc.printf("\r\n");
Trumple 2:1cbb20dd1733 224 pc.printf("\r\n");
Trumple 2:1cbb20dd1733 225 pc.printf(" Sensorsaurus | Team 24 GDP | Southampton | 2014\r\n");
Trumple 2:1cbb20dd1733 226 pc.printf("\r\n");
Trumple 2:1cbb20dd1733 227 pc.printf("\r\n");
Trumple 0:fcab3b154e49 228 #endif
Trumple 1:27b35752c5d0 229 //sdcard sd = sdcard();
Trumple 0:fcab3b154e49 230
Trumple 0:fcab3b154e49 231 //TODO: read basenode pin
Trumple 0:fcab3b154e49 232 #ifdef DEBUG
Trumple 0:fcab3b154e49 233 pc.printf("[MAIN] Basenode switch: %i\r\n", isBasenode);
Trumple 0:fcab3b154e49 234 #endif
Trumple 0:fcab3b154e49 235
Trumple 0:fcab3b154e49 236 //TODO: load configuration from SD
Trumple 0:fcab3b154e49 237
Trumple 2:1cbb20dd1733 238 getLocalAddress();
Trumple 2:1cbb20dd1733 239
Trumple 0:fcab3b154e49 240 if (isBasenode)
Trumple 1:27b35752c5d0 241 {
Trumple 1:27b35752c5d0 242 getLocalAddress();
Trumple 2:1cbb20dd1733 243 h.connect();
Trumple 2:1cbb20dd1733 244
Trumple 2:1cbb20dd1733 245 string timestampStr = h.get("time.bitnode.co.uk", 80, "/");
Trumple 2:1cbb20dd1733 246 time_t timestamp = atoi(timestampStr.c_str());
Trumple 2:1cbb20dd1733 247
Trumple 1:27b35752c5d0 248 set_time(timestamp);
Trumple 1:27b35752c5d0 249
Trumple 2:1cbb20dd1733 250 pc.printf("[MAIN] Got time: %i\r\n", timestamp);
Trumple 2:1cbb20dd1733 251
Trumple 2:1cbb20dd1733 252 xbee.registerMessageCallback(MESSAGE_JOIN_NETWORK_REQUEST, handleJoinNetworkRequest);
Trumple 2:1cbb20dd1733 253 xbee.registerMessageCallback(MESSAGE_SENSOR_DATA, handleSensorData);
Trumple 1:27b35752c5d0 254
Trumple 0:fcab3b154e49 255 while(1)
Trumple 0:fcab3b154e49 256 {
Trumple 0:fcab3b154e49 257 #ifdef DEBUG
Trumple 0:fcab3b154e49 258 pc.printf("[MAIN] Basenode is idle\r\n");
Trumple 0:fcab3b154e49 259 #endif
Trumple 0:fcab3b154e49 260
Trumple 2:1cbb20dd1733 261 wait(1);
Trumple 2:1cbb20dd1733 262 xbee.processIncomingData();
Trumple 0:fcab3b154e49 263 }
Trumple 1:27b35752c5d0 264 }
Trumple 0:fcab3b154e49 265 else
Trumple 8:fd531fe7637b 266 {
Trumple 1:27b35752c5d0 267 sensorinterface sensors = sensorinterface();
Trumple 8:fd531fe7637b 268 sif = &sensors;
Trumple 1:27b35752c5d0 269 getNetworkParameters();
Trumple 1:27b35752c5d0 270
Trumple 0:fcab3b154e49 271 while(1)
Trumple 0:fcab3b154e49 272 {
Trumple 2:1cbb20dd1733 273 xbee.processIncomingData();
jakehodges 6:92ddc620a78f 274
jakehodges 6:92ddc620a78f 275 //TODO: if message queue exceeds MAX_QUEUE SIZE, write older readings to SD card.
jakehodges 6:92ddc620a78f 276
jakehodges 6:92ddc620a78f 277 //if xbee is awake send contents of message queue
jakehodges 6:92ddc620a78f 278 if (xbee.isCTS())
jakehodges 6:92ddc620a78f 279 {
jakehodges 6:92ddc620a78f 280 while(!messageQueue.empty())
jakehodges 6:92ddc620a78f 281 {
jakehodges 6:92ddc620a78f 282 snail::sensordata message = messageQueue.front();
jakehodges 6:92ddc620a78f 283 xbee.send(message, sizeof(message));
jakehodges 6:92ddc620a78f 284 messageQueue.pop();
jakehodges 6:92ddc620a78f 285 }
jakehodges 6:92ddc620a78f 286 }
Trumple 0:fcab3b154e49 287
Trumple 4:0bab12a0cc9a 288 //check if it's time to poll
Trumple 2:1cbb20dd1733 289 if (time(NULL) - lastPollTime > pollInterval)
Trumple 0:fcab3b154e49 290 {
Trumple 0:fcab3b154e49 291 #ifdef DEBUG
Trumple 0:fcab3b154e49 292 pc.printf("[MAIN] Requesting data...\r\n");
Trumple 0:fcab3b154e49 293 #endif
Trumple 0:fcab3b154e49 294 sensors.requestData();
Trumple 0:fcab3b154e49 295 lastPollTime = time(NULL);
Trumple 0:fcab3b154e49 296 }
Trumple 0:fcab3b154e49 297
Trumple 0:fcab3b154e49 298 //if there is data waiting for us...
Trumple 0:fcab3b154e49 299 if (sensors.isDataWaiting())
Trumple 0:fcab3b154e49 300 {
Trumple 0:fcab3b154e49 301 #ifdef DEBUG
Trumple 0:fcab3b154e49 302 pc.printf("[MAIN] Data waiting, reading data...\r\n");
Trumple 0:fcab3b154e49 303 #endif
Trumple 1:27b35752c5d0 304
Trumple 0:fcab3b154e49 305 d_reply data = sensors.readData();
Trumple 1:27b35752c5d0 306
Trumple 0:fcab3b154e49 307 #ifdef DEBUG
Trumple 4:0bab12a0cc9a 308 pc.printf("[MAIN] Got data: ");
Trumple 2:1cbb20dd1733 309 for (int i = 0; i < data.readings.size(); i++)
jakehodges 3:71b090ec5c69 310 pc.printf("0x%.2X|", data.readings[i]);
Trumple 4:0bab12a0cc9a 311 pc.printf("\r\n");
Trumple 0:fcab3b154e49 312 #endif
Trumple 1:27b35752c5d0 313
Trumple 4:0bab12a0cc9a 314 string readings_str(data.readings.begin(), data.readings.end());
Trumple 4:0bab12a0cc9a 315 char readings[sizeof(snail::sensordata().payload)];
Trumple 4:0bab12a0cc9a 316 memcpy(readings, readings_str.c_str(), sizeof(readings));
Trumple 4:0bab12a0cc9a 317
Trumple 10:13176e7bd4c8 318 //TODO: Get real I2C address
Trumple 4:0bab12a0cc9a 319 snail::sensordata message(baseNodeAddress, data.type, data.type, time(NULL), readings, data.readings.size());
Trumple 10:13176e7bd4c8 320
jakehodges 6:92ddc620a78f 321 messageQueue.push(message);
Trumple 4:0bab12a0cc9a 322
Trumple 0:fcab3b154e49 323 //log
Trumple 1:27b35752c5d0 324 //sd.write(static_cast<long int>(time(NULL)), data);
Trumple 0:fcab3b154e49 325 }
Trumple 0:fcab3b154e49 326 }
Trumple 1:27b35752c5d0 327 }
Trumple 0:fcab3b154e49 328 }