Maxim Integrated / Mbed 2 deprecated DeepCover Embedded Security in IoT

Dependencies:   MaximInterface mbed

Committer:
IanBenzMaxim
Date:
Thu Jul 21 11:06:13 2016 -0500
Revision:
17:41be4896ed6d
Parent:
16:6bce01c1dd90
Child:
20:cdba71cb5506
Fixed issue with LCD controller initialization on some boards due to power instability. Updated following downstream restructuring in OneWire library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 1:e1c7c1c636af 1 /*******************************************************************************
IanBenzMaxim 1:e1c7c1c636af 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
IanBenzMaxim 1:e1c7c1c636af 3 *
IanBenzMaxim 1:e1c7c1c636af 4 * Permission is hereby granted, free of charge, to any person obtaining a
IanBenzMaxim 1:e1c7c1c636af 5 * copy of this software and associated documentation files (the "Software"),
IanBenzMaxim 1:e1c7c1c636af 6 * to deal in the Software without restriction, including without limitation
IanBenzMaxim 1:e1c7c1c636af 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
IanBenzMaxim 1:e1c7c1c636af 8 * and/or sell copies of the Software, and to permit persons to whom the
IanBenzMaxim 1:e1c7c1c636af 9 * Software is furnished to do so, subject to the following conditions:
IanBenzMaxim 1:e1c7c1c636af 10 *
IanBenzMaxim 1:e1c7c1c636af 11 * The above copyright notice and this permission notice shall be included
IanBenzMaxim 1:e1c7c1c636af 12 * in all copies or substantial portions of the Software.
IanBenzMaxim 1:e1c7c1c636af 13 *
IanBenzMaxim 1:e1c7c1c636af 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
IanBenzMaxim 1:e1c7c1c636af 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
IanBenzMaxim 1:e1c7c1c636af 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IanBenzMaxim 1:e1c7c1c636af 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
IanBenzMaxim 1:e1c7c1c636af 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
IanBenzMaxim 1:e1c7c1c636af 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
IanBenzMaxim 1:e1c7c1c636af 20 * OTHER DEALINGS IN THE SOFTWARE.
IanBenzMaxim 1:e1c7c1c636af 21 *
IanBenzMaxim 1:e1c7c1c636af 22 * Except as contained in this notice, the name of Maxim Integrated
IanBenzMaxim 1:e1c7c1c636af 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
IanBenzMaxim 1:e1c7c1c636af 24 * Products, Inc. Branding Policy.
IanBenzMaxim 1:e1c7c1c636af 25 *
IanBenzMaxim 1:e1c7c1c636af 26 * The mere transfer of this software does not imply any licenses
IanBenzMaxim 1:e1c7c1c636af 27 * of trade secrets, proprietary technology, copyrights, patents,
IanBenzMaxim 1:e1c7c1c636af 28 * trademarks, maskwork rights, or any other form of intellectual
IanBenzMaxim 1:e1c7c1c636af 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
IanBenzMaxim 1:e1c7c1c636af 30 * ownership rights.
IanBenzMaxim 1:e1c7c1c636af 31 *******************************************************************************
IanBenzMaxim 1:e1c7c1c636af 32 */
IanBenzMaxim 1:e1c7c1c636af 33
IanBenzMaxim 1:e1c7c1c636af 34 #include <vector>
IanBenzMaxim 1:e1c7c1c636af 35
IanBenzMaxim 1:e1c7c1c636af 36 #include "WebServerInterface.hpp"
IanBenzMaxim 1:e1c7c1c636af 37 #include "ESP8266.hpp"
IanBenzMaxim 16:6bce01c1dd90 38 #include "Slaves/Authenticators/ISha256MacCoproc.h"
IanBenzMaxim 1:e1c7c1c636af 39 #include "common.hpp"
IanBenzMaxim 6:b6bafd0a7013 40 #include "Serial.h"
IanBenzMaxim 6:b6bafd0a7013 41 #include "wait_api.h"
IanBenzMaxim 6:b6bafd0a7013 42
IanBenzMaxim 8:594529956266 43 using OneWire::ISha256MacCoproc;
IanBenzMaxim 1:e1c7c1c636af 44
IanBenzMaxim 10:5eb19685b496 45 const char WebServerInterface::wifiSsid[] = "WifiSsid";
IanBenzMaxim 10:5eb19685b496 46 const char WebServerInterface::wifiPassword[] = "WifiPassword";
IanBenzMaxim 12:5f8727ba1493 47 const char WebServerInterface::serverAddress[] = "www.mxim-security.us";
IanBenzMaxim 3:ac723be395d9 48 const unsigned int WebServerInterface::serverPort = 80;
IanBenzMaxim 1:e1c7c1c636af 49 const char WebServerInterface::serverPostPath[] = "/post.php";
IanBenzMaxim 1:e1c7c1c636af 50 const char WebServerInterface::serverChallengePath[] = "/challenge.php";
IanBenzMaxim 1:e1c7c1c636af 51
IanBenzMaxim 1:e1c7c1c636af 52 // HTTP formatting constants
IanBenzMaxim 1:e1c7c1c636af 53 static const char keyValSeparator = '=';
IanBenzMaxim 1:e1c7c1c636af 54 static const char fieldSeparator = '&';
IanBenzMaxim 1:e1c7c1c636af 55 static const std::string newline = "\r\n";
IanBenzMaxim 1:e1c7c1c636af 56 static const char sessionIdKey[] = "SessionId";
IanBenzMaxim 1:e1c7c1c636af 57
IanBenzMaxim 1:e1c7c1c636af 58 // Authentication MAC constants
IanBenzMaxim 6:b6bafd0a7013 59 static const size_t challengeLen = 32;
IanBenzMaxim 6:b6bafd0a7013 60 static const uint8_t defaultPaddingByte = 0x00;
IanBenzMaxim 1:e1c7c1c636af 61
IanBenzMaxim 1:e1c7c1c636af 62 /// Select the Transport Secret for the web server in the Controller.
IanBenzMaxim 1:e1c7c1c636af 63 /// @returns True on success.
IanBenzMaxim 6:b6bafd0a7013 64 static bool setHttpPostSecret(ISha256MacCoproc & MacCoproc)
IanBenzMaxim 1:e1c7c1c636af 65 {
IanBenzMaxim 6:b6bafd0a7013 66 ISha256MacCoproc::DevicePage::Buffer fillData;
IanBenzMaxim 6:b6bafd0a7013 67 std::memset(fillData, defaultPaddingByte, ISha256MacCoproc::DevicePage::length);
IanBenzMaxim 6:b6bafd0a7013 68 // static_assert(ISha256MacCoproc::DevicePage::length > ISha256MacCoproc::SlaveSecretData::length);
IanBenzMaxim 6:b6bafd0a7013 69 return (MacCoproc.computeSlaveSecret(fillData, fillData, reinterpret_cast<const ISha256MacCoproc::SlaveSecretData::Buffer &>(fillData)) == ISha256MacCoproc::Success);
IanBenzMaxim 1:e1c7c1c636af 70 }
IanBenzMaxim 1:e1c7c1c636af 71
IanBenzMaxim 1:e1c7c1c636af 72 WebServerInterface::WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc)
IanBenzMaxim 1:e1c7c1c636af 73 : esp8266(esp8266), pc(pc)
IanBenzMaxim 1:e1c7c1c636af 74 {
IanBenzMaxim 1:e1c7c1c636af 75
IanBenzMaxim 1:e1c7c1c636af 76 }
IanBenzMaxim 1:e1c7c1c636af 77
IanBenzMaxim 1:e1c7c1c636af 78 bool WebServerInterface::initialize()
IanBenzMaxim 1:e1c7c1c636af 79 {
IanBenzMaxim 1:e1c7c1c636af 80 esp8266.setPowered(true);
IanBenzMaxim 1:e1c7c1c636af 81 esp8266.reset();
IanBenzMaxim 1:e1c7c1c636af 82 bool result = (esp8266.performSelfTest() == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 83 if (!result)
IanBenzMaxim 1:e1c7c1c636af 84 {
IanBenzMaxim 1:e1c7c1c636af 85 return false;
IanBenzMaxim 1:e1c7c1c636af 86 }
IanBenzMaxim 1:e1c7c1c636af 87 result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 88 if (!result)
IanBenzMaxim 1:e1c7c1c636af 89 {
IanBenzMaxim 1:e1c7c1c636af 90 return false;
IanBenzMaxim 1:e1c7c1c636af 91 }
IanBenzMaxim 1:e1c7c1c636af 92 result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 93 if (!result)
IanBenzMaxim 1:e1c7c1c636af 94 {
IanBenzMaxim 1:e1c7c1c636af 95 return false;
IanBenzMaxim 1:e1c7c1c636af 96 }
IanBenzMaxim 1:e1c7c1c636af 97 result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 98 if (!result)
IanBenzMaxim 1:e1c7c1c636af 99 {
IanBenzMaxim 1:e1c7c1c636af 100 return false;
IanBenzMaxim 1:e1c7c1c636af 101 }
IanBenzMaxim 1:e1c7c1c636af 102 return true;
IanBenzMaxim 1:e1c7c1c636af 103 }
IanBenzMaxim 1:e1c7c1c636af 104
IanBenzMaxim 1:e1c7c1c636af 105 /// Format an HTTP GET request as a string for transmission.
IanBenzMaxim 1:e1c7c1c636af 106 /// @param host Web server address.
IanBenzMaxim 1:e1c7c1c636af 107 /// @param path Web server location to retrieve.
IanBenzMaxim 1:e1c7c1c636af 108 /// @param sessionId Session ID used to identify this controller.
IanBenzMaxim 1:e1c7c1c636af 109 /// @returns GET request string.
IanBenzMaxim 1:e1c7c1c636af 110 static std::string formatHttpGet(const std::string & host, const std::string & path, const std::string & sessionId)
IanBenzMaxim 1:e1c7c1c636af 111 {
IanBenzMaxim 1:e1c7c1c636af 112 std::ostringstream httpGetStream;
IanBenzMaxim 1:e1c7c1c636af 113 httpGetStream << "GET " << path;
IanBenzMaxim 1:e1c7c1c636af 114 if (sessionId.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 115 httpGetStream << '?' << sessionIdKey << keyValSeparator << sessionId;
IanBenzMaxim 1:e1c7c1c636af 116 httpGetStream << " HTTP/1.1" << newline;
IanBenzMaxim 1:e1c7c1c636af 117 httpGetStream << "Host: " << host << newline;
IanBenzMaxim 1:e1c7c1c636af 118 httpGetStream << newline;
IanBenzMaxim 1:e1c7c1c636af 119 return httpGetStream.str();
IanBenzMaxim 1:e1c7c1c636af 120 }
IanBenzMaxim 1:e1c7c1c636af 121
IanBenzMaxim 1:e1c7c1c636af 122 /// Computes a MAC using the Transport Secret to sign HTTP POST requests.
IanBenzMaxim 1:e1c7c1c636af 123 /// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC.
IanBenzMaxim 1:e1c7c1c636af 124 /// @param input Message array used for MAC calculation.
IanBenzMaxim 1:e1c7c1c636af 125 /// @param ilen Length of array input.
IanBenzMaxim 1:e1c7c1c636af 126 /// @param output Calculated MAC output.
IanBenzMaxim 6:b6bafd0a7013 127 static void calculateHttpPostMac(const ISha256MacCoproc & macCoproc, const uint8_t * input, size_t ilen, ISha256MacCoproc::Mac & output)
IanBenzMaxim 1:e1c7c1c636af 128 {
IanBenzMaxim 6:b6bafd0a7013 129 ISha256MacCoproc::DeviceScratchpad block;
IanBenzMaxim 6:b6bafd0a7013 130 size_t index = 0;
IanBenzMaxim 6:b6bafd0a7013 131 ISha256MacCoproc::AuthMacData padding;
IanBenzMaxim 1:e1c7c1c636af 132 std::memset(padding, defaultPaddingByte, padding.length);
IanBenzMaxim 1:e1c7c1c636af 133 std::memset(output, defaultPaddingByte, output.length); // Set initial hash value
IanBenzMaxim 1:e1c7c1c636af 134 while (index < ilen)
IanBenzMaxim 1:e1c7c1c636af 135 {
IanBenzMaxim 1:e1c7c1c636af 136 if ((index + block.length) <= ilen) // Full block
IanBenzMaxim 1:e1c7c1c636af 137 {
IanBenzMaxim 1:e1c7c1c636af 138 std::memcpy(block, &input[index], block.length);
IanBenzMaxim 1:e1c7c1c636af 139 index += block.length;
IanBenzMaxim 1:e1c7c1c636af 140 }
IanBenzMaxim 1:e1c7c1c636af 141 else // Partial block with padding
IanBenzMaxim 1:e1c7c1c636af 142 {
IanBenzMaxim 1:e1c7c1c636af 143 std::memcpy(block, &input[index], ilen - index);
IanBenzMaxim 1:e1c7c1c636af 144 std::memset(&block[ilen - index], defaultPaddingByte, block.length - (ilen - index));
IanBenzMaxim 1:e1c7c1c636af 145 index = ilen;
IanBenzMaxim 1:e1c7c1c636af 146 }
IanBenzMaxim 1:e1c7c1c636af 147 // Write data to coprocessor and hash block
IanBenzMaxim 1:e1c7c1c636af 148 macCoproc.computeAuthMac(output, block, padding, output);
IanBenzMaxim 1:e1c7c1c636af 149 }
IanBenzMaxim 1:e1c7c1c636af 150 }
IanBenzMaxim 1:e1c7c1c636af 151
IanBenzMaxim 1:e1c7c1c636af 152 /// Format an HTTP POST request as a string for transmission.
IanBenzMaxim 1:e1c7c1c636af 153 /// @param host Web server address.
IanBenzMaxim 1:e1c7c1c636af 154 /// @param path Web server location to receive POST.
IanBenzMaxim 1:e1c7c1c636af 155 /// @param sessionId Session ID used to identify this Controller.
IanBenzMaxim 1:e1c7c1c636af 156 /// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC.
IanBenzMaxim 1:e1c7c1c636af 157 /// @param event Event message type.
IanBenzMaxim 1:e1c7c1c636af 158 /// @param initialPostBody Message body as determined by the event message type.
IanBenzMaxim 1:e1c7c1c636af 159 /// @param challenge Challenge previously received from web server for use in authentication MAC.
IanBenzMaxim 1:e1c7c1c636af 160 /// @returns POST request string.
IanBenzMaxim 1:e1c7c1c636af 161 static std::string formatHttpPost(const std::string & host, const std::string & path, const std::string & sessionId,
IanBenzMaxim 6:b6bafd0a7013 162 const ISha256MacCoproc & macCoproc, PostEvent event, const std::string & initialPostBody,
IanBenzMaxim 6:b6bafd0a7013 163 const uint8_t (&challenge)[challengeLen])
IanBenzMaxim 1:e1c7c1c636af 164 {
IanBenzMaxim 6:b6bafd0a7013 165 const size_t headerReserve = 115, bodyReserve = 200;
IanBenzMaxim 1:e1c7c1c636af 166
IanBenzMaxim 1:e1c7c1c636af 167 std::string httpPost;
IanBenzMaxim 1:e1c7c1c636af 168 httpPost.reserve(initialPostBody.length() + headerReserve + bodyReserve);
IanBenzMaxim 1:e1c7c1c636af 169
IanBenzMaxim 1:e1c7c1c636af 170 // Add session ID to post body
IanBenzMaxim 1:e1c7c1c636af 171 if (sessionId.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 172 {
IanBenzMaxim 1:e1c7c1c636af 173 httpPost += sessionIdKey;
IanBenzMaxim 1:e1c7c1c636af 174 httpPost += keyValSeparator;
IanBenzMaxim 1:e1c7c1c636af 175 httpPost += sessionId;
IanBenzMaxim 1:e1c7c1c636af 176 }
IanBenzMaxim 1:e1c7c1c636af 177
IanBenzMaxim 1:e1c7c1c636af 178 // Add event to post body
IanBenzMaxim 1:e1c7c1c636af 179 std::string eventString;
IanBenzMaxim 1:e1c7c1c636af 180 switch (event)
IanBenzMaxim 1:e1c7c1c636af 181 {
IanBenzMaxim 1:e1c7c1c636af 182 case SensorDataEvent:
IanBenzMaxim 1:e1c7c1c636af 183 eventString = "SensorData";
IanBenzMaxim 1:e1c7c1c636af 184 break;
IanBenzMaxim 1:e1c7c1c636af 185
IanBenzMaxim 1:e1c7c1c636af 186 case InvalidSensorEvent:
IanBenzMaxim 1:e1c7c1c636af 187 eventString = "InvalidSensor";
IanBenzMaxim 1:e1c7c1c636af 188 break;
IanBenzMaxim 1:e1c7c1c636af 189 }
IanBenzMaxim 1:e1c7c1c636af 190 if (eventString.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 191 {
IanBenzMaxim 1:e1c7c1c636af 192 if (httpPost.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 193 httpPost += fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 194 httpPost += "Event";
IanBenzMaxim 1:e1c7c1c636af 195 httpPost += keyValSeparator;
IanBenzMaxim 1:e1c7c1c636af 196 httpPost += eventString;
IanBenzMaxim 1:e1c7c1c636af 197 }
IanBenzMaxim 1:e1c7c1c636af 198
IanBenzMaxim 1:e1c7c1c636af 199 // Add initial post body
IanBenzMaxim 1:e1c7c1c636af 200 if (initialPostBody.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 201 {
IanBenzMaxim 1:e1c7c1c636af 202 if (httpPost.length() > 0)
IanBenzMaxim 1:e1c7c1c636af 203 httpPost += fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 204 httpPost += initialPostBody;
IanBenzMaxim 1:e1c7c1c636af 205 }
IanBenzMaxim 1:e1c7c1c636af 206
IanBenzMaxim 1:e1c7c1c636af 207 // Combine initial post body with initial secret and hash
IanBenzMaxim 6:b6bafd0a7013 208 std::vector<uint8_t> hashInput;
IanBenzMaxim 1:e1c7c1c636af 209 hashInput.reserve(challengeLen + httpPost.length());
IanBenzMaxim 1:e1c7c1c636af 210 hashInput.insert(hashInput.end(), challenge, challenge + challengeLen);
IanBenzMaxim 1:e1c7c1c636af 211 hashInput.insert(hashInput.end(), httpPost.begin(), httpPost.end());
IanBenzMaxim 6:b6bafd0a7013 212 ISha256MacCoproc::Mac mac;
IanBenzMaxim 1:e1c7c1c636af 213 calculateHttpPostMac(macCoproc, &hashInput[0], hashInput.size(), mac);
IanBenzMaxim 1:e1c7c1c636af 214
IanBenzMaxim 1:e1c7c1c636af 215 char contentLen[5];
IanBenzMaxim 1:e1c7c1c636af 216 std::snprintf(contentLen, sizeof(contentLen) / sizeof(char), "%u", (hashInput.size() - challengeLen) + (mac.length * charsPerByte) + 5 /* &MAC= */);
IanBenzMaxim 1:e1c7c1c636af 217
IanBenzMaxim 1:e1c7c1c636af 218 // Construct full post request
IanBenzMaxim 1:e1c7c1c636af 219 httpPost = "";
IanBenzMaxim 1:e1c7c1c636af 220 httpPost += "POST ";
IanBenzMaxim 1:e1c7c1c636af 221 httpPost += path;
IanBenzMaxim 1:e1c7c1c636af 222 httpPost += " HTTP/1.1";
IanBenzMaxim 1:e1c7c1c636af 223 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 224 httpPost += "Host: ";
IanBenzMaxim 1:e1c7c1c636af 225 httpPost += host;
IanBenzMaxim 1:e1c7c1c636af 226 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 227 httpPost += "Accept: */*";
IanBenzMaxim 1:e1c7c1c636af 228 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 229 httpPost += "Content-Length: ";
IanBenzMaxim 1:e1c7c1c636af 230 httpPost += contentLen;
IanBenzMaxim 1:e1c7c1c636af 231 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 232 httpPost += "Content-Type: application/x-www-form-urlencoded";
IanBenzMaxim 1:e1c7c1c636af 233 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 234 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 235 // Add post body
IanBenzMaxim 1:e1c7c1c636af 236 httpPost.append(reinterpret_cast<char *>(&hashInput[challengeLen]), hashInput.size() - challengeLen);
IanBenzMaxim 1:e1c7c1c636af 237 // Convert hash to hex string and add to post body
IanBenzMaxim 1:e1c7c1c636af 238 httpPost += fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 239 httpPost += "MAC";
IanBenzMaxim 1:e1c7c1c636af 240 httpPost += keyValSeparator;
IanBenzMaxim 1:e1c7c1c636af 241 byteArrayToHexString(mac, mac.length, httpPost);
IanBenzMaxim 1:e1c7c1c636af 242 httpPost += newline;
IanBenzMaxim 1:e1c7c1c636af 243
IanBenzMaxim 1:e1c7c1c636af 244 return httpPost;
IanBenzMaxim 1:e1c7c1c636af 245 }
IanBenzMaxim 1:e1c7c1c636af 246
IanBenzMaxim 6:b6bafd0a7013 247 bool WebServerInterface::authPostHttpEvent(ISha256MacCoproc & macCoproc, PostEvent event, const std::string & postData, bool setSecret)
IanBenzMaxim 1:e1c7c1c636af 248 {
IanBenzMaxim 1:e1c7c1c636af 249 const std::string challengeSearch(newline + newline);
IanBenzMaxim 1:e1c7c1c636af 250 bool result;
IanBenzMaxim 6:b6bafd0a7013 251 uint8_t challenge[challengeLen];
IanBenzMaxim 1:e1c7c1c636af 252 std::string response;
IanBenzMaxim 1:e1c7c1c636af 253
IanBenzMaxim 1:e1c7c1c636af 254 std::memset(challenge, defaultPaddingByte, challengeLen);
IanBenzMaxim 1:e1c7c1c636af 255 response.reserve(300);
IanBenzMaxim 1:e1c7c1c636af 256
IanBenzMaxim 1:e1c7c1c636af 257 if (setSecret)
IanBenzMaxim 1:e1c7c1c636af 258 {
IanBenzMaxim 1:e1c7c1c636af 259 result = setHttpPostSecret(macCoproc);
IanBenzMaxim 1:e1c7c1c636af 260 if (!result)
IanBenzMaxim 1:e1c7c1c636af 261 return result;
IanBenzMaxim 1:e1c7c1c636af 262 }
IanBenzMaxim 1:e1c7c1c636af 263
IanBenzMaxim 1:e1c7c1c636af 264 // Open connection
IanBenzMaxim 1:e1c7c1c636af 265 esp8266.clearRecvData(); // Clear received data buffer
IanBenzMaxim 1:e1c7c1c636af 266 result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 267 if (result)
IanBenzMaxim 1:e1c7c1c636af 268 {
IanBenzMaxim 1:e1c7c1c636af 269 // Request challenge
IanBenzMaxim 1:e1c7c1c636af 270 result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, sessionId)) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 271 if (result)
IanBenzMaxim 1:e1c7c1c636af 272 {
IanBenzMaxim 1:e1c7c1c636af 273 // Receive server response
IanBenzMaxim 1:e1c7c1c636af 274 for (int i = 0; i < 10; i++)
IanBenzMaxim 1:e1c7c1c636af 275 {
IanBenzMaxim 1:e1c7c1c636af 276 while (esp8266.recvIpDataReadable())
IanBenzMaxim 1:e1c7c1c636af 277 {
IanBenzMaxim 1:e1c7c1c636af 278 char read = esp8266.getcRecvIpData();
IanBenzMaxim 1:e1c7c1c636af 279 if (pc != NULL)
IanBenzMaxim 1:e1c7c1c636af 280 pc->putc(read);
IanBenzMaxim 1:e1c7c1c636af 281 if (response.length() < response.capacity())
IanBenzMaxim 1:e1c7c1c636af 282 {
IanBenzMaxim 1:e1c7c1c636af 283 response += read;
IanBenzMaxim 1:e1c7c1c636af 284 }
IanBenzMaxim 1:e1c7c1c636af 285 else
IanBenzMaxim 1:e1c7c1c636af 286 {
IanBenzMaxim 1:e1c7c1c636af 287 wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
IanBenzMaxim 1:e1c7c1c636af 288 goto close_get_connection;
IanBenzMaxim 1:e1c7c1c636af 289 }
IanBenzMaxim 1:e1c7c1c636af 290 }
IanBenzMaxim 1:e1c7c1c636af 291 wait_ms(100);
IanBenzMaxim 1:e1c7c1c636af 292 }
IanBenzMaxim 1:e1c7c1c636af 293 // Close connection
IanBenzMaxim 1:e1c7c1c636af 294 close_get_connection:
IanBenzMaxim 1:e1c7c1c636af 295 esp8266.closeConnection();
IanBenzMaxim 1:e1c7c1c636af 296
IanBenzMaxim 1:e1c7c1c636af 297 // Parse challenge from response
IanBenzMaxim 6:b6bafd0a7013 298 size_t challengePos = response.find(challengeSearch);
IanBenzMaxim 1:e1c7c1c636af 299 if ((challengePos != std::string::npos) && ((challengePos + challengeSearch.length() + (challengeLen * charsPerByte)) <= response.length()))
IanBenzMaxim 1:e1c7c1c636af 300 {
IanBenzMaxim 1:e1c7c1c636af 301 challengePos += challengeSearch.length();
IanBenzMaxim 6:b6bafd0a7013 302 for (size_t i = 0; i < challengeLen; i++)
IanBenzMaxim 1:e1c7c1c636af 303 {
IanBenzMaxim 1:e1c7c1c636af 304 std::sscanf(response.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]);
IanBenzMaxim 1:e1c7c1c636af 305 }
IanBenzMaxim 1:e1c7c1c636af 306 }
IanBenzMaxim 1:e1c7c1c636af 307
IanBenzMaxim 1:e1c7c1c636af 308 // Post sensor data
IanBenzMaxim 3:ac723be395d9 309 result = (esp8266.openConnection(ESP8266::TCP, serverAddress, serverPort) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 310 if (result)
IanBenzMaxim 1:e1c7c1c636af 311 {
IanBenzMaxim 1:e1c7c1c636af 312 result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, sessionId, macCoproc, event, postData, challenge)) == ESP8266::AT_OK);
IanBenzMaxim 1:e1c7c1c636af 313 wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
IanBenzMaxim 1:e1c7c1c636af 314 }
IanBenzMaxim 1:e1c7c1c636af 315 }
IanBenzMaxim 1:e1c7c1c636af 316
IanBenzMaxim 1:e1c7c1c636af 317 // Close connection
IanBenzMaxim 1:e1c7c1c636af 318 esp8266.closeConnection();
IanBenzMaxim 1:e1c7c1c636af 319 }
IanBenzMaxim 1:e1c7c1c636af 320
IanBenzMaxim 1:e1c7c1c636af 321 return result;
IanBenzMaxim 1:e1c7c1c636af 322 }
IanBenzMaxim 1:e1c7c1c636af 323
IanBenzMaxim 1:e1c7c1c636af 324 std::string WebServerInterface::formatSensorDataPostBody(const SensorData & sensorData)
IanBenzMaxim 1:e1c7c1c636af 325 {
IanBenzMaxim 1:e1c7c1c636af 326 // Create initial post body string from input data
IanBenzMaxim 1:e1c7c1c636af 327 std::ostringstream postBodyStream;
IanBenzMaxim 1:e1c7c1c636af 328 postBodyStream << "Temp" << keyValSeparator << static_cast<int>(sensorData.temp);
IanBenzMaxim 1:e1c7c1c636af 329 postBodyStream << fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 330 postBodyStream << "FilterLife" << keyValSeparator << static_cast<unsigned>(sensorData.filterLife);
IanBenzMaxim 1:e1c7c1c636af 331 postBodyStream << fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 332 postBodyStream << "TempAlarm" << keyValSeparator << (sensorData.tempAlarm() ? "true" : "false");
IanBenzMaxim 1:e1c7c1c636af 333 postBodyStream << fieldSeparator;
IanBenzMaxim 1:e1c7c1c636af 334 postBodyStream << "FilterLifeAlarm" << keyValSeparator << (sensorData.filterLifeAlarm() ? "true" : "false");
IanBenzMaxim 1:e1c7c1c636af 335 return postBodyStream.str();
IanBenzMaxim 1:e1c7c1c636af 336 }