├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md └── app ├── app.ino ├── config.h ├── credentials.ino ├── iothubClient.ino ├── message.ino └── serialReader.ino /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft. All rights reserved. 2 | # Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | language: generic 5 | branches: 6 | only: 7 | - master 8 | env: 9 | global: 10 | - IDE_VERSION=1.8.1 11 | matrix: 12 | - BOARD="esp8266:esp8266:thingdev" 13 | before_install: 14 | - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 15 | - sleep 3 16 | - export DISPLAY=:1.0 17 | - wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz 18 | - tar xf arduino-$IDE_VERSION-linux64.tar.xz 19 | - mv arduino-$IDE_VERSION $HOME/arduino-ide 20 | - export PATH=$PATH:$HOME/arduino-ide 21 | - if [[ "$BOARD" =~ "arduino:samd:" ]]; then 22 | arduino --install-boards arduino:samd; 23 | arduino --install-library WiFi101; 24 | arduino --install-library RTCZero; 25 | arduino --install-library NTPClient; 26 | fi 27 | - if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then 28 | arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --install-boards esp8266:esp8266; 29 | arduino --pref "boardsmanager.additional.urls=" --save-prefs; 30 | arduino --install-library NTPClient; 31 | arduino --install-library NTPClient; 32 | fi 33 | - findAndReplace() { sed -i'' -e"s|$1|$2|g" "$3"; } 34 | - buildExampleSketch() { 35 | EXAMPLE_SKETCH=$PWD/$1/$1.ino; 36 | 37 | if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then 38 | findAndReplace WiFi101 ESP8266WiFi $EXAMPLE_SKETCH; 39 | findAndReplace WiFiSSLClient WiFiClientSecure $EXAMPLE_SKETCH; 40 | findAndReplace WiFiUdp WiFiUdp $EXAMPLE_SKETCH; 41 | fi 42 | 43 | arduino --verbose-build --verify --board $BOARD $EXAMPLE_SKETCH; 44 | } 45 | install: 46 | - arduino --install-library "AzureIoTUtility" 47 | - arduino --install-library "AzureIoTHub" 48 | - arduino --install-library "AzureIoTProtocol_MQTT" 49 | - arduino --install-library "ArduinoJson" 50 | - arduino --install-library "DHT sensor library" 51 | - arduino --install-library "Adafruit Unified Sensor" 52 | # a slash bug in the arduino IoT lib 53 | - sed -i -e 's/azure_c_shared_utility\\crt_abstractions.h/azure_c_shared_utility\/crt_abstractions.h/g' /home/travis/Arduino/libraries/AzureIoTHub/src/esp8266/azcpgmspace.h 54 | - sed -i -e 's/azure_umqtt_c\\mqtt_client.h/azure_umqtt_c\/mqtt_client.h/g' /home/travis/Arduino/libraries/AzureIoTProtocol_MQTT/src/AzureIoTProtocol_MQTT.h 55 | script: 56 | - buildExampleSketch app 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - c 5 | products: 6 | - azure 7 | - azure-iot-hub 8 | name: IoT Hub SparkFun ESP8266 Thing-Dev Client application 9 | urlFragment: spark-fun-esp8266-client 10 | description: "This repo contains an arduino application that runs on board SparkFun ESP8266 Thing-Dev with a DHT22 temperature and humidity sensor." 11 | --- 12 | 13 | # IoT Hub SparkFun ESP8266 Thing-Dev Client application 14 | [![Build Status](https://travis-ci.org/Azure-Samples/iot-hub-SparkFun-ThingDev-client-app.svg?branch=master)](https://travis-ci.org/Azure-Samples/iot-hub-SparkFun-ThingDev-client-app) 15 | 16 | > This repo contains the source code to help you get familiar with Azure IoT using the Azure IoT SparkFun ESP8266 Thing-Dev Starter Kit. You will find the [lesson-based tutorials on Azure.com](https://docs.microsoft.com/azure/iot-hub/iot-hub-sparkfun-esp8266-thing-dev-get-started). 17 | 18 | This repo contains an arduino application that runs on board SparkFun ESP8266 Thing-Dev with a DHT22 temperature&humidity sensor, and then sends these data to your IoT hub. At the same time, this application receives Cloud-to-Device message from your IoT hub, and takes actions according to the C2D command. 19 | 20 | ## Prepare your Azure IoT Hub 21 | You can follow [this page](https://docs.microsoft.com/azure/iot-hub/iot-hub-sparkfun-esp8266-thing-dev-get-started) to create your Azure IoT hub and register your device. 22 | 23 | ## Install board with your Arduino IDE 24 | 1. Start Arduino and open Preferences window. 25 | 2. Enter `http://arduino.esp8266.com/stable/package_esp8266com_index.json` into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas. 26 | 3. Open Boards Manager from `Tools > Board` menu and install esp8266 platform 2.2.0 or later. 27 | 4. Select your ESP8266 board from `Tools > Board` menu after installation. 28 | 29 | ## Install libraries 30 | Install the following libraries from `Sketch -> Include library -> Manage libraries` 31 | 32 | * AzureIoTHub 33 | * AzureIoTUtility 34 | * AzureIoTProtocol_MQTT 35 | * ArduinoJson 36 | * DHT sensor library 37 | * Adafruit Unified Sensor 38 | 39 | ## Connect your sensor with your board 40 | ### Connect with a physical DHT22 sensor 41 | You can follow the image to connect your DHT22 with your SparkFun ESP8266 Thing-Dev. 42 | 43 | ![DHT22](https://docs.microsoft.com/en-us/azure/iot-hub/media/iot-hub-sparkfun-thing-dev-get-started/15_connections_on_breadboard.png) 44 | 45 | ### DON'T HAVE A PHYSICAL DHT22? 46 | You can use the application to simulate temperature&humidity data and send to your IoT hub. 47 | 1. Open the `app/config.h` file. 48 | 2. Change the `SIMULATED_DATA` value from `false` to `true`. 49 | 50 | ## Configure and run sample application 51 | Upload the `app.ino` to your board. 52 | 53 | ### Input your credential information 54 | After you successfully upload the code to your board. You will see some prompt, input your credential information according to the prompts. 55 | 56 | ### Send Cloud-to-Device command 57 | You can send a C2D message to your device. You can see the device prints out the message and blinks once receiving the message. 58 | 59 | ### Send Device Method command 60 | You can send `start` or `stop` device method command to your Pi to start/stop sending message to your IoT hub. 61 | -------------------------------------------------------------------------------- /app/app.ino: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | // Please use an Arduino IDE 1.6.8 or greater 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "config.h" 15 | 16 | static bool messagePending = false; 17 | static bool messageSending = true; 18 | 19 | static char *connectionString; 20 | static char *ssid; 21 | static char *pass; 22 | 23 | static int interval = INTERVAL; 24 | 25 | void blinkLED() 26 | { 27 | digitalWrite(LED_PIN, HIGH); 28 | delay(500); 29 | digitalWrite(LED_PIN, LOW); 30 | } 31 | 32 | void initWifi() 33 | { 34 | // Attempt to connect to Wifi network: 35 | Serial.printf("Attempting to connect to SSID: %s.\r\n", ssid); 36 | 37 | // Connect to WPA/WPA2 network. Change this line if using open or WEP network: 38 | WiFi.begin(ssid, pass); 39 | while (WiFi.status() != WL_CONNECTED) 40 | { 41 | // Get Mac Address and show it. 42 | // WiFi.macAddress(mac) save the mac address into a six length array, but the endian may be different. The huzzah board should 43 | // start from mac[0] to mac[5], but some other kinds of board run in the oppsite direction. 44 | uint8_t mac[6]; 45 | WiFi.macAddress(mac); 46 | Serial.printf("You device with MAC address %02x:%02x:%02x:%02x:%02x:%02x connects to %s failed! Waiting 10 seconds to retry.\r\n", 47 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ssid); 48 | WiFi.begin(ssid, pass); 49 | delay(10000); 50 | } 51 | Serial.printf("Connected to wifi %s.\r\n", ssid); 52 | } 53 | 54 | void initTime() 55 | { 56 | time_t epochTime; 57 | configTime(0, 0, "pool.ntp.org", "time.nist.gov"); 58 | 59 | while (true) 60 | { 61 | epochTime = time(NULL); 62 | 63 | if (epochTime == 0) 64 | { 65 | Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); 66 | delay(2000); 67 | } 68 | else 69 | { 70 | Serial.printf("Fetched NTP epoch time is: %lu.\r\n", epochTime); 71 | break; 72 | } 73 | } 74 | } 75 | 76 | static IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle; 77 | void setup() 78 | { 79 | pinMode(LED_PIN, OUTPUT); 80 | 81 | initSerial(); 82 | delay(2000); 83 | readCredentials(); 84 | 85 | initWifi(); 86 | initTime(); 87 | initSensor(); 88 | 89 | /* 90 | * Break changes in version 1.0.34: AzureIoTHub library removed AzureIoTClient class. 91 | * So we remove the code below to avoid compile error. 92 | */ 93 | // initIoThubClient(); 94 | 95 | iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol); 96 | if (iotHubClientHandle == NULL) 97 | { 98 | Serial.println("Failed on IoTHubClient_CreateFromConnectionString."); 99 | while (1); 100 | } 101 | 102 | IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, receiveMessageCallback, NULL); 103 | IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientHandle, deviceMethodCallback, NULL); 104 | IoTHubClient_LL_SetDeviceTwinCallback(iotHubClientHandle, twinCallback, NULL); 105 | } 106 | 107 | static int messageCount = 1; 108 | void loop() 109 | { 110 | if (!messagePending && messageSending) 111 | { 112 | char messagePayload[MESSAGE_MAX_LEN]; 113 | bool temperatureAlert = readMessage(messageCount, messagePayload); 114 | sendMessage(iotHubClientHandle, messagePayload, temperatureAlert); 115 | messageCount++; 116 | delay(interval); 117 | } 118 | IoTHubClient_LL_DoWork(iotHubClientHandle); 119 | delay(10); 120 | } 121 | -------------------------------------------------------------------------------- /app/config.h: -------------------------------------------------------------------------------- 1 | // Physical device information for board and sensor 2 | #define DEVICE_ID "SparkFun ESP8266 Thing Dev" 3 | #define DHT_TYPE DHT22 4 | 5 | // Pin layout configuration 6 | #define LED_PIN 5 7 | #define DHT_PIN 2 8 | 9 | #define TEMPERATURE_ALERT 30 10 | 11 | // Interval time(ms) for sending message to IoT Hub 12 | #define INTERVAL 2000 13 | 14 | // If don't have a physical DHT sensor, can send simulated data to IoT hub 15 | #define SIMULATED_DATA false 16 | 17 | // EEPROM address configuration 18 | #define EEPROM_SIZE 512 19 | 20 | // SSID and SSID password's length should < 32 bytes 21 | // http://serverfault.com/a/45509 22 | #define SSID_LEN 32 23 | #define PASS_LEN 32 24 | #define CONNECTION_STRING_LEN 256 25 | 26 | #define MESSAGE_MAX_LEN 256 27 | -------------------------------------------------------------------------------- /app/credentials.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Read parameters from EEPROM or Serial 4 | void readCredentials() 5 | { 6 | int ssidAddr = 0; 7 | int passAddr = ssidAddr + SSID_LEN; 8 | int connectionStringAddr = passAddr + SSID_LEN; 9 | 10 | // malloc for parameters 11 | ssid = (char *)malloc(SSID_LEN); 12 | pass = (char *)malloc(PASS_LEN); 13 | connectionString = (char *)malloc(CONNECTION_STRING_LEN); 14 | 15 | // try to read out the credential information, if failed, the length should be 0. 16 | int ssidLength = EEPROMread(ssidAddr, ssid); 17 | int passLength = EEPROMread(passAddr, pass); 18 | int connectionStringLength = EEPROMread(connectionStringAddr, connectionString); 19 | 20 | if (ssidLength > 0 && passLength > 0 && connectionStringLength > 0 && !needEraseEEPROM()) 21 | { 22 | return; 23 | } 24 | 25 | // read from Serial and save to EEPROM 26 | readFromSerial("Input your Wi-Fi SSID: ", ssid, SSID_LEN, 0); 27 | EEPROMWrite(ssidAddr, ssid, strlen(ssid)); 28 | 29 | readFromSerial("Input your Wi-Fi password: ", pass, PASS_LEN, 0); 30 | EEPROMWrite(passAddr, pass, strlen(pass)); 31 | 32 | readFromSerial("Input your Azure IoT hub device connection string: ", connectionString, CONNECTION_STRING_LEN, 0); 33 | EEPROMWrite(connectionStringAddr, connectionString, strlen(connectionString)); 34 | } 35 | 36 | bool needEraseEEPROM() 37 | { 38 | char result = 'n'; 39 | readFromSerial("Do you need re-input your credential information?(Auto skip this after 5 seconds)[Y/n]", &result, 1, 5000); 40 | if (result == 'Y' || result == 'y') 41 | { 42 | clearParam(); 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | // reset the EEPROM 49 | void clearParam() 50 | { 51 | char data[EEPROM_SIZE]; 52 | memset(data, '\0', EEPROM_SIZE); 53 | EEPROMWrite(0, data, EEPROM_SIZE); 54 | } 55 | 56 | #define EEPROM_END 0 57 | #define EEPROM_START 1 58 | void EEPROMWrite(int addr, char *data, int size) 59 | { 60 | EEPROM.begin(EEPROM_SIZE); 61 | // write the start marker 62 | EEPROM.write(addr, EEPROM_START); 63 | addr++; 64 | for (int i = 0; i < size; i++) 65 | { 66 | EEPROM.write(addr, data[i]); 67 | addr++; 68 | } 69 | EEPROM.write(addr, EEPROM_END); 70 | EEPROM.commit(); 71 | EEPROM.end(); 72 | } 73 | 74 | // read bytes from addr util '\0' 75 | // return the length of read out. 76 | int EEPROMread(int addr, char *buf) 77 | { 78 | EEPROM.begin(EEPROM_SIZE); 79 | int count = -1; 80 | char c = EEPROM.read(addr); 81 | addr++; 82 | if (c != EEPROM_START) 83 | { 84 | return 0; 85 | } 86 | while (c != EEPROM_END && count < EEPROM_SIZE) 87 | { 88 | c = (char)EEPROM.read(addr); 89 | count++; 90 | addr++; 91 | buf[count] = c; 92 | } 93 | EEPROM.end(); 94 | return count; 95 | } 96 | -------------------------------------------------------------------------------- /app/iothubClient.ino: -------------------------------------------------------------------------------- 1 | static WiFiClientSecure sslClient; // for ESP8266 2 | 3 | const char *onSuccess = "\"Successfully invoke device method\""; 4 | const char *notFound = "\"No method found\""; 5 | 6 | /* 7 | * The new version of AzureIoTHub library change the AzureIoTHubClient signature. 8 | * As a temporary solution, we will test the definition of AzureIoTHubVersion, which is only defined 9 | * in the new AzureIoTHub library version. Once we totally deprecate the last version, we can take 10 | * the #ifdef out. 11 | * Break changes in version 1.0.34: AzureIoTHub library removed AzureIoTClient class. 12 | * So we remove the code below to avoid compile error. 13 | */ 14 | 15 | /* 16 | * #ifdef AzureIoTHubVersion 17 | * static AzureIoTHubClient iotHubClient; 18 | * void initIoThubClient() 19 | * { 20 | * iotHubClient.begin(sslClient); 21 | * } 22 | * #else 23 | * static AzureIoTHubClient iotHubClient(sslClient); 24 | * void initIoThubClient() 25 | * { 26 | * iotHubClient.begin(); 27 | * } 28 | * #endif 29 | */ 30 | 31 | static void sendCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void *userContextCallback) 32 | { 33 | if (IOTHUB_CLIENT_CONFIRMATION_OK == result) 34 | { 35 | Serial.println("Message sent to Azure IoT Hub."); 36 | blinkLED(); 37 | } 38 | else 39 | { 40 | Serial.println("Failed to send message to Azure IoT Hub."); 41 | } 42 | messagePending = false; 43 | } 44 | 45 | static void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, char *buffer, bool temperatureAlert) 46 | { 47 | IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char *)buffer, strlen(buffer)); 48 | if (messageHandle == NULL) 49 | { 50 | Serial.println("Unable to create a new IoTHubMessage."); 51 | } 52 | else 53 | { 54 | MAP_HANDLE properties = IoTHubMessage_Properties(messageHandle); 55 | Map_Add(properties, "temperatureAlert", temperatureAlert ? "true" : "false"); 56 | Serial.printf("Sending message: %s.\r\n", buffer); 57 | if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, NULL) != IOTHUB_CLIENT_OK) 58 | { 59 | Serial.println("Failed to hand over the message to IoTHubClient."); 60 | } 61 | else 62 | { 63 | messagePending = true; 64 | Serial.println("IoTHubClient accepted the message for delivery."); 65 | } 66 | 67 | IoTHubMessage_Destroy(messageHandle); 68 | } 69 | } 70 | 71 | void start() 72 | { 73 | Serial.println("Start sending temperature and humidity data."); 74 | messageSending = true; 75 | } 76 | 77 | void stop() 78 | { 79 | Serial.println("Stop sending temperature and humidity data."); 80 | messageSending = false; 81 | } 82 | 83 | IOTHUBMESSAGE_DISPOSITION_RESULT receiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void *userContextCallback) 84 | { 85 | IOTHUBMESSAGE_DISPOSITION_RESULT result; 86 | const unsigned char *buffer; 87 | size_t size; 88 | if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK) 89 | { 90 | Serial.println("Unable to IoTHubMessage_GetByteArray."); 91 | result = IOTHUBMESSAGE_REJECTED; 92 | } 93 | else 94 | { 95 | /*buffer is not zero terminated*/ 96 | char *temp = (char *)malloc(size + 1); 97 | 98 | if (temp == NULL) 99 | { 100 | return IOTHUBMESSAGE_ABANDONED; 101 | } 102 | 103 | strncpy(temp, (const char *)buffer, size); 104 | temp[size] = '\0'; 105 | Serial.printf("Receive C2D message: %s.\r\n", temp); 106 | free(temp); 107 | blinkLED(); 108 | } 109 | return IOTHUBMESSAGE_ACCEPTED; 110 | } 111 | 112 | int deviceMethodCallback(const char *methodName, const unsigned char *payload, size_t size, unsigned char **response, size_t *response_size, void *userContextCallback) 113 | { 114 | Serial.printf("Try to invoke method %s.\r\n", methodName); 115 | const char *responseMessage = onSuccess; 116 | int result = 200; 117 | 118 | if (strcmp(methodName, "start") == 0) 119 | { 120 | start(); 121 | } 122 | else if (strcmp(methodName, "stop") == 0) 123 | { 124 | stop(); 125 | } 126 | else 127 | { 128 | Serial.printf("No method %s found.\r\n", methodName); 129 | responseMessage = notFound; 130 | result = 404; 131 | } 132 | 133 | *response_size = strlen(responseMessage); 134 | *response = (unsigned char *)malloc(*response_size); 135 | strncpy((char *)(*response), responseMessage, *response_size); 136 | 137 | return result; 138 | } 139 | 140 | void twinCallback( 141 | DEVICE_TWIN_UPDATE_STATE updateState, 142 | const unsigned char *payLoad, 143 | size_t size, 144 | void *userContextCallback) 145 | { 146 | char *temp = (char *)malloc(size + 1); 147 | for (int i = 0; i < size; i++) 148 | { 149 | temp[i] = (char)(payLoad[i]); 150 | } 151 | temp[size] = '\0'; 152 | parseTwinMessage(temp); 153 | free(temp); 154 | } 155 | -------------------------------------------------------------------------------- /app/message.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if SIMULATED_DATA 6 | 7 | void initSensor() 8 | { 9 | // use SIMULATED_DATA, no sensor need to be inited 10 | } 11 | 12 | float readTemperature() 13 | { 14 | return random(20, 30); 15 | } 16 | 17 | float readHumidity() 18 | { 19 | return random(30, 40); 20 | } 21 | 22 | #else 23 | 24 | static DHT dht(DHT_PIN, DHT_TYPE); 25 | void initSensor() 26 | { 27 | dht.begin(); 28 | } 29 | 30 | float readTemperature() 31 | { 32 | return dht.readTemperature(); 33 | } 34 | 35 | float readHumidity() 36 | { 37 | return dht.readHumidity(); 38 | } 39 | 40 | #endif 41 | 42 | bool readMessage(int messageId, char *payload) 43 | { 44 | float temperature = readTemperature(); 45 | float humidity = readHumidity(); 46 | StaticJsonBuffer jsonBuffer; 47 | JsonObject &root = jsonBuffer.createObject(); 48 | root["deviceId"] = DEVICE_ID; 49 | root["messageId"] = messageId; 50 | bool temperatureAlert = false; 51 | 52 | // NAN is not the valid json, change it to NULL 53 | if (std::isnan(temperature)) 54 | { 55 | root["temperature"] = NULL; 56 | } 57 | else 58 | { 59 | root["temperature"] = temperature; 60 | if (temperature > TEMPERATURE_ALERT) 61 | { 62 | temperatureAlert = true; 63 | } 64 | } 65 | 66 | if (std::isnan(humidity)) 67 | { 68 | root["humidity"] = NULL; 69 | } 70 | else 71 | { 72 | root["humidity"] = humidity; 73 | } 74 | root.printTo(payload, MESSAGE_MAX_LEN); 75 | return temperatureAlert; 76 | } 77 | 78 | void parseTwinMessage(char *message) 79 | { 80 | StaticJsonBuffer jsonBuffer; 81 | JsonObject &root = jsonBuffer.parseObject(message); 82 | if (!root.success()) 83 | { 84 | Serial.printf("Parse %s failed.\r\n", message); 85 | return; 86 | } 87 | 88 | if (root["desired"]["interval"].success()) 89 | { 90 | interval = root["desired"]["interval"]; 91 | } 92 | else if (root.containsKey("interval")) 93 | { 94 | interval = root["interval"]; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/serialReader.ino: -------------------------------------------------------------------------------- 1 | void initSerial() 2 | { 3 | // Start serial and initialize stdout 4 | Serial.begin(115200); 5 | Serial.setDebugOutput(true); 6 | Serial.println("Serial successfully inited."); 7 | } 8 | 9 | /* Read a string whose length should in (0, lengthLimit) from Serial and save it into buf. 10 | * 11 | * prompt - the interact message and buf should be allocaled already and return true. 12 | * buf - a part of memory which is already allocated to save string read from serial 13 | * maxLen - the buf's len, which should be upper bound of the read-in string's length, this should > 0 14 | * timeout - If after timeout(ms), return false with nothing saved to buf. 15 | * If no timeout <= 0, this function will not return until there is something read. 16 | */ 17 | bool readFromSerial(char *prompt, char *buf, int maxLen, int timeout) 18 | { 19 | int timer = 0, delayTime = 1000; 20 | String input = ""; 21 | if (maxLen <= 0) 22 | { 23 | // nothing can be read 24 | return false; 25 | } 26 | 27 | Serial.println(prompt); 28 | while (1) 29 | { 30 | input = Serial.readString(); 31 | int len = input.length(); 32 | if (len > maxLen) 33 | { 34 | Serial.printf("Your input should less than %d character(s), now you input %d characters.\r\n", maxLen, len); 35 | } 36 | else if (len > 0) 37 | { 38 | // save the input into the buf 39 | sprintf(buf, "%s", input.c_str()); 40 | return true; 41 | } 42 | 43 | // if timeout, return false directly 44 | timer += delayTime; 45 | if (timeout > 0 && timer >= timeout) 46 | { 47 | Serial.println("You input nothing, skip..."); 48 | return false; 49 | } 50 | // delay a time before next read 51 | delay(delayTime); 52 | } 53 | } 54 | --------------------------------------------------------------------------------