DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

The MAXREFDES155# is an internet-of-things (IoT) embedded-security reference design, built to authenticate and control a sensing node using elliptic-curve-based public-key cryptography with control and notification from a web server.

The hardware includes an ARM® mbed™ shield and attached sensor endpoint. The shield contains a DS2476 DeepCover® ECDSA/SHA-2 coprocessor, Wifi communication, LCD push-button controls, and status LEDs. The sensor endpoint is attached to the shield using a 300mm cable and contains a DS28C36 DeepCover ECDSA/SHA-2 authenticator, IR-thermal sensor, and aiming laser for the IR sensor. The MAXREFDES155# is equipped with a standard Arduino® form-factor shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The combination of these two devices represent an IoT device. Communication to the web server is accomplished with the shield Wifi circuitry. Communication from the shield to the attached sensor module is accomplished over I2C . The sensor module represents an IoT endpoint that generates small data with a requirement for message authenticity/integrity and secure on/off operational control.

The design is hierarchical with each mbed platform and shield communicating data from the sensor node to a web server that maintains a centralized log and dispatches notifications as necessary. The simplicity of this design enables rapid integration into any star-topology IoT network to provide security with the low overhead and cost provided by the ECDSA-P256 asymmetric-key and SHA-256 symmetric-key algorithms.

More information about the MAXREFDES155# is available on the Maxim Integrated website.

Committer:
IanBenzMaxim
Date:
Fri Feb 24 11:23:12 2017 -0600
Revision:
0:33d4e66780c0
Child:
3:d2799d8497c0
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 0:33d4e66780c0 1 /*******************************************************************************
IanBenzMaxim 0:33d4e66780c0 2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
IanBenzMaxim 0:33d4e66780c0 3 *
IanBenzMaxim 0:33d4e66780c0 4 * Permission is hereby granted, free of charge, to any person obtaining a
IanBenzMaxim 0:33d4e66780c0 5 * copy of this software and associated documentation files (the "Software"),
IanBenzMaxim 0:33d4e66780c0 6 * to deal in the Software without restriction, including without limitation
IanBenzMaxim 0:33d4e66780c0 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
IanBenzMaxim 0:33d4e66780c0 8 * and/or sell copies of the Software, and to permit persons to whom the
IanBenzMaxim 0:33d4e66780c0 9 * Software is furnished to do so, subject to the following conditions:
IanBenzMaxim 0:33d4e66780c0 10 *
IanBenzMaxim 0:33d4e66780c0 11 * The above copyright notice and this permission notice shall be included
IanBenzMaxim 0:33d4e66780c0 12 * in all copies or substantial portions of the Software.
IanBenzMaxim 0:33d4e66780c0 13 *
IanBenzMaxim 0:33d4e66780c0 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
IanBenzMaxim 0:33d4e66780c0 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
IanBenzMaxim 0:33d4e66780c0 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IanBenzMaxim 0:33d4e66780c0 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
IanBenzMaxim 0:33d4e66780c0 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
IanBenzMaxim 0:33d4e66780c0 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
IanBenzMaxim 0:33d4e66780c0 20 * OTHER DEALINGS IN THE SOFTWARE.
IanBenzMaxim 0:33d4e66780c0 21 *
IanBenzMaxim 0:33d4e66780c0 22 * Except as contained in this notice, the name of Maxim Integrated
IanBenzMaxim 0:33d4e66780c0 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
IanBenzMaxim 0:33d4e66780c0 24 * Products, Inc. Branding Policy.
IanBenzMaxim 0:33d4e66780c0 25 *
IanBenzMaxim 0:33d4e66780c0 26 * The mere transfer of this software does not imply any licenses
IanBenzMaxim 0:33d4e66780c0 27 * of trade secrets, proprietary technology, copyrights, patents,
IanBenzMaxim 0:33d4e66780c0 28 * trademarks, maskwork rights, or any other form of intellectual
IanBenzMaxim 0:33d4e66780c0 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
IanBenzMaxim 0:33d4e66780c0 30 * ownership rights.
IanBenzMaxim 0:33d4e66780c0 31 *******************************************************************************/
IanBenzMaxim 0:33d4e66780c0 32
IanBenzMaxim 0:33d4e66780c0 33 #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
IanBenzMaxim 0:33d4e66780c0 34 #include <rapidjson/document.h>
IanBenzMaxim 0:33d4e66780c0 35 #include <rapidjson/writer.h>
IanBenzMaxim 0:33d4e66780c0 36 #include <rapidjson/stringbuffer.h>
IanBenzMaxim 0:33d4e66780c0 37
IanBenzMaxim 0:33d4e66780c0 38 #include <stdint.h>
IanBenzMaxim 0:33d4e66780c0 39 #include <cassert>
IanBenzMaxim 0:33d4e66780c0 40 #include <iostream>
IanBenzMaxim 0:33d4e66780c0 41 #include <string>
IanBenzMaxim 0:33d4e66780c0 42 #include <utility>
IanBenzMaxim 0:33d4e66780c0 43 #include "Image.hpp"
IanBenzMaxim 0:33d4e66780c0 44 #include "Text.hpp"
IanBenzMaxim 0:33d4e66780c0 45 #include "WindowManager.hpp"
IanBenzMaxim 0:33d4e66780c0 46 #include "ErrorWindow.hpp"
IanBenzMaxim 0:33d4e66780c0 47 #include "DisplayIdWindow.hpp"
IanBenzMaxim 0:33d4e66780c0 48 #include "NormalOperationWindow.hpp"
IanBenzMaxim 0:33d4e66780c0 49 #include "DisplayGraphicWindow.hpp"
IanBenzMaxim 0:33d4e66780c0 50 #include "HexConversions.hpp"
IanBenzMaxim 0:33d4e66780c0 51 #include "DS2476.hpp"
IanBenzMaxim 0:33d4e66780c0 52 #include "SensorNode.hpp"
IanBenzMaxim 0:33d4e66780c0 53
IanBenzMaxim 0:33d4e66780c0 54 extern DS2476 coproc;
IanBenzMaxim 0:33d4e66780c0 55 extern SensorNode sensorNode;
IanBenzMaxim 0:33d4e66780c0 56 extern std::string webId;
IanBenzMaxim 0:33d4e66780c0 57
IanBenzMaxim 0:33d4e66780c0 58 extern "C" {
IanBenzMaxim 0:33d4e66780c0 59 void ComputeSHA256(unsigned char* message, short length, unsigned short skipconst,
IanBenzMaxim 0:33d4e66780c0 60 unsigned short reverse, unsigned char* digest);
IanBenzMaxim 0:33d4e66780c0 61 }
IanBenzMaxim 0:33d4e66780c0 62
IanBenzMaxim 0:33d4e66780c0 63 static const size_t defaultChunkSize = 256; // Default allocation size for rapidjson.
IanBenzMaxim 0:33d4e66780c0 64 static const int jsonMaxDecimalPlaces = 2; // Number of decimal places to use when writing JSON.
IanBenzMaxim 0:33d4e66780c0 65
IanBenzMaxim 0:33d4e66780c0 66 // Separate multiple JSON commands received on the socket.
IanBenzMaxim 0:33d4e66780c0 67 // Returns a list of begin and end iterators within the input message.
IanBenzMaxim 0:33d4e66780c0 68 static std::vector<std::pair<const char *, const char *> > separateCommands(const char * receivedData, size_t receivedDataSize)
IanBenzMaxim 0:33d4e66780c0 69 {
IanBenzMaxim 0:33d4e66780c0 70 std::vector<std::pair<const char *, const char *> > commands;
IanBenzMaxim 0:33d4e66780c0 71 unsigned int counter = 0;
IanBenzMaxim 0:33d4e66780c0 72 size_t beginIdx;
IanBenzMaxim 0:33d4e66780c0 73 for (size_t i = 0; i < receivedDataSize; i++)
IanBenzMaxim 0:33d4e66780c0 74 {
IanBenzMaxim 0:33d4e66780c0 75 if (receivedData[i] == '{')
IanBenzMaxim 0:33d4e66780c0 76 {
IanBenzMaxim 0:33d4e66780c0 77 if (counter == 0)
IanBenzMaxim 0:33d4e66780c0 78 {
IanBenzMaxim 0:33d4e66780c0 79 beginIdx = i;
IanBenzMaxim 0:33d4e66780c0 80 }
IanBenzMaxim 0:33d4e66780c0 81 counter++;
IanBenzMaxim 0:33d4e66780c0 82 }
IanBenzMaxim 0:33d4e66780c0 83 else if (receivedData[i] == '}')
IanBenzMaxim 0:33d4e66780c0 84 {
IanBenzMaxim 0:33d4e66780c0 85 if (counter > 0)
IanBenzMaxim 0:33d4e66780c0 86 {
IanBenzMaxim 0:33d4e66780c0 87 counter--;
IanBenzMaxim 0:33d4e66780c0 88 if (counter == 0)
IanBenzMaxim 0:33d4e66780c0 89 {
IanBenzMaxim 0:33d4e66780c0 90 commands.push_back(std::make_pair(&receivedData[beginIdx], &receivedData[i + 1]));
IanBenzMaxim 0:33d4e66780c0 91 }
IanBenzMaxim 0:33d4e66780c0 92 }
IanBenzMaxim 0:33d4e66780c0 93 }
IanBenzMaxim 0:33d4e66780c0 94 }
IanBenzMaxim 0:33d4e66780c0 95 return commands;
IanBenzMaxim 0:33d4e66780c0 96 }
IanBenzMaxim 0:33d4e66780c0 97
IanBenzMaxim 0:33d4e66780c0 98 // Adds signature information to an existing JSON document.
IanBenzMaxim 0:33d4e66780c0 99 static DS2476::CmdResult signData(bool validSignature, const std::vector<uint8_t> & challenge, rapidjson::Document & document)
IanBenzMaxim 0:33d4e66780c0 100 {
IanBenzMaxim 0:33d4e66780c0 101 // Move contents of document to a new location and create an empty object in document.
IanBenzMaxim 0:33d4e66780c0 102 rapidjson::Value data(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 103 data.Swap(document);
IanBenzMaxim 0:33d4e66780c0 104 // Convert data to a string and generate a signature from that string.
IanBenzMaxim 0:33d4e66780c0 105 rapidjson::StringBuffer dataBuffer;
IanBenzMaxim 0:33d4e66780c0 106 rapidjson::Writer<rapidjson::StringBuffer> writer(dataBuffer);
IanBenzMaxim 0:33d4e66780c0 107 writer.SetMaxDecimalPlaces(jsonMaxDecimalPlaces);
IanBenzMaxim 0:33d4e66780c0 108 data.Accept(writer);
IanBenzMaxim 0:33d4e66780c0 109 std::vector<uint8_t> signDataBuffer(dataBuffer.GetString(), dataBuffer.GetString() + dataBuffer.GetLength());
IanBenzMaxim 0:33d4e66780c0 110 signDataBuffer.insert(signDataBuffer.end(), challenge.begin(), challenge.end());
IanBenzMaxim 0:33d4e66780c0 111 DS2476::Buffer ds2476Buffer(32);
IanBenzMaxim 0:33d4e66780c0 112 ComputeSHA256(&signDataBuffer[0], signDataBuffer.size(), false, false, &ds2476Buffer[0]);
IanBenzMaxim 0:33d4e66780c0 113 DS2476::CmdResult result = coproc.writeBuffer(ds2476Buffer);
IanBenzMaxim 0:33d4e66780c0 114 if (result == DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 115 {
IanBenzMaxim 0:33d4e66780c0 116 DS2476::Signature signatureBuffer;
IanBenzMaxim 0:33d4e66780c0 117 result = coproc.generateEcdsaSignature(DS2476::KeyNumA, signatureBuffer);
IanBenzMaxim 0:33d4e66780c0 118 if (result == DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 119 {
IanBenzMaxim 0:33d4e66780c0 120 if (!validSignature)
IanBenzMaxim 0:33d4e66780c0 121 signatureBuffer.r[0]++;
IanBenzMaxim 0:33d4e66780c0 122 // Construct the final document with the original data and the generated signature.
IanBenzMaxim 0:33d4e66780c0 123 rapidjson::Value signature(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 124 signature.AddMember("r", rapidjson::Value(byteArrayToHexString(signatureBuffer.r.data(),
IanBenzMaxim 0:33d4e66780c0 125 signatureBuffer.r.size()).c_str(), document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 126 signature.AddMember("s", rapidjson::Value(byteArrayToHexString(signatureBuffer.s.data(),
IanBenzMaxim 0:33d4e66780c0 127 signatureBuffer.s.size()).c_str(), document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 128 document.AddMember("data", data, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 129 document.AddMember("signature", signature, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 130 }
IanBenzMaxim 0:33d4e66780c0 131 }
IanBenzMaxim 0:33d4e66780c0 132 return result;
IanBenzMaxim 0:33d4e66780c0 133 }
IanBenzMaxim 0:33d4e66780c0 134
IanBenzMaxim 0:33d4e66780c0 135 // Parse and verify a signed JSON string.
IanBenzMaxim 0:33d4e66780c0 136 static DS2476::CmdResult verifySignedData(const std::string & verifyData, rapidjson::Document & signedData)
IanBenzMaxim 0:33d4e66780c0 137 {
IanBenzMaxim 0:33d4e66780c0 138 using rapidjson::Value;
IanBenzMaxim 0:33d4e66780c0 139 using std::string;
IanBenzMaxim 0:33d4e66780c0 140
IanBenzMaxim 0:33d4e66780c0 141 // Parse string and validate object schema.
IanBenzMaxim 0:33d4e66780c0 142 signedData.Parse(verifyData.c_str());
IanBenzMaxim 0:33d4e66780c0 143 if (!(signedData.IsObject() && signedData.HasMember("data") && signedData.HasMember("signature")))
IanBenzMaxim 0:33d4e66780c0 144 {
IanBenzMaxim 0:33d4e66780c0 145 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 146 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 147 }
IanBenzMaxim 0:33d4e66780c0 148 Value & data = signedData["data"];
IanBenzMaxim 0:33d4e66780c0 149 const Value & signature = signedData["signature"];
IanBenzMaxim 0:33d4e66780c0 150 if (!(data.IsObject() && signature.IsObject() && signature.HasMember("r") && signature.HasMember("s")))
IanBenzMaxim 0:33d4e66780c0 151 {
IanBenzMaxim 0:33d4e66780c0 152 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 153 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 154 }
IanBenzMaxim 0:33d4e66780c0 155 const Value & signatureR = signature["r"];
IanBenzMaxim 0:33d4e66780c0 156 const Value & signatureS = signature["s"];
IanBenzMaxim 0:33d4e66780c0 157 if (!(signatureR.IsString() && signatureS.IsString()))
IanBenzMaxim 0:33d4e66780c0 158 {
IanBenzMaxim 0:33d4e66780c0 159 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 160 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 161 }
IanBenzMaxim 0:33d4e66780c0 162
IanBenzMaxim 0:33d4e66780c0 163 // Parse signature.
IanBenzMaxim 0:33d4e66780c0 164 std::vector<uint8_t> parsedBytes =
IanBenzMaxim 0:33d4e66780c0 165 hexStringToByteArray(std::string(signatureR.GetString(), signatureR.GetStringLength()));
IanBenzMaxim 0:33d4e66780c0 166 DS2476::Signature signatureBuffer;
IanBenzMaxim 0:33d4e66780c0 167 if (parsedBytes.size() != signatureBuffer.r.size())
IanBenzMaxim 0:33d4e66780c0 168 {
IanBenzMaxim 0:33d4e66780c0 169 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 170 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 171 }
IanBenzMaxim 0:33d4e66780c0 172 std::copy(parsedBytes.begin(), parsedBytes.end(), signatureBuffer.r.begin());
IanBenzMaxim 0:33d4e66780c0 173 parsedBytes = hexStringToByteArray(std::string(signatureS.GetString(), signatureS.GetStringLength()));
IanBenzMaxim 0:33d4e66780c0 174 if (parsedBytes.size() != signatureBuffer.s.size())
IanBenzMaxim 0:33d4e66780c0 175 {
IanBenzMaxim 0:33d4e66780c0 176 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 177 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 178 }
IanBenzMaxim 0:33d4e66780c0 179 std::copy(parsedBytes.begin(), parsedBytes.end(), signatureBuffer.s.begin());
IanBenzMaxim 0:33d4e66780c0 180
IanBenzMaxim 0:33d4e66780c0 181 // Compute hash of the data.
IanBenzMaxim 0:33d4e66780c0 182 // Need to use string searching here since there isn't currently a way to access raw elements
IanBenzMaxim 0:33d4e66780c0 183 // in rapidjson, and creating another copy of the data might consume too much memory.
IanBenzMaxim 0:33d4e66780c0 184 const string rawDataSearch("\"data\":");
IanBenzMaxim 0:33d4e66780c0 185 string::size_type rawDataBegin = verifyData.find(rawDataSearch);
IanBenzMaxim 0:33d4e66780c0 186 if ((rawDataBegin == string::npos) || ((rawDataBegin + rawDataSearch.size()) >= verifyData.size()))
IanBenzMaxim 0:33d4e66780c0 187 {
IanBenzMaxim 0:33d4e66780c0 188 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 189 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 190 }
IanBenzMaxim 0:33d4e66780c0 191 rawDataBegin += rawDataSearch.size();
IanBenzMaxim 0:33d4e66780c0 192 string::size_type rawDataEnd = verifyData.find(",\"signature\"", rawDataBegin);
IanBenzMaxim 0:33d4e66780c0 193 if (rawDataEnd == string::npos)
IanBenzMaxim 0:33d4e66780c0 194 {
IanBenzMaxim 0:33d4e66780c0 195 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 196 return DS2476::AuthenticationError;
IanBenzMaxim 0:33d4e66780c0 197 }
IanBenzMaxim 0:33d4e66780c0 198 const string::size_type chunkSize = 64;
IanBenzMaxim 0:33d4e66780c0 199 for (string::size_type i = rawDataBegin; i < rawDataEnd; i += chunkSize)
IanBenzMaxim 0:33d4e66780c0 200 {
IanBenzMaxim 0:33d4e66780c0 201 const string::size_type remainingLength = rawDataEnd - i;
IanBenzMaxim 0:33d4e66780c0 202 DS2476::CmdResult result = coproc.computeMultiblockHash(i == 0, remainingLength < chunkSize,
IanBenzMaxim 0:33d4e66780c0 203 DS2476::Buffer(verifyData.c_str() + i, verifyData.c_str() + i + std::min(remainingLength, chunkSize)));
IanBenzMaxim 0:33d4e66780c0 204 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 205 {
IanBenzMaxim 0:33d4e66780c0 206 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 207 return result;
IanBenzMaxim 0:33d4e66780c0 208 }
IanBenzMaxim 0:33d4e66780c0 209 }
IanBenzMaxim 0:33d4e66780c0 210 // Verify signature.
IanBenzMaxim 0:33d4e66780c0 211 DS2476::CmdResult result =
IanBenzMaxim 0:33d4e66780c0 212 coproc.verifyEcdsaSignature(DS2476::KeyNumC, DS2476::THASH, signatureBuffer);
IanBenzMaxim 0:33d4e66780c0 213 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 214 {
IanBenzMaxim 0:33d4e66780c0 215 signedData.RemoveAllMembers();
IanBenzMaxim 0:33d4e66780c0 216 return result;
IanBenzMaxim 0:33d4e66780c0 217 }
IanBenzMaxim 0:33d4e66780c0 218
IanBenzMaxim 0:33d4e66780c0 219 // Strip signing information from document.
IanBenzMaxim 0:33d4e66780c0 220 rapidjson::Value swapObject(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 221 swapObject.Swap(data);
IanBenzMaxim 0:33d4e66780c0 222 swapObject.Swap(signedData);
IanBenzMaxim 0:33d4e66780c0 223 return result;
IanBenzMaxim 0:33d4e66780c0 224 }
IanBenzMaxim 0:33d4e66780c0 225
IanBenzMaxim 0:33d4e66780c0 226 // Send a JSON document to the server.
IanBenzMaxim 0:33d4e66780c0 227 static void sendJson(const rapidjson::Value & document, TCPSocket & socket)
IanBenzMaxim 0:33d4e66780c0 228 {
IanBenzMaxim 0:33d4e66780c0 229 rapidjson::StringBuffer buffer;
IanBenzMaxim 0:33d4e66780c0 230 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
IanBenzMaxim 0:33d4e66780c0 231 writer.SetMaxDecimalPlaces(jsonMaxDecimalPlaces);
IanBenzMaxim 0:33d4e66780c0 232 document.Accept(writer);
IanBenzMaxim 0:33d4e66780c0 233 socket.send(buffer.GetString(), buffer.GetLength());
IanBenzMaxim 0:33d4e66780c0 234 }
IanBenzMaxim 0:33d4e66780c0 235
IanBenzMaxim 0:33d4e66780c0 236 void NormalOperationWindow::sendMessage(const char * message)
IanBenzMaxim 0:33d4e66780c0 237 {
IanBenzMaxim 0:33d4e66780c0 238 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 239 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 240 document.AddMember("message", rapidjson::StringRef(message), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 241 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 242 }
IanBenzMaxim 0:33d4e66780c0 243
IanBenzMaxim 0:33d4e66780c0 244 static std::string getValidSignatureButtonText(bool validSignature)
IanBenzMaxim 0:33d4e66780c0 245 {
IanBenzMaxim 0:33d4e66780c0 246 return validSignature ? "Use invalid sig." : "Use valid sig.";
IanBenzMaxim 0:33d4e66780c0 247 }
IanBenzMaxim 0:33d4e66780c0 248
IanBenzMaxim 0:33d4e66780c0 249 void NormalOperationWindow::showWebId()
IanBenzMaxim 0:33d4e66780c0 250 {
IanBenzMaxim 0:33d4e66780c0 251 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 252 {
IanBenzMaxim 0:33d4e66780c0 253 windowManager()->push(new DisplayIdWindow(DisplayIdWindow::PopupMode));
IanBenzMaxim 0:33d4e66780c0 254 }
IanBenzMaxim 0:33d4e66780c0 255 }
IanBenzMaxim 0:33d4e66780c0 256
IanBenzMaxim 0:33d4e66780c0 257 void NormalOperationWindow::toggleValidSignature()
IanBenzMaxim 0:33d4e66780c0 258 {
IanBenzMaxim 0:33d4e66780c0 259 validSignature = !validSignature;
IanBenzMaxim 0:33d4e66780c0 260 validSignatureButton.setText(getValidSignatureButtonText(validSignature));
IanBenzMaxim 0:33d4e66780c0 261 }
IanBenzMaxim 0:33d4e66780c0 262
IanBenzMaxim 0:33d4e66780c0 263 NormalOperationWindow::NormalOperationWindow(TCPSocket * socket, Graphic * parent) : Window(parent),
IanBenzMaxim 0:33d4e66780c0 264 socket(socket), validSignature(true), lastSensorNodeState(Disconnected),
IanBenzMaxim 0:33d4e66780c0 265 lastObjectTemp(0), lastAmbientTemp(0),
IanBenzMaxim 0:33d4e66780c0 266 validSignatureButton(getValidSignatureButtonText(validSignature), this),
IanBenzMaxim 0:33d4e66780c0 267 showWebIdButton("Show web ID", this)
IanBenzMaxim 0:33d4e66780c0 268 {
IanBenzMaxim 0:33d4e66780c0 269 assert(socket != NULL);
IanBenzMaxim 0:33d4e66780c0 270
IanBenzMaxim 0:33d4e66780c0 271 validSignatureButton.setClickedHandler(Button::EventHandler(this, &NormalOperationWindow::toggleValidSignature));
IanBenzMaxim 0:33d4e66780c0 272 showWebIdButton.setClickedHandler(Button::EventHandler(this, &NormalOperationWindow::showWebId));
IanBenzMaxim 0:33d4e66780c0 273 validSignatureButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 274 }
IanBenzMaxim 0:33d4e66780c0 275
IanBenzMaxim 0:33d4e66780c0 276 NormalOperationWindow::SensorNodeState NormalOperationWindow::detectSensorNode()
IanBenzMaxim 0:33d4e66780c0 277 {
IanBenzMaxim 0:33d4e66780c0 278 SensorNodeState sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 279 if (sensorNode.detect())
IanBenzMaxim 0:33d4e66780c0 280 {
IanBenzMaxim 0:33d4e66780c0 281 bool provisioned;
IanBenzMaxim 0:33d4e66780c0 282 if (sensorNode.getProvisioned(provisioned))
IanBenzMaxim 0:33d4e66780c0 283 {
IanBenzMaxim 0:33d4e66780c0 284 if (provisioned)
IanBenzMaxim 0:33d4e66780c0 285 {
IanBenzMaxim 0:33d4e66780c0 286 if (sensorNode.authenticate())
IanBenzMaxim 0:33d4e66780c0 287 {
IanBenzMaxim 0:33d4e66780c0 288 bool laserEnabled;
IanBenzMaxim 0:33d4e66780c0 289 if (sensorNode.getLaserEnabled(laserEnabled))
IanBenzMaxim 0:33d4e66780c0 290 {
IanBenzMaxim 0:33d4e66780c0 291 sensorNodeState = (laserEnabled ? ValidLaserEnabled : ValidLaserDisabled);
IanBenzMaxim 0:33d4e66780c0 292 }
IanBenzMaxim 0:33d4e66780c0 293 else
IanBenzMaxim 0:33d4e66780c0 294 {
IanBenzMaxim 0:33d4e66780c0 295 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 296 }
IanBenzMaxim 0:33d4e66780c0 297 }
IanBenzMaxim 0:33d4e66780c0 298 else
IanBenzMaxim 0:33d4e66780c0 299 {
IanBenzMaxim 0:33d4e66780c0 300 sensorNodeState = Invalid;
IanBenzMaxim 0:33d4e66780c0 301 }
IanBenzMaxim 0:33d4e66780c0 302 }
IanBenzMaxim 0:33d4e66780c0 303 else
IanBenzMaxim 0:33d4e66780c0 304 {
IanBenzMaxim 0:33d4e66780c0 305 bool provisionResult = sensorNode.provision();
IanBenzMaxim 0:33d4e66780c0 306 if (provisionResult)
IanBenzMaxim 0:33d4e66780c0 307 {
IanBenzMaxim 0:33d4e66780c0 308 // Detect the new state after provisioning.
IanBenzMaxim 0:33d4e66780c0 309 sensorNodeState = detectSensorNode();
IanBenzMaxim 0:33d4e66780c0 310 }
IanBenzMaxim 0:33d4e66780c0 311 else
IanBenzMaxim 0:33d4e66780c0 312 {
IanBenzMaxim 0:33d4e66780c0 313 sensorNodeState = FailedProvision;
IanBenzMaxim 0:33d4e66780c0 314 }
IanBenzMaxim 0:33d4e66780c0 315 }
IanBenzMaxim 0:33d4e66780c0 316 }
IanBenzMaxim 0:33d4e66780c0 317 else
IanBenzMaxim 0:33d4e66780c0 318 {
IanBenzMaxim 0:33d4e66780c0 319 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 320 }
IanBenzMaxim 0:33d4e66780c0 321 }
IanBenzMaxim 0:33d4e66780c0 322 else
IanBenzMaxim 0:33d4e66780c0 323 {
IanBenzMaxim 0:33d4e66780c0 324 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 325 }
IanBenzMaxim 0:33d4e66780c0 326 return sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 327 }
IanBenzMaxim 0:33d4e66780c0 328
IanBenzMaxim 0:33d4e66780c0 329 NormalOperationWindow::Result NormalOperationWindow::sendStatus(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 330 {
IanBenzMaxim 0:33d4e66780c0 331 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 332 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 333
IanBenzMaxim 0:33d4e66780c0 334 // Insert Web ID.
IanBenzMaxim 0:33d4e66780c0 335 document.AddMember("id", rapidjson::StringRef(webId.c_str()), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 336
IanBenzMaxim 0:33d4e66780c0 337 // Insert device public key.
IanBenzMaxim 0:33d4e66780c0 338 rapidjson::Value publicKey(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 339 DS2476::Page page;
IanBenzMaxim 0:33d4e66780c0 340 DS2476::CmdResult result = coproc.readMemory(DS2476::PublicKeyAX, page);
IanBenzMaxim 0:33d4e66780c0 341 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 342 {
IanBenzMaxim 0:33d4e66780c0 343 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 344 {
IanBenzMaxim 0:33d4e66780c0 345 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 346 windowManager()->push(new ErrorWindow("Failed to read PublicKeyAX"));
IanBenzMaxim 0:33d4e66780c0 347 }
IanBenzMaxim 0:33d4e66780c0 348 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 349 }
IanBenzMaxim 0:33d4e66780c0 350 publicKey.AddMember("x", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 351 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 352 result = coproc.readMemory(DS2476::PublicKeyAY, page);
IanBenzMaxim 0:33d4e66780c0 353 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 354 {
IanBenzMaxim 0:33d4e66780c0 355 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 356 {
IanBenzMaxim 0:33d4e66780c0 357 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 358 windowManager()->push(new ErrorWindow("Failed to read PublicKeyAY"));
IanBenzMaxim 0:33d4e66780c0 359 }
IanBenzMaxim 0:33d4e66780c0 360 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 361 }
IanBenzMaxim 0:33d4e66780c0 362 publicKey.AddMember("y", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 363 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 364 document.AddMember("publicKey", publicKey, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 365
IanBenzMaxim 0:33d4e66780c0 366 // Insert device certificate.
IanBenzMaxim 0:33d4e66780c0 367 rapidjson::Value certificate(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 368 result = coproc.readMemory(DS2476::UserData14, page);
IanBenzMaxim 0:33d4e66780c0 369 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 370 {
IanBenzMaxim 0:33d4e66780c0 371 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 372 {
IanBenzMaxim 0:33d4e66780c0 373 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 374 windowManager()->push(new ErrorWindow("Failed to read UserData14"));
IanBenzMaxim 0:33d4e66780c0 375 }
IanBenzMaxim 0:33d4e66780c0 376 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 377 }
IanBenzMaxim 0:33d4e66780c0 378 certificate.AddMember("r", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 379 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 380 result = coproc.readMemory(DS2476::UserData15, page);
IanBenzMaxim 0:33d4e66780c0 381 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 382 {
IanBenzMaxim 0:33d4e66780c0 383 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 384 {
IanBenzMaxim 0:33d4e66780c0 385 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 386 windowManager()->push(new ErrorWindow("Failed to read UserData15"));
IanBenzMaxim 0:33d4e66780c0 387 }
IanBenzMaxim 0:33d4e66780c0 388 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 389 }
IanBenzMaxim 0:33d4e66780c0 390 certificate.AddMember("s", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 391 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 392 document.AddMember("certificate", certificate, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 393
IanBenzMaxim 0:33d4e66780c0 394 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 395 result = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 396 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 397 {
IanBenzMaxim 0:33d4e66780c0 398 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 399 {
IanBenzMaxim 0:33d4e66780c0 400 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 401 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 402 }
IanBenzMaxim 0:33d4e66780c0 403 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 404 }
IanBenzMaxim 0:33d4e66780c0 405 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 406 return NoChange;
IanBenzMaxim 0:33d4e66780c0 407 }
IanBenzMaxim 0:33d4e66780c0 408
IanBenzMaxim 0:33d4e66780c0 409 NormalOperationWindow::Result NormalOperationWindow::sendObjectTemp(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 410 {
IanBenzMaxim 0:33d4e66780c0 411 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 412 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 413
IanBenzMaxim 0:33d4e66780c0 414 // Read object temperatue and add to document.
IanBenzMaxim 0:33d4e66780c0 415 double objectTemp;
IanBenzMaxim 0:33d4e66780c0 416 bool sensorResult = sensorNode.readTemp(SensorNode::ObjectTemp, objectTemp);
IanBenzMaxim 0:33d4e66780c0 417 if (!sensorResult)
IanBenzMaxim 0:33d4e66780c0 418 {
IanBenzMaxim 0:33d4e66780c0 419 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 420 {
IanBenzMaxim 0:33d4e66780c0 421 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 422 windowManager()->push(new ErrorWindow("Failed to read object temperature"));
IanBenzMaxim 0:33d4e66780c0 423 }
IanBenzMaxim 0:33d4e66780c0 424 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 425 }
IanBenzMaxim 0:33d4e66780c0 426 document.AddMember("objectTemp", objectTemp, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 427
IanBenzMaxim 0:33d4e66780c0 428 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 429 DS2476::CmdResult coprocResult = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 430 if (coprocResult != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 431 {
IanBenzMaxim 0:33d4e66780c0 432 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 433 {
IanBenzMaxim 0:33d4e66780c0 434 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 435 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 436 }
IanBenzMaxim 0:33d4e66780c0 437 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 438 }
IanBenzMaxim 0:33d4e66780c0 439 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 440
IanBenzMaxim 0:33d4e66780c0 441 lastObjectTemp = objectTemp;
IanBenzMaxim 0:33d4e66780c0 442 return NoChange;
IanBenzMaxim 0:33d4e66780c0 443 }
IanBenzMaxim 0:33d4e66780c0 444
IanBenzMaxim 0:33d4e66780c0 445 NormalOperationWindow::Result NormalOperationWindow::sendAmbientTemp(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 446 {
IanBenzMaxim 0:33d4e66780c0 447 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 448 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 449
IanBenzMaxim 0:33d4e66780c0 450 // Read ambient temperatue and add to document.
IanBenzMaxim 0:33d4e66780c0 451 double ambientTemp;
IanBenzMaxim 0:33d4e66780c0 452 bool sensorResult = sensorNode.readTemp(SensorNode::AmbientTemp, ambientTemp);
IanBenzMaxim 0:33d4e66780c0 453 if (!sensorResult)
IanBenzMaxim 0:33d4e66780c0 454 {
IanBenzMaxim 0:33d4e66780c0 455 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 456 {
IanBenzMaxim 0:33d4e66780c0 457 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 458 windowManager()->push(new ErrorWindow("Failed to read ambient temperature"));
IanBenzMaxim 0:33d4e66780c0 459 }
IanBenzMaxim 0:33d4e66780c0 460 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 461 }
IanBenzMaxim 0:33d4e66780c0 462 document.AddMember("ambientTemp", ambientTemp, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 463
IanBenzMaxim 0:33d4e66780c0 464 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 465 DS2476::CmdResult coprocResult = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 466 if (coprocResult != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 467 {
IanBenzMaxim 0:33d4e66780c0 468 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 469 {
IanBenzMaxim 0:33d4e66780c0 470 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 471 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 472 }
IanBenzMaxim 0:33d4e66780c0 473 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 474 }
IanBenzMaxim 0:33d4e66780c0 475 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 476
IanBenzMaxim 0:33d4e66780c0 477 lastAmbientTemp = ambientTemp;
IanBenzMaxim 0:33d4e66780c0 478 return NoChange;
IanBenzMaxim 0:33d4e66780c0 479 }
IanBenzMaxim 0:33d4e66780c0 480
IanBenzMaxim 0:33d4e66780c0 481 void NormalOperationWindow::displayImage(const std::vector<uint8_t> & imageData)
IanBenzMaxim 0:33d4e66780c0 482 {
IanBenzMaxim 0:33d4e66780c0 483 const unsigned int width = 64;
IanBenzMaxim 0:33d4e66780c0 484 const unsigned int height = imageData.size() / (width / Bitmap::pixelsPerSegment);
IanBenzMaxim 0:33d4e66780c0 485 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 486 {
IanBenzMaxim 0:33d4e66780c0 487 windowManager()->push(
IanBenzMaxim 0:33d4e66780c0 488 new DisplayGraphicWindow(
IanBenzMaxim 0:33d4e66780c0 489 new Image(Bitmap(width, height, &imageData[0], Bitmap::ScanLineFormat))
IanBenzMaxim 0:33d4e66780c0 490 )
IanBenzMaxim 0:33d4e66780c0 491 );
IanBenzMaxim 0:33d4e66780c0 492 }
IanBenzMaxim 0:33d4e66780c0 493 }
IanBenzMaxim 0:33d4e66780c0 494
IanBenzMaxim 0:33d4e66780c0 495 NormalOperationWindow::Result NormalOperationWindow::processReceivedData(size_t recvBufSize)
IanBenzMaxim 0:33d4e66780c0 496 {
IanBenzMaxim 0:33d4e66780c0 497 // Separate commands and process each one.
IanBenzMaxim 0:33d4e66780c0 498 std::vector<std::pair<const char *, const char *> > commands = separateCommands(recvBuf, recvBufSize);
IanBenzMaxim 0:33d4e66780c0 499 for (std::vector<std::pair<const char *, const char *> >::const_iterator it = commands.begin(); it != commands.end(); it++)
IanBenzMaxim 0:33d4e66780c0 500 {
IanBenzMaxim 0:33d4e66780c0 501 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 502 rapidjson::Document data(&allocator);
IanBenzMaxim 0:33d4e66780c0 503 // Verify command signature.
IanBenzMaxim 0:33d4e66780c0 504 DS2476::CmdResult verifySignedResult = verifySignedData(std::string(it->first, it->second), data);
IanBenzMaxim 0:33d4e66780c0 505 switch (verifySignedResult)
IanBenzMaxim 0:33d4e66780c0 506 {
IanBenzMaxim 0:33d4e66780c0 507 case DS2476::Success: // Command passed authentication.
IanBenzMaxim 0:33d4e66780c0 508 {
IanBenzMaxim 0:33d4e66780c0 509 // Verify command schema.
IanBenzMaxim 0:33d4e66780c0 510 sendMessage("Received data is authentic");
IanBenzMaxim 0:33d4e66780c0 511 if (data.IsObject() && data.HasMember("command"))
IanBenzMaxim 0:33d4e66780c0 512 {
IanBenzMaxim 0:33d4e66780c0 513 const rapidjson::Value & command = data["command"];
IanBenzMaxim 0:33d4e66780c0 514 if (command.IsString())
IanBenzMaxim 0:33d4e66780c0 515 {
IanBenzMaxim 0:33d4e66780c0 516 // Parse challenge if included.
IanBenzMaxim 0:33d4e66780c0 517 std::vector<uint8_t> challengeData;
IanBenzMaxim 0:33d4e66780c0 518 if (data.HasMember("challenge"))
IanBenzMaxim 0:33d4e66780c0 519 {
IanBenzMaxim 0:33d4e66780c0 520 const rapidjson::Value & challenge = data["challenge"];
IanBenzMaxim 0:33d4e66780c0 521 if (challenge.IsString())
IanBenzMaxim 0:33d4e66780c0 522 {
IanBenzMaxim 0:33d4e66780c0 523 challengeData =
IanBenzMaxim 0:33d4e66780c0 524 hexStringToByteArray(std::string(challenge.GetString(), challenge.GetStringLength()));
IanBenzMaxim 0:33d4e66780c0 525 }
IanBenzMaxim 0:33d4e66780c0 526 }
IanBenzMaxim 0:33d4e66780c0 527
IanBenzMaxim 0:33d4e66780c0 528 // Execute the command.
IanBenzMaxim 0:33d4e66780c0 529 if (command == "getStatus")
IanBenzMaxim 0:33d4e66780c0 530 {
IanBenzMaxim 0:33d4e66780c0 531 Result result = sendStatus(challengeData);
IanBenzMaxim 0:33d4e66780c0 532 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 533 return result;
IanBenzMaxim 0:33d4e66780c0 534 }
IanBenzMaxim 0:33d4e66780c0 535 else if (command == "readObjectTemp")
IanBenzMaxim 0:33d4e66780c0 536 {
IanBenzMaxim 0:33d4e66780c0 537 if ((lastSensorNodeState == ValidLaserDisabled) || (lastSensorNodeState == ValidLaserEnabled))
IanBenzMaxim 0:33d4e66780c0 538 {
IanBenzMaxim 0:33d4e66780c0 539 Result result = sendObjectTemp(challengeData);
IanBenzMaxim 0:33d4e66780c0 540 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 541 return result;
IanBenzMaxim 0:33d4e66780c0 542 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 543 }
IanBenzMaxim 0:33d4e66780c0 544 }
IanBenzMaxim 0:33d4e66780c0 545 else if (command == "readAmbientTemp")
IanBenzMaxim 0:33d4e66780c0 546 {
IanBenzMaxim 0:33d4e66780c0 547 if ((lastSensorNodeState == ValidLaserDisabled) || (lastSensorNodeState == ValidLaserEnabled))
IanBenzMaxim 0:33d4e66780c0 548 {
IanBenzMaxim 0:33d4e66780c0 549 Result result = sendAmbientTemp(challengeData);
IanBenzMaxim 0:33d4e66780c0 550 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 551 return result;
IanBenzMaxim 0:33d4e66780c0 552 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 553 }
IanBenzMaxim 0:33d4e66780c0 554 }
IanBenzMaxim 0:33d4e66780c0 555 else if (command == "enableModule")
IanBenzMaxim 0:33d4e66780c0 556 {
IanBenzMaxim 0:33d4e66780c0 557 if (lastSensorNodeState == ValidLaserDisabled)
IanBenzMaxim 0:33d4e66780c0 558 {
IanBenzMaxim 0:33d4e66780c0 559 if (sensorNode.setLaserEnabled(true,
IanBenzMaxim 0:33d4e66780c0 560 SensorNode::PrintHandler(this, &NormalOperationWindow::sendMessage)))
IanBenzMaxim 0:33d4e66780c0 561 {
IanBenzMaxim 0:33d4e66780c0 562 lastSensorNodeState = ValidLaserEnabled;
IanBenzMaxim 0:33d4e66780c0 563 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 564 }
IanBenzMaxim 0:33d4e66780c0 565 }
IanBenzMaxim 0:33d4e66780c0 566 }
IanBenzMaxim 0:33d4e66780c0 567 else if (command == "disableModule")
IanBenzMaxim 0:33d4e66780c0 568 {
IanBenzMaxim 0:33d4e66780c0 569 if (lastSensorNodeState == ValidLaserEnabled)
IanBenzMaxim 0:33d4e66780c0 570 {
IanBenzMaxim 0:33d4e66780c0 571 if (sensorNode.setLaserEnabled(false,
IanBenzMaxim 0:33d4e66780c0 572 SensorNode::PrintHandler(this, &NormalOperationWindow::sendMessage)))
IanBenzMaxim 0:33d4e66780c0 573 {
IanBenzMaxim 0:33d4e66780c0 574 lastSensorNodeState = ValidLaserDisabled;
IanBenzMaxim 0:33d4e66780c0 575 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 576 }
IanBenzMaxim 0:33d4e66780c0 577 }
IanBenzMaxim 0:33d4e66780c0 578 }
IanBenzMaxim 0:33d4e66780c0 579 else if (command == "displayImage")
IanBenzMaxim 0:33d4e66780c0 580 {
IanBenzMaxim 0:33d4e66780c0 581 if (data.HasMember("image"))
IanBenzMaxim 0:33d4e66780c0 582 {
IanBenzMaxim 0:33d4e66780c0 583 const rapidjson::Value & image = data["image"];
IanBenzMaxim 0:33d4e66780c0 584 if (image.IsString())
IanBenzMaxim 0:33d4e66780c0 585 {
IanBenzMaxim 0:33d4e66780c0 586 displayImage(
IanBenzMaxim 0:33d4e66780c0 587 hexStringToByteArray(
IanBenzMaxim 0:33d4e66780c0 588 std::string(image.GetString(), image.GetStringLength())
IanBenzMaxim 0:33d4e66780c0 589 )
IanBenzMaxim 0:33d4e66780c0 590 );
IanBenzMaxim 0:33d4e66780c0 591 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 592 }
IanBenzMaxim 0:33d4e66780c0 593 }
IanBenzMaxim 0:33d4e66780c0 594 }
IanBenzMaxim 0:33d4e66780c0 595 }
IanBenzMaxim 0:33d4e66780c0 596 }
IanBenzMaxim 0:33d4e66780c0 597 }
IanBenzMaxim 0:33d4e66780c0 598 break;
IanBenzMaxim 0:33d4e66780c0 599
IanBenzMaxim 0:33d4e66780c0 600 case DS2476::AuthenticationError: // Command failed authentication.
IanBenzMaxim 0:33d4e66780c0 601 {
IanBenzMaxim 0:33d4e66780c0 602 const char message[] = "Received data is not authentic";
IanBenzMaxim 0:33d4e66780c0 603 sendMessage(message);
IanBenzMaxim 0:33d4e66780c0 604 Text * messageText = new Text(message);
IanBenzMaxim 0:33d4e66780c0 605 messageText->setWordWrap(true);
IanBenzMaxim 0:33d4e66780c0 606 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 607 {
IanBenzMaxim 0:33d4e66780c0 608 windowManager()->push(new DisplayGraphicWindow(messageText));
IanBenzMaxim 0:33d4e66780c0 609 }
IanBenzMaxim 0:33d4e66780c0 610 }
IanBenzMaxim 0:33d4e66780c0 611 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 612
IanBenzMaxim 0:33d4e66780c0 613 default: // Hardware error occurred.
IanBenzMaxim 0:33d4e66780c0 614 {
IanBenzMaxim 0:33d4e66780c0 615 const char message[] = "Unable to veify received data";
IanBenzMaxim 0:33d4e66780c0 616 sendMessage(message);
IanBenzMaxim 0:33d4e66780c0 617 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 618 {
IanBenzMaxim 0:33d4e66780c0 619 windowManager()->push(new ErrorWindow(message));
IanBenzMaxim 0:33d4e66780c0 620 }
IanBenzMaxim 0:33d4e66780c0 621 }
IanBenzMaxim 0:33d4e66780c0 622 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 623 }
IanBenzMaxim 0:33d4e66780c0 624 }
IanBenzMaxim 0:33d4e66780c0 625 return NoChange;
IanBenzMaxim 0:33d4e66780c0 626 }
IanBenzMaxim 0:33d4e66780c0 627
IanBenzMaxim 0:33d4e66780c0 628 void NormalOperationWindow::doLayout()
IanBenzMaxim 0:33d4e66780c0 629 {
IanBenzMaxim 0:33d4e66780c0 630 showWebIdButton.setWidth(width());
IanBenzMaxim 0:33d4e66780c0 631 showWebIdButton.setHeight(showWebIdButton.preferredHeight());
IanBenzMaxim 0:33d4e66780c0 632 showWebIdButton.setX(0);
IanBenzMaxim 0:33d4e66780c0 633 showWebIdButton.setY(height() - showWebIdButton.height());
IanBenzMaxim 0:33d4e66780c0 634 validSignatureButton.setWidth(width());
IanBenzMaxim 0:33d4e66780c0 635 validSignatureButton.setHeight(validSignatureButton.preferredHeight());
IanBenzMaxim 0:33d4e66780c0 636 validSignatureButton.setX(0);
IanBenzMaxim 0:33d4e66780c0 637 validSignatureButton.setY(showWebIdButton.y() - validSignatureButton.height() - 1);
IanBenzMaxim 0:33d4e66780c0 638 }
IanBenzMaxim 0:33d4e66780c0 639
IanBenzMaxim 0:33d4e66780c0 640 Bitmap NormalOperationWindow::render() const
IanBenzMaxim 0:33d4e66780c0 641 {
IanBenzMaxim 0:33d4e66780c0 642 // Format current status text.
IanBenzMaxim 0:33d4e66780c0 643 std::string sensorNodeStateText;
IanBenzMaxim 0:33d4e66780c0 644 switch (lastSensorNodeState)
IanBenzMaxim 0:33d4e66780c0 645 {
IanBenzMaxim 0:33d4e66780c0 646 case Disconnected:
IanBenzMaxim 0:33d4e66780c0 647 sensorNodeStateText = "Disconnected";
IanBenzMaxim 0:33d4e66780c0 648 break;
IanBenzMaxim 0:33d4e66780c0 649
IanBenzMaxim 0:33d4e66780c0 650 case Invalid:
IanBenzMaxim 0:33d4e66780c0 651 sensorNodeStateText = "Invalid";
IanBenzMaxim 0:33d4e66780c0 652 break;
IanBenzMaxim 0:33d4e66780c0 653
IanBenzMaxim 0:33d4e66780c0 654 case ValidLaserDisabled:
IanBenzMaxim 0:33d4e66780c0 655 case ValidLaserEnabled:
IanBenzMaxim 0:33d4e66780c0 656 sensorNodeStateText = "Valid";
IanBenzMaxim 0:33d4e66780c0 657 break;
IanBenzMaxim 0:33d4e66780c0 658 }
IanBenzMaxim 0:33d4e66780c0 659
IanBenzMaxim 0:33d4e66780c0 660 char displayString[100];
IanBenzMaxim 0:33d4e66780c0 661 std::snprintf(displayString, sizeof(displayString) / sizeof(displayString[0]),
IanBenzMaxim 0:33d4e66780c0 662 "Object temp: %.2f\nAmbient temp: %.2f\nSensor node: %s",
IanBenzMaxim 0:33d4e66780c0 663 lastObjectTemp, lastAmbientTemp, sensorNodeStateText.c_str());
IanBenzMaxim 0:33d4e66780c0 664
IanBenzMaxim 0:33d4e66780c0 665 Bitmap bitmap(width(), height());
IanBenzMaxim 0:33d4e66780c0 666 Text description((std::string(displayString)));
IanBenzMaxim 0:33d4e66780c0 667 description.update();
IanBenzMaxim 0:33d4e66780c0 668 bitmap.overlay(description.render(), description.x(), description.y());
IanBenzMaxim 0:33d4e66780c0 669 bitmap.overlay(validSignatureButton.render(), validSignatureButton.x(), validSignatureButton.y());
IanBenzMaxim 0:33d4e66780c0 670 bitmap.overlay(showWebIdButton.render(), showWebIdButton.x(), showWebIdButton.y());
IanBenzMaxim 0:33d4e66780c0 671 return bitmap;
IanBenzMaxim 0:33d4e66780c0 672 }
IanBenzMaxim 0:33d4e66780c0 673
IanBenzMaxim 0:33d4e66780c0 674 void NormalOperationWindow::doPostLayout()
IanBenzMaxim 0:33d4e66780c0 675 {
IanBenzMaxim 0:33d4e66780c0 676 // Detect sensor node.
IanBenzMaxim 0:33d4e66780c0 677 SensorNodeState sensorNodeState = detectSensorNode();
IanBenzMaxim 0:33d4e66780c0 678 if (sensorNodeState == FailedProvision)
IanBenzMaxim 0:33d4e66780c0 679 {
IanBenzMaxim 0:33d4e66780c0 680 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 681 {
IanBenzMaxim 0:33d4e66780c0 682 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 683 windowManager()->push(new ErrorWindow("Sensor node provision failed"));
IanBenzMaxim 0:33d4e66780c0 684 }
IanBenzMaxim 0:33d4e66780c0 685 return;
IanBenzMaxim 0:33d4e66780c0 686 }
IanBenzMaxim 0:33d4e66780c0 687 if (sensorNodeState != lastSensorNodeState)
IanBenzMaxim 0:33d4e66780c0 688 {
IanBenzMaxim 0:33d4e66780c0 689 lastSensorNodeState = sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 690 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 691 }
IanBenzMaxim 0:33d4e66780c0 692
IanBenzMaxim 0:33d4e66780c0 693 // Process socket data.
IanBenzMaxim 0:33d4e66780c0 694 int recvResult = socket->recv(recvBuf, sizeof(recvBuf) / sizeof(recvBuf[0]));
IanBenzMaxim 0:33d4e66780c0 695 if (recvResult > 0)
IanBenzMaxim 0:33d4e66780c0 696 {
IanBenzMaxim 0:33d4e66780c0 697 std::cout.write(recvBuf, recvResult) << std::endl;
IanBenzMaxim 0:33d4e66780c0 698 Result result = processReceivedData(recvResult);
IanBenzMaxim 0:33d4e66780c0 699 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 700 return;
IanBenzMaxim 0:33d4e66780c0 701 }
IanBenzMaxim 0:33d4e66780c0 702 else if (recvResult != NSAPI_ERROR_WOULD_BLOCK)
IanBenzMaxim 0:33d4e66780c0 703 {
IanBenzMaxim 0:33d4e66780c0 704 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 705 {
IanBenzMaxim 0:33d4e66780c0 706 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 707 windowManager()->push(new ErrorWindow("Socket recieve failed"));
IanBenzMaxim 0:33d4e66780c0 708 }
IanBenzMaxim 0:33d4e66780c0 709 return;
IanBenzMaxim 0:33d4e66780c0 710 }
IanBenzMaxim 0:33d4e66780c0 711 }
IanBenzMaxim 0:33d4e66780c0 712
IanBenzMaxim 0:33d4e66780c0 713 bool NormalOperationWindow::doProcessKey(Key key)
IanBenzMaxim 0:33d4e66780c0 714 {
IanBenzMaxim 0:33d4e66780c0 715 bool handled;
IanBenzMaxim 0:33d4e66780c0 716 switch (key)
IanBenzMaxim 0:33d4e66780c0 717 {
IanBenzMaxim 0:33d4e66780c0 718 case UpKey:
IanBenzMaxim 0:33d4e66780c0 719 validSignatureButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 720 handled = true;
IanBenzMaxim 0:33d4e66780c0 721 break;
IanBenzMaxim 0:33d4e66780c0 722
IanBenzMaxim 0:33d4e66780c0 723 case DownKey:
IanBenzMaxim 0:33d4e66780c0 724 showWebIdButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 725 handled = true;
IanBenzMaxim 0:33d4e66780c0 726 break;
IanBenzMaxim 0:33d4e66780c0 727
IanBenzMaxim 0:33d4e66780c0 728 default:
IanBenzMaxim 0:33d4e66780c0 729 handled = false;
IanBenzMaxim 0:33d4e66780c0 730 break;
IanBenzMaxim 0:33d4e66780c0 731 }
IanBenzMaxim 0:33d4e66780c0 732 return handled;
IanBenzMaxim 0:33d4e66780c0 733 }
IanBenzMaxim 0:33d4e66780c0 734