Simple and Stabile Arduino + Azure IoT SDK Sample

/*
 Name:		Arduino.ino
 Created:	5/5/2020 3:40:20 PM
 Author:	KevinSaye
*/
#include <DHT_U.h>                          // version 1.3.8
#include <DHT.h>                            // version 1.3.8
#include <WiFiUdp.h>                        // version 1.0
#include <WiFiServerSecureBearSSL.h>
#include <WiFiServerSecureAxTLS.h>
#include <WiFiServerSecure.h>
#include <WiFiServer.h>
#include <WiFiClientSecureBearSSL.h>
#include <WiFiClientSecureAxTLS.h>
#include <WiFiClientSecure.h>
#include <WiFiClient.h>
#include <ESP8266WiFiType.h>
#include <ESP8266WiFiSTA.h>
#include <ESP8266WiFiScan.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFiGeneric.h>
#include <ESP8266WiFiAP.h>
#include <ESP8266WiFi.h>
#include <CertStoreBearSSL.h>
#include <BearSSLHelpers.h>
#include <AzureIoTHub.h>                // version 1.0.45
#include <AzureIoTUtility.h>            // version 1.0.45
#include <AzureIoTProtocol_MQTT.h>      // version 1.0.45

// Times before 2010 (1970 + 40 years) are invalid
#define MIN_EPOCH 40 * 365 * 24 * 3600
#define DHTPIN        D2
#define DHTTYPE       DHT22

IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;
IOTHUB_CLIENT_STATUS status;
time_t epochTime;
DHT dht(DHTPIN, DHTTYPE);

const char compile_date[] = __DATE__ " " __TIME__;
const String WiFiSSID           = "mywifi";
const String WiFiPassword       = "password";
const String ConnectionString   = "HostName=voiddetection.azure-devices.net;DeviceId=tub3;SharedAccessKey=W8X*********ID3sIXKe8uYpo=";
int lastTemperature;
int currentTemperature;
int messageCounter;
static unsigned int messageTrackingId;

void setup() {
    // setting up the WiFi information
    WiFi.stopSmartConfig();
    WiFi.enableAP(false);
    WiFi.setAutoReconnect(true);
    String HostName = ConnectionString.substring(ConnectionString.indexOf("DeviceId=") + 9);
    HostName = HostName.substring(0, HostName.indexOf(";"));
    WiFi.hostname(HostName);
    WiFi.begin(WiFiSSID.c_str(), WiFiPassword.c_str());
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }
    Serial.println("IP" + WiFi.localIP().toString());

    // configuring the time, needed by the Azure IoT SDK
    configTime(0, 0, "pool.ntp.org", "time.nist.gov");
    while (true) {
        epochTime = time(NULL);

        if (epochTime  300) {
        sendTemperature(currentTemperature);
        lastTemperature = currentTemperature;
        messageCounter = 0;
    }

    // this is required to check the cloud for activity, else C2D messages / methods and TWINs are only checked when sending a message
    IoTHubClient_LL_DoWork(iotHubClientHandle);     

    // if we have a connection and actions to perform, loop until all actions are completed
    while ((IoTHubClient_LL_GetSendStatus(iotHubClientHandle, &status) == IOTHUB_CLIENT_OK)
            && (status == IOTHUB_CLIENT_SEND_STATUS_BUSY)){
        IoTHubClient_LL_DoWork(iotHubClientHandle);
        ThreadAPI_Sleep(100);
    }

    // normal sleep for 1 second until looping.  Keep this setting low, else we could lose TCP connections
    ThreadAPI_Sleep(1000);
}

void connectionCallback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* userContextCallback)
{
    Serial.println("Connection Status result: " + String(ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS, result)) + " reason: " +
        String(ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, reason)));
}

static int deviceMethodCallback(const char* method_name, const unsigned char* payload,
    size_t size, unsigned char** response, size_t* response_size, void* userContextCallback)
{
    (void)userContextCallback;

    // printing to the screen our Method
    Serial.println("Method: " + String(method_name) + " payload: " + String((char*)payload).substring(0,size));

    // sending a response to the Method
    int result = 200;
    const char responseMessage[] = "{\"response\":\"Success\"}";
    *response_size = sizeof(responseMessage) - 1;
    *response = (unsigned char*)malloc(*response_size);
    (void)memcpy(*response, responseMessage, *response_size);

    return result;
}

static void sendTemperature(int temperature) {
    String  messageString = "{\'Temperature\":";
    messageString += temperature;
    messageString += "}";
    Serial.println("Sending: " + messageString);
    IOTHUB_MESSAGE_HANDLE message = IoTHubMessage_CreateFromString(messageString.c_str());
    IoTHubClient_LL_SendEventAsync(iotHubClientHandle, message, sendMessageCallback, NULL);
}

static void sendMessage(String messageString) {
    // a simple example of sending a message
    Serial.println("Sending: " + messageString);
    IOTHUB_MESSAGE_HANDLE message = IoTHubMessage_CreateFromString(messageString.c_str());
    IoTHubClient_LL_SendEventAsync(iotHubClientHandle, message, sendMessageCallback, NULL);
}

void sendMessageCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
    // we get a callback when the message is receieved by IoT Hub
    messageTrackingId = (unsigned int)(uintptr_t)userContextCallback;
    Serial.println("Message Id: " + String(messageTrackingId) + " status is: "
        + String(ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result)));
}

static IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    // here we process any C2D messages
    IOTHUBMESSAGE_DISPOSITION_RESULT result = IOTHUBMESSAGE_ACCEPTED;
    const unsigned char* buffer;
    size_t size;
    if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK)
    {
        Serial.println("ERROR: unable to IoTHubMessage_GetByteArray");
        result = IOTHUBMESSAGE_ABANDONED;
    }
    else
    {
        /*buffer is not zero terminated*/
        char* temp = (char*)malloc(size + 1);
        if (temp == NULL)
        {
            Serial.println("ERROR: failed to malloc");
            result = IOTHUBMESSAGE_ABANDONED;
        }
        else
        {
            (void)memcpy(temp, buffer, size);
            temp[size] = '\0';
            Serial.println(temp);
            free(temp);
        }
    }
    return result;
}

static void deviceTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad,
    size_t size, void* userContextCallback)
{
    // here we get the full TWIN at boot time or partial TWIN at update
    (void)userContextCallback;
    Serial.println("TWIN Callback: " + String((char*)payLoad).substring(0, size));
}

void setTWINProperty(String TWINproperty, int value) {
    // simple example of setting a TWIN
    String  TWIN = "{\'";
    TWIN += TWINproperty;
    TWIN += "\':";
    TWIN += value;
    TWIN += "}";
    size_t reportedStateSize = strlen(TWIN.c_str());

    (void)IoTHubClient_LL_SendReportedState(iotHubClientHandle, (const unsigned char*)TWIN.c_str(),
        reportedStateSize, reportedStateCallback, iotHubClientHandle);
}

void setTWINProperty(String TWINproperty, String value) {

    String  TWIN = "{\'";
    TWIN += TWINproperty;
    TWIN += "\':\"";
    TWIN += value;
    TWIN += "\"}";
    size_t reportedStateSize = strlen(TWIN.c_str());

    (void)IoTHubClient_LL_SendReportedState(iotHubClientHandle, (const unsigned char*)TWIN.c_str(),
        reportedStateSize, reportedStateCallback, iotHubClientHandle);
}

static void reportedStateCallback(int status_code, void* userContextCallback)
{
    (void)userContextCallback;
    Serial.println("Device Twin reported properties update completed with result: " + String(status_code));
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s