Dreamforce 2013 MiniHack Thermostat Challenge

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

Committer:
ansond
Date:
Tue Nov 05 21:29:58 2013 +0000
Revision:
0:bca7aceedd02
Child:
1:4c7d9aee324f
initial checkin

Who changed what in which revision?

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