MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification
Dependencies: MaximInterface mbed
The MAXREFDES143# is an Internet of Things (IoT) embedded security reference design, built to protect an industrial sensing node by means of authentication and notification to a web server. The hardware includes a peripheral module representing a protected sensor node monitoring operating temperature and remaining life of a filter (simulated through ambient light sensing) and an mbed shield representing a controller node responsible for monitoring one or more sensor nodes. The design is hierarchical with each controller node communicating data from connected sensor nodes to a web server that maintains a centralized log and dispatches notifications as necessary. The mbed shield contains a Wi-Fi module, a DS2465 coprocessor with 1-Wire® master function, an LCD, LEDs, and pushbuttons. The protected sensor node contains a DS28E15 authenticator, a DS7505 temperature sensor, and a MAX44009 light sensor. The mbed shield communicates to a web server by the onboard Wi-Fi module and to the protected sensor node with I2C and 1-Wire. The MAXREFDES143# is equipped with a standard shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The simplicity of this design enables rapid integration into any star-topology IoT network requiring the heightened security with low overhead provided by the SHA-256 symmetric-key algorithm.
More information about the MAXREFDES143# is available on the Maxim Integrated website.
Revision 32:0a09505a656d, committed 2017-11-06
- Comitter:
- IanBenzMaxim
- Date:
- Mon Nov 06 17:34:13 2017 -0600
- Parent:
- 31:7b10bcb3e0fc
- Child:
- 33:55e8581148a5
- Commit message:
- Updated to use MaximInterface library.
Changed in this revision
--- a/DS7505.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/DS7505.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,205 +28,178 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
+#include <I2C.h>
+#include <wait_api.h>
#include "DS7505.hpp"
-#include "I2C.h"
-#include "wait_api.h"
-#define I2C_WRITE 0
-#define I2C_READ 1
-
-static const int I2C_WRITE_OK = 1;
+static const int I2C_Write_Ok = 1;
static const uint8_t DS7505_Config_SD_Bit = 0x01; // Enable shutdown mode
DS7505::DS7505(mbed::I2C & I2C_interface, uint8_t I2C_address)
- : m_current_config(Config_9b_Res, true), m_I2C_interface(I2C_interface), m_I2C_address(I2C_address)
-{
-
-}
+ : m_current_config(Config_9b_Res, true), m_I2C_interface(I2C_interface),
+ m_I2C_address(I2C_address) {}
-uint8_t DS7505::get_measure_delay_ms(Config_Resolution resolution)
-{
+uint8_t DS7505::get_measure_delay_ms(Config_Resolution resolution) {
uint8_t measure_delay_ms;
-
- switch (resolution)
- {
- case Config_9b_Res:
- measure_delay_ms = 25;
- break;
- case Config_10b_Res:
- measure_delay_ms = 50;
- break;
- case Config_11b_Res:
- measure_delay_ms = 100;
- break;
- case Config_12b_Res:
- measure_delay_ms = 200;
- break;
- default:
- measure_delay_ms = 0;
- break;
+
+ switch (resolution) {
+ case Config_9b_Res:
+ measure_delay_ms = 25;
+ break;
+ case Config_10b_Res:
+ measure_delay_ms = 50;
+ break;
+ case Config_11b_Res:
+ measure_delay_ms = 100;
+ break;
+ case Config_12b_Res:
+ measure_delay_ms = 200;
+ break;
+ default:
+ measure_delay_ms = 0;
+ break;
}
-
+
return measure_delay_ms;
}
-bool DS7505::read_temp_sensor_data(uint16_t & sensor_data) const
-{
+bool DS7505::read_temp_sensor_data(uint16_t & sensor_data) const {
bool result;
uint8_t upperByte, lowerByte;
int sub_res;
-
+
sensor_data = 0;
m_I2C_interface.start();
- sub_res = m_I2C_interface.write(m_I2C_address | I2C_READ);
- if (sub_res == I2C_WRITE_OK)
- {
+ sub_res = m_I2C_interface.write(m_I2C_address | 1);
+ if (sub_res == I2C_Write_Ok) {
upperByte = m_I2C_interface.read(mbed::I2C::ACK);
lowerByte = m_I2C_interface.read(mbed::I2C::NoACK);
}
m_I2C_interface.stop();
- if (sub_res == I2C_WRITE_OK)
- {
+ if (sub_res == I2C_Write_Ok) {
sensor_data = ((((uint16_t)upperByte) << 8) | lowerByte);
result = true;
- }
- else
- {
+ } else {
// Handle hardware malfunction
result = false;
}
-
+
return result;
}
-bool DS7505::set_register_pointer(Register pointer_reg) const
-{
+bool DS7505::set_register_pointer(Register pointer_reg) const {
int res;
-
+
m_I2C_interface.start();
- res = m_I2C_interface.write(m_I2C_address | I2C_WRITE);
- if (res == I2C_WRITE_OK)
- {
+ res = m_I2C_interface.write(m_I2C_address);
+ if (res == I2C_Write_Ok) {
res = m_I2C_interface.write(pointer_reg);
}
m_I2C_interface.stop();
-
- return (res == I2C_WRITE_OK);
+
+ return (res == I2C_Write_Ok);
}
-bool DS7505::write_register(Register write_reg, uint8_t write_val) const
-{
+bool DS7505::write_register(Register write_reg, uint8_t write_val) const {
bool res;
-
+
m_I2C_interface.start();
- res = m_I2C_interface.write(m_I2C_address | I2C_WRITE);
- if (res == I2C_WRITE_OK)
- {
+ res = m_I2C_interface.write(m_I2C_address);
+ if (res == I2C_Write_Ok) {
res = m_I2C_interface.write(write_reg);
- if (res == I2C_WRITE_OK)
+ if (res == I2C_Write_Ok)
res = m_I2C_interface.write(write_val);
}
m_I2C_interface.stop();
-
- return (res == I2C_WRITE_OK);
+
+ return (res == I2C_Write_Ok);
}
-bool DS7505::write_current_config() const
-{
+bool DS7505::write_current_config() const {
uint8_t DS7505_Config_Val = m_current_config.resolution;
if (m_current_config.enable_shutdown_mode)
DS7505_Config_Val |= DS7505_Config_SD_Bit;
return write_register(Configuration_Reg, DS7505_Config_Val);
}
-DS7505::Result DS7505::set_resolution(uint8_t resolution)
-{
- switch (resolution)
- {
- case 1:
- m_current_config.resolution = Config_9b_Res;
- break;
- case 2:
- m_current_config.resolution = Config_10b_Res;
- break;
- case 3:
- m_current_config.resolution = Config_11b_Res;
- break;
- case 4:
- m_current_config.resolution = Config_12b_Res;
- break;
- default:
- return Out_of_Range;
+DS7505::Result DS7505::set_resolution(uint8_t resolution) {
+ switch (resolution) {
+ case 1:
+ m_current_config.resolution = Config_9b_Res;
+ break;
+ case 2:
+ m_current_config.resolution = Config_10b_Res;
+ break;
+ case 3:
+ m_current_config.resolution = Config_11b_Res;
+ break;
+ case 4:
+ m_current_config.resolution = Config_12b_Res;
+ break;
+ default:
+ return Out_of_Range;
}
-
+
// Write DS7505 configuration
- if (!write_current_config())
- {
+ if (!write_current_config()) {
// Handle hardware malfunction
return Hardware_Failure;
}
-
+
// Set pointer to temperature register
- if (!set_register_pointer(Temperature_Reg))
- {
+ if (!set_register_pointer(Temperature_Reg)) {
// Handle hardware malfunction
return Hardware_Failure;
}
-
+
return Success;
}
-DS7505::Result DS7505::read_temp_sensor(uint16_t & sensor_data) const
-{
+DS7505::Result DS7505::read_temp_sensor(uint16_t & sensor_data) const {
bool res;
-
- if (m_current_config.enable_shutdown_mode)
- {
+
+ if (m_current_config.enable_shutdown_mode) {
// Disable shutdown mode
m_current_config.enable_shutdown_mode = false;
res = write_current_config();
if (!res)
return Hardware_Failure;
-
+
// DS7505 measures temperature
-
+
// Enable shutdown mode
m_current_config.enable_shutdown_mode = true;
res = write_current_config();
if (!res)
return Hardware_Failure;
-
+
// Set pointer to temperature register
res = set_register_pointer(Temperature_Reg);
if (!res)
return Hardware_Failure;
-
+
// Sleep for maximum time needed for sample
wait_ms(get_measure_delay_ms(m_current_config.resolution));
}
// else: shutdown mode disabled
// DS7505 is constantly measuring temperature
-
+
// Read temperature from sensor
- if (!read_temp_sensor_data(sensor_data))
- {
+ if (!read_temp_sensor_data(sensor_data)) {
return Hardware_Failure;
}
-
+
return Success;
}
-DS7505::Result DS7505::read_current_temp(int16_t & temperature) const
-{
+DS7505::Result DS7505::read_current_temp(int16_t & temperature) const {
uint16_t sensor_data;
Result result;
-
+
result = read_temp_sensor(sensor_data);
- if (result == Success)
- {
+ if (result == Success) {
// Convert temperature to have an exponent of 10^-2
temperature = ((int8_t)(sensor_data >> 8)) * 100;
if (sensor_data & 0x0080)
@@ -241,14 +214,12 @@
return result;
}
-DS7505::Result DS7505::read_current_temp(double & temperature) const
-{
+DS7505::Result DS7505::read_current_temp(double & temperature) const {
uint16_t sensor_data;
Result result;
-
+
result = read_temp_sensor(sensor_data);
- if (result == Success)
- {
+ if (result == Success) {
// Convert sensor data to floating-point temperature
temperature = ((int8_t)(sensor_data >> 8));
if (sensor_data & 0x0080)
@@ -263,14 +234,12 @@
return result;
}
-DS7505::Result DS7505::read_current_temp(int8_t & temperature) const
-{
+DS7505::Result DS7505::read_current_temp(int8_t & temperature) const {
uint16_t sensor_data;
Result result;
-
+
result = read_temp_sensor(sensor_data);
- if (result == Success)
- {
+ if (result == Success) {
// Convert sensor data to integer temperature
temperature = ((int8_t)(sensor_data >> 8));
}
--- a/DS7505.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/DS7505.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,110 +28,101 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef DS7505_HPP
#define DS7505_HPP
#include <stdint.h>
-namespace mbed
-{
- class I2C;
-}
+namespace mbed { class I2C; }
/// Interface to the DS7505 temperature sensor.
-class DS7505
-{
+class DS7505 {
public:
- enum Result
- {
- Success,
- Hardware_Failure,
- Out_of_Range
- };
-
+ enum Result { Success, Hardware_Failure, Out_of_Range };
+
/// @param I2C_interface A configured I2C interface to use for communication.
/// @param I2C_address Device bus address in mbed format.
DS7505(mbed::I2C & I2C_interface, uint8_t I2C_address);
-
+
/// Set the resolution for temperature conversions.
/// @param resolution Number of decimal bit from 1 to 4.
Result set_resolution(uint8_t resolution);
-
+
/// Reads the current temperature with an exponent of 10^-2.
- /// @note Compatible with Bluetooth characteristic: org.bluetooth.characteristic.temperature.
+ /// @note Compatible with Bluetooth characteristic:
+ /// org.bluetooth.characteristic.temperature.
Result read_current_temp(int16_t & temperature) const;
-
+
/// Reads the current temperature as a floating point value.
Result read_current_temp(double & temperature) const;
-
+
/// Reads the current temperature as an integer value.
Result read_current_temp(int8_t & temperature) const;
-
+
private:
/// Bit resolution of temperature conversions.
- enum Config_Resolution
- {
+ enum Config_Resolution {
Config_9b_Res = 0x00,
Config_10b_Res = 0x20,
Config_11b_Res = 0x40,
Config_12b_Res = 0x60
};
-
+
/// DS7505 Register addresses.
- enum Register
- {
+ enum Register {
Temperature_Reg = 0x00,
Configuration_Reg = 0x01,
Thyst_Reg = 0x02,
Tos_Reg = 0x03
};
-
+
/// Represents a DS7505 configuration.
- struct Config
- {
+ struct Config {
Config_Resolution resolution;
bool enable_shutdown_mode;
-
+
Config(Config_Resolution resolution, bool enable_shutdown_mode)
- : resolution(resolution), enable_shutdown_mode(enable_shutdown_mode) { }
+ : resolution(resolution), enable_shutdown_mode(enable_shutdown_mode) {}
};
-
+
/// @note Mark as mutable to allow manipulation by read_temp_sensor().
mutable Config m_current_config;
-
+
mbed::I2C & m_I2C_interface;
uint8_t m_I2C_address;
-
- /// Returns the maximum time needed in ms for a sample at the specified resolution.
+
+ /// Returns the maximum time needed in milliseconds for a sample at the
+ /// specified resolution.
static uint8_t get_measure_delay_ms(Config_Resolution resolution);
-
- /// Reads the current temperature via I2C.
- /// Assumes that the I2C register pointer is already set to the temperature register.
- /// @param sensor_data Output for raw data from DS7505 with upper and lower bytes combined.
+
+ /// Reads the current temperature via I2C. Assumes that the I2C register
+ /// pointer is already set to the temperature register.
+ /// @param sensor_data
+ /// Output for raw data from DS7505 with upper and lower bytes combined.
/// @returns True on success.
bool read_temp_sensor_data(uint16_t & sensor_data) const;
-
+
/// Reads the current temperature with support for shutdown mode.
- /// @param sensor_data Output for raw data from DS7505 with upper and lower bytes combined.
+ /// @param sensor_data Output for raw data from DS7505 with upper and lower
+ /// bytes combined.
/// @returns Success or Hardware_Failure.
Result read_temp_sensor(uint16_t & sensor_data) const;
-
+
/// Sets the I2C register pointer for the next operation.
/// @param pointer_reg Desired register to set.
/// @returns True on success.
/// @note Allow marking const since not public.
bool set_register_pointer(Register pointer_reg) const;
-
+
/// Writes to a device register via I2C.
/// @param write_reg Register to write to.
/// @param write_val Value to write to the register.
/// @returns True on success.
/// @note Allow marking const since not public
bool write_register(Register write_reg, uint8_t write_val) const;
-
+
/// Writes the current configuration via I2C.
/// @returns True on success.
/// @note Allow marking const since not public
--- a/Display.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/Display.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,63 +28,66 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#include <sstream>
+#include <I2C.h>
+#include <wait_api.h>
#include "Display.hpp"
-#include "I2C.h"
-#include "wait_api.h"
-//LCD Commands
-//If the RS bit is set to logic 1, these display bytes are stored in the display RAM at the address specified by the data pointer. The data pointer is
-//automatically updated and the data is directed to the intended ST7036i device. If the RS bit of the last control byte is set to
-//logic 0, these command bytes will be decoded and the setting of the device will be changed according to the received commands.
-enum LCD_Commands
-{
- ControlByte = 0x00, //Only one control byte will be sent. Only a stream of data bytes is allowed to follow.
- ControlByte_RS_Set = 0x40, //Only one control byte will be sent with the RS bit set. Only a stream of data bytes is allowed to follow.
- ControlBytes = 0x80, //Another control byte will follow, unless an I2C Stop condition is received.
- ControlBytes_RS_Set = 0xC0, //RS Set and another control byte will follow, unless an I2C Stop condition is received.
+// LCD Commands
+// If the RS bit is set to logic 1, these display bytes are stored in the
+// display RAM at the address specified by the data pointer. The data pointer is
+// automatically updated and the data is directed to the intended ST7036i
+// device. If the RS bit of the last control byte is set to logic 0, these
+// command bytes will be decoded and the setting of the device will be changed
+// according to the received commands.
+enum LCD_Commands {
+ // Only one control byte will be sent.
+ // Only a stream of data bytes is allowed to follow.
+ ControlByte = 0x00,
+ // Only one control byte will be sent with the RS bit set.
+ // Only a stream of data bytes is allowed to follow.
+ ControlByte_RS_Set = 0x40,
+ // Another control byte will follow, unless an I2C Stop condition is received.
+ ControlBytes = 0x80,
+ // RS Set and another control byte will follow, unless an I2C Stop condition
+ // is received.
+ ControlBytes_RS_Set =0xC0
};
-//LCD Instructions
-enum LCD_Instructions
-{
+// LCD Instructions
+enum LCD_Instructions {
ClearDisplay = 0x01,
- Display_OFF = 0x08, //Display off
- Display_ON = 0x0C, //Display on, cursor off, cursor position off
+ Display_OFF = 0x08, // Display off
+ Display_ON = 0x0C, // Display on, cursor off, cursor position off
ReturnHome = 0x02,
SetDdramAddress = 0x80
};
// LED Driver Port Registers
// Initial port state 0x80
-enum LED_Driver_Ports
-{
+enum LED_Driver_Ports {
P1 = 0x01,
- P2 = 0x02, // Blue LED
- P3 = 0x03, // Green LED
- P4 = 0x04 // Red LED
+ P2 = 0x02, // Blue LED
+ P3 = 0x03, // Green LED
+ P4 = 0x04 // Red LED
};
// Convert a byte color value into the representation used by the MAX7306 PWM registers
-static uint8_t convertColorToPwmRegVal(uint8_t color)
-{
+static uint8_t convertColorToPwmRegVal(uint8_t color) {
const uint8_t staticOffRegVal = 0x80; // LED is static off by setting to input
- const uint8_t staticOnRegVal = 0x00; // LED is static on
- const uint8_t minOnRegVal = 0x01; // LED on for minimum duty cycle
-
+ const uint8_t staticOnRegVal = 0x00; // LED is static on
+ const uint8_t minOnRegVal = 0x01; // LED on for minimum duty cycle
+
uint8_t regVal;
if (color == 0x00) // Use static off for no color
{
regVal = staticOffRegVal;
- }
- else if (color == 0xFF) // Use static on for full color
+ } else if (color == 0xFF) // Use static on for full color
{
regVal = staticOnRegVal;
- }
- else // Use standard PWN for all other values
+ } else // Use standard PWN for all other values
{
// The 3 least significant bits cannot be rendered with the MAX7306
regVal = color >> 3;
@@ -94,176 +97,164 @@
return regVal;
}
-Display::Display(mbed::I2C & I2C_intf, uint8_t LCD_I2C_addr, uint8_t LED_driver_I2C_addr)
- : m_I2C_intf(I2C_intf), m_LCD_I2C_addr(LCD_I2C_addr), m_LED_driver_I2C_addr(LED_driver_I2C_addr)
-{
-
-}
+Display::Display(mbed::I2C & I2C_intf, uint8_t LCD_I2C_addr,
+ uint8_t LED_driver_I2C_addr)
+ : m_I2C_intf(I2C_intf), m_LCD_I2C_addr(LCD_I2C_addr),
+ m_LED_driver_I2C_addr(LED_driver_I2C_addr) {}
-void Display::initialize(void)
-{
+void Display::initialize() {
initializeLCD();
initializeLED_Driver();
}
-void Display::initializeLED_Driver(void)
-{
- const uint8_t Configuration26 = 0x26; //intial port state 0xEC
- const uint8_t Configuration27 = 0x27; //intial port state 0x8F
-
- //Intial mode
- //write to Configuration Register 0x26
+void Display::initializeLED_Driver() {
+ const uint8_t Configuration26 = 0x26; // Intial port state 0xEC
+ const uint8_t Configuration27 = 0x27; // Intial port state 0x8F
+
+ // Intial mode
+ // Write to Configuration Register 0x26
m_I2C_intf.start();
m_I2C_intf.write(m_LED_driver_I2C_addr);
m_I2C_intf.write(Configuration26);
- //RST does reset PWM/blink counters, RST resets registers to power-on-reset state
- m_I2C_intf.write(0x1F);
+ // RST resets registers to power-on-reset state
+ // RST does reset PWM/blink counters,
+ m_I2C_intf.write(0x1F);
m_I2C_intf.stop();
-
- //Write to Configuration Register 0x27
+
+ // Write to Configuration Register 0x27
m_I2C_intf.start();
m_I2C_intf.write(m_LED_driver_I2C_addr);
m_I2C_intf.write(Configuration27);
- //Enable bus time out, set P1,P2,P3 to be controlled by their registers (0x01,0x02,0x03)
- m_I2C_intf.write(0x0E);
+ // Enable bus time out, and set P1, P2, P3 to be controlled by their registers
+ // (0x01, 0x02, 0x03)
+ m_I2C_intf.write(0x0E);
m_I2C_intf.stop();
}
-void Display::setBackLightColor(const Color & color)
-{
+void Display::setBackLightColor(const Color & color) {
// Red
m_I2C_intf.start();
m_I2C_intf.write(m_LED_driver_I2C_addr);
m_I2C_intf.write(P4);
- m_I2C_intf.write(convertColorToPwmRegVal(color.R));
+ m_I2C_intf.write(convertColorToPwmRegVal(color.R));
m_I2C_intf.stop();
-
+
// Green
m_I2C_intf.start();
m_I2C_intf.write(m_LED_driver_I2C_addr);
m_I2C_intf.write(P3);
- m_I2C_intf.write(convertColorToPwmRegVal(color.G));
+ m_I2C_intf.write(convertColorToPwmRegVal(color.G));
m_I2C_intf.stop();
-
+
// Blue
m_I2C_intf.start();
m_I2C_intf.write(m_LED_driver_I2C_addr);
m_I2C_intf.write(P2);
- m_I2C_intf.write(convertColorToPwmRegVal(color.B));
+ m_I2C_intf.write(convertColorToPwmRegVal(color.B));
m_I2C_intf.stop();
}
-void Display::clearLine(Line line)
-{
+void Display::clearLine(Line line) {
writeCompleteLine("", line);
setCursorPosition(line);
}
-void Display::clearDisplay(void)
-{
+void Display::clearDisplay() {
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
- m_I2C_intf.write(ControlByte); //No more control bytes will be sent
+ m_I2C_intf.write(ControlByte); //No more control bytes will be sent
m_I2C_intf.write(ClearDisplay);
m_I2C_intf.stop();
}
-void Display::initializeLCD(void)
-{
+void Display::initializeLCD() {
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
- m_I2C_intf.write(ControlByte); //No more control bytes will be sent
- m_I2C_intf.write(0x38); //Function Set IS[2:1] = 0,0 (&h38 = Single height font, 0x3C = double height font)
- m_I2C_intf.write(0x39); //Function Set IS[2:1] = (0,1)
- //When IS[2:1]=(0,0): normal instruction be selected(refer instruction table 0)
- //When IS[2:1]=(0,1): extension instruction be selected(refer instruction table 1 )
- //When IS[2:1]=(1,0): extension instruction be selected(refer instruction table 2 )
- m_I2C_intf.write(0x14); //BIAS SET
- m_I2C_intf.write(0x70); //CONTRAST (was 0x78)
- m_I2C_intf.write(0x5E); //POWER/ICON CONTROL/CONTRAST (upper two bits)
- m_I2C_intf.write(0x6D); //FOLLOWER CONTROL
+ m_I2C_intf.write(ControlByte); // No more control bytes will be sent
+ // Function Set IS[2:1] = 0,0 (&h38 = Single height font, 0x3C = double height font)
+ m_I2C_intf.write(0x38);
+ m_I2C_intf.write(0x39); //Function Set IS[2:1] = (0,1)
+ // When IS[2:1]=(0,0): normal instruction be selected(refer instruction table 0)
+ // When IS[2:1]=(0,1): extension instruction be selected(refer instruction table 1)
+ // When IS[2:1]=(1,0): extension instruction be selected(refer instruction table 2)
+ m_I2C_intf.write(0x14); // BIAS SET
+ m_I2C_intf.write(0x70); // CONTRAST (was 0x78)
+ m_I2C_intf.write(0x5E); // POWER/ICON CONTROL/CONTRAST (upper two bits)
+ m_I2C_intf.write(0x6D); // FOLLOWER CONTROL
m_I2C_intf.stop();
- wait_ms(200); //Wait for power stable
+ wait_ms(200); // Wait for power stable
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
- m_I2C_intf.write(ControlByte); //No more control bytes will be sent
- m_I2C_intf.write(Display_ON); //Display on, cursor on, cursor position on
- m_I2C_intf.write(ClearDisplay); //Clear Display
- m_I2C_intf.write(0x06); //ENTRY MODE
+ m_I2C_intf.write(ControlByte); // No more control bytes will be sent
+ m_I2C_intf.write(Display_ON); // Display on, cursor on, cursor position on
+ m_I2C_intf.write(ClearDisplay); // Clear Display
+ m_I2C_intf.write(0x06); // ENTRY MODE
m_I2C_intf.stop();
}
-void Display::writeCharacter(uint8_t character)
-{
+void Display::writeCharacter(uint8_t character) {
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
- m_I2C_intf.write(ControlByte_RS_Set); //No more control bytes will be sent
- m_I2C_intf.write(character); //Display on, cursor on, cursor position on
- m_I2C_intf.stop();
+ m_I2C_intf.write(ControlByte_RS_Set); // No more control bytes will be sent
+ m_I2C_intf.write(character); // Display on, cursor on, cursor position on
+ m_I2C_intf.stop();
}
-void Display::writeText(const std::string & text)
-{
+void Display::writeText(const std::string & text) {
const char RETURN_CHAR = 0x16;
-
+
size_t length = text.length();
if (length > lineLength)
length = lineLength;
-
+
//Write to LCD
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
m_I2C_intf.write(ControlByte_RS_Set);
-
- for(size_t i = 0; i < length; i++)
- {
- if(text[i] != RETURN_CHAR)
+
+ for (size_t i = 0; i < length; i++) {
+ if (text[i] != RETURN_CHAR)
m_I2C_intf.write(text[i]);
}
-
+
m_I2C_intf.stop();
}
-void Display::setCursorPosition(Line line, size_t position)
-{
- if (position > (lineLength - 1)) // Set to last line character for values outside the upper bound
+void Display::setCursorPosition(Line line, size_t position) {
+ // Set to last line character for values outside the upper bound
+ if (position > (lineLength - 1))
position = (lineLength - 1);
m_I2C_intf.start();
m_I2C_intf.write(m_LCD_I2C_addr);
m_I2C_intf.write(ControlByte); // No more control bytes will be sent
- if(line == SecondLine) // Offset for second line
+ if (line == SecondLine) // Offset for second line
position += 0x40;
m_I2C_intf.write(SetDdramAddress | position);
m_I2C_intf.stop();
}
-void Display::writeLine(const std::string & text, Line line)
-{
+void Display::writeLine(const std::string & text, Line line) {
setCursorPosition(line);
writeText(text);
}
-void Display::writeCompleteLine(const std::string & text, Line line)
-{
+void Display::writeCompleteLine(const std::string & text, Line line) {
// Add padding to user's string
std::string writeText(text);
if (writeText.length() < lineLength)
writeText.append(lineLength - writeText.length(), ' ');
-
+
writeLine(writeText, line);
}
-void Display::writeMessage(const std::string & message)
-{
- if (message.length() > lineLength)
- {
+void Display::writeMessage(const std::string & message) {
+ if (message.length() > lineLength) {
// Find split point
std::istringstream messageStream(message);
std::string word;
size_t splitIndex = 0;
- do
- {
+ do {
if (word.length() > 0)
splitIndex += (word.length() + 1);
std::getline(messageStream, word, ' ');
@@ -272,15 +263,11 @@
{
writeCompleteLine(message.substr(0, lineLength), FirstLine);
writeCompleteLine(message.substr(lineLength), SecondLine);
- }
- else
- {
+ } else {
writeCompleteLine(message.substr(0, splitIndex - 1), FirstLine);
writeCompleteLine(message.substr(splitIndex), SecondLine);
}
- }
- else
- {
+ } else {
writeCompleteLine(message, FirstLine);
writeCompleteLine("", SecondLine);
}
--- a/Display.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/Display.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,8 +28,7 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef DISPLAY_HPP
#define DISPLAY_HPP
@@ -42,66 +41,62 @@
/// Interface to the Newhaven Display NHD-C0220BiZ-FS(RGB)-FBW-3VM LCD module
/// and MAX7306 PWM LED driver for backlight color selection.
-class Display
-{
+class Display {
public:
/// Display line referenced from top
- enum Line
- {
- FirstLine = 0,
- SecondLine
- };
-
+ enum Line { FirstLine = 0, SecondLine };
+
/// 24-bit RGB color for the backlight.
- struct Color
- {
+ struct Color {
uint8_t R, G, B;
};
-
+
/// Length in character os a display line.
static const size_t lineLength = 20;
-
+
/// @param I2C_interface A configured I2C interface to use for communication.
/// @param LCD_I2C_address LCD module bus address in mbed format.
/// @param LED_driver_I2C_addr PWM LED driver (MAX7306) bus address in mbed format.
- Display(mbed::I2C & I2C_intf, uint8_t LCD_I2C_addr, uint8_t LED_driver_I2C_addr);
-
+ Display(mbed::I2C & I2C_intf, uint8_t LCD_I2C_addr,
+ uint8_t LED_driver_I2C_addr);
+
/// Initialize display components.
- void initialize(void);
-
+ void initialize();
+
/// Clear all display lines.
- void clearDisplay(void);
-
+ void clearDisplay();
+
/// Clear a specific display line.
void clearLine(Line line);
-
+
/// Write a single character to the display at the current cursor position.
void writeCharacter(uint8_t character);
-
+
/// Write text to the display at the current cursor position.
void writeText(const std::string & text);
-
+
/// Set cursor to a certain line and zero-index position within the line.
void setCursorPosition(Line line, size_t position = 0);
-
+
/// Writes text to the display starting at the beginning of the line.
void writeLine(const std::string & text, Line line);
-
- /// Writes text to the display starting at the beginning of the line and clears the remainder of the line.
+
+ /// Writes text to the display starting at the beginning of the line and
+ /// clears the remainder of the line.
void writeCompleteLine(const std::string & text, Line line);
-
- // Writes a message to the display with text wrapping allowed at spaces.
+
+ /// Writes a message to the display with text wrapping allowed at spaces.
void writeMessage(const std::string & text);
- // Set the display backlight to a certain color.
+ /// Set the display backlight to a certain color.
void setBackLightColor(const Color & color);
-
-private:
+
+private:
mbed::I2C & m_I2C_intf;
uint8_t m_LCD_I2C_addr, m_LED_driver_I2C_addr;
-
- void initializeLCD(void);
- void initializeLED_Driver(void);
+
+ void initializeLCD();
+ void initializeLED_Driver();
};
#endif
--- a/ESP8266.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/ESP8266.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,30 +28,25 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#include <cstdlib>
+#include <Timer.h>
+#include <wait_api.h>
#include "ESP8266.hpp"
-#include "Timer.h"
-#include "wait_api.h"
-static inline void disableRecvData()
-{
- __disable_irq();
-}
+static inline void disableRecvData() { __disable_irq(); }
-static inline void enableRecvData()
-{
- __enable_irq();
-}
+static inline void enableRecvData() { __enable_irq(); }
-ESP8266::ESP8266(const PinName tx, const PinName rx, const PinName rst, const PinName CH_PD, const int baud, mbed::Serial * debugMsgIntf)
- : AT_intf(tx, rx), resetPin(rst), powerDownPin(CH_PD), debugMsg(debugMsgIntf), parseRecvReset(false)
-{
+ESP8266::ESP8266(const PinName tx, const PinName rx, const PinName rst,
+ const PinName CH_PD, const int baud,
+ mbed::Serial * debugMsgIntf)
+ : AT_intf(tx, rx), resetPin(rst), powerDownPin(CH_PD),
+ debugMsg(debugMsgIntf), parseRecvReset(false) {
AT_intf.baud(baud);
AT_intf.attach(this, &ESP8266::recv_AT_data_cb);
-
+
// Ensure that device is not held in reset
if (resetPin.is_connected())
resetPin = 1;
@@ -59,10 +54,8 @@
setPowered(false);
}
-void ESP8266::reset()
-{
- if (resetPin.is_connected())
- {
+void ESP8266::reset() {
+ if (resetPin.is_connected()) {
resetPin = 0;
wait_ms(100);
resetPin = 1;
@@ -70,40 +63,34 @@
}
}
-bool ESP8266::powered() const
-{
+bool ESP8266::powered() const {
bool isPowered;
- if (powerDownPin.is_connected())
- {
+ if (powerDownPin.is_connected()) {
isPowered = powerDownPin.read();
- }
- else
- {
+ } else {
isPowered = false;
}
return isPowered;
}
-void ESP8266::setPowered(bool powered)
-{
+void ESP8266::setPowered(bool powered) {
if (powerDownPin.is_connected())
powerDownPin = powered;
}
-ESP8266::CmdResult ESP8266::performSelfTest()
-{
+ESP8266::CmdResult ESP8266::performSelfTest() {
return sendCommand(CmdBuilder(""));
}
-ESP8266::CmdResult ESP8266::setCurrentWifiMode(const ESP8266::WifiMode mode)
-{
+ESP8266::CmdResult ESP8266::setCurrentWifiMode(const ESP8266::WifiMode mode) {
CmdBuilder builder("CWMODE_CUR");
builder.addRawArgument(mode);
return sendCommand(builder);
}
-ESP8266::CmdResult ESP8266::joinCurrentAccessPoint(const std::string & ssid, const std::string & pwd, const std::string & bssid)
-{
+ESP8266::CmdResult ESP8266::joinCurrentAccessPoint(const std::string & ssid,
+ const std::string & pwd,
+ const std::string & bssid) {
CmdBuilder builder("CWJAP_CUR");
builder.addStringArgument(ssid);
builder.addStringArgument(pwd);
@@ -112,33 +99,31 @@
return sendCommand(builder);
}
-ESP8266::CmdResult ESP8266::quitAccessPoint()
-{
+ESP8266::CmdResult ESP8266::quitAccessPoint() {
return sendCommand(CmdBuilder("CWQAP"));
}
-ESP8266::CmdResult ESP8266::setMaxRFTXPower(const float power_dBm)
-{
+ESP8266::CmdResult ESP8266::setMaxRFTXPower(const float power_dBm) {
int power_arg = (int)(power_dBm * 4);
if (power_arg > 82)
power_arg = 82;
else if (power_arg < 0)
power_arg = 0;
-
+
CmdBuilder builder("RFPOWER");
builder.addRawArgument(power_arg);
return sendCommand(builder);
}
-ESP8266::CmdResult ESP8266::ping(const std::string & IP)
-{
+ESP8266::CmdResult ESP8266::ping(const std::string & IP) {
CmdBuilder builder("PING");
builder.addStringArgument(IP);
return sendCommand(builder);
}
-ESP8266::CmdResult ESP8266::openConnection(const ESP8266::ConnType type, const std::string & remoteIP, const unsigned int remotePort)
-{
+ESP8266::CmdResult ESP8266::openConnection(const ESP8266::ConnType type,
+ const std::string & remoteIP,
+ const unsigned int remotePort) {
CmdBuilder builder("CIPSTART");
builder.addStringArgument((type == TCP) ? "TCP" : "UDP");
builder.addStringArgument(remoteIP);
@@ -146,13 +131,11 @@
return sendCommand(builder);
}
-ESP8266::CmdResult ESP8266::closeConnection()
-{
+ESP8266::CmdResult ESP8266::closeConnection() {
return sendCommand(CmdBuilder("CIPCLOSE"));
}
-ESP8266::CmdResult ESP8266::sendData(const std::string & data)
-{
+ESP8266::CmdResult ESP8266::sendData(const std::string & data) {
CmdBuilder builder("CIPSEND");
builder.addRawArgument(data.length());
ESP8266::CmdResult result = sendCommand(builder);
@@ -161,105 +144,94 @@
return result;
}
-ESP8266::CmdResult ESP8266::sendCommand(const CmdBuilder & cmd)
-{
+ESP8266::CmdResult ESP8266::sendCommand(const CmdBuilder & cmd) {
return send_AT_data(cmd.str(), true);
}
-bool ESP8266::recvIpDataReadable()
-{
+bool ESP8266::recvIpDataReadable() {
bool result;
-
+
disableRecvData(); // Lock queue access
-
+
result = !recvIpDataBuffer.empty();
-
+
enableRecvData(); // Unlock queue access
-
+
return result;
}
-char ESP8266::getcRecvIpData()
-{
+char ESP8266::getcRecvIpData() {
char received;
-
+
disableRecvData(); // Lock queue access
-
+
// Pop next char or set to NTC if not data in buffer
if (!recvIpDataBuffer.pop(received))
received = '\0';
-
+
enableRecvData(); // Unlock queue access
-
+
return received;
}
-void ESP8266::clearRecvData()
-{
- disableRecvData(); // Lock queue access
-
- recvIpDataBuffer.reset();
- parseRecvReset = true;
-
- enableRecvData(); // Unlock queue access
+void ESP8266::clearRecvData() {
+ disableRecvData(); // Lock queue access
+
+ recvIpDataBuffer.reset();
+ parseRecvReset = true;
+
+ enableRecvData(); // Unlock queue access
}
-ESP8266::CmdResult ESP8266::send_AT_data(const std::string & cmdString, const bool expectEcho)
-{
+ESP8266::CmdResult ESP8266::send_AT_data(const std::string & cmdString,
+ const bool expectEcho) {
const int timeout_ms = 10000;
-
+
mbed::Timer timer;
ESP8266::CmdResult result = ESP8266::HardwareError;
std::string response;
-
+
disableRecvData(); // Lock for manual data handling in this procedure
-
+
// Flush receive buffer
while (AT_intf.readable())
AT_intf.getc();
-
+
// Begin counting for timeout
timer.start();
-
- for (size_t i = 0; i < cmdString.length(); i++)
- {
+
+ for (size_t i = 0; i < cmdString.length(); i++) {
// Write next character
- while (!AT_intf.writeable())
- {
- if (timer.read_ms() > timeout_ms)
- {
+ while (!AT_intf.writeable()) {
+ if (timer.read_ms() > timeout_ms) {
result = TimeoutError;
goto exit;
}
}
AT_intf.putc(cmdString[i]);
// Wait for echo
- if (expectEcho && (cmdString[i] != '\r') && (cmdString[i] != '\n'))
- {
- while (!AT_intf.readable())
- {
- if (timer.read_ms() > timeout_ms)
- {
+ if (expectEcho && (cmdString[i] != '\r') && (cmdString[i] != '\n')) {
+ while (!AT_intf.readable()) {
+ if (timer.read_ms() > timeout_ms) {
result = TimeoutError;
goto exit;
}
}
// Compare to written character
- if (AT_intf.getc() != cmdString[i])
- {
+ if (AT_intf.getc() != cmdString[i]) {
// Handle error
result = ESP8266::HardwareError;
goto exit;
}
}
}
-
- while (result == ESP8266::HardwareError)
- {
+
+ while (result == ESP8266::HardwareError) {
// Wait to receive something
response.clear();
- while (!read_line(response)) ;
-
+ while (!read_line(response))
+ ;
+
// Check if valid response
if (response == "OK")
result = ESP8266::AT_OK;
@@ -271,42 +243,34 @@
result = ESP8266::AT_OK;
else if (response == "ALREADY CONNECT") // Used by AT+CIPSTART
result = ESP8266::AT_OK;
-
- if (timer.read_ms() > timeout_ms)
- {
+
+ if (timer.read_ms() > timeout_ms) {
result = TimeoutError;
break;
}
}
-
+
exit:
enableRecvData(); // Enable interrupt processing
return result;
}
-bool ESP8266::read_line(std::string & line)
-{
+bool ESP8266::read_line(std::string & line) {
char received;
-
- while (AT_intf.readable())
- {
+
+ while (AT_intf.readable()) {
received = AT_intf.getc();
- if (received == '\n')
- {
+ if (received == '\n') {
return true;
- }
- else if (received != '\r')
- {
+ } else if (received != '\r') {
line.push_back(received);
}
}
return false;
}
-void ESP8266::recv_AT_data_cb()
-{
- while (AT_intf.readable())
- {
+void ESP8266::recv_AT_data_cb() {
+ while (AT_intf.readable()) {
char received = AT_intf.getc();
parseRecvIpData(received);
parseRecvConnClosedMsg(received);
@@ -314,153 +278,114 @@
}
}
-void ESP8266::parseRecvIpData(const char received)
-{
- enum DataRecvState
- {
- Header,
- Length,
- Data,
- Reset
- };
-
+void ESP8266::parseRecvIpData(const char received) {
+ enum DataRecvState { Header, Length, Data, Reset };
+
static const char findChars[] = "+IPD,";
static const size_t maxSizeDigits = 4;
-
+
static size_t dataFinishedSize = 0;
static size_t index = 0;
- static char sizeDigits[] = { '\0', '\0', '\0', '\0', '\0' };
+ static char sizeDigits[] = {'\0', '\0', '\0', '\0', '\0'};
static DataRecvState state = Header;
-
+
if (parseRecvReset)
state = Reset;
-
- switch (state)
- {
+
+ switch (state) {
case Reset:
default:
index = 0;
dataFinishedSize = 0;
state = Header;
// Continue processing switch
-
+
case Header:
- if (received == findChars[index])
- {
- if (findChars[++index] == '\0')
- {
+ if (received == findChars[index]) {
+ if (findChars[++index] == '\0') {
index = 0;
state = Length;
}
- }
- else
- {
+ } else {
state = Reset;
}
break;
-
- case Length:
- if ((received <= '9') && (received >= '0'))
- {
- if (index < maxSizeDigits)
- {
+
+ case Length:
+ if ((received <= '9') && (received >= '0')) {
+ if (index < maxSizeDigits) {
sizeDigits[index++] = received;
- }
- else
- {
+ } else {
state = Reset;
}
- }
- else if (received == ':')
- {
+ } else if (received == ':') {
dataFinishedSize = std::atoi(sizeDigits);
- if (dataFinishedSize == 0)
- {
+ if (dataFinishedSize == 0) {
state = Reset;
- }
- else
- {
+ } else {
index = 0;
state = Data;
}
- }
- else
- {
+ } else {
state = Reset;
}
break;
-
+
case Data:
- if (index < dataFinishedSize)
- {
+ if (index < dataFinishedSize) {
recvIpDataBuffer.push(received);
index++;
- }
- else
- {
+ } else {
state = Reset;
}
break;
};
}
-void ESP8266::parseRecvConnClosedMsg(const char received)
-{
+void ESP8266::parseRecvConnClosedMsg(const char received) {
static const char findChars[] = "CLOSED";
-
+
static int index = 0;
-
+
bool shouldReset = parseRecvReset;
-
- if (received == findChars[index])
- {
- if (findChars[++index] == '\0')
- {
+
+ if (received == findChars[index]) {
+ if (findChars[++index] == '\0') {
printDbgMsg(findChars);
shouldReset = true;
}
- }
- else
- {
+ } else {
shouldReset = true;
}
-
- if (shouldReset)
- {
+
+ if (shouldReset) {
index = 0;
}
}
-void ESP8266::printDbgMsg(const char * message)
-{
+void ESP8266::printDbgMsg(const char * message) {
if (debugMsg != NULL)
debugMsg->printf("%s", message);
}
-ESP8266::CmdBuilder::CmdBuilder(const std::string & cmd)
-{
- clear(cmd);
-}
+ESP8266::CmdBuilder::CmdBuilder(const std::string & cmd) { clear(cmd); }
-void ESP8266::CmdBuilder::clear(const std::string & cmd)
-{
+void ESP8266::CmdBuilder::clear(const std::string & cmd) {
numArgs = 0;
cmdStream.str("");
-
+
cmdStream << "AT";
if (cmd != "")
cmdStream << "+" << cmd;
}
-void ESP8266::CmdBuilder::addStringArgument(const std::string & arg)
-{
+void ESP8266::CmdBuilder::addStringArgument(const std::string & arg) {
std::ostringstream argStream;
argStream << "\"" << arg << "\"";
addRawArgument<std::string>(argStream.str());
}
-std::string ESP8266::CmdBuilder::str() const
-{
+std::string ESP8266::CmdBuilder::str() const {
std::string cmdString = cmdStream.str();
cmdString.append("\r\n");
return cmdString;
--- a/ESP8266.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/ESP8266.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,146 +28,134 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef ESP8266_HPP
#define ESP8266_HPP
#include <string>
#include <sstream>
-
-#include "PinNames.h"
-#include "Serial.h"
-#include "DigitalOut.h"
-#include "CircularBuffer.h"
-
-namespace mbed { class Serial; }
+#include <PinNames.h>
+#include <Serial.h>
+#include <DigitalOut.h>
+#include <CircularBuffer.h>
/// Interface to the ESP8266 Wi-Fi module.
-class ESP8266
-{
+class ESP8266 {
public:
/// Result of sending an AT command.
- enum CmdResult
- {
+ enum CmdResult {
AT_OK = 1,
AT_FAIL = 0,
AT_ERROR = -1,
HardwareError = -2,
TimeoutError = -3
};
-
+
/// ESP8266 Wi-Fi mode.
- enum WifiMode
- {
- station_mode = 1,
- softAP_mode = 2,
- softAP_station_mode = 3
- };
-
+ enum WifiMode { station_mode = 1, softAP_mode = 2, softAP_station_mode = 3 };
+
/// Connection type.
- enum ConnType
- {
- TCP,
- UDP
- };
-
+ enum ConnType { TCP, UDP };
+
/// Recovery time between Send Data operation as specified by datasheet.
- static const unsigned int sendDataRecoveryTimeMs = 1000;
-
+ static const int sendDataRecoveryTimeMs = 1000;
+
/// Builds command strings for the ESP8266 with proper formatting.
- class CmdBuilder
- {
+ class CmdBuilder {
public:
/// @param cmd Command of the format "AT+[cmd]".
CmdBuilder(const std::string & cmd = "");
-
+
/// Clear all arguments.
/// @param cmd Command of the format "AT+[cmd]".
void clear(const std::string & cmd);
-
+
/// Append an argument using the default string conversion for that type.
/// @param arg Argument to append to the command.
- template <typename T> void addRawArgument(const T & arg)
- {
+ template <typename T> void addRawArgument(const T & arg) {
cmdStream << ((numArgs == 0) ? "=" : ",") << arg;
numArgs++;
}
-
+
/// Append a string argument with proper quoting.
/// @param arg Argument to append to the command.
void addStringArgument(const std::string & arg);
-
+
/// Create a string suitable for use with sendCommand().
/// @returns The formatted command string.
std::string str() const;
-
+
private:
int numArgs;
std::ostringstream cmdStream;
};
-
+
/// @param tx Transmit pin from mbed to ESP8266.
/// @param rx Receive pin from ESP8266 to mbed.
/// @param rst Reset pin on ESP8266.
/// @param CH_PD Power-down pin on ESP8266.
/// @param baud Baud rate that the ESP8266 is using.
/// @param debugMsgIntf Optional serial interface for debugging messages.
- ESP8266(const PinName tx, const PinName rx, const PinName rst, const PinName CH_PD, const int baud, mbed::Serial * debugMsgIntf = NULL);
-
+ ESP8266(const PinName tx, const PinName rx, const PinName rst,
+ const PinName CH_PD, const int baud,
+ mbed::Serial * debugMsgIntf = NULL);
+
/// Reset the ESP8266 via the hardware reset pin.
void reset();
-
+
// Update the baud rate for the ESP8266.
void setBaud(int baud) { AT_intf.baud(baud); }
-
+
/// @{
/// Control if the ESP8266 is powered via the hardware power-down pin.
bool powered() const;
void setPowered(bool powered);
/// @}
-
+
/// Perform a self-test on the ESP8266.
CmdResult performSelfTest();
-
+
/// Set the current Wi-Fi mode.
CmdResult setCurrentWifiMode(const WifiMode mode);
-
+
/// Join a Wi-Fi access point.
/// @param ssid Network SSID to connect to.
/// @param pwd Network password.
/// @param bssid Optional network BSSID.
- CmdResult joinCurrentAccessPoint(const std::string & ssid, const std::string & pwd, const std::string & bssid = "");
-
+ CmdResult joinCurrentAccessPoint(const std::string & ssid,
+ const std::string & pwd,
+ const std::string & bssid = "");
+
/// Quit the current access point.
CmdResult quitAccessPoint();
-
+
/// Set the maximum WiFi tranmission power.
/// @param power_dBm Power in dBm valid from 0 to 20.5 in 0.25 dBm increments.
CmdResult setMaxRFTXPower(const float power_dBm);
-
+
/// Ping a host via the current access point.
/// @param IP IP address or resolvable hostname.
CmdResult ping(const std::string & IP);
-
+
/// Open a connection to a host via the current access point.
/// @param type TCP or UPD connection.
/// @param remoteIP IP address or resolvable hostname to connect to.
/// @param remotePort Port on the host to connect to.
- CmdResult openConnection(const ConnType type, const std::string & remoteIP, const unsigned int remotePort);
-
+ CmdResult openConnection(const ConnType type, const std::string & remoteIP,
+ const unsigned int remotePort);
+
/// Close the connection to the current host.
CmdResult closeConnection();
-
+
/// Send data to the currently connected host.
/// @param data May be in text or binary form.
CmdResult sendData(const std::string & data);
-
+
/// Send an AT command to the ESP8266.
/// @param cmd Formatted command to send.
CmdResult sendCommand(const CmdBuilder & cmd);
-
+
/// Check if received IP data is available in the buffer.
/// @note Allow some processing delay to happen between calls to this function.
/// @returns True if data is available.
@@ -176,33 +164,37 @@
char getcRecvIpData();
/// Clear all received data from the buffer.
void clearRecvData();
-
-private:
+
+private:
mbed::Serial AT_intf;
mbed::DigitalOut resetPin;
- mutable mbed::DigitalOut powerDownPin; ///< @note Mark as mutable for use in powered().
- mbed::CircularBuffer<char, 1024> recvIpDataBuffer; ///< Received IP data buffer.
+ /// @note Mark as mutable for use in powered().
+ mutable mbed::DigitalOut powerDownPin;
+ /// Received IP data buffer.
+ mbed::CircularBuffer<char, 1024> recvIpDataBuffer;
mbed::Serial * debugMsg;
- volatile bool parseRecvReset; ///< Indicates when AT interface received data parsers should be reset.
-
+ /// Indicates when AT interface received data parsers should be reset.
+ volatile bool parseRecvReset;
+
/// Send raw AT data to the ESP8266.
/// @param cmdString Data to send.
/// @param expectEcho True if the ESP8266 will echo sent data back.
CmdResult send_AT_data(const std::string & cmdString, const bool expectEcho);
-
+
/// Attempts to read an entire line terminated with \r\n from the AT interface.
/// \r will be preserved in the final string and \n will be stripped.
/// @param line Buffer to store received characters in.
/// @returns True if an entire line was read.
bool read_line(std::string & line);
-
+
/// Callback for when data is received on the AT interface.
void recv_AT_data_cb();
/// Parse the next character received on the AT interface checking for valid IP data.
void parseRecvIpData(const char received);
- /// Parse the next character receive on the AT interface for the connection closed message.
+ /// Parse the next character receive on the AT interface for the connection
+ /// closed message.
void parseRecvConnClosedMsg(const char received);
-
+
/// Print a message on the debugging interface if setup.
/// @param message Null terminated string.
void printDbgMsg(const char * message);
--- a/Factory.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/Factory.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,127 +28,160 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
+#include <MaximInterface/Devices/DS2465.hpp>
+#include <MaximInterface/Devices/DS28E15_22_25.hpp>
+#include <MaximInterface/Utilities/Segment.hpp>
#include "Factory.hpp"
#include "SensorNode.hpp"
-#include "Masters/DS2465/DS2465.h"
-#include "Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h"
-#include "wait_api.h"
-using namespace OneWire;
+using namespace MaximInterface;
/// The valid master secret for the system.
-static const DS2465::Secret masterSecret = { { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x32 } };
+static const Sha256::Hash masterSecret = {
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x32};
/// An invalid master secret for example purposes.
-static const DS2465::Secret invalidMasterSecret = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
+static const Sha256::Hash invalidMasterSecret = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-bool provisionCoprocessor(DS2465 & ds2465)
-{
- bool result = (ds2465.setMasterSecret(masterSecret) == ISha256MacCoproc::Success);
- if (result)
- {
+bool provisionCoprocessor(DS2465 & ds2465) {
+ bool result = !ds2465.writeMasterSecret(masterSecret);
+ if (result) {
SensorNode::AuthData authData;
- DS28E15_22_25::Page pageData;
+ DS28E15::Page pageData;
pageData.fill(uint8_t(SensorNode::defaultPaddingByte));
- std::copy(authData.segment.begin(), authData.segment.end(), pageData.begin());
- result = (ds2465.writeScratchpad(pageData.data(), pageData.size()) == OneWireMaster::Success);
+ const std::pair<DS28E15::Page::iterator, DS28E15::Page::iterator>
+ pageSegment =
+ createSegment(pageData.begin(), pageData.end(),
+ authData.segment.size(), authData.segmentNum);
+ if (pageSegment.first != pageData.end()) {
+ std::copy(authData.segment.begin(), authData.segment.end(),
+ pageSegment.first);
+ }
+ result = !ds2465.writePage(0, pageData);
}
- if (result)
- {
- result = (ds2465.copyScratchpadToPage(0) == OneWireMaster::Success);
- if (result)
- wait_ms(DS2465::eepromPageWriteDelayMs);
- }
-
return result;
}
-bool provisionSensorNode(SensorNode & sensorNode, bool validSecret)
-{
+bool provisionSensorNode(SensorNode & sensorNode, bool validSecret) {
const int blockNum = sensorNode.authData.pageNum / 2;
- const DS28E15_22_25::BlockProtection desiredProtection(false, false, false, true, blockNum); // Authentication Protection only
-
+ const DS28E15::BlockProtection desiredProtection(
+ false, false, false, true, blockNum); // Authentication Protection only
+
// Reset to starting defaults
sensorNode.authData.reset();
-
+
// Read current protection status
- DS28E15_22_25::BlockProtection protectionStatus;
- bool result;
- // Read block protections
- result = (sensorNode.ds28e15.readBlockProtection(blockNum, protectionStatus) == OneWireSlave::Success);
+ DS28E15::BlockProtection protectionStatus;
+ bool result =
+ !sensorNode.ds28e15.readBlockProtection(blockNum, protectionStatus);
// Check if invalid protections are set
if (result)
- result = ((protectionStatus.statusByte() & ~(desiredProtection.statusByte())) == 0x00);
+ result = ((protectionStatus.statusByte() &
+ ~(desiredProtection.statusByte())) == 0x00);
// Load secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(validSecret ? masterSecret : invalidMasterSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(
+ validSecret ? masterSecret : invalidMasterSecret);
// Load master secret from scratchpad without locking
if (result)
- result = (sensorNode.ds28e15.loadSecret(false) == OneWireSlave::Success);
-
+ result = !sensorNode.ds28e15.loadSecret(false);
+
// Setup is complete if not using a valid secret
if (!validSecret)
return result;
-
+
// Create constant partial secret
- DS28E15_22_25::Scratchpad partialSecret;
- DS28E15_22_25::Page pageData;
+ DS28E15::Scratchpad partialSecret;
+ DS28E15::Page pageData;
partialSecret.fill(uint8_t(SensorNode::defaultPaddingByte));
-
+
// Read page data
if (result)
- result = (sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData);
// Load partial secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(partialSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(partialSecret);
// Compute secret
if (result)
- result = (sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false);
// Configure slave secret on DS2465
- if (result)
- result = (DS28E15_22_25::computeNextSecret(sensorNode.ds2465, pageData, sensorNode.authData.pageNum, partialSecret, sensorNode.ds28e15.romId(), sensorNode.ds28e15.manId()) == ISha256MacCoproc::Success);
+ if (result) {
+ const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
+ pageData, sensorNode.authData.pageNum, partialSecret,
+ sensorNode.romId(), sensorNode.manId);
+ result = !sensorNode.ds2465.computeSlaveSecret(data);
+ }
// Enable authentication protection if not set
- if (result && (protectionStatus != desiredProtection))
- result = (sensorNode.ds28e15.writeAuthBlockProtection(sensorNode.ds2465, desiredProtection, protectionStatus) == OneWireSlave::Success);
+ if (result && (protectionStatus != desiredProtection)) {
+ const Sha256::WriteMacData data = DS28E15::createProtectionWriteMacData(
+ desiredProtection, protectionStatus, sensorNode.romId(),
+ sensorNode.manId);
+ Sha256::Hash mac;
+ result = !sensorNode.ds2465.computeWriteMac(data, mac);
+ if (result)
+ result =
+ !sensorNode.ds28e15.writeAuthBlockProtection(desiredProtection, mac);
+ }
// Write initial filter life and set all other segments to default value
- if (result)
- {
- DS28E15_22_25::Segment blankSegment;
+ if (result) {
+ DS28E15::Segment blankSegment;
blankSegment.fill(uint8_t(SensorNode::defaultPaddingByte));
- for (size_t i = 0; i < DS28E15_22_25::segmentsPerPage; i++)
- {
- result = (sensorNode.ds28e15.writeAuthSegment(sensorNode.ds2465, sensorNode.authData.pageNum, i,
- ((i == sensorNode.authData.segmentNum) ? sensorNode.authData.segment : blankSegment),
- DS28E15_22_25::segmentFromPage(i, pageData), false) == OneWireSlave::Success);
-
+ for (int i = 0; i < DS28E15::segmentsPerPage; i++) {
+ const DS28E15::Segment newSegment = (i == sensorNode.authData.segmentNum)
+ ? sensorNode.authData.segment
+ : blankSegment;
+ const std::pair<DS28E15::Page::iterator, DS28E15::Page::iterator>
+ pageSegment = createSegment(pageData.begin(), pageData.end(),
+ DS28E15::Segment::size(), i);
+ DS28E15::Segment oldSegment;
+ std::copy(pageSegment.first, pageSegment.second, oldSegment.begin());
+ const Sha256::WriteMacData data = DS28E15::createSegmentWriteMacData(
+ sensorNode.authData.pageNum, i, newSegment, oldSegment,
+ sensorNode.romId(), sensorNode.manId);
+ Sha256::Hash mac;
+ result = !sensorNode.ds2465.computeWriteMac(data, mac);
+ if (!result)
+ break;
+ result = !sensorNode.ds28e15.writeAuthSegment(sensorNode.authData.pageNum,
+ i, newSegment, mac);
if (!result)
break;
}
}
-
+
// Reload secret with known page values
// Load master secret into scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(masterSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(masterSecret);
// Load master secret
if (result)
- result = (sensorNode.ds28e15.loadSecret(false) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.loadSecret(false);
// Read page data
if (result)
- result = (sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.readPage(sensorNode.authData.pageNum, pageData);
// Write partial secret to scratchpad
if (result)
- result = (sensorNode.ds28e15.writeScratchpad(partialSecret) == OneWireSlave::Success);
+ result = !sensorNode.ds28e15.writeScratchpad(partialSecret);
// Compute secret
if (result)
- result = (sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false) == OneWireSlave::Success);
+ result =
+ !sensorNode.ds28e15.computeSecret(sensorNode.authData.pageNum, false);
// Configure slave secret on DS2465
- if (result)
- result = (DS28E15_22_25::computeNextSecret(sensorNode.ds2465, pageData, sensorNode.authData.pageNum, partialSecret, sensorNode.ds28e15.romId(), sensorNode.ds28e15.manId()) == ISha256MacCoproc::Success);
+ if (result) {
+ const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
+ pageData, sensorNode.authData.pageNum, partialSecret,
+ sensorNode.romId(), sensorNode.manId);
+ result = !sensorNode.ds2465.computeSlaveSecret(data);
+ }
return result;
}
\ No newline at end of file
--- a/Factory.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/Factory.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,15 +28,14 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef FACTORY_HPP
#define FACTORY_HPP
#include <stdint.h>
-namespace OneWire { class DS2465; }
+namespace MaximInterface { class DS2465; }
class SensorNode;
/// Represents the secure factory that will perform the initial provisioning of
@@ -44,10 +43,11 @@
/// Provision the DS2465 on a Controller.
/// @returns True on success.
-bool provisionCoprocessor(OneWire::DS2465 & ds2465);
+bool provisionCoprocessor(MaximInterface::DS2465 & ds2465);
/// Provision the DS28E15 on a Sensor Node.
-/// @param validSecret True to provision using the valid system secret or false to imitate an invalid Controller.
+/// @param validSecret True to provision using the valid system secret or false
+/// to imitate an invalid Controller.
/// @returns True on success.
bool provisionSensorNode(SensorNode & sensorNode, bool validSecret);
--- a/HexConversions.cpp Tue Apr 04 14:10:48 2017 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
-* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-* OTHER DEALINGS IN THE SOFTWARE.
-*
-* Except as contained in this notice, the name of Maxim Integrated
-* Products, Inc. shall not be used except as stated in the Maxim Integrated
-* Products, Inc. Branding Policy.
-*
-* The mere transfer of this software does not imply any licenses
-* of trade secrets, proprietary technology, copyrights, patents,
-* trademarks, maskwork rights, or any other form of intellectual
-* property whatsoever. Maxim Integrated Products, Inc. retains all
-* ownership rights.
-*******************************************************************************
-*/
-
-#include <stdio.h>
-#include "HexConversions.hpp"
-
-const size_t charsPerByte = 2;
-
-std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize)
-{
- std::string hexString;
- hexString.reserve(byteArraySize * charsPerByte);
- byteArrayToHexString(byteArray, byteArraySize, hexString);
- return hexString;
-}
-
-void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString)
-{
- char hexBuf[charsPerByte + 1];
- for (size_t i = 0; i < byteArraySize; i++)
- {
- snprintf(hexBuf, (sizeof(hexBuf) / sizeof(hexBuf[0])), "%2.2X", byteArray[i]);
- hexString.append(hexBuf, charsPerByte);
- }
-}
\ No newline at end of file
--- a/HexConversions.hpp Tue Apr 04 14:10:48 2017 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -******************************************************************************* -*/ - -#ifndef HEXCONVERSIONS_HPP -#define HEXCONVERSIONS_HPP - -#include <string> -#include <stdint.h> -#include <stddef.h> - -/// Characters per byte for hex data. -extern const size_t charsPerByte; - -/// Creates a new hex string from a byte array. -std::string byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize); - -/// Appends a hex string created from a byte array to an existing string. -void byteArrayToHexString(const uint8_t * byteArray, size_t byteArraySize, std::string & hexString); - -#endif \ No newline at end of file
--- a/MAX44009.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/MAX44009.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,58 +28,52 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
+#include <I2C.h>
#include "MAX44009.hpp"
-#include "I2C.h"
static const int I2C_OK = 0;
MAX44009::MAX44009(mbed::I2C & I2C_interface, uint8_t I2C_address)
- : m_I2C_interface(I2C_interface), m_I2C_address(I2C_address)
-{
-
-}
+ : m_I2C_interface(I2C_interface), m_I2C_address(I2C_address) {}
-MAX44009::Result MAX44009::read_current_lux(double & lux) const
-{
+MAX44009::Result MAX44009::read_current_lux(double & lux) const {
uint8_t I2C_data, mantissa, exponent;
-
+
I2C_data = Lux_High_Byte_Reg;
- if (m_I2C_interface.write(m_I2C_address, reinterpret_cast<char *>(&I2C_data), 1, true) != I2C_OK)
- {
+ if (m_I2C_interface.write(m_I2C_address, reinterpret_cast<char *>(&I2C_data),
+ 1, true) != I2C_OK) {
m_I2C_interface.stop();
return Hardware_Failure;
}
- if (m_I2C_interface.read(m_I2C_address, reinterpret_cast<char *>(&I2C_data), 1, true) != I2C_OK)
- {
+ if (m_I2C_interface.read(m_I2C_address, reinterpret_cast<char *>(&I2C_data),
+ 1, true) != I2C_OK) {
m_I2C_interface.stop();
return Hardware_Failure;
}
mantissa = (I2C_data << 4);
exponent = (I2C_data >> 4);
-
+
I2C_data = Lux_Low_Byte_Reg;
- if (m_I2C_interface.write(m_I2C_address, reinterpret_cast<char *>(&I2C_data), 1, true) != I2C_OK)
- {
+ if (m_I2C_interface.write(m_I2C_address, reinterpret_cast<char *>(&I2C_data),
+ 1, true) != I2C_OK) {
m_I2C_interface.stop();
return Hardware_Failure;
}
- if (m_I2C_interface.read(m_I2C_address, reinterpret_cast<char *>(&I2C_data), 1, false) != I2C_OK)
- {
+ if (m_I2C_interface.read(m_I2C_address, reinterpret_cast<char *>(&I2C_data),
+ 1, false) != I2C_OK) {
m_I2C_interface.stop();
return Hardware_Failure;
}
mantissa |= (I2C_data & 0x0F);
-
+
unsigned long calc_result = 1;
- if (exponent > 0)
- {
+ if (exponent > 0) {
calc_result <<= exponent;
}
calc_result *= mantissa;
lux = calc_result * 0.045;
-
+
return Success;
}
\ No newline at end of file
--- a/MAX44009.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/MAX44009.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,8 +28,7 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef MAX44009_HPP
#define MAX44009_HPP
@@ -39,31 +38,22 @@
namespace mbed { class I2C; }
/// Interface to the MAX44009 optical light sensor.
-class MAX44009
-{
+class MAX44009 {
public:
- enum Result
- {
- Success,
- Hardware_Failure
- };
-
+ enum Result { Success, Hardware_Failure };
+
/// @param I2C_interface A configured I2C interface to use for communication.
/// @param I2C_address Device bus address in mbed format.
MAX44009(mbed::I2C & I2C_interface, uint8_t I2C_address);
-
+
/// Read the current lux from the MAX44009.
/// @returns Success or Hardware_Failure.
Result read_current_lux(double & lux) const;
-
+
private:
/// MAX44009 Register addresses.
- enum Register
- {
- Lux_High_Byte_Reg = 0x03,
- Lux_Low_Byte_Reg = 0x04
- };
-
+ enum Register { Lux_High_Byte_Reg = 0x03, Lux_Low_Byte_Reg = 0x04 };
+
mbed::I2C & m_I2C_interface;
uint8_t m_I2C_address;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterface.lib Mon Nov 06 17:34:13 2017 -0600 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/Maxim-Integrated/code/MaximInterface/#d6de0a14c777
--- a/OneWire.lib Tue Apr 04 14:10:48 2017 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://developer.mbed.org/teams/Maxim-Integrated/code/OneWire/#f0e0a7976846
--- a/SensorData.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/SensorData.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,8 +28,7 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef SENSORDATA_HPP
#define SENSORDATA_HPP
@@ -37,14 +36,13 @@
#include <stdint.h>
/// Contains a set of sensor measurements.
-struct SensorData
-{
+struct SensorData {
static const int8_t tempAlarmLevel = 26;
static const uint8_t filterLifeAlarmLevel = 20;
-
+
int8_t temp;
uint8_t filterLife;
-
+
bool tempAlarm() const { return (temp >= tempAlarmLevel); }
bool filterLifeAlarm() const { return (filterLife <= filterLifeAlarmLevel); }
};
--- a/SensorNode.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/SensorNode.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,222 +28,217 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
+#include <I2C.h>
+#include <MaximInterface/Devices/DS2465.hpp>
+#include <MaximInterface/Links/RomCommands.hpp>
+#include <MaximInterface/Platforms/mbed/Sleep.hpp>
#include "SensorNode.hpp"
#include "SensorData.hpp"
-#include "Masters/DS2465/DS2465.h"
-#include "RomId/RomCommands.h"
-#include "I2C.h"
#ifdef TARGET_MAX32600
-#include "max32600.h"
-#include "clkman_regs.h"
-#include "tpu_regs.h"
+#include <max32600.h>
+#include <clkman_regs.h>
+#include <tpu_regs.h>
#else
#include <cstdlib>
#endif
-using namespace OneWire;
-using namespace OneWire::RomCommands;
+using namespace MaximInterface;
+const ManId SensorNode::manId = {0, 0};
bool SensorNode::rngInitialized = false;
-void SensorNode::initializeRng()
-{
+void SensorNode::initializeRng() {
#ifdef TARGET_MAX32600
- MXC_CLKMAN->clk_config |= (MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_ENABLE | MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_RESET_N); // Enable crypto oscillator
- while ((MXC_CLKMAN->intfl & MXC_F_CLKMAN_INTFL_CRYPTO_STABLE) != MXC_F_CLKMAN_INTFL_CRYPTO_STABLE) ; // Wait for crypto oscillator stability
- MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_CRYPTO_GATE_N; // Disable crypto clock gating
- MXC_CLKMAN->crypt_clk_ctrl_2_prng = MXC_CLKMAN->clk_ctrl_10_prng = 1; // Set PRNG clock to crypto clock
- MXC_CLKMAN->clk_gate_ctrl2 |= (1 << MXC_F_CLKMAN_CLK_GATE_CTRL2_TPU_CLK_GATER_POS); // Use dynamic clock gating
+ // Enable crypto oscillator
+ MXC_CLKMAN->clk_config |= (MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_ENABLE |
+ MXC_F_CLKMAN_CLK_CONFIG_CRYPTO_RESET_N);
+ // Wait for crypto oscillator stability
+ while ((MXC_CLKMAN->intfl & MXC_F_CLKMAN_INTFL_CRYPTO_STABLE) !=
+ MXC_F_CLKMAN_INTFL_CRYPTO_STABLE);
+ // Disable crypto clock gating
+ MXC_CLKMAN->clk_ctrl |= MXC_F_CLKMAN_CLK_CTRL_CRYPTO_GATE_N;
+ // Set PRNG clock to crypto clock
+ MXC_CLKMAN->crypt_clk_ctrl_2_prng = MXC_CLKMAN->clk_ctrl_10_prng = 1;
+ // Use dynamic clock gating
+ MXC_CLKMAN->clk_gate_ctrl2 |=
+ (1 << MXC_F_CLKMAN_CLK_GATE_CTRL2_TPU_CLK_GATER_POS);
#endif
}
-SensorNode::SensorNode(mbed::I2C & i2c, uint8_t ds7505_i2c_addr, uint8_t max44009_i2c_addr, DS2465 & ds2465)
- : m_initialLux(1), ds2465(ds2465), selector(ds2465), ds28e15(selector), ds7505(i2c, ds7505_i2c_addr), max44009(i2c, max44009_i2c_addr)
-{
- if (!rngInitialized)
- {
+SensorNode::SensorNode(::mbed::I2C & i2c, uint8_t ds7505_i2c_addr,
+ uint8_t max44009_i2c_addr, DS2465 & ds2465)
+ : initialLux_(1), ds2465(ds2465),
+ ds28e15(MaximInterface::mbed::Sleep::instance(), ds2465, &skipRom),
+ ds7505(i2c, ds7505_i2c_addr), max44009(i2c, max44009_i2c_addr) {
+ if (!rngInitialized) {
initializeRng();
rngInitialized = true;
}
}
-bool SensorNode::initializeSensors()
-{
- return (max44009.read_current_lux(m_initialLux) == MAX44009::Success);
+bool SensorNode::initializeSensors() {
+ return (max44009.read_current_lux(initialLux_) == MAX44009::Success);
}
-bool SensorNode::setSecret()
-{
- DS28E15_22_25::Scratchpad scratchpad;
- DS28E15_22_25::Page pageData;
-
+bool SensorNode::setSecret() {
// Create constant partial secret
+ DS28E15::Scratchpad scratchpad;
scratchpad.fill(uint8_t(defaultPaddingByte));
- // Read page data
- bool result = (ds2465.readMemory(DS2465::UserMemoryPage0, pageData.data(), pageData.size(), false) == OneWireMaster::Success);
// Calculate secret
- if (result)
- {
- result = (DS28E15_22_25::computeNextSecret(ds2465, pageData, authData.pageNum, scratchpad, ds28e15.romId(), ds28e15.manId()) == ISha256MacCoproc::Success);
- }
- return result;
+ const Sha256::SlaveSecretData data = DS28E15::createSlaveSecretData(
+ DS28E15::Page(), authData.pageNum, scratchpad, romId_, manId);
+ return !ds2465.computeSlaveSecretWithSwap(data, 0, DS2465::FullPage);
}
-bool SensorNode::checkProvisioned(bool & provisioned)
-{
- DS28E15_22_25::BlockProtection protectionStatus;
+bool SensorNode::checkProvisioned(bool & provisioned) {
+ DS28E15::BlockProtection protectionStatus;
bool result;
-
-
- result = (ds28e15.readBlockProtection(0, protectionStatus) == OneWireSlave::Success);
- if (result)
- {
- if (!protectionStatus.noProtection())
- {
- result = (ds28e15.readSegment(authData.pageNum, authData.segmentNum, authData.segment) == OneWireSlave::Success);
+
+ result = !ds28e15.readBlockProtection(0, protectionStatus);
+ if (result) {
+ if (!protectionStatus.noProtection()) {
+ result = !ds28e15.readSegment(authData.pageNum, authData.segmentNum,
+ authData.segment);
if (result)
provisioned = true;
- }
- else
- {
+ } else {
provisioned = false;
}
}
return result;
}
-bool SensorNode::checkAuthentic(unsigned int userEntropy)
-{
- DS28E15_22_25::Scratchpad challenge;
- DS28E15_22_25::Page pageData;
-
+bool SensorNode::checkAuthentic(unsigned int userEntropy) {
+ DS28E15::Scratchpad challenge;
+ DS28E15::Page pageData;
+
// Read page data
- if (ds28e15.readPage(authData.pageNum, pageData, false) != OneWireSlave::Success)
+ if (ds28e15.readPage(authData.pageNum, pageData))
return false;
-
+
// Create random challenge
// Use hardare RNG on MAX32600
-#ifdef TARGET_MAX32600
+#ifdef TARGET_MAX32600
MXC_TPU->prng_user_entropy = userEntropy;
#else
std::srand(userEntropy);
#endif
- for (size_t i = 0; i < challenge.size(); i++)
- {
+ for (size_t i = 0; i < challenge.size(); i++) {
#ifdef TARGET_MAX32600
challenge[i] = MXC_TPU->prng_rnd_num;
#else
- challenge[i] = std::rand();
+ challenge[i] = std::rand();
#endif
}
// Write challenge to scratchpad
- if (ds28e15.writeScratchpad(challenge) != OneWireSlave::Success)
+ if (ds28e15.writeScratchpad(challenge))
return false;
// Have device compute MAC
- DS28E15_22_25::Mac nodeMac;
- if (ds28e15.computeReadPageMac(0, false, nodeMac) != OneWireSlave::Success)
+ Sha256::Hash nodeMac;
+ if (ds28e15.computeReadPageMac(0, false, nodeMac))
return false;
// Compute expected MAC
- DS28E15_22_25::Mac controllerMac;
- if (DS28E15_22_25::computeAuthMac(ds2465, pageData, authData.pageNum, challenge, ds28e15.romId(), ds28e15.manId(), controllerMac) != ISha256MacCoproc::Success)
+ const Sha256::AuthMacData controllerMacData = DS28E15::createAuthMacData(
+ pageData, authData.pageNum, challenge, romId_, manId);
+ Sha256::Hash controllerMac;
+ if (ds2465.computeAuthMac(controllerMacData, controllerMac))
return false;
// Check if authentic
return (nodeMac == controllerMac);
}
-bool SensorNode::readSensorData(SensorData & sensorData)
-{
+bool SensorNode::readSensorData(SensorData & sensorData) {
bool result;
int8_t temp;
-
+
// Read temperature sensor
result = (ds7505.read_current_temp(temp) == DS7505::Success);
-
- if (result)
- {
+
+ if (result) {
sensorData.temp = temp;
-
+
// Read light sensor
double currentLux;
result = (max44009.read_current_lux(currentLux) == MAX44009::Success);
- if (result)
- {
+ if (result) {
// Convert lux to remaining filter life
- sensorData.filterLife = (unsigned int)((currentLux / m_initialLux) * 100);
+ sensorData.filterLife =
+ static_cast<uint8_t>((currentLux / initialLux_) * 100);
}
}
-
+
return result;
}
-bool SensorNode::checkAndWriteAuthData(SensorData & sensorData)
-{
+bool SensorNode::checkAndWriteAuthData(SensorData & sensorData) {
bool result = true;
-
- if (sensorData.filterLife > authData.filterLife)
- {
- sensorData.filterLife = authData.filterLife;
+
+ if (sensorData.filterLife > authData.filterLife()) {
+ sensorData.filterLife = authData.filterLife();
+ } else if (sensorData.filterLife < authData.filterLife()) {
+ AuthData newAuthData = authData;
+ newAuthData.filterLife() = sensorData.filterLife;
+ const Sha256::WriteMacData macData = DS28E15::createSegmentWriteMacData(
+ authData.pageNum, authData.segmentNum, newAuthData.segment,
+ authData.segment, romId_, manId);
+ Sha256::Hash mac;
+ result = !ds2465.computeWriteMac(macData, mac);
+ if (result)
+ result = !ds28e15.writeAuthSegment(authData.pageNum, authData.segmentNum,
+ newAuthData.segment, mac);
+ if (result)
+ authData = newAuthData;
}
- else if (sensorData.filterLife < authData.filterLife)
- {
- AuthData oldAuthData(authData);
- authData.filterLife = sensorData.filterLife;
- // Write new filter life to DS28E15
- result = (ds28e15.writeAuthSegment(ds2465, authData.pageNum, authData.segmentNum, authData.segment, oldAuthData.segment, false) == OneWireSlave::Success);
- }
-
+
return result;
}
-SensorNode::State SensorNode::detect(unsigned int userEntropy)
-{
+SensorNode::State SensorNode::detect(unsigned int userEntropy) {
bool provisioned;
-
- ds2465.OWSetSpeed(DS2465::OverdriveSpeed);
-
- RomId romId;
- if (OWReadRom(ds2465, romId) != OneWireMaster::Success)
+
+ ds2465.setSpeed(DS2465::OverdriveSpeed);
+
+ if (readRom(ds2465, romId_))
return UnableToCommunicate;
- ds28e15.setRomId(romId);
-
+
if (!checkProvisioned(provisioned))
return UnableToCommunicate;
-
+
if (!provisioned)
- return NotProvisioned;
-
+ return NotProvisioned;
+
if (!setSecret())
return UnableToCommunicate;
-
+
if (!checkAuthentic(userEntropy))
return NotAuthentic;
-
+
if (!initializeSensors())
return UnableToCommunicate;
-
+
return Authentic;
}
-SensorNode::State SensorNode::authenticatedReadSensorData(unsigned int userEntropy, SensorData & sensorData)
-{
- ds2465.OWSetSpeed(DS2465::OverdriveSpeed);
-
+SensorNode::State
+SensorNode::authenticatedReadSensorData(unsigned int userEntropy,
+ SensorData & sensorData) {
+ ds2465.setSpeed(DS2465::OverdriveSpeed);
+
if (!setSecret())
return UnableToCommunicate;
-
+
if (!checkAuthentic(userEntropy))
return NotAuthentic;
-
+
if (!readSensorData(sensorData))
return UnableToCommunicate;
-
+
if (!checkAndWriteAuthData(sensorData))
return NotAuthentic;
-
+
return Authentic;
}
\ No newline at end of file
--- a/SensorNode.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/SensorNode.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,129 +28,126 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef SENSORNODE_HPP
#define SENSORNODE_HPP
#include <stdint.h>
-#include <cstring>
-
+#include <MaximInterface/Devices/DS28E15_22_25.hpp>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include <MaximInterface/Utilities/ManId.hpp>
#include "DS7505.hpp"
#include "MAX44009.hpp"
-#include "Slaves/Authenticators/DS28E15_22_25/DS28E15.h"
class SensorData;
-namespace OneWire
-{
- class RomId;
- class DS2465;
-}
+namespace MaximInterface { class DS2465; }
namespace mbed { class I2C; }
/// Interface to the Authenticated Sensor Node peripheral board.
-class SensorNode
-{
+class SensorNode {
public:
- enum State
- {
+ enum State {
UnableToCommunicate, ///< I2C or 1-Wire communication failure.
- NotProvisioned, ///< DS28E15 has not been provisioned.
- NotAuthentic, ///< DS28E15 is not authentic.
- Authentic ///< DS218E15 is authentic.
+ NotProvisioned, ///< DS28E15 has not been provisioned.
+ NotAuthentic, ///< DS28E15 is not authentic.
+ Authentic ///< DS218E15 is authentic.
};
-
+
/// @param i2c Configured I2C communication interface.
/// @param ds7505_i2c_addr I2C bus address of the DS7505 in mbed format.
/// @param max44009_i2c_addr I2C bus address of the MAX44009 in mbed format.
/// @param ds2465 Interface to DS2465 on the Controller.
- SensorNode(mbed::I2C & i2c, uint8_t ds7505_i2c_addr, uint8_t max44009_i2c_addr, OneWire::DS2465 & ds2465);
-
+ SensorNode(mbed::I2C & i2c, uint8_t ds7505_i2c_addr,
+ uint8_t max44009_i2c_addr, MaximInterface::DS2465 & ds2465);
+
/// Detect if an authentic Sensor Node is connected.
/// @param userEntropy Additional entropy to supply to the RNG.
/// @returns Authentic on success.
State detect(unsigned int userEntropy);
-
+
/// Read the current temperature and filter life measurements with authentication.
/// @param userEntropy Additional entropy to supply to the RNG.
/// @param sensorData Measurements output location.
/// @returns Authentic on success.
- State authenticatedReadSensorData(unsigned int userEntropy, SensorData & sensorData);
-
+ State authenticatedReadSensorData(unsigned int userEntropy,
+ SensorData & sensorData);
+
/// Reads the current temperature and filter life measurements.
/// @param sensorData Measurements output location.
/// @returns True on success or false if unable to communicate with a sensor.
bool readSensorData(SensorData & sensorData);
-
+
/// Get the ROM ID for this sensor node.
- const OneWire::RomId romId() const { return ds28e15.romId(); }
-
+ const MaximInterface::RomId romId() const { return romId_; }
+
/// Get the initial lux measurement for this sensor node.
- double initialLux() const { return m_initialLux; }
-
+ double initialLux() const { return initialLux_; }
+
// Grant access to hardware interfaces for provisioning.
- friend bool provisionCoprocessor(OneWire::DS2465 & ds2465);
+ friend bool provisionCoprocessor(MaximInterface::DS2465 & ds2465);
friend bool provisionSensorNode(SensorNode & sensorNode, bool validSecret);
-
+
private:
/// Authenticated data stored in DS28E15.
- struct AuthData
- {
+ struct AuthData {
static const uint8_t initialFilterLife = 100;
- OneWire::DS28E15_22_25::Segment segment;
- uint8_t & filterLife;
- unsigned int pageNum, segmentNum;
-
- AuthData() : filterLife(segment[0]), pageNum(0), segmentNum(0) { reset(); }
-
- void reset()
- {
+ MaximInterface::DS28E15::Segment segment;
+ int pageNum, segmentNum;
+
+ uint8_t & filterLife() { return segment[0]; }
+ const uint8_t & filterLife() const { return segment[0]; }
+
+ AuthData() : pageNum(0), segmentNum(0) { reset(); }
+
+ void reset() {
segment.fill(0);
- filterLife = initialFilterLife;
+ filterLife() = initialFilterLife;
}
};
-
+
/// Padding value used in creation of the Slave Secret.
static const uint8_t defaultPaddingByte = 0x00;
-
+
+ static const MaximInterface::ManId manId;
+
/// Indicates hardware RNG is initialized.
static bool rngInitialized;
// Initialize the hardware RNG.
static void initializeRng();
-
+
/// Initial lux measurement taken on initialization.
/// Assumed to be the maximum intensity that will be observed.
- double m_initialLux;
-
+ double initialLux_;
+
/// Authenticated data stored on the DS28E15.
AuthData authData;
-
+
// Hardware interfaces
- OneWire::DS2465 & ds2465; ///< Interface to DS2465 on Controller.
- OneWire::SingledropRomIterator selector;
- OneWire::DS28E15 ds28e15; ///< DS28E15 for authentication.
- DS7505 ds7505; ///< DS7505 temperature sensor.
+ MaximInterface::DS2465 & ds2465; ///< Interface to DS2465 on Controller.
+ MaximInterface::DS28E15 ds28e15; ///< DS28E15 for authentication.
+ MaximInterface::RomId romId_;
+ DS7505 ds7505; ///< DS7505 temperature sensor.
MAX44009 max44009; ///< MAX44009 optical light sensor.
-
+
/// Initialize sensors for measurement.
/// @returns True on success.
bool initializeSensors();
-
+
/// Select the Slave Secret for this Sensor Node in the Controller.
/// @returns True on success.
bool setSecret();
-
+
/// Check if the Sensor Board is provisioned.
/// @param provisioned True if the sensor board is provisioned.
/// @returns True if provisioning check was successful.
bool checkProvisioned(bool & provisioned);
-
+
/// Check if the Sensor Board is authentic.
/// @param userEntropy Additional entropy to supply to the RNG.
/// @returns True if the Sensor Board passed the authentication check.
bool checkAuthentic(unsigned int userEntropy);
-
+
/// Checks if the authenticated data stored in the DS28E15 needs to be updated.
/// Updates the authenticated data if necessary.
/// @param sensorData Current sensor data to check.
--- a/WebServerInterface.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/WebServerInterface.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,26 +28,26 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#include <vector>
+#include <Serial.h>
+#include <wait_api.h>
+#include <MaximInterface/Devices/DS2465.hpp>
+#include <MaximInterface/Utilities/HexConversions.hpp>
#include "WebServerInterface.hpp"
#include "ESP8266.hpp"
-#include "Slaves/Authenticators/ISha256MacCoproc.h"
#include "SensorData.hpp"
-#include "HexConversions.hpp"
-#include "Serial.h"
-#include "wait_api.h"
-using OneWire::ISha256MacCoproc;
+using namespace MaximInterface;
const char WebServerInterface::wifiSsid[] = "WifiSsid";
const char WebServerInterface::wifiPassword[] = "WifiPassword";
const char WebServerInterface::serverAddress[] = "www.maxim-security.com";
const unsigned int WebServerInterface::serverPort = 80;
const char WebServerInterface::serverPostPath[] = "/maxrefdes143/post.php";
-const char WebServerInterface::serverChallengePath[] = "/maxrefdes143/challenge.php";
+const char WebServerInterface::serverChallengePath[] =
+ "/maxrefdes143/challenge.php";
// HTTP formatting constants
static const char keyValSeparator = '=';
@@ -61,32 +61,27 @@
/// Select the Transport Secret for the web server in the Controller.
/// @returns True on success.
-static bool setHttpPostSecret(ISha256MacCoproc & MacCoproc, const OneWire::RomId & sessionId)
-{
- ISha256MacCoproc::DevicePage fillData;
- fillData.fill(defaultPaddingByte);
- ISha256MacCoproc::SlaveSecretData secretData;
- secretData.fill(defaultPaddingByte);
- std::copy(sessionId.buffer.begin(), sessionId.buffer.end(), secretData.begin());
- return (MacCoproc.computeSlaveSecret(fillData, fillData, secretData) == ISha256MacCoproc::Success);
+static bool setHttpPostSecret(DS2465 & macCoproc, const RomId & sessionId) {
+ Sha256::SlaveSecretData data;
+ data.fill(defaultPaddingByte);
+ std::copy(sessionId.begin(), sessionId.end(), data.begin() + 64);
+ return !macCoproc.computeSlaveSecret(data);
}
-bool WebServerInterface::initialize()
-{
+bool WebServerInterface::initialize() {
esp8266.setPowered(true);
esp8266.reset();
bool result = (esp8266.performSelfTest() == ESP8266::AT_OK);
- if (result)
- {
- result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK);
+ if (result) {
+ result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) ==
+ ESP8266::AT_OK);
}
- if (result)
- {
+ if (result) {
result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK);
}
- if (result)
- {
- result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK);
+ if (result) {
+ result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) ==
+ ESP8266::AT_OK);
}
return result;
}
@@ -96,8 +91,9 @@
/// @param path Web server location to retrieve.
/// @param sessionId Session ID used to identify this controller.
/// @returns GET request string.
-static std::string formatHttpGet(const std::string & host, const std::string & path, const std::string & sessionId)
-{
+static std::string formatHttpGet(const std::string & host,
+ const std::string & path,
+ const std::string & sessionId) {
std::ostringstream httpGetStream;
httpGetStream << "GET " << path;
if (sessionId.length() > 0)
@@ -109,32 +105,35 @@
}
/// Computes a MAC using the Transport Secret to sign HTTP POST requests.
-/// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC.
+/// @param macCoproc
+/// Coprocessor such as the DS2465 used to calculate the authentication MAC.
/// @param input Message array used for MAC calculation.
/// @param ilen Length of array input.
/// @param output Calculated MAC output.
-static void calculateHttpPostMac(const ISha256MacCoproc & macCoproc, const uint8_t * input, size_t ilen, ISha256MacCoproc::Mac & output)
-{
- ISha256MacCoproc::DeviceScratchpad block;
- size_t index = 0;
- ISha256MacCoproc::AuthMacData padding;
- padding.fill(defaultPaddingByte);
+static void calculateHttpPostMac(const DS2465 & macCoproc,
+ const uint8_t * input, size_t ilen,
+ Sha256::Hash & output) {
+ const size_t blockSize = 32;
output.fill(defaultPaddingByte); // Set initial hash value
- while (index < ilen)
- {
- if ((index + block.size()) <= ilen) // Full block
+ Sha256::AuthMacData macData;
+ macData.fill(defaultPaddingByte);
+ while (ilen > 0) {
+ Sha256::AuthMacData::iterator macDataBegin =
+ std::copy(output.begin(), output.end(), macData.begin());
+ if (ilen >= blockSize) // Full block
{
- std::memcpy(block.data(), &input[index], block.size());
- index += block.size();
- }
- else // Partial block with padding
+ std::copy(input, input + blockSize, macDataBegin);
+ input += blockSize;
+ ilen -= blockSize;
+ } else // Partial block with padding
{
- std::memcpy(block.data(), &input[index], ilen - index);
- std::memset(&block[ilen - index], defaultPaddingByte, block.size() - (ilen - index));
- index = ilen;
+ macDataBegin = std::copy(input, input + ilen, macDataBegin);
+ std::fill(macDataBegin, macDataBegin + (blockSize - ilen),
+ defaultPaddingByte);
+ ilen = 0;
}
// Write data to coprocessor and hash block
- macCoproc.computeAuthMac(output, block, padding, output);
+ macCoproc.computeAuthMac(macData, output);
}
}
@@ -142,68 +141,70 @@
/// @param host Web server address.
/// @param path Web server location to receive POST.
/// @param sessionId Session ID used to identify this Controller.
-/// @param macCoproc Coprocessor such as the DS2465 used to calculate the authentication MAC.
+/// @param macCoproc
+/// Coprocessor such as the DS2465 used to calculate the authentication MAC.
/// @param event Event message type.
/// @param initialPostBody Message body as determined by the event message type.
-/// @param challenge Challenge previously received from web server for use in authentication MAC.
+/// @param challenge
+/// Challenge previously received from web server for use in authentication MAC.
/// @returns POST request string.
-static std::string formatHttpPost(const std::string & host, const std::string & path, const std::string & sessionId,
- const ISha256MacCoproc & macCoproc, PostEvent event, const std::string & initialPostBody,
- const uint8_t (&challenge)[challengeLen])
-{
+static std::string formatHttpPost(const std::string & host,
+ const std::string & path,
+ const std::string & sessionId,
+ const DS2465 & macCoproc, PostEvent event,
+ const std::string & initialPostBody,
+ const uint8_t (&challenge)[challengeLen]) {
const size_t headerReserve = 115, bodyReserve = 200;
-
+
std::string httpPost;
httpPost.reserve(initialPostBody.length() + headerReserve + bodyReserve);
-
+
// Add session ID to post body
- if (sessionId.length() > 0)
- {
+ if (sessionId.length() > 0) {
httpPost += sessionIdKey;
httpPost += keyValSeparator;
httpPost += sessionId;
}
-
+
// Add event to post body
std::string eventString;
- switch (event)
- {
+ switch (event) {
case SensorDataEvent:
eventString = "SensorData";
break;
-
+
case InvalidSensorEvent:
eventString = "InvalidSensor";
break;
}
- if (eventString.length() > 0)
- {
+ if (eventString.length() > 0) {
if (httpPost.length() > 0)
httpPost += fieldSeparator;
httpPost += "Event";
httpPost += keyValSeparator;
httpPost += eventString;
}
-
+
// Add initial post body
- if (initialPostBody.length() > 0)
- {
+ if (initialPostBody.length() > 0) {
if (httpPost.length() > 0)
httpPost += fieldSeparator;
httpPost += initialPostBody;
}
-
+
// Combine initial post body with initial secret and hash
std::vector<uint8_t> hashInput;
hashInput.reserve(challengeLen + httpPost.length());
hashInput.assign(challenge, challenge + challengeLen);
hashInput.insert(hashInput.end(), httpPost.begin(), httpPost.end());
- ISha256MacCoproc::Mac mac;
+ Sha256::Hash mac;
calculateHttpPostMac(macCoproc, &hashInput[0], hashInput.size(), mac);
-
+
char contentLen[5];
- snprintf(contentLen, sizeof(contentLen) / sizeof(contentLen[0]), "%u", (hashInput.size() - challengeLen) + (mac.size() * charsPerByte) + 5 /* &MAC= */);
-
+ snprintf(contentLen, sizeof(contentLen) / sizeof(contentLen[0]), "%u",
+ (hashInput.size() - challengeLen) + (mac.size() * 2) +
+ 5 /* &MAC= */);
+
// Construct full post request
httpPost = "";
httpPost += "POST ";
@@ -222,56 +223,54 @@
httpPost += newline;
httpPost += newline;
// Add post body
- httpPost.append(reinterpret_cast<char *>(&hashInput[challengeLen]), hashInput.size() - challengeLen);
+ httpPost.append(reinterpret_cast<char *>(&hashInput[challengeLen]),
+ hashInput.size() - challengeLen);
// Convert hash to hex string and add to post body
httpPost += fieldSeparator;
httpPost += "MAC";
httpPost += keyValSeparator;
- byteArrayToHexString(mac.data(), mac.size(), httpPost);
+ httpPost += byteArrayToHexString(mac.data(), mac.size());
httpPost += newline;
-
+
return httpPost;
}
-bool WebServerInterface::authPostHttpEvent(ISha256MacCoproc & macCoproc, PostEvent event, const std::string & postData, bool setSecret)
-{
+bool WebServerInterface::authPostHttpEvent(DS2465 & macCoproc, PostEvent event,
+ const std::string & postData,
+ bool setSecret) {
const std::string challengeSearch(newline + newline);
bool result;
uint8_t challenge[challengeLen];
std::string response;
-
+
std::memset(challenge, defaultPaddingByte, challengeLen);
response.reserve(300);
-
- if (setSecret)
- {
+
+ if (setSecret) {
result = setHttpPostSecret(macCoproc, m_sessionId);
if (!result)
return result;
}
-
+
// Open connection
esp8266.clearRecvData(); // Clear received data buffer
- result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) == ESP8266::AT_OK);
- if (result)
- {
+ result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) ==
+ ESP8266::AT_OK);
+ if (result) {
// Request challenge
- result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString)) == ESP8266::AT_OK);
- if (result)
- {
+ result =
+ (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath,
+ m_sessionIdString)) == ESP8266::AT_OK);
+ if (result) {
// Receive server response
- for (int i = 0; i < 10; i++)
- {
- while (esp8266.recvIpDataReadable())
- {
+ for (int i = 0; i < 10; i++) {
+ while (esp8266.recvIpDataReadable()) {
char read = esp8266.getcRecvIpData();
- if (response.length() < response.capacity())
- {
+ if (response.length() < response.capacity()) {
response += read;
- }
- else
- {
- wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
+ } else {
+ // Wait for ESP8266 specified recovery time
+ wait_ms(ESP8266::sendDataRecoveryTimeMs);
goto close_get_connection;
}
}
@@ -280,50 +279,59 @@
// Close connection
close_get_connection:
esp8266.closeConnection();
-
+
// Parse challenge from response
size_t challengePos = response.find(challengeSearch);
- if ((challengePos != std::string::npos) && ((challengePos + challengeSearch.length() + (challengeLen * charsPerByte)) <= response.length()))
- {
+ const size_t challengeStringLen = challengeLen * 2;
+ if ((challengePos != std::string::npos) &&
+ ((challengePos + challengeSearch.length() + challengeStringLen) <=
+ response.length())) {
challengePos += challengeSearch.length();
- for (size_t i = 0; i < challengeLen; i++)
- {
- std::sscanf(response.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]);
- }
+ const std::vector<uint_least8_t> parsedChallenge = hexStringToByteArray(
+ response.substr(challengePos, challengeStringLen));
+ std::copy(parsedChallenge.begin(), parsedChallenge.end(), challenge);
}
-
+
// Post sensor data
- result = (esp8266.openConnection(ESP8266::TCP, serverAddress, serverPort) == ESP8266::AT_OK);
- if (result)
- {
- result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge)) == ESP8266::AT_OK);
- wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
+ result = (esp8266.openConnection(ESP8266::TCP, serverAddress,
+ serverPort) == ESP8266::AT_OK);
+ if (result) {
+ result =
+ (esp8266.sendData(formatHttpPost(
+ serverAddress, serverPostPath, m_sessionIdString, macCoproc,
+ event, postData, challenge)) == ESP8266::AT_OK);
+ wait_ms(
+ ESP8266::
+ sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
}
}
-
+
// Close connection
esp8266.closeConnection();
}
-
+
return result;
}
-std::string WebServerInterface::formatSensorDataPostBody(const SensorData & sensorData)
-{
+std::string
+WebServerInterface::formatSensorDataPostBody(const SensorData & sensorData) {
// Create initial post body string from input data
std::ostringstream postBodyStream;
- postBodyStream << "Temp" << keyValSeparator << static_cast<int>(sensorData.temp);
+ postBodyStream << "Temp" << keyValSeparator
+ << static_cast<int>(sensorData.temp);
postBodyStream << fieldSeparator;
- postBodyStream << "FilterLife" << keyValSeparator << static_cast<unsigned>(sensorData.filterLife);
+ postBodyStream << "FilterLife" << keyValSeparator
+ << static_cast<unsigned>(sensorData.filterLife);
postBodyStream << fieldSeparator;
- postBodyStream << "TempAlarm" << keyValSeparator << (sensorData.tempAlarm() ? "true" : "false");
+ postBodyStream << "TempAlarm" << keyValSeparator
+ << (sensorData.tempAlarm() ? "true" : "false");
postBodyStream << fieldSeparator;
- postBodyStream << "FilterLifeAlarm" << keyValSeparator << (sensorData.filterLifeAlarm() ? "true" : "false");
+ postBodyStream << "FilterLifeAlarm" << keyValSeparator
+ << (sensorData.filterLifeAlarm() ? "true" : "false");
return postBodyStream.str();
}
-void WebServerInterface::setSessionId(const OneWire::RomId & sessionId)
-{
- m_sessionIdString = byteArrayToHexString(sessionId.buffer.data(), sessionId.buffer.size());
- m_sessionId = sessionId;
+void WebServerInterface::setSessionId(const RomId & sessionId) {
+ m_sessionIdString = byteArrayToHexString(sessionId.data(), sessionId.size());
+ m_sessionId = sessionId;
}
\ No newline at end of file
--- a/WebServerInterface.hpp Tue Apr 04 14:10:48 2017 -0500
+++ b/WebServerInterface.hpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,60 +28,59 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#ifndef WEBSERVERINTERFACE_HPP
#define WEBSERVERINTERFACE_HPP
#include <string>
-#include "RomId/RomId.h"
+#include <MaximInterface/Utilities/RomId.hpp>
/// The message type described by the POST.
-enum PostEvent
-{
- SensorDataEvent, ///< Adding sensor data to the log.
+enum PostEvent {
+ SensorDataEvent, ///< Adding sensor data to the log.
InvalidSensorEvent ///< Reporting an invalid sensor node.
};
namespace mbed { class Serial; }
-namespace OneWire { class ISha256MacCoproc; }
+namespace MaximInterface { class DS2465; }
class ESP8266;
struct SensorData;
/// Network interface to the web server supporting authenticated posting of event
/// through an HTTP challenge-respones scheme with SHA-256 data signing.
-class WebServerInterface
-{
-public:
+class WebServerInterface {
+public:
/// @param esp8266 Interface to ESP8266 for Wi-Fi access.
/// @param pc Optional serial interface for received web traffic.
- WebServerInterface(ESP8266 & esp8266) : esp8266(esp8266) { }
-
+ WebServerInterface(ESP8266 & esp8266) : esp8266(esp8266) {}
+
/// Initialize network interface and connect to access point.
/// @returns True on success.
bool initialize();
-
+
/// Send an authenticated event message to the web server.
- /// @param macCoProc Coprocessor such as the DS2465 used to calculate the authentication MAC.
+ /// @param macCoProc
+ /// Coprocessor such as the DS2465 used to calculate the authentication MAC.
/// @param event Event message type.
/// @postData Message body as determined by the event message type.
/// @setSecret True if the Transport Secret needs to be selected in the coprocessor.
/// @returns True on success.
- bool authPostHttpEvent(OneWire::ISha256MacCoproc & macCoproc, PostEvent event, const std::string & postData, bool setSecret);
-
+ bool authPostHttpEvent(MaximInterface::DS2465 & macCoproc, PostEvent event,
+ const std::string & postData, bool setSecret);
+
/// Format sensor data as text suitable for use in a POST body.
/// @param sensorData Sensor data to format.
/// @returns Data formatted for web server.
static std::string formatSensorDataPostBody(const SensorData & sensorData);
-
+
/// @{
/// Session ID used by the web server to distinguish between multiple Controllers.
- const OneWire::RomId & sessionId() const { return m_sessionId; }
+ const MaximInterface::RomId & sessionId() const { return m_sessionId; }
const std::string & sessionIdString() const { return m_sessionIdString; }
- void setSessionId(const OneWire::RomId & sessionId);
+ void setSessionId(const MaximInterface::RomId & sessionId);
/// @}
-
+
private:
/// @{
/// Configuration strings.
@@ -92,10 +91,10 @@
static const char serverPostPath[];
static const char serverChallengePath[];
/// @}
-
- OneWire::RomId m_sessionId;
+
+ MaximInterface::RomId m_sessionId;
std::string m_sessionIdString;
-
+
ESP8266 & esp8266;
};
--- a/main.cpp Tue Apr 04 14:10:48 2017 -0500
+++ b/main.cpp Mon Nov 06 17:34:13 2017 -0600
@@ -28,278 +28,255 @@
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
-*******************************************************************************
-*/
+*******************************************************************************/
#include <sstream>
-
+#include <mbed.h>
+#include <MaximInterface/Devices/DS2465.hpp>
+#include <MaximInterface/Platforms/mbed/I2CMaster.hpp>
+#include <MaximInterface/Platforms/mbed/Sleep.hpp>
+#include <MaximInterface/Utilities/RomId.hpp>
#include "SensorData.hpp"
#include "WebServerInterface.hpp"
#include "Factory.hpp"
#include "SensorNode.hpp"
-#include "Masters/DS2465/DS2465.h"
#include "Display.hpp"
-#include "RomId/RomId.h"
#include "ESP8266.hpp"
-#include "mbed.h"
-using OneWire::RomId;
-using OneWire::DS2465;
+using namespace MaximInterface;
/// Main status for the program.
-enum Status
-{
- InitializingController, ///< Configure DS2465 and connect to network.
- DisplaySessionId, ///< Display ID for use with website.
+enum Status {
+ InitializingController, ///< Configure DS2465 and connect to network.
+ DisplaySessionId, ///< Display ID for use with website.
SensorNodeNeedsDetection, ///< Prompt user to insert Sensor Node.
- DetectingSensorNode, ///< Check if Sensor Node present.
+ DetectingSensorNode, ///< Check if Sensor Node present.
SensorNodeNeedsProvision, ///< Sensor Node needs to be provisioned.
- ProvisioningSensorNode, ///< Provisioning Sensor Node to factory defaults.
- NormalOperation, ///< The normal demo operation state.
- SensorNodeNotAuthentic, ///< Sensor Node failed authentication check.
+ ProvisioningSensorNode, ///< Provisioning Sensor Node to factory defaults.
+ NormalOperation, ///< The normal demo operation state.
+ SensorNodeNotAuthentic, ///< Sensor Node failed authentication check.
ControllerInitializationError, ///< Failed to initialize Controller.
- ControllerHardwareError, ///< Controller hardware failed unexpectedly.
- SensorNodeHardwareError ///< Sensor Node hardware failed unexpectedly.
+ ControllerHardwareError, ///< Controller hardware failed unexpectedly.
+ SensorNodeHardwareError ///< Sensor Node hardware failed unexpectedly.
};
/// @{
/// Configuration options.
-static const unsigned int webPostIntervalMs = 10000;
-static const unsigned int webPostRetryIntervalMs = 1000;
-static const uint8_t maxConsecutiveWebPostErrors = 3;
+static const int webPostIntervalMs = 10000;
+static const int webPostRetryIntervalMs = 1000;
+static const int maxConsecutiveWebPostErrors = 3;
/// @}
/// @{
/// LCD display colors.
-static const Display::Color Teal = { 0x00, 0xB2, 0xA9 };
-static const Display::Color Red = { 0xFF, 0x00, 0x00 };
-static const Display::Color Green = { 0x00, 0xFF, 0x00 };
-static const Display::Color Purple = { 0x6E, 0x25, 0x85 };
+static const Display::Color Teal = {0x00, 0xB2, 0xA9};
+static const Display::Color Red = {0xFF, 0x00, 0x00};
+static const Display::Color Green = {0x00, 0xFF, 0x00};
+static const Display::Color Purple = {0x6E, 0x25, 0x85};
/// @}
/// @{
/// Peripheral and pin definitions
-static Serial pc(USBTX, USBRX);
static DigitalIn provisionButton(D13);
static DigitalIn invalidateButton(D5);
static DigitalOut tempAlarmLed(D11, 1);
static DigitalOut filterLifeAlarmLed(D10, 1);
static I2C i2c(D14, D15);
static Display lcd(i2c, 0x78, 0x98);
-static DS2465 ds2465(i2c, 0x30);
+static MaximInterface::mbed::I2CMaster i2cWrapper(i2c);
+static DS2465 ds2465(MaximInterface::mbed::Sleep::instance(), i2cWrapper, 0x30);
static SensorNode sensorNode(i2c, 0x90, 0x94, ds2465);
static ESP8266 esp8266(D1, D0, D2, D3, 38400);
static WebServerInterface webIntf(esp8266);
/// @}
-static bool useInvalidSecret = false; ///< Imitate an invalid controller when posting to web server.
+/// Imitate an invalid controller when posting to web server.
+static bool useInvalidSecret = false;
static unsigned int randomSeed = 0; ///< Create extra entropy for challenge.
static Status currentStatus = InitializingController;
static bool result = false;
-static uint8_t consecutiveWebPostErrors = 0; ///< Account for a few network errors in case of flaky connection.
+/// Account for a few network errors in case of flaky connection.
+static uint8_t consecutiveWebPostErrors = 0;
static Timer webPostTimer; ///< Software timer to track web posting interval.
-static Timer retryTimer; ///< Software timer to track authentication retries.
+static Timer retryTimer; ///< Software timer to track authentication retries.
-static void blinkLeds(unsigned int time_ms); ///< Invert LEDs for a given amount of time.
-static bool buttonPressed(DigitalIn & button); ///< Checks if button is pressed (returns true) and waits for release.
-static void displayStatus(Status status); ///< Display status message on LCD.
-static void displaySensorData(const SensorData & sensorData); ///< Display sensor data on the LCD.
-static bool readWebSessionId(OneWire::RomId & sessionId); ///< Read device's web session ID from it's nonvolatile storage.
+/// Invert LEDs for a given amount of time.
+static void blinkLeds(int time_ms);
+/// Checks if button is pressed (returns true) and waits for release.
+static bool buttonPressed(DigitalIn & button);
+/// Display status message on LCD.
+static void displayStatus(Status status);
+/// Display sensor data on the LCD.
+static void displaySensorData(const SensorData & sensorData);
+/// Read device's web session ID from it's nonvolatile storage.
+static bool readWebSessionId(RomId & sessionId);
#ifdef ASSEMBLY_TEST
-#include "AssemblyTest.cpp"
+#include "AssemblyTest.hpp"
#endif
-int main()
-{
+int main() {
blinkLeds(500);
-
+
#ifdef ASSEMBLY_TEST
assemblyTest();
#endif
-
- while (true)
- {
+
+ while (true) {
Status nextStatus = currentStatus;
- switch (currentStatus)
- {
+ switch (currentStatus) {
case InitializingController:
- pc.baud(115200);
i2c.frequency(100000);
webPostTimer.start();
-
+
// Set initial LCD state
lcd.initialize();
displayStatus(currentStatus);
-
+
// Connect to Wifi network
result = webIntf.initialize();
-
+
// Read session ID
- if (result)
- {
- OneWire::RomId sessionId;
+ if (result) {
+ RomId sessionId;
result = readWebSessionId(sessionId);
- if (result)
- {
- webIntf.setSessionId(sessionId);
+ if (result) {
+ webIntf.setSessionId(sessionId);
}
}
-
+
// Provision DS2465 with master secret and page data
- if (result)
- {
+ if (result) {
result = provisionCoprocessor(ds2465);
}
-
- if (result)
- {
+
+ if (result) {
nextStatus = DisplaySessionId;
- }
- else
- {
+ } else {
nextStatus = ControllerInitializationError;
}
break;
-
+
case DisplaySessionId:
// Wait for user to press Provision button
- if (buttonPressed(provisionButton))
- {
+ if (buttonPressed(provisionButton)) {
nextStatus = SensorNodeNeedsDetection;
}
break;
-
+
case SensorNodeNeedsDetection:
// Wait for user to press Provision button
- if (buttonPressed(provisionButton))
- {
+ if (buttonPressed(provisionButton)) {
nextStatus = DetectingSensorNode;
}
break;
-
+
case DetectingSensorNode:
// Perform Sensor Node detection sequence
- switch (sensorNode.detect(randomSeed))
- {
+ switch (sensorNode.detect(randomSeed)) {
case SensorNode::UnableToCommunicate:
default:
nextStatus = SensorNodeHardwareError;
break;
-
+
case SensorNode::NotProvisioned:
nextStatus = SensorNodeNeedsProvision;
break;
-
+
case SensorNode::NotAuthentic:
nextStatus = SensorNodeNotAuthentic;
break;
-
+
case SensorNode::Authentic:
nextStatus = NormalOperation;
break;
}
break;
-
+
case SensorNodeNeedsProvision:
// Wait for user to press Provision button
- if (buttonPressed(provisionButton))
- {
+ if (buttonPressed(provisionButton)) {
nextStatus = ProvisioningSensorNode;
}
break;
-
- case ProvisioningSensorNode:
- if (!buttonPressed(invalidateButton)) // Provision normally
- {
- if (provisionSensorNode(sensorNode, true))
- {
+
+ case ProvisioningSensorNode:
+ if (!buttonPressed(invalidateButton)) { // Provision normally
+ if (provisionSensorNode(sensorNode, true)) {
nextStatus = NormalOperation;
- }
- else
- {
+ } else {
nextStatus = SensorNodeNotAuthentic;
}
- }
- else // Invalidate button also pressed; Load invalid secret
- {
+ } else { // Invalidate button also pressed; Load invalid secret
// Provision with invalid secret
- if (provisionSensorNode(sensorNode, false))
- {
+ if (provisionSensorNode(sensorNode, false)) {
nextStatus = NormalOperation;
- }
- else
- {
+ } else {
nextStatus = SensorNodeHardwareError;
}
}
break;
-
- case NormalOperation:
+
+ case NormalOperation:
// Check if user pressed Provision button
- if (buttonPressed(provisionButton))
- {
+ if (buttonPressed(provisionButton)) {
// Re-provision Sensor Node
nextStatus = ProvisioningSensorNode;
}
// Check if user pressed Invalidate button
- else if (buttonPressed(invalidateButton))
- {
+ else if (buttonPressed(invalidateButton)) {
// Toggle between using valid and invalid secret
// 1 blink = invalid; 2 blinks = valid
useInvalidSecret = !useInvalidSecret;
blinkLeds(100);
- if (!useInvalidSecret)
- {
+ if (!useInvalidSecret) {
wait_ms(100);
blinkLeds(100);
}
}
// Check node and display measurements
- else
- {
+ else {
SensorData sensorData;
// Read sensor data with authentication
- switch (sensorNode.authenticatedReadSensorData(randomSeed, sensorData))
- {
+ switch (
+ sensorNode.authenticatedReadSensorData(randomSeed, sensorData)) {
case SensorNode::Authentic:
// Update measurements on LCD
displaySensorData(sensorData);
-
+
// Update alarm LEDs
- tempAlarmLed = !sensorData.tempAlarm(); // Active Low
+ tempAlarmLed = !sensorData.tempAlarm(); // Active Low
filterLifeAlarmLed = !sensorData.filterLifeAlarm(); // Active Low
-
+
// Send measurements to web if time interval reached
- if (static_cast<unsigned int>(webPostTimer.read_ms()) >= webPostIntervalMs)
- {
+ if (webPostTimer.read_ms() >= webPostIntervalMs) {
// Format, sign, and transmit data to web server
- result = webIntf.authPostHttpEvent(ds2465, SensorDataEvent, WebServerInterface::formatSensorDataPostBody(sensorData), !useInvalidSecret);
- if (result)
- {
+ result = webIntf.authPostHttpEvent(
+ ds2465, SensorDataEvent,
+ WebServerInterface::formatSensorDataPostBody(sensorData),
+ !useInvalidSecret);
+ if (result) {
// Reset timer count after logging sample complete
webPostTimer.reset();
consecutiveWebPostErrors = 0;
}
// There was likely an error establishing a web connection
- else if (++consecutiveWebPostErrors < maxConsecutiveWebPostErrors)
- {
+ else if (++consecutiveWebPostErrors < maxConsecutiveWebPostErrors) {
// Wait and try again
wait_ms(webPostRetryIntervalMs);
}
// Too many retry attempts
- else
- {
+ else {
// Assume we have lost network connection
nextStatus = ControllerHardwareError;
}
}
break;
-
+
case SensorNode::NotAuthentic:
nextStatus = SensorNodeNotAuthentic;
break;
-
+
case SensorNode::UnableToCommunicate:
default:
nextStatus = SensorNodeHardwareError;
@@ -307,51 +284,45 @@
}
}
break;
-
+
case SensorNodeNotAuthentic:
// Wait for some time before retrying authentication
retryTimer.reset();
retryTimer.start();
- do
- {
+ do {
// Wait for user to press Provision button
- if (buttonPressed(provisionButton))
- {
+ if (buttonPressed(provisionButton)) {
nextStatus = ProvisioningSensorNode;
break;
}
// Try to authenticate and return to normal operation
- else if (static_cast<unsigned int>(webPostTimer.read_ms()) >= webPostIntervalMs)
- {
+ else if (webPostTimer.read_ms() >= webPostIntervalMs) {
// Send event message to server
- result = webIntf.authPostHttpEvent(ds2465, InvalidSensorEvent, "", !useInvalidSecret);
- if (result)
- {
+ result = webIntf.authPostHttpEvent(ds2465, InvalidSensorEvent, "",
+ !useInvalidSecret);
+ if (result) {
// Reset timer count after logging complete
webPostTimer.reset();
consecutiveWebPostErrors = 0;
-
+
// Try to authenticate again
nextStatus = SensorNodeNeedsDetection;
- }
- else if (++consecutiveWebPostErrors < maxConsecutiveWebPostErrors)
- {
+ } else if (++consecutiveWebPostErrors < maxConsecutiveWebPostErrors) {
// There was likely an error establishing a web connection
// Wait and try again
wait_ms(webPostRetryIntervalMs);
}
// Too many retry attempts
- else
- {
+ else {
// Assume we have lost network connection
nextStatus = ControllerHardwareError;
break;
}
}
- } while (static_cast<unsigned int>(retryTimer.read_ms()) < webPostIntervalMs);
+ } while (retryTimer.read_ms() < webPostIntervalMs);
retryTimer.stop();
break;
-
+
case ControllerInitializationError:
case ControllerHardwareError:
case SensorNodeHardwareError:
@@ -360,12 +331,11 @@
break;
}
// Check if status changed
- if (currentStatus != nextStatus)
- {
+ if (currentStatus != nextStatus) {
currentStatus = nextStatus;
displayStatus(currentStatus); // Display status message on LCD
}
-
+
// Change seed value on every loop pass
randomSeed++;
}
@@ -373,8 +343,7 @@
/// Blink all LEDs for a certain amount of time.
/// @param time_ms Time in ms to blink for.
-static void blinkLeds(unsigned int time_ms)
-{
+static void blinkLeds(int time_ms) {
tempAlarmLed = !tempAlarmLed;
filterLifeAlarmLed = !filterLifeAlarmLed;
wait_ms(time_ms);
@@ -385,12 +354,11 @@
/// Check if a button is pressed and wait for it to be release.
/// @param button Active low button to check.
/// @returns True if pressed.
-static bool buttonPressed(DigitalIn & button)
-{
+static bool buttonPressed(DigitalIn & button) {
const int buttonPressed = 0; // Active low
- if (button == buttonPressed)
- {
- while (button == buttonPressed) ;
+ if (button == buttonPressed) {
+ while (button == buttonPressed)
+ ;
return true;
}
// else
@@ -398,60 +366,58 @@
}
/// Display the current status of the Controller on the LCD display.
-static void displayStatus(Status status)
-{
- switch (status)
- {
+static void displayStatus(Status status) {
+ switch (status) {
case InitializingController:
lcd.writeMessage("Initializing Controller...");
lcd.setBackLightColor(Teal);
break;
-
+
case DisplaySessionId:
lcd.writeLine("ID: " + webIntf.sessionIdString(), Display::FirstLine);
lcd.writeLine("Provision to begin", Display::SecondLine);
lcd.setBackLightColor(Teal);
break;
-
+
case SensorNodeNeedsDetection:
lcd.writeMessage("Insert Sensor Node and press Provision");
lcd.setBackLightColor(Teal);
break;
-
+
case DetectingSensorNode:
lcd.writeMessage("Detecting Sensor Node...");
lcd.setBackLightColor(Teal);
break;
-
+
case SensorNodeNeedsProvision:
lcd.writeMessage("Sensor Node Needs Provision");
lcd.setBackLightColor(Teal);
break;
-
+
case ProvisioningSensorNode:
lcd.writeMessage("Provisioning Sensor Node");
lcd.setBackLightColor(Teal);
break;
-
+
case NormalOperation:
// Everything handled in displaySensorData()
break;
-
+
case SensorNodeNotAuthentic:
lcd.writeMessage("Sensor Node Not Authentic");
lcd.setBackLightColor(Purple);
break;
-
+
case ControllerInitializationError:
lcd.writeMessage("Initialization Error Check Wi-Fi");
lcd.setBackLightColor(Red);
break;
-
+
case ControllerHardwareError:
lcd.writeMessage("Controller Hardware Error: Check Wi-Fi");
lcd.setBackLightColor(Red);
break;
-
+
case SensorNodeHardwareError:
lcd.writeMessage("Sensor Node Hardware Error");
lcd.setBackLightColor(Red);
@@ -460,13 +426,13 @@
}
/// Display sensor data on the LCD display during normal operation.
-static void displaySensorData(const SensorData & sensorData)
-{
+static void displaySensorData(const SensorData & sensorData) {
std::ostringstream stream;
stream << "Chiller Temp: " << static_cast<int>(sensorData.temp) << "C";
lcd.writeCompleteLine(stream.str(), Display::FirstLine);
stream.str(""); // Clear stream
- stream << "Filter Life: " << static_cast<unsigned int>(sensorData.filterLife) << "%";
+ stream << "Filter Life: " << static_cast<unsigned int>(sensorData.filterLife)
+ << "%";
lcd.writeCompleteLine(stream.str(), Display::SecondLine);
lcd.setBackLightColor(Green);
}
@@ -475,20 +441,20 @@
/// @note Session ID is taken from the ROM ID of the MAX66242.
/// @param[out] Session ID string.
/// @returns True on success.
-static bool readWebSessionId(OneWire::RomId & sessionId)
-{
+static bool readWebSessionId(RomId & sessionId) {
const uint8_t I2C_address = 0x32;
const uint8_t ROM_address = 0x68;
RomId romId;
-
+
// Set register pointer
if (i2c.write(I2C_address, reinterpret_cast<const char *>(&ROM_address), 1) != 0)
return false;
// Read ROM ID
- if (i2c.read(I2C_address, reinterpret_cast<char *>(romId.buffer.data()), romId.buffer.size()) != 0)
+ if (i2c.read(I2C_address, reinterpret_cast<char *>(romId.data()),
+ romId.size()) != 0)
return false;
// Check if CRC valid
- if (!romId.valid())
+ if (!valid(romId))
return false;
sessionId = romId;
return true;
MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification