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:
Mon Mar 06 18:02:09 2017 -0600
Revision:
6:0c9050b02876
Parent:
4:cd2dc3e7433f
Child:
7:66c5dedc750b
Laser state now displayed during normal operation.

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 0:33d4e66780c0 72 unsigned 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 0:33d4e66780c0 254 windowManager()->push(new DisplayIdWindow(DisplayIdWindow::PopupMode));
IanBenzMaxim 0:33d4e66780c0 255 }
IanBenzMaxim 0:33d4e66780c0 256 }
IanBenzMaxim 0:33d4e66780c0 257
IanBenzMaxim 0:33d4e66780c0 258 void NormalOperationWindow::toggleValidSignature()
IanBenzMaxim 0:33d4e66780c0 259 {
IanBenzMaxim 0:33d4e66780c0 260 validSignature = !validSignature;
IanBenzMaxim 0:33d4e66780c0 261 validSignatureButton.setText(getValidSignatureButtonText(validSignature));
IanBenzMaxim 0:33d4e66780c0 262 }
IanBenzMaxim 0:33d4e66780c0 263
IanBenzMaxim 0:33d4e66780c0 264 NormalOperationWindow::NormalOperationWindow(TCPSocket * socket, Graphic * parent) : Window(parent),
IanBenzMaxim 0:33d4e66780c0 265 socket(socket), validSignature(true), lastSensorNodeState(Disconnected),
IanBenzMaxim 0:33d4e66780c0 266 lastObjectTemp(0), lastAmbientTemp(0),
IanBenzMaxim 0:33d4e66780c0 267 validSignatureButton(getValidSignatureButtonText(validSignature), this),
IanBenzMaxim 0:33d4e66780c0 268 showWebIdButton("Show web ID", this)
IanBenzMaxim 0:33d4e66780c0 269 {
IanBenzMaxim 0:33d4e66780c0 270 assert(socket != NULL);
IanBenzMaxim 0:33d4e66780c0 271
IanBenzMaxim 0:33d4e66780c0 272 validSignatureButton.setClickedHandler(Button::EventHandler(this, &NormalOperationWindow::toggleValidSignature));
IanBenzMaxim 0:33d4e66780c0 273 showWebIdButton.setClickedHandler(Button::EventHandler(this, &NormalOperationWindow::showWebId));
IanBenzMaxim 0:33d4e66780c0 274 validSignatureButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 275 }
IanBenzMaxim 0:33d4e66780c0 276
IanBenzMaxim 0:33d4e66780c0 277 NormalOperationWindow::SensorNodeState NormalOperationWindow::detectSensorNode()
IanBenzMaxim 0:33d4e66780c0 278 {
IanBenzMaxim 0:33d4e66780c0 279 SensorNodeState sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 280 if (sensorNode.detect())
IanBenzMaxim 0:33d4e66780c0 281 {
IanBenzMaxim 0:33d4e66780c0 282 bool provisioned;
IanBenzMaxim 0:33d4e66780c0 283 if (sensorNode.getProvisioned(provisioned))
IanBenzMaxim 0:33d4e66780c0 284 {
IanBenzMaxim 0:33d4e66780c0 285 if (provisioned)
IanBenzMaxim 0:33d4e66780c0 286 {
IanBenzMaxim 0:33d4e66780c0 287 if (sensorNode.authenticate())
IanBenzMaxim 0:33d4e66780c0 288 {
IanBenzMaxim 0:33d4e66780c0 289 bool laserEnabled;
IanBenzMaxim 0:33d4e66780c0 290 if (sensorNode.getLaserEnabled(laserEnabled))
IanBenzMaxim 0:33d4e66780c0 291 {
IanBenzMaxim 0:33d4e66780c0 292 sensorNodeState = (laserEnabled ? ValidLaserEnabled : ValidLaserDisabled);
IanBenzMaxim 0:33d4e66780c0 293 }
IanBenzMaxim 0:33d4e66780c0 294 else
IanBenzMaxim 0:33d4e66780c0 295 {
IanBenzMaxim 0:33d4e66780c0 296 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 297 }
IanBenzMaxim 0:33d4e66780c0 298 }
IanBenzMaxim 0:33d4e66780c0 299 else
IanBenzMaxim 0:33d4e66780c0 300 {
IanBenzMaxim 0:33d4e66780c0 301 sensorNodeState = Invalid;
IanBenzMaxim 0:33d4e66780c0 302 }
IanBenzMaxim 0:33d4e66780c0 303 }
IanBenzMaxim 0:33d4e66780c0 304 else
IanBenzMaxim 0:33d4e66780c0 305 {
IanBenzMaxim 0:33d4e66780c0 306 bool provisionResult = sensorNode.provision();
IanBenzMaxim 0:33d4e66780c0 307 if (provisionResult)
IanBenzMaxim 0:33d4e66780c0 308 {
IanBenzMaxim 0:33d4e66780c0 309 // Detect the new state after provisioning.
IanBenzMaxim 0:33d4e66780c0 310 sensorNodeState = detectSensorNode();
IanBenzMaxim 0:33d4e66780c0 311 }
IanBenzMaxim 0:33d4e66780c0 312 else
IanBenzMaxim 0:33d4e66780c0 313 {
IanBenzMaxim 0:33d4e66780c0 314 sensorNodeState = FailedProvision;
IanBenzMaxim 0:33d4e66780c0 315 }
IanBenzMaxim 0:33d4e66780c0 316 }
IanBenzMaxim 0:33d4e66780c0 317 }
IanBenzMaxim 0:33d4e66780c0 318 else
IanBenzMaxim 0:33d4e66780c0 319 {
IanBenzMaxim 0:33d4e66780c0 320 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 321 }
IanBenzMaxim 0:33d4e66780c0 322 }
IanBenzMaxim 0:33d4e66780c0 323 else
IanBenzMaxim 0:33d4e66780c0 324 {
IanBenzMaxim 0:33d4e66780c0 325 sensorNodeState = Disconnected;
IanBenzMaxim 0:33d4e66780c0 326 }
IanBenzMaxim 0:33d4e66780c0 327 return sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 328 }
IanBenzMaxim 0:33d4e66780c0 329
IanBenzMaxim 0:33d4e66780c0 330 NormalOperationWindow::Result NormalOperationWindow::sendStatus(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 331 {
IanBenzMaxim 0:33d4e66780c0 332 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 333 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 334
IanBenzMaxim 0:33d4e66780c0 335 // Insert Web ID.
IanBenzMaxim 0:33d4e66780c0 336 document.AddMember("id", rapidjson::StringRef(webId.c_str()), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 337
IanBenzMaxim 0:33d4e66780c0 338 // Insert device public key.
IanBenzMaxim 0:33d4e66780c0 339 rapidjson::Value publicKey(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 340 DS2476::Page page;
IanBenzMaxim 0:33d4e66780c0 341 DS2476::CmdResult result = coproc.readMemory(DS2476::PublicKeyAX, page);
IanBenzMaxim 0:33d4e66780c0 342 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 343 {
IanBenzMaxim 0:33d4e66780c0 344 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 345 {
IanBenzMaxim 0:33d4e66780c0 346 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 347 windowManager()->push(new ErrorWindow("Failed to read PublicKeyAX"));
IanBenzMaxim 0:33d4e66780c0 348 }
IanBenzMaxim 0:33d4e66780c0 349 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 350 }
IanBenzMaxim 0:33d4e66780c0 351 publicKey.AddMember("x", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 352 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 353 result = coproc.readMemory(DS2476::PublicKeyAY, page);
IanBenzMaxim 0:33d4e66780c0 354 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 355 {
IanBenzMaxim 0:33d4e66780c0 356 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 357 {
IanBenzMaxim 0:33d4e66780c0 358 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 359 windowManager()->push(new ErrorWindow("Failed to read PublicKeyAY"));
IanBenzMaxim 0:33d4e66780c0 360 }
IanBenzMaxim 0:33d4e66780c0 361 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 362 }
IanBenzMaxim 0:33d4e66780c0 363 publicKey.AddMember("y", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 364 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 365 document.AddMember("publicKey", publicKey, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 366
IanBenzMaxim 0:33d4e66780c0 367 // Insert device certificate.
IanBenzMaxim 0:33d4e66780c0 368 rapidjson::Value certificate(rapidjson::kObjectType);
IanBenzMaxim 0:33d4e66780c0 369 result = coproc.readMemory(DS2476::UserData14, page);
IanBenzMaxim 0:33d4e66780c0 370 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 371 {
IanBenzMaxim 0:33d4e66780c0 372 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 373 {
IanBenzMaxim 0:33d4e66780c0 374 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 375 windowManager()->push(new ErrorWindow("Failed to read UserData14"));
IanBenzMaxim 0:33d4e66780c0 376 }
IanBenzMaxim 0:33d4e66780c0 377 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 378 }
IanBenzMaxim 0:33d4e66780c0 379 certificate.AddMember("r", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 380 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 381 result = coproc.readMemory(DS2476::UserData15, page);
IanBenzMaxim 0:33d4e66780c0 382 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 383 {
IanBenzMaxim 0:33d4e66780c0 384 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 385 {
IanBenzMaxim 0:33d4e66780c0 386 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 387 windowManager()->push(new ErrorWindow("Failed to read UserData15"));
IanBenzMaxim 0:33d4e66780c0 388 }
IanBenzMaxim 0:33d4e66780c0 389 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 390 }
IanBenzMaxim 0:33d4e66780c0 391 certificate.AddMember("s", rapidjson::Value(byteArrayToHexString(page.data(), page.size()).c_str(),
IanBenzMaxim 0:33d4e66780c0 392 document.GetAllocator()).Move(), document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 393 document.AddMember("certificate", certificate, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 394
IanBenzMaxim 0:33d4e66780c0 395 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 396 result = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 397 if (result != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 398 {
IanBenzMaxim 0:33d4e66780c0 399 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 400 {
IanBenzMaxim 0:33d4e66780c0 401 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 402 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 403 }
IanBenzMaxim 0:33d4e66780c0 404 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 405 }
IanBenzMaxim 0:33d4e66780c0 406 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 407 return NoChange;
IanBenzMaxim 0:33d4e66780c0 408 }
IanBenzMaxim 0:33d4e66780c0 409
IanBenzMaxim 0:33d4e66780c0 410 NormalOperationWindow::Result NormalOperationWindow::sendObjectTemp(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 411 {
IanBenzMaxim 0:33d4e66780c0 412 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 413 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 414
IanBenzMaxim 0:33d4e66780c0 415 // Read object temperatue and add to document.
IanBenzMaxim 0:33d4e66780c0 416 double objectTemp;
IanBenzMaxim 0:33d4e66780c0 417 bool sensorResult = sensorNode.readTemp(SensorNode::ObjectTemp, objectTemp);
IanBenzMaxim 0:33d4e66780c0 418 if (!sensorResult)
IanBenzMaxim 0:33d4e66780c0 419 {
IanBenzMaxim 0:33d4e66780c0 420 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 421 {
IanBenzMaxim 0:33d4e66780c0 422 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 423 windowManager()->push(new ErrorWindow("Failed to read object temperature"));
IanBenzMaxim 0:33d4e66780c0 424 }
IanBenzMaxim 0:33d4e66780c0 425 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 426 }
IanBenzMaxim 0:33d4e66780c0 427 document.AddMember("objectTemp", objectTemp, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 428
IanBenzMaxim 0:33d4e66780c0 429 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 430 DS2476::CmdResult coprocResult = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 431 if (coprocResult != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 432 {
IanBenzMaxim 0:33d4e66780c0 433 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 434 {
IanBenzMaxim 0:33d4e66780c0 435 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 436 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 437 }
IanBenzMaxim 0:33d4e66780c0 438 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 439 }
IanBenzMaxim 0:33d4e66780c0 440 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 441
IanBenzMaxim 0:33d4e66780c0 442 lastObjectTemp = objectTemp;
IanBenzMaxim 0:33d4e66780c0 443 return NoChange;
IanBenzMaxim 0:33d4e66780c0 444 }
IanBenzMaxim 0:33d4e66780c0 445
IanBenzMaxim 0:33d4e66780c0 446 NormalOperationWindow::Result NormalOperationWindow::sendAmbientTemp(const std::vector<uint8_t> & challenge)
IanBenzMaxim 0:33d4e66780c0 447 {
IanBenzMaxim 0:33d4e66780c0 448 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 449 rapidjson::Document document(rapidjson::kObjectType, &allocator);
IanBenzMaxim 0:33d4e66780c0 450
IanBenzMaxim 0:33d4e66780c0 451 // Read ambient temperatue and add to document.
IanBenzMaxim 0:33d4e66780c0 452 double ambientTemp;
IanBenzMaxim 0:33d4e66780c0 453 bool sensorResult = sensorNode.readTemp(SensorNode::AmbientTemp, ambientTemp);
IanBenzMaxim 0:33d4e66780c0 454 if (!sensorResult)
IanBenzMaxim 0:33d4e66780c0 455 {
IanBenzMaxim 0:33d4e66780c0 456 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 457 {
IanBenzMaxim 0:33d4e66780c0 458 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 459 windowManager()->push(new ErrorWindow("Failed to read ambient temperature"));
IanBenzMaxim 0:33d4e66780c0 460 }
IanBenzMaxim 0:33d4e66780c0 461 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 462 }
IanBenzMaxim 0:33d4e66780c0 463 document.AddMember("ambientTemp", ambientTemp, document.GetAllocator());
IanBenzMaxim 0:33d4e66780c0 464
IanBenzMaxim 0:33d4e66780c0 465 // Sign data and transmit to server.
IanBenzMaxim 0:33d4e66780c0 466 DS2476::CmdResult coprocResult = signData(validSignature, challenge, document);
IanBenzMaxim 0:33d4e66780c0 467 if (coprocResult != DS2476::Success)
IanBenzMaxim 0:33d4e66780c0 468 {
IanBenzMaxim 0:33d4e66780c0 469 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 470 {
IanBenzMaxim 0:33d4e66780c0 471 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 472 windowManager()->push(new ErrorWindow("Failed to sign data"));
IanBenzMaxim 0:33d4e66780c0 473 }
IanBenzMaxim 0:33d4e66780c0 474 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 475 }
IanBenzMaxim 0:33d4e66780c0 476 sendJson(document, *socket);
IanBenzMaxim 0:33d4e66780c0 477
IanBenzMaxim 0:33d4e66780c0 478 lastAmbientTemp = ambientTemp;
IanBenzMaxim 0:33d4e66780c0 479 return NoChange;
IanBenzMaxim 0:33d4e66780c0 480 }
IanBenzMaxim 0:33d4e66780c0 481
IanBenzMaxim 0:33d4e66780c0 482 void NormalOperationWindow::displayImage(const std::vector<uint8_t> & imageData)
IanBenzMaxim 0:33d4e66780c0 483 {
IanBenzMaxim 0:33d4e66780c0 484 const unsigned int width = 64;
IanBenzMaxim 0:33d4e66780c0 485 const unsigned int height = imageData.size() / (width / Bitmap::pixelsPerSegment);
IanBenzMaxim 0:33d4e66780c0 486 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 487 {
IanBenzMaxim 0:33d4e66780c0 488 windowManager()->push(
IanBenzMaxim 0:33d4e66780c0 489 new DisplayGraphicWindow(
IanBenzMaxim 0:33d4e66780c0 490 new Image(Bitmap(width, height, &imageData[0], Bitmap::ScanLineFormat))
IanBenzMaxim 0:33d4e66780c0 491 )
IanBenzMaxim 0:33d4e66780c0 492 );
IanBenzMaxim 0:33d4e66780c0 493 }
IanBenzMaxim 0:33d4e66780c0 494 }
IanBenzMaxim 0:33d4e66780c0 495
IanBenzMaxim 0:33d4e66780c0 496 NormalOperationWindow::Result NormalOperationWindow::processReceivedData(size_t recvBufSize)
IanBenzMaxim 0:33d4e66780c0 497 {
IanBenzMaxim 0:33d4e66780c0 498 // Separate commands and process each one.
IanBenzMaxim 0:33d4e66780c0 499 std::vector<std::pair<const char *, const char *> > commands = separateCommands(recvBuf, recvBufSize);
IanBenzMaxim 0:33d4e66780c0 500 for (std::vector<std::pair<const char *, const char *> >::const_iterator it = commands.begin(); it != commands.end(); it++)
IanBenzMaxim 0:33d4e66780c0 501 {
IanBenzMaxim 0:33d4e66780c0 502 rapidjson::MemoryPoolAllocator<> allocator(defaultChunkSize);
IanBenzMaxim 0:33d4e66780c0 503 rapidjson::Document data(&allocator);
IanBenzMaxim 0:33d4e66780c0 504 // Verify command signature.
IanBenzMaxim 0:33d4e66780c0 505 DS2476::CmdResult verifySignedResult = verifySignedData(std::string(it->first, it->second), data);
IanBenzMaxim 0:33d4e66780c0 506 switch (verifySignedResult)
IanBenzMaxim 0:33d4e66780c0 507 {
IanBenzMaxim 0:33d4e66780c0 508 case DS2476::Success: // Command passed authentication.
IanBenzMaxim 0:33d4e66780c0 509 {
IanBenzMaxim 0:33d4e66780c0 510 // Verify command schema.
IanBenzMaxim 0:33d4e66780c0 511 sendMessage("Received data is authentic");
IanBenzMaxim 0:33d4e66780c0 512 if (data.IsObject() && data.HasMember("command"))
IanBenzMaxim 0:33d4e66780c0 513 {
IanBenzMaxim 0:33d4e66780c0 514 const rapidjson::Value & command = data["command"];
IanBenzMaxim 0:33d4e66780c0 515 if (command.IsString())
IanBenzMaxim 0:33d4e66780c0 516 {
IanBenzMaxim 0:33d4e66780c0 517 // Parse challenge if included.
IanBenzMaxim 0:33d4e66780c0 518 std::vector<uint8_t> challengeData;
IanBenzMaxim 0:33d4e66780c0 519 if (data.HasMember("challenge"))
IanBenzMaxim 0:33d4e66780c0 520 {
IanBenzMaxim 0:33d4e66780c0 521 const rapidjson::Value & challenge = data["challenge"];
IanBenzMaxim 0:33d4e66780c0 522 if (challenge.IsString())
IanBenzMaxim 0:33d4e66780c0 523 {
IanBenzMaxim 0:33d4e66780c0 524 challengeData =
IanBenzMaxim 0:33d4e66780c0 525 hexStringToByteArray(std::string(challenge.GetString(), challenge.GetStringLength()));
IanBenzMaxim 0:33d4e66780c0 526 }
IanBenzMaxim 0:33d4e66780c0 527 }
IanBenzMaxim 0:33d4e66780c0 528
IanBenzMaxim 0:33d4e66780c0 529 // Execute the command.
IanBenzMaxim 0:33d4e66780c0 530 if (command == "getStatus")
IanBenzMaxim 0:33d4e66780c0 531 {
IanBenzMaxim 0:33d4e66780c0 532 Result result = sendStatus(challengeData);
IanBenzMaxim 0:33d4e66780c0 533 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 534 return result;
IanBenzMaxim 0:33d4e66780c0 535 }
IanBenzMaxim 0:33d4e66780c0 536 else if (command == "readObjectTemp")
IanBenzMaxim 0:33d4e66780c0 537 {
IanBenzMaxim 0:33d4e66780c0 538 if ((lastSensorNodeState == ValidLaserDisabled) || (lastSensorNodeState == ValidLaserEnabled))
IanBenzMaxim 0:33d4e66780c0 539 {
IanBenzMaxim 0:33d4e66780c0 540 Result result = sendObjectTemp(challengeData);
IanBenzMaxim 0:33d4e66780c0 541 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 542 return result;
IanBenzMaxim 0:33d4e66780c0 543 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 544 }
IanBenzMaxim 0:33d4e66780c0 545 }
IanBenzMaxim 0:33d4e66780c0 546 else if (command == "readAmbientTemp")
IanBenzMaxim 0:33d4e66780c0 547 {
IanBenzMaxim 0:33d4e66780c0 548 if ((lastSensorNodeState == ValidLaserDisabled) || (lastSensorNodeState == ValidLaserEnabled))
IanBenzMaxim 0:33d4e66780c0 549 {
IanBenzMaxim 0:33d4e66780c0 550 Result result = sendAmbientTemp(challengeData);
IanBenzMaxim 0:33d4e66780c0 551 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 552 return result;
IanBenzMaxim 0:33d4e66780c0 553 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 554 }
IanBenzMaxim 0:33d4e66780c0 555 }
IanBenzMaxim 0:33d4e66780c0 556 else if (command == "enableModule")
IanBenzMaxim 0:33d4e66780c0 557 {
IanBenzMaxim 0:33d4e66780c0 558 if (lastSensorNodeState == ValidLaserDisabled)
IanBenzMaxim 0:33d4e66780c0 559 {
IanBenzMaxim 0:33d4e66780c0 560 if (sensorNode.setLaserEnabled(true,
IanBenzMaxim 0:33d4e66780c0 561 SensorNode::PrintHandler(this, &NormalOperationWindow::sendMessage)))
IanBenzMaxim 0:33d4e66780c0 562 {
IanBenzMaxim 0:33d4e66780c0 563 lastSensorNodeState = ValidLaserEnabled;
IanBenzMaxim 0:33d4e66780c0 564 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 565 }
IanBenzMaxim 0:33d4e66780c0 566 }
IanBenzMaxim 0:33d4e66780c0 567 }
IanBenzMaxim 0:33d4e66780c0 568 else if (command == "disableModule")
IanBenzMaxim 0:33d4e66780c0 569 {
IanBenzMaxim 0:33d4e66780c0 570 if (lastSensorNodeState == ValidLaserEnabled)
IanBenzMaxim 0:33d4e66780c0 571 {
IanBenzMaxim 0:33d4e66780c0 572 if (sensorNode.setLaserEnabled(false,
IanBenzMaxim 0:33d4e66780c0 573 SensorNode::PrintHandler(this, &NormalOperationWindow::sendMessage)))
IanBenzMaxim 0:33d4e66780c0 574 {
IanBenzMaxim 0:33d4e66780c0 575 lastSensorNodeState = ValidLaserDisabled;
IanBenzMaxim 0:33d4e66780c0 576 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 577 }
IanBenzMaxim 0:33d4e66780c0 578 }
IanBenzMaxim 0:33d4e66780c0 579 }
IanBenzMaxim 0:33d4e66780c0 580 else if (command == "displayImage")
IanBenzMaxim 0:33d4e66780c0 581 {
IanBenzMaxim 0:33d4e66780c0 582 if (data.HasMember("image"))
IanBenzMaxim 0:33d4e66780c0 583 {
IanBenzMaxim 0:33d4e66780c0 584 const rapidjson::Value & image = data["image"];
IanBenzMaxim 0:33d4e66780c0 585 if (image.IsString())
IanBenzMaxim 0:33d4e66780c0 586 {
IanBenzMaxim 0:33d4e66780c0 587 displayImage(
IanBenzMaxim 0:33d4e66780c0 588 hexStringToByteArray(
IanBenzMaxim 0:33d4e66780c0 589 std::string(image.GetString(), image.GetStringLength())
IanBenzMaxim 0:33d4e66780c0 590 )
IanBenzMaxim 0:33d4e66780c0 591 );
IanBenzMaxim 0:33d4e66780c0 592 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 593 }
IanBenzMaxim 0:33d4e66780c0 594 }
IanBenzMaxim 0:33d4e66780c0 595 }
IanBenzMaxim 0:33d4e66780c0 596 }
IanBenzMaxim 0:33d4e66780c0 597 }
IanBenzMaxim 0:33d4e66780c0 598 }
IanBenzMaxim 0:33d4e66780c0 599 break;
IanBenzMaxim 0:33d4e66780c0 600
IanBenzMaxim 0:33d4e66780c0 601 case DS2476::AuthenticationError: // Command failed authentication.
IanBenzMaxim 0:33d4e66780c0 602 {
IanBenzMaxim 0:33d4e66780c0 603 const char message[] = "Received data is not authentic";
IanBenzMaxim 0:33d4e66780c0 604 sendMessage(message);
IanBenzMaxim 0:33d4e66780c0 605 Text * messageText = new Text(message);
IanBenzMaxim 0:33d4e66780c0 606 messageText->setWordWrap(true);
IanBenzMaxim 0:33d4e66780c0 607 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 608 {
IanBenzMaxim 0:33d4e66780c0 609 windowManager()->push(new DisplayGraphicWindow(messageText));
IanBenzMaxim 0:33d4e66780c0 610 }
IanBenzMaxim 0:33d4e66780c0 611 }
IanBenzMaxim 0:33d4e66780c0 612 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 613
IanBenzMaxim 0:33d4e66780c0 614 default: // Hardware error occurred.
IanBenzMaxim 0:33d4e66780c0 615 {
IanBenzMaxim 0:33d4e66780c0 616 const char message[] = "Unable to veify received data";
IanBenzMaxim 0:33d4e66780c0 617 sendMessage(message);
IanBenzMaxim 0:33d4e66780c0 618 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 619 {
IanBenzMaxim 0:33d4e66780c0 620 windowManager()->push(new ErrorWindow(message));
IanBenzMaxim 0:33d4e66780c0 621 }
IanBenzMaxim 0:33d4e66780c0 622 }
IanBenzMaxim 0:33d4e66780c0 623 return WindowsChanged;
IanBenzMaxim 0:33d4e66780c0 624 }
IanBenzMaxim 0:33d4e66780c0 625 }
IanBenzMaxim 0:33d4e66780c0 626 return NoChange;
IanBenzMaxim 0:33d4e66780c0 627 }
IanBenzMaxim 0:33d4e66780c0 628
IanBenzMaxim 0:33d4e66780c0 629 void NormalOperationWindow::doLayout()
IanBenzMaxim 0:33d4e66780c0 630 {
IanBenzMaxim 0:33d4e66780c0 631 showWebIdButton.setWidth(width());
IanBenzMaxim 0:33d4e66780c0 632 showWebIdButton.setHeight(showWebIdButton.preferredHeight());
IanBenzMaxim 0:33d4e66780c0 633 showWebIdButton.setX(0);
IanBenzMaxim 0:33d4e66780c0 634 showWebIdButton.setY(height() - showWebIdButton.height());
IanBenzMaxim 0:33d4e66780c0 635 validSignatureButton.setWidth(width());
IanBenzMaxim 0:33d4e66780c0 636 validSignatureButton.setHeight(validSignatureButton.preferredHeight());
IanBenzMaxim 0:33d4e66780c0 637 validSignatureButton.setX(0);
IanBenzMaxim 0:33d4e66780c0 638 validSignatureButton.setY(showWebIdButton.y() - validSignatureButton.height() - 1);
IanBenzMaxim 0:33d4e66780c0 639 }
IanBenzMaxim 0:33d4e66780c0 640
IanBenzMaxim 6:0c9050b02876 641 static std::string doubleToString(double input)
IanBenzMaxim 6:0c9050b02876 642 {
IanBenzMaxim 6:0c9050b02876 643 char inputString[8];
IanBenzMaxim 6:0c9050b02876 644 snprintf(inputString, sizeof(inputString) / sizeof(inputString[0]), "%.2f", input);
IanBenzMaxim 6:0c9050b02876 645 return std::string(inputString);
IanBenzMaxim 6:0c9050b02876 646 }
IanBenzMaxim 6:0c9050b02876 647
IanBenzMaxim 0:33d4e66780c0 648 Bitmap NormalOperationWindow::render() const
IanBenzMaxim 0:33d4e66780c0 649 {
IanBenzMaxim 0:33d4e66780c0 650 // Format current status text.
IanBenzMaxim 0:33d4e66780c0 651 std::string sensorNodeStateText;
IanBenzMaxim 0:33d4e66780c0 652 switch (lastSensorNodeState)
IanBenzMaxim 0:33d4e66780c0 653 {
IanBenzMaxim 0:33d4e66780c0 654 case Disconnected:
IanBenzMaxim 0:33d4e66780c0 655 sensorNodeStateText = "Disconnected";
IanBenzMaxim 0:33d4e66780c0 656 break;
IanBenzMaxim 0:33d4e66780c0 657
IanBenzMaxim 0:33d4e66780c0 658 case Invalid:
IanBenzMaxim 0:33d4e66780c0 659 sensorNodeStateText = "Invalid";
IanBenzMaxim 0:33d4e66780c0 660 break;
IanBenzMaxim 0:33d4e66780c0 661
IanBenzMaxim 0:33d4e66780c0 662 case ValidLaserDisabled:
IanBenzMaxim 6:0c9050b02876 663 sensorNodeStateText = "Valid, laser disabled";
IanBenzMaxim 6:0c9050b02876 664 break;
IanBenzMaxim 6:0c9050b02876 665
IanBenzMaxim 0:33d4e66780c0 666 case ValidLaserEnabled:
IanBenzMaxim 6:0c9050b02876 667 sensorNodeStateText = "Valid, laser enabled";
IanBenzMaxim 0:33d4e66780c0 668 break;
IanBenzMaxim 3:d2799d8497c0 669
IanBenzMaxim 3:d2799d8497c0 670 case FailedProvision:
IanBenzMaxim 3:d2799d8497c0 671 break;
IanBenzMaxim 0:33d4e66780c0 672 }
IanBenzMaxim 6:0c9050b02876 673
IanBenzMaxim 0:33d4e66780c0 674 Bitmap bitmap(width(), height());
IanBenzMaxim 6:0c9050b02876 675 Text description("Object temp: " + doubleToString(lastObjectTemp) +
IanBenzMaxim 6:0c9050b02876 676 "\nAmbient temp: " + doubleToString(lastAmbientTemp) +
IanBenzMaxim 6:0c9050b02876 677 "\nSensor node: " + sensorNodeStateText);
IanBenzMaxim 6:0c9050b02876 678 description.setWidth(width());
IanBenzMaxim 6:0c9050b02876 679 description.setHeight(validSignatureButton.y());
IanBenzMaxim 6:0c9050b02876 680 description.setWordWrap(true);
IanBenzMaxim 0:33d4e66780c0 681 description.update();
IanBenzMaxim 0:33d4e66780c0 682 bitmap.overlay(description.render(), description.x(), description.y());
IanBenzMaxim 0:33d4e66780c0 683 bitmap.overlay(validSignatureButton.render(), validSignatureButton.x(), validSignatureButton.y());
IanBenzMaxim 0:33d4e66780c0 684 bitmap.overlay(showWebIdButton.render(), showWebIdButton.x(), showWebIdButton.y());
IanBenzMaxim 0:33d4e66780c0 685 return bitmap;
IanBenzMaxim 0:33d4e66780c0 686 }
IanBenzMaxim 0:33d4e66780c0 687
IanBenzMaxim 0:33d4e66780c0 688 void NormalOperationWindow::doPostLayout()
IanBenzMaxim 0:33d4e66780c0 689 {
IanBenzMaxim 0:33d4e66780c0 690 // Detect sensor node.
IanBenzMaxim 0:33d4e66780c0 691 SensorNodeState sensorNodeState = detectSensorNode();
IanBenzMaxim 0:33d4e66780c0 692 if (sensorNodeState == FailedProvision)
IanBenzMaxim 0:33d4e66780c0 693 {
IanBenzMaxim 0:33d4e66780c0 694 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 695 {
IanBenzMaxim 0:33d4e66780c0 696 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 697 windowManager()->push(new ErrorWindow("Sensor node provision failed"));
IanBenzMaxim 0:33d4e66780c0 698 }
IanBenzMaxim 0:33d4e66780c0 699 return;
IanBenzMaxim 0:33d4e66780c0 700 }
IanBenzMaxim 0:33d4e66780c0 701 if (sensorNodeState != lastSensorNodeState)
IanBenzMaxim 0:33d4e66780c0 702 {
IanBenzMaxim 0:33d4e66780c0 703 lastSensorNodeState = sensorNodeState;
IanBenzMaxim 0:33d4e66780c0 704 invalidateRegion();
IanBenzMaxim 0:33d4e66780c0 705 }
IanBenzMaxim 0:33d4e66780c0 706
IanBenzMaxim 0:33d4e66780c0 707 // Process socket data.
IanBenzMaxim 0:33d4e66780c0 708 int recvResult = socket->recv(recvBuf, sizeof(recvBuf) / sizeof(recvBuf[0]));
IanBenzMaxim 0:33d4e66780c0 709 if (recvResult > 0)
IanBenzMaxim 0:33d4e66780c0 710 {
IanBenzMaxim 3:d2799d8497c0 711 std::printf("%*s\n", recvResult, recvBuf);
IanBenzMaxim 0:33d4e66780c0 712 Result result = processReceivedData(recvResult);
IanBenzMaxim 0:33d4e66780c0 713 if (result != NoChange)
IanBenzMaxim 0:33d4e66780c0 714 return;
IanBenzMaxim 0:33d4e66780c0 715 }
IanBenzMaxim 0:33d4e66780c0 716 else if (recvResult != NSAPI_ERROR_WOULD_BLOCK)
IanBenzMaxim 0:33d4e66780c0 717 {
IanBenzMaxim 0:33d4e66780c0 718 if (windowManager() != NULL)
IanBenzMaxim 0:33d4e66780c0 719 {
IanBenzMaxim 0:33d4e66780c0 720 windowManager()->pop();
IanBenzMaxim 0:33d4e66780c0 721 windowManager()->push(new ErrorWindow("Socket recieve failed"));
IanBenzMaxim 0:33d4e66780c0 722 }
IanBenzMaxim 0:33d4e66780c0 723 return;
IanBenzMaxim 0:33d4e66780c0 724 }
IanBenzMaxim 0:33d4e66780c0 725 }
IanBenzMaxim 0:33d4e66780c0 726
IanBenzMaxim 0:33d4e66780c0 727 bool NormalOperationWindow::doProcessKey(Key key)
IanBenzMaxim 0:33d4e66780c0 728 {
IanBenzMaxim 0:33d4e66780c0 729 bool handled;
IanBenzMaxim 0:33d4e66780c0 730 switch (key)
IanBenzMaxim 0:33d4e66780c0 731 {
IanBenzMaxim 0:33d4e66780c0 732 case UpKey:
IanBenzMaxim 0:33d4e66780c0 733 validSignatureButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 734 handled = true;
IanBenzMaxim 0:33d4e66780c0 735 break;
IanBenzMaxim 0:33d4e66780c0 736
IanBenzMaxim 0:33d4e66780c0 737 case DownKey:
IanBenzMaxim 0:33d4e66780c0 738 showWebIdButton.setFocused();
IanBenzMaxim 0:33d4e66780c0 739 handled = true;
IanBenzMaxim 0:33d4e66780c0 740 break;
IanBenzMaxim 0:33d4e66780c0 741
IanBenzMaxim 0:33d4e66780c0 742 default:
IanBenzMaxim 0:33d4e66780c0 743 handled = false;
IanBenzMaxim 0:33d4e66780c0 744 break;
IanBenzMaxim 0:33d4e66780c0 745 }
IanBenzMaxim 0:33d4e66780c0 746 return handled;
IanBenzMaxim 0:33d4e66780c0 747 }
IanBenzMaxim 0:33d4e66780c0 748