Dreamforce 2013 MiniHack Thermostat Challenge - remotes

Dependencies:   C12832_lcd EthernetInterface-ansond-patched HTTPClient-thermostat-remotes LM75B MMA7660 SocketIO WebSocketClient-ThermostatDemo mbed-rtos mbed picojson

Fork of df-2013-minihack-thermostat-complete by MBED_DEMOS

Committer:
ansond
Date:
Sun Nov 10 02:18:02 2013 +0000
Revision:
3:58f1cc293901
Parent:
1:3faa003ad6e6
switched json parser

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:26c48388f725 1 /* Thermostat.cpp */
ansond 0:26c48388f725 2 /* Copyright (C) 2013 mbed.org, MIT License
ansond 0:26c48388f725 3 *
ansond 0:26c48388f725 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:26c48388f725 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
ansond 0:26c48388f725 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:26c48388f725 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:26c48388f725 8 * furnished to do so, subject to the following conditions:
ansond 0:26c48388f725 9 *
ansond 0:26c48388f725 10 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:26c48388f725 11 * substantial portions of the Software.
ansond 0:26c48388f725 12 *
ansond 0:26c48388f725 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:26c48388f725 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:26c48388f725 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:26c48388f725 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:26c48388f725 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:26c48388f725 18 */
ansond 0:26c48388f725 19
ansond 0:26c48388f725 20 //
ansond 0:26c48388f725 21 // 2013 DreamForce MiniHack -
ansond 0:26c48388f725 22 // Look for the method: Thermostat::parseAndActOnControlMessage(char *json)
ansond 0:26c48388f725 23 // From there, add code to look for a "text" message - send its contents to the LCD panel
ansond 0:26c48388f725 24 // using the this->display(char *) method. You can use the other messages as a reference.
ansond 0:26c48388f725 25 //
ansond 0:26c48388f725 26
ansond 0:26c48388f725 27 /*
ansond 0:26c48388f725 28 * Operation: with the MBED appboard - the following is available:
ansond 0:26c48388f725 29 * 1. connect/disconnect: push and hold the joystick forward (towards potentiometer) until a connect/disconnect message is seen
ansond 0:26c48388f725 30 * 2. control messages
ansond 0:26c48388f725 31 * "led1" --> "on" or "off" (led1 is also used as the TX status...)
ansond 0:26c48388f725 32 * "led2" --> "on" or "off" (led2 is also used as the RX status...)
ansond 0:26c48388f725 33 * "led3" --> "on" or "off"
ansond 0:26c48388f725 34 * "led4" --> "on" or "off"
ansond 0:26c48388f725 35 * "blink" --> <dont care> should blink all 4 LEDs a few times
ansond 0:26c48388f725 36 * "reset" --> <dont care> will reset the simulated error state for the device
ansond 0:26c48388f725 37 * 3. simulated error state: depress and hold the joystick until the RGB LED turns red
ansond 0:26c48388f725 38 * 4. rotate the potentiometer closest to the LCD panel to manipulate the battery level (0 - 100%)
ansond 0:26c48388f725 39 * 5. rotate the potentiometer nearest the RGB LED to add/subtract 10 degrees from the current ambient temperature
ansond 0:26c48388f725 40 */
ansond 0:26c48388f725 41
ansond 0:26c48388f725 42 // Primary include
ansond 0:26c48388f725 43 #include "Thermostat.h"
ansond 0:26c48388f725 44
ansond 0:26c48388f725 45 // DreamForce 2013 Tunables START
ansond 0:26c48388f725 46
ansond 3:58f1cc293901 47 // set our location
ansond 3:58f1cc293901 48 int location_index = 0;
ansond 0:26c48388f725 49
ansond 3:58f1cc293901 50 // Remoted Thermostats
ansond 3:58f1cc293901 51 // Thermostat 1: Austin TX 30.2500 –97.7500
ansond 3:58f1cc293901 52 // Thermostat 2: Phoenix AZ 33.4500 -112.0667
ansond 3:58f1cc293901 53 // Thermostat 3: Dallas TX 32.7758 -96.7967
ansond 3:58f1cc293901 54 // Thermostat 4: Miami FL 25.7877 -80.2241
ansond 3:58f1cc293901 55 // Thermostat 5: Chicago IL 41.8819 –87.6278
ansond 3:58f1cc293901 56 // Thermostat 6: Memphis TN 35.1174 -89.9711
ansond 3:58f1cc293901 57 // Thermostat 7: Seattle WA 47.6097 –122.3331
ansond 3:58f1cc293901 58 // Thermostat 8: New York NY 40.6700 –73.9400
ansond 3:58f1cc293901 59 // Thermostat 9: Raleigh NC 35.8189 –78.6447
ansond 3:58f1cc293901 60 // Thermostat 10: Moscone 37.7842 –122.4016
ansond 3:58f1cc293901 61 float latitudes[10] = { 30.2500, 33.4500, 32.7758, 25.7877, 41.8819, 35.1174, 47.6097, 40.6700, 35.8189, 37.7842};
ansond 3:58f1cc293901 62 float longitudes[10] = { -97.7500, -112.0667, -96.7967, -80.2241, -87.6278, -89.9711, -122.3331, -73.9400, -78.6447, -122.4016};
ansond 3:58f1cc293901 63 char *locations[10] = { "DF Thermostat-Austin TX", "DF Thermostat-Phoenix AZ", "DF Thermostat-Dallas TX", "DF Thermostat-Miami FL",
ansond 3:58f1cc293901 64 "DF Thermostat-Chicago IL", "DF Thermostat-Memphis TN", "DF Thermostat-Seattle WA",
ansond 3:58f1cc293901 65 "DF Thermostat-New York NY", "DF Thermostat-Raleigh NC", "DF Thermostat-Moscone Center"};
ansond 0:26c48388f725 66
ansond 0:26c48388f725 67 // DreamForce 2013 Tunables END
ansond 0:26c48388f725 68
ansond 0:26c48388f725 69 // Wait Loop default sleep per iteration
ansond 0:26c48388f725 70 #define DEFAULT_MAIN_LOOP_WAIT 2.0 // 2 seconds
ansond 0:26c48388f725 71
ansond 0:26c48388f725 72 // JSON parsing support
ansond 3:58f1cc293901 73 #include "MbedJSONValue.h"
ansond 0:26c48388f725 74
ansond 0:26c48388f725 75 //
ansond 0:26c48388f725 76 // Accelerometer Support
ansond 0:26c48388f725 77 //
ansond 0:26c48388f725 78 #include "MMA7660.h"
ansond 0:26c48388f725 79 MMA7660 acc(p28, p27);
ansond 0:26c48388f725 80
ansond 0:26c48388f725 81 //
ansond 0:26c48388f725 82 // Temperature Sensor Support
ansond 0:26c48388f725 83 //
ansond 0:26c48388f725 84 #include "LM75B.h"
ansond 0:26c48388f725 85 LM75B temp_sensor(p28,p27);
ansond 0:26c48388f725 86
ansond 0:26c48388f725 87 //
ansond 0:26c48388f725 88 // Ethernet support
ansond 0:26c48388f725 89 //
ansond 0:26c48388f725 90 #include "EthernetInterface.h"
ansond 0:26c48388f725 91 EthernetInterface ethernet;
ansond 0:26c48388f725 92
ansond 0:26c48388f725 93 //
ansond 0:26c48388f725 94 // Thermostat SocketIO Support
ansond 0:26c48388f725 95 //
ansond 0:26c48388f725 96 #include "ThermostatSocketIO.h"
ansond 3:58f1cc293901 97 ThermostatSocketIO socketio(locations[location_index]);
ansond 0:26c48388f725 98
ansond 0:26c48388f725 99 // Include LED Utils
ansond 0:26c48388f725 100 #include "Thermostat-LEDUtils.h"
ansond 0:26c48388f725 101
ansond 0:26c48388f725 102 // Include Base Utils
ansond 0:26c48388f725 103 #include "Thermostat-BaseUtils.h"
ansond 0:26c48388f725 104
ansond 0:26c48388f725 105 // Include Location Stubs
ansond 0:26c48388f725 106 #include "Thermostat-Location.h"
ansond 0:26c48388f725 107
ansond 0:26c48388f725 108 // Default constructor
ansond 0:26c48388f725 109 Thermostat::Thermostat() {
ansond 0:26c48388f725 110 this->m_temperature = 0.0;
ansond 0:26c48388f725 111 this->m_battery = 50.0;
ansond 0:26c48388f725 112 this->m_status = "OK";
ansond 0:26c48388f725 113 }
ansond 0:26c48388f725 114
ansond 0:26c48388f725 115 // Destructor
ansond 0:26c48388f725 116 Thermostat::~Thermostat() {
ansond 0:26c48388f725 117 // close down connections
ansond 0:26c48388f725 118 socketio.close();
ansond 0:26c48388f725 119 ethernet.disconnect();
ansond 0:26c48388f725 120 this->turnRGBLEDBlue();
ansond 0:26c48388f725 121 }
ansond 0:26c48388f725 122
ansond 0:26c48388f725 123 // get the temp
ansond 0:26c48388f725 124 float Thermostat::getTemperature() {
ansond 0:26c48388f725 125 // get Pot 2 an additive/subtractive value to the ambient temp
ansond 0:26c48388f725 126 float scale = Pot2.read();
ansond 0:26c48388f725 127 scale = scale * 20.0; // scale to 0 - 20
ansond 0:26c48388f725 128 scale = scale - 10.0; // scale -10 to +10
ansond 0:26c48388f725 129
ansond 0:26c48388f725 130 // Get the Temperature (in C)
ansond 0:26c48388f725 131 float c = temp_sensor.read();
ansond 0:26c48388f725 132 float f = ((9/5) * c ) + 32;
ansond 0:26c48388f725 133
ansond 0:26c48388f725 134 // now get the ambient temp and scale it
ansond 0:26c48388f725 135 this->m_temperature = c + scale;
ansond 0:26c48388f725 136 this->display("Temp %.1f C (%.1f F)",this->m_temperature,f);
ansond 0:26c48388f725 137 this->display_lcd("Temp: %.1f C (%.1f F)",this->m_temperature,f);
ansond 0:26c48388f725 138
ansond 0:26c48388f725 139 // return the temperature
ansond 0:26c48388f725 140 return this->m_temperature;
ansond 0:26c48388f725 141 }
ansond 0:26c48388f725 142
ansond 0:26c48388f725 143 // get the current battery level
ansond 0:26c48388f725 144 float Thermostat::getBatteryLevel() {
ansond 0:26c48388f725 145 // get Pot 1 an additive/subtractive value to simulate battery level
ansond 0:26c48388f725 146 this->m_battery = Pot1.read();
ansond 0:26c48388f725 147 this->m_battery = this->m_battery * 100.0; // scale to 0 - 100;
ansond 0:26c48388f725 148
ansond 0:26c48388f725 149 // return the battery level
ansond 0:26c48388f725 150 return this->m_battery;
ansond 0:26c48388f725 151 }
ansond 0:26c48388f725 152
ansond 0:26c48388f725 153 // receive from the heroku SocketIO web service
ansond 0:26c48388f725 154 char *Thermostat::receiveFromWSService(char *buffer) {
ansond 0:26c48388f725 155 bool success = socketio.read(buffer);
ansond 0:26c48388f725 156 if (success == true)
ansond 0:26c48388f725 157 this->display("SocketIO: Read success");
ansond 0:26c48388f725 158 else
ansond 0:26c48388f725 159 this->display("SocketIO: Read failure");
ansond 0:26c48388f725 160
ansond 0:26c48388f725 161 return buffer;
ansond 0:26c48388f725 162 }
ansond 0:26c48388f725 163
ansond 0:26c48388f725 164 // translate the LED status
ansond 0:26c48388f725 165 int Thermostat::translateLEDStatus(const char *status, int current) {
ansond 0:26c48388f725 166 int i_status = current;
ansond 0:26c48388f725 167
ansond 0:26c48388f725 168 if (status != NULL && strlen(status) > 0) {
ansond 0:26c48388f725 169 if (strcmp(status,"on") == 0 || strcmp(status,"ON") == 0 || strcmp(status,"On") == 0 || strcmp(status,"1") == 0 || strcmp(status,"oN") == 0)
ansond 0:26c48388f725 170 i_status = 1;
ansond 0:26c48388f725 171 if (strcmp(status,"off") == 0 || strcmp(status,"OFF") == 0 || strcmp(status,"Off") == 0 || strcmp(status,"0") == 0 || strcmp(status,"oFF") == 0 || strcmp(status,"oF") == 0 || strcmp(status,"ofF") == 0)
ansond 0:26c48388f725 172 i_status = 0;
ansond 0:26c48388f725 173 }
ansond 0:26c48388f725 174
ansond 0:26c48388f725 175 // return the status
ansond 0:26c48388f725 176 return i_status;
ansond 0:26c48388f725 177 }
ansond 0:26c48388f725 178
ansond 0:26c48388f725 179 // reset the device status to OK
ansond 0:26c48388f725 180 void Thermostat::resetDeviceStatus() {
ansond 0:26c48388f725 181 this->turnRGBLEDGreen();
ansond 0:26c48388f725 182 this->m_status = "OK";
ansond 0:26c48388f725 183 socketio.resetMessageCounter();
ansond 0:26c48388f725 184 this->resetAllLEDs();
ansond 0:26c48388f725 185 }
ansond 0:26c48388f725 186
ansond 0:26c48388f725 187 // basic parsing and processing of the control message
ansond 0:26c48388f725 188 //
ansond 0:26c48388f725 189 // Control Message Format: 5:::{"name":"control-device","args":[{"hello":"world"}]}
ansond 0:26c48388f725 190 //
ansond 0:26c48388f725 191 void Thermostat::parseAndActOnControlMessage(char *json) {
ansond 3:58f1cc293901 192 MbedJSONValue result;
ansond 3:58f1cc293901 193
ansond 0:26c48388f725 194 if (json != NULL && strlen(json) > 0 && strstr(json,"{") != NULL) {
ansond 0:26c48388f725 195 // move past the socket.io header
ansond 0:26c48388f725 196 char *json_proper = strstr(json,"{");
ansond 0:26c48388f725 197
ansond 0:26c48388f725 198 // parse the packet
ansond 3:58f1cc293901 199 parse(result,json_proper);
ansond 3:58f1cc293901 200
ansond 0:26c48388f725 201 // loop through the array and parse/process each element
ansond 3:58f1cc293901 202 for(int i=0;i<result["args"].size();++i) {
ansond 0:26c48388f725 203 // Toggle LEDs
ansond 3:58f1cc293901 204 if (result["args"][i]["led1"].get<string>().size() > 0) led1.write(this->translateLEDStatus(result["args"][i]["led1"].get<string>().c_str(),(int)led1));
ansond 3:58f1cc293901 205 if (result["args"][i]["led2"].get<string>().size() > 0) led2.write(this->translateLEDStatus(result["args"][i]["led2"].get<string>().c_str(),(int)led2));
ansond 3:58f1cc293901 206 if (result["args"][i]["led3"].get<string>().size() > 0) led3.write(this->translateLEDStatus(result["args"][i]["led3"].get<string>().c_str(),(int)led3));
ansond 3:58f1cc293901 207 if (result["args"][i]["led4"].get<string>().size() > 0) led4.write(this->translateLEDStatus(result["args"][i]["led4"].get<string>().c_str(),(int)led4));
ansond 3:58f1cc293901 208 if (result["args"][i]["reset"].get<string>().size() > 0) this->resetDeviceStatus();
ansond 3:58f1cc293901 209 if (result["args"][i]["blink"].get<string>().size() > 0) this->blinkAllLEDs();
ansond 0:26c48388f725 210
ansond 0:26c48388f725 211 //
ansond 0:26c48388f725 212 // 2013 DreamForce MiniHack - add code to look for a "text" message - send its contents to the LCD panel
ansond 1:3faa003ad6e6 213 // using the this->displayTextMessage(char *) method
ansond 0:26c48388f725 214 //
ansond 0:26c48388f725 215 // Answer:
ansond 0:26c48388f725 216 //
ansond 3:58f1cc293901 217 if (result["args"][i]["text"].get<string>().size() > 0) this->displayTextMessage(result["args"][i]["text"].get<string>().c_str());
ansond 0:26c48388f725 218 }
ansond 0:26c48388f725 219 }
ansond 0:26c48388f725 220 }
ansond 0:26c48388f725 221
ansond 0:26c48388f725 222 // recv and process a control message
ansond 0:26c48388f725 223 void Thermostat::processControlMessage() {
ansond 0:26c48388f725 224
ansond 0:26c48388f725 225 if (socketio.is_connected()) {
ansond 0:26c48388f725 226 char message[SOCKETIO_MESSAGE_LENGTH];
ansond 0:26c48388f725 227 if (socketio.read(message)) {
ansond 0:26c48388f725 228 // log the message
ansond 0:26c48388f725 229 this->display("Received control message: %s",message);
ansond 0:26c48388f725 230
ansond 0:26c48388f725 231 // process the message
ansond 0:26c48388f725 232 this->parseAndActOnControlMessage(message);
ansond 0:26c48388f725 233
ansond 0:26c48388f725 234 // blink the RX led
ansond 0:26c48388f725 235 this->blinkTransportRxLED();
ansond 0:26c48388f725 236 }
ansond 0:26c48388f725 237 else {
ansond 0:26c48388f725 238 // no messages received - log
ansond 0:26c48388f725 239 this->display("No control message received. OK");
ansond 0:26c48388f725 240 }
ansond 0:26c48388f725 241 }
ansond 0:26c48388f725 242 }
ansond 0:26c48388f725 243
ansond 0:26c48388f725 244 // send status (no params) to the service
ansond 0:26c48388f725 245 void Thermostat::sendStatus() {
ansond 0:26c48388f725 246 // send the status
ansond 0:26c48388f725 247 this->sendStatus(this->getTemperature(),this->getBatteryLevel());
ansond 0:26c48388f725 248 }
ansond 0:26c48388f725 249
ansond 0:26c48388f725 250 // send status (temp & battery) to the service
ansond 0:26c48388f725 251 void Thermostat::sendStatus(float temp, int bat) {
ansond 0:26c48388f725 252 // incorporate location coordinates
ansond 0:26c48388f725 253 this->sendStatus(temp,this->m_latitude,this->m_longitude,bat);
ansond 0:26c48388f725 254 }
ansond 0:26c48388f725 255
ansond 0:26c48388f725 256 // send status (temp, lat/long, battery) to the service
ansond 0:26c48388f725 257 void Thermostat::sendStatus(float temp, float latitude, float longitude, float bat) {
ansond 0:26c48388f725 258 // Announce
ansond 0:26c48388f725 259 this->display("Send: status...");
ansond 0:26c48388f725 260 this->display_lcd("Sending status...");
ansond 0:26c48388f725 261
ansond 0:26c48388f725 262 // now send...
ansond 0:26c48388f725 263 int sent = socketio.emit(temp,latitude,longitude,bat,this->getErrorState(),this->m_status);
ansond 0:26c48388f725 264
ansond 0:26c48388f725 265 // Log
ansond 0:26c48388f725 266 if (sent > 0) {
ansond 0:26c48388f725 267 this->display("Send success. Ready...");
ansond 0:26c48388f725 268 this->display_lcd("Send status: OK.\r\nSleeping...");
ansond 0:26c48388f725 269 }
ansond 0:26c48388f725 270 else {
ansond 0:26c48388f725 271 this->display("Send Failed: sent=%d",sent);
ansond 0:26c48388f725 272 this->display_lcd("Send status: FAILED.\r\nSleeping...");
ansond 0:26c48388f725 273 }
ansond 0:26c48388f725 274
ansond 0:26c48388f725 275 // blink the TX led
ansond 0:26c48388f725 276 this->blinkTransportTxLED();
ansond 0:26c48388f725 277 }
ansond 0:26c48388f725 278
ansond 0:26c48388f725 279 // connect to the heroku WebService
ansond 0:26c48388f725 280 bool Thermostat::connectWebSocketService() {
ansond 0:26c48388f725 281 // Log
ansond 0:26c48388f725 282 this->display("Connecting to SocketIO...");
ansond 0:26c48388f725 283 this->display_lcd("SocketIO connecting...");
ansond 0:26c48388f725 284
ansond 0:26c48388f725 285 // only connect if we are not already so
ansond 0:26c48388f725 286 if (!socketio.is_connected()) socketio.connect();
ansond 0:26c48388f725 287
ansond 0:26c48388f725 288 // check connection status
ansond 0:26c48388f725 289 bool connected = socketio.is_connected();
ansond 0:26c48388f725 290
ansond 0:26c48388f725 291 // log
ansond 0:26c48388f725 292 if (connected == true) {
ansond 0:26c48388f725 293 this->display("SocketIO: Connected!");
ansond 0:26c48388f725 294 this->display_lcd("SocketIO: Connected.");
ansond 0:26c48388f725 295 }
ansond 0:26c48388f725 296 else {
ansond 0:26c48388f725 297 this->display("SocketIO: Not connected!");
ansond 0:26c48388f725 298 this->display_lcd("SocketIO: Connect FAILED.");
ansond 0:26c48388f725 299 }
ansond 0:26c48388f725 300
ansond 0:26c48388f725 301 // return the status
ansond 0:26c48388f725 302 return connected;
ansond 0:26c48388f725 303 }
ansond 0:26c48388f725 304
ansond 0:26c48388f725 305 // Connect up Ethernet
ansond 0:26c48388f725 306 bool Thermostat::connectEthernet() {
ansond 0:26c48388f725 307 bool connected = false;
ansond 0:26c48388f725 308 char *ipAddr = NULL;
ansond 0:26c48388f725 309
ansond 0:26c48388f725 310 // Use DHCP
ansond 0:26c48388f725 311 this->display("Initializing Ethernet...");
ansond 0:26c48388f725 312 this->display_lcd("Ethernet: Initializing...");
ansond 0:26c48388f725 313 ethernet.init();
ansond 0:26c48388f725 314
ansond 0:26c48388f725 315 // attempt connection
ansond 0:26c48388f725 316 this->display("Connecting Ethernet...");
ansond 0:26c48388f725 317 this->display_lcd("Ethernet: Connecting...");
ansond 0:26c48388f725 318 if (ethernet.connect() == 0) connected = true;
ansond 0:26c48388f725 319
ansond 0:26c48388f725 320 // check connection status
ansond 0:26c48388f725 321 if (connected) {
ansond 0:26c48388f725 322 ipAddr = ethernet.getIPAddress();
ansond 0:26c48388f725 323 if (ipAddr != NULL && strlen(ipAddr) > 0)
ansond 0:26c48388f725 324 connected = true;
ansond 0:26c48388f725 325 }
ansond 0:26c48388f725 326
ansond 0:26c48388f725 327 // log
ansond 0:26c48388f725 328 if (connected == true) {
ansond 0:26c48388f725 329 this->display("Ethernet: Connected.\r\nIP: %s", ipAddr);
ansond 0:26c48388f725 330 this->display_lcd("Ethernet: Connected\r\nIP: %s",ipAddr);
ansond 0:26c48388f725 331 }
ansond 0:26c48388f725 332 else {
ansond 0:26c48388f725 333 this->display("Ethernet: Not connected");
ansond 0:26c48388f725 334 this->display_lcd("Ethernet: Connect FAILED.");
ansond 0:26c48388f725 335 }
ansond 0:26c48388f725 336
ansond 0:26c48388f725 337 // return the status
ansond 0:26c48388f725 338 return connected;
ansond 0:26c48388f725 339 }
ansond 0:26c48388f725 340
ansond 0:26c48388f725 341 // gracefully de-register and close down the WS connection
ansond 0:26c48388f725 342 void Thermostat::gracefullyDisconnect() {
ansond 0:26c48388f725 343 // disconnect
ansond 0:26c48388f725 344 if (socketio.is_connected()) socketio.close();
ansond 0:26c48388f725 345
ansond 0:26c48388f725 346 // announce
ansond 0:26c48388f725 347 this->display("Disconnected.");
ansond 0:26c48388f725 348 this->display_lcd("Disconnected.");
ansond 0:26c48388f725 349 this->turnRGBLEDBlue();
ansond 0:26c48388f725 350
ansond 0:26c48388f725 351 // reset any status
ansond 0:26c48388f725 352 this->m_status = "OK";
ansond 0:26c48388f725 353 socketio.resetMessageCounter();
ansond 0:26c48388f725 354 }
ansond 0:26c48388f725 355
ansond 0:26c48388f725 356 // external function in main() to check for the CTRL-C key press to exit the application gracefully
ansond 0:26c48388f725 357 extern void checkForExit();
ansond 0:26c48388f725 358
ansond 0:26c48388f725 359 // main loop
ansond 0:26c48388f725 360 void Thermostat::mainLoop() {
ansond 0:26c48388f725 361 // initialize our location
ansond 0:26c48388f725 362 this->initLocation();
ansond 0:26c48388f725 363
ansond 0:26c48388f725 364 // begin the main loop
ansond 0:26c48388f725 365 while(true) {
ansond 0:26c48388f725 366 // sleep for a bit
ansond 0:26c48388f725 367 checkForExit();
ansond 0:26c48388f725 368 wait(DEFAULT_MAIN_LOOP_WAIT);
ansond 0:26c48388f725 369
ansond 0:26c48388f725 370 // announce our position
ansond 0:26c48388f725 371 this->updateCoordinates();
ansond 0:26c48388f725 372
ansond 0:26c48388f725 373 // check and react to the joystick button press
ansond 0:26c48388f725 374 if (joystick_pressed) {
ansond 0:26c48388f725 375 if (this->m_rgbLEDColor > 1) {
ansond 0:26c48388f725 376 this->turnRGBLEDRed();
ansond 0:26c48388f725 377 this->m_status = "FAIL";
ansond 0:26c48388f725 378 }
ansond 0:26c48388f725 379 else {
ansond 0:26c48388f725 380 this->turnRGBLEDGreen();
ansond 0:26c48388f725 381 this->m_status = "OK";
ansond 0:26c48388f725 382 }
ansond 0:26c48388f725 383 }
ansond 0:26c48388f725 384 else if (socketio.is_connected() && this->m_rgbLEDColor > 121) {
ansond 0:26c48388f725 385 this->turnRGBLEDGreen();
ansond 0:26c48388f725 386 }
ansond 0:26c48388f725 387
ansond 0:26c48388f725 388 // check the status of the joystick
ansond 0:26c48388f725 389 if (joystick) {
ansond 0:26c48388f725 390 if (socketio.is_connected()) {
ansond 0:26c48388f725 391 // announce
ansond 0:26c48388f725 392 this->display("Disconnecting...");
ansond 0:26c48388f725 393 this->display_lcd("Disconnecting...");
ansond 0:26c48388f725 394
ansond 0:26c48388f725 395 // disconnect
ansond 0:26c48388f725 396 this->gracefullyDisconnect();
ansond 0:26c48388f725 397 }
ansond 0:26c48388f725 398 else if (!socketio.is_connected()){
ansond 0:26c48388f725 399 // announce
ansond 0:26c48388f725 400 this->display("Re-connecting...");
ansond 0:26c48388f725 401 this->display_lcd("Re-connecting...");
ansond 0:26c48388f725 402
ansond 0:26c48388f725 403 // re-connect
ansond 0:26c48388f725 404 if (this->connectWebSocketService()) {
ansond 0:26c48388f725 405 // announce
ansond 0:26c48388f725 406 this->display("Reconnect success");
ansond 0:26c48388f725 407 this->display_lcd("Reconnect: SUCCESS");
ansond 0:26c48388f725 408 this->turnRGBLEDGreen();
ansond 0:26c48388f725 409 this->resetAllLEDs();
ansond 0:26c48388f725 410 }
ansond 0:26c48388f725 411 else {
ansond 0:26c48388f725 412 // announce
ansond 0:26c48388f725 413 this->display("Reconnect failure");
ansond 0:26c48388f725 414 this->display_lcd("Reconnect: FAILED");
ansond 0:26c48388f725 415 this->gracefullyDisconnect();
ansond 0:26c48388f725 416 this->turnRGBLEDRed();
ansond 0:26c48388f725 417 }
ansond 0:26c48388f725 418 }
ansond 0:26c48388f725 419 }
ansond 0:26c48388f725 420
ansond 3:58f1cc293901 421 // if not connected... reconnect
ansond 3:58f1cc293901 422 if (!socketio.is_connected()){
ansond 3:58f1cc293901 423 // announce
ansond 3:58f1cc293901 424 this->display("Re-connecting...");
ansond 3:58f1cc293901 425 this->display_lcd("Re-connecting...");
ansond 3:58f1cc293901 426
ansond 3:58f1cc293901 427 // re-connect
ansond 3:58f1cc293901 428 if (this->connectWebSocketService()) {
ansond 3:58f1cc293901 429 // announce
ansond 3:58f1cc293901 430 this->display("Reconnect success");
ansond 3:58f1cc293901 431 this->display_lcd("Reconnect: SUCCESS");
ansond 3:58f1cc293901 432 this->turnRGBLEDGreen();
ansond 3:58f1cc293901 433 this->resetAllLEDs();
ansond 3:58f1cc293901 434 }
ansond 3:58f1cc293901 435 else {
ansond 3:58f1cc293901 436 // announce
ansond 3:58f1cc293901 437 this->display("Reconnect failure");
ansond 3:58f1cc293901 438 this->display_lcd("Reconnect: FAILED");
ansond 3:58f1cc293901 439 this->gracefullyDisconnect();
ansond 3:58f1cc293901 440 this->turnRGBLEDRed();
ansond 3:58f1cc293901 441 }
ansond 3:58f1cc293901 442 }
ansond 3:58f1cc293901 443
ansond 0:26c48388f725 444 // if we are connected, send our status
ansond 0:26c48388f725 445 if (socketio.is_connected()) {
ansond 0:26c48388f725 446 // send status
ansond 0:26c48388f725 447 this->sendStatus();
ansond 0:26c48388f725 448 checkForExit();
ansond 0:26c48388f725 449 }
ansond 0:26c48388f725 450
ansond 0:26c48388f725 451 // if we are connected, read any control we may receive
ansond 0:26c48388f725 452 if (socketio.is_connected()) {
ansond 0:26c48388f725 453 // process control messages
ansond 0:26c48388f725 454 this->processControlMessage();
ansond 0:26c48388f725 455 checkForExit();
ansond 0:26c48388f725 456 }
ansond 0:26c48388f725 457 }
ansond 0:26c48388f725 458 }
ansond 0:26c48388f725 459
ansond 0:26c48388f725 460 // Run the Demo
ansond 0:26c48388f725 461 void Thermostat::runDemo() {
ansond 0:26c48388f725 462 // Announce
ansond 0:26c48388f725 463 this->display("Thermostat Hands-On Demo v1.0");
ansond 0:26c48388f725 464 this->display_lcd("Thermostat Hands-On\r\nDemo v1.0");
ansond 0:26c48388f725 465
ansond 0:26c48388f725 466 // init the RGB LED
ansond 0:26c48388f725 467 this->display("Initializing LEDs...");
ansond 0:26c48388f725 468 this->turnRGBLEDBlue();
ansond 0:26c48388f725 469
ansond 0:26c48388f725 470 // Log
ansond 0:26c48388f725 471 this->display("Connecting...");
ansond 0:26c48388f725 472 this->display_lcd("Connecting...");
ansond 0:26c48388f725 473
ansond 0:26c48388f725 474 // connect and send the initial status
ansond 0:26c48388f725 475 if (this->connectEthernet() == true && this->connectWebSocketService() == true) {
ansond 0:26c48388f725 476 this->sendStatus();
ansond 0:26c48388f725 477 this->mainLoop();
ansond 0:26c48388f725 478 }
ansond 0:26c48388f725 479 else {
ansond 0:26c48388f725 480 this->display("Connection failure. Application exiting...");
ansond 0:26c48388f725 481 this->display_lcd("Connect: FAILURE.\r\nApplication Exiting");
ansond 0:26c48388f725 482 }
ansond 0:26c48388f725 483
ansond 0:26c48388f725 484 // exit the application if we get here
ansond 0:26c48388f725 485 exit(1);
ansond 0:26c48388f725 486 }