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:
Thu Apr 06 15:16:30 2017 -0500
Revision:
8:a0d75dff3c9b
Parent:
7:66c5dedc750b
Child:
10:71359af61af8
Simplified graphics system for better clarity and expandability.

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