vincent wong
Published © GPL3+

Project KOOL: Temperature and Humidity Remote Monitoring

This KOOL project is a proof-of-concept implementation of temperature and humidity remote monitoring for a cold water delivery company.

IntermediateFull instructions provided10,103

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
×1
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
DELL Inspiron 15
×1
Advantech ARK-1123
×1

Software apps and online services

Microsoft Azure
Microsoft Azure
Visual Studio 2015
Microsoft Visual Studio 2015
Arduino IDE
Arduino IDE

Story

Read more

Code

remote_monitoring.ino

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// Use Arduino IDE 1.6.8 or later.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <WiFi101.h>
#include "remote_monitoring.h"
#include "NTPClient.h"
#include "AzureIoTHubClient.h"

WiFiSSLClient sslClient;
AzureIoTHubClient iotHubClient(sslClient);

static const char ssid[] = "[Your WiFi network SSID or name]";
static const char pass[] = "[Your WiFi network WPA password or WEP key]";

int status = WL_IDLE_STATUS;

void setup() {
    // The Feather M0 loses it's COMn connection with every reset.
    // This 10 s delay allows you to reselect the COM port and open the serial monitor window.
    delay(10000);
    
    initSerial();

    initWifi();
    
    initTime();
}

void loop() {
    // Run the Remote Monitoring from the Azure IoT Hub C SDK
    // You must set the device id, device key, IoT Hub name and IotHub suffix in
    // remote_monitoring.c
    remote_monitoring_run();
}

void initSerial() {
    // Start serial and initialize stdout
    Serial.begin(115200);
    //Serial.setDebugOutput(true);
}

void initWifi() {
    // Attempt to connect to Wifi network:
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);

    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("Connected to wifi");
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void initTime() {
#ifdef ARDUINO_SAMD_FEATHER_M0
    Adafruit_WINC1500UDP     _udp;
#elif defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000)
    WiFiUDP     _udp;
#endif

    time_t epochTime = (time_t)-1;

    NTPClient ntpClient;
    ntpClient.begin();

    while (true) {
        epochTime = ntpClient.getEpochTime("0.pool.ntp.org");

        if (epochTime == (time_t)-1) {
            Serial.println("Fetching NTP epoch time failed! Waiting 5 seconds to retry.");
            delay(5000);
        } else {
            Serial.print("Fetched NTP epoch time is: ");
            Serial.println(epochTime);
            break;
        }
    }
    
    ntpClient.end();

    struct timeval tv;
    tv.tv_sec = epochTime;
    tv.tv_usec = 0;

    settimeofday(&tv, NULL);
}

remote_monitoring.h

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef REMOTE_MONITORING_H
#define REMOTE_MONITORING_H

#ifdef __cplusplus
extern "C" {
#endif

void remote_monitoring_run(void);

#ifdef __cplusplus
}
#endif

#endif /* REMOTE_MONITORING_H */

remote_monitoring.c

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "AzureIoTHub.h"
#include "sdk/schemaserializer.h"
#include "dht11.h"


static const char* deviceId = "[device-id]";
static const char* deviceKey = "[device-key]";
static const char* hubName = "[hub-name]";
static const char* hubSuffix = "azure-devices.net";

// Define the Model
BEGIN_NAMESPACE(Contoso);

DECLARE_STRUCT(SystemProperties,
    ascii_char_ptr, DeviceID,
    _Bool, Enabled
);

DECLARE_STRUCT(DeviceProperties,
ascii_char_ptr, DeviceID,
_Bool, HubEnabledState
);

DECLARE_MODEL(Thermostat,

    /* Event data (temperature, external temperature and humidity) */
    WITH_DATA(int, Temperature),
    WITH_DATA(int, ExternalTemperature),
    WITH_DATA(int, Humidity),
    WITH_DATA(ascii_char_ptr, DeviceId),

    /* Device Info - This is command metadata + some extra fields */
    WITH_DATA(ascii_char_ptr, ObjectType),
    WITH_DATA(_Bool, IsSimulatedDevice),
    WITH_DATA(ascii_char_ptr, Version),
    WITH_DATA(DeviceProperties, DeviceProperties),
    WITH_DATA(ascii_char_ptr_no_quotes, Commands),

    /* Commands implemented by the device */
    WITH_ACTION(SetTemperature, int, temperature),
    WITH_ACTION(SetHumidity, int, humidity)
);

END_NAMESPACE(Contoso);

EXECUTE_COMMAND_RESULT SetTemperature(Thermostat* thermostat, int temperature)
{
    LogInfo("Received temperature %d\r\n", temperature);
    thermostat->Temperature = temperature;
    return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT SetHumidity(Thermostat* thermostat, int humidity)
{
    LogInfo("Received humidity %d\r\n", humidity);
    thermostat->Humidity = humidity;
    return EXECUTE_COMMAND_SUCCESS;
}

static void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
{
    IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
    if (messageHandle == NULL)
    {
        LogInfo("unable to create a new IoTHubMessage\r\n");
    }
    else
    {
        if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
        {
            LogInfo("failed to hand over the message to IoTHubClient");
        }
        else
        {
            LogInfo("IoTHubClient accepted the message for delivery\r\n");
        }

        IoTHubMessage_Destroy(messageHandle);
    }
    free((void*)buffer);
}

/*this function "links" IoTHub to the serialization library*/
static IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubMessage(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    IOTHUBMESSAGE_DISPOSITION_RESULT result;
    const unsigned char* buffer;
    size_t size;
    if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK)
    {
        LogInfo("unable to IoTHubMessage_GetByteArray\r\n");
        result = EXECUTE_COMMAND_ERROR;
    }
    else
    {
        /*buffer is not zero terminated*/
        char* temp = malloc(size + 1);
        if (temp == NULL)
        {
            LogInfo("failed to malloc\r\n");
            result = EXECUTE_COMMAND_ERROR;
        }
        else
        {
            EXECUTE_COMMAND_RESULT executeCommandResult;

            memcpy(temp, buffer, size);
            temp[size] = '\0';
            executeCommandResult = EXECUTE_COMMAND(userContextCallback, temp);
            result =
                (executeCommandResult == EXECUTE_COMMAND_ERROR) ? IOTHUBMESSAGE_ABANDONED :
                (executeCommandResult == EXECUTE_COMMAND_SUCCESS) ? IOTHUBMESSAGE_ACCEPTED :
                IOTHUBMESSAGE_REJECTED;
            free(temp);
        }
    }
    return result;
}

void remote_monitoring_run(void)
{
        initDHT();

        srand((unsigned int)time(NULL));
        if (serializer_init(NULL) != SERIALIZER_OK)
        {
            LogInfo("Failed on serializer_init\r\n");
        }
        else
        {
            IOTHUB_CLIENT_CONFIG config;
            IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;

            config.deviceId = deviceId;
            config.deviceKey = deviceKey;
            config.iotHubName = hubName;
            config.iotHubSuffix = hubSuffix;
            config.protocol = HTTP_Protocol;

            iotHubClientHandle = IoTHubClient_LL_Create(&config);
            if (iotHubClientHandle == NULL)
            {
                LogInfo("Failed on IoTHubClient_CreateFromConnectionString\r\n");
            }
            else
            {
#ifdef MBED_BUILD_TIMESTAMP
                // For mbed add the certificate information
                if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
                {
                    LogInfo("failure to set option \"TrustedCerts\"\r\n");
                }
#endif // MBED_BUILD_TIMESTAMP

                Thermostat* thermostat = CREATE_MODEL_INSTANCE(Contoso, Thermostat);
                if (thermostat == NULL)
                {
                    LogInfo("Failed on CREATE_MODEL_INSTANCE\r\n");
                }
                else
                {
                    STRING_HANDLE commandsMetadata;

                    if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, IoTHubMessage, thermostat) != IOTHUB_CLIENT_OK)
                    {
                        LogInfo("unable to IoTHubClient_SetMessageCallback\r\n");
                    }
                    else
                    {

                        /* send the device info upon startup so that the cloud app knows
                        what commands are available and the fact that the device is up */
                        thermostat->ObjectType = "DeviceInfo";
                        thermostat->IsSimulatedDevice = false;
                        thermostat->Version = "1.0";
                        thermostat->DeviceProperties.HubEnabledState = true;
                        thermostat->DeviceProperties.DeviceID = (char*)deviceId;

                        commandsMetadata = STRING_new();
                        if (commandsMetadata == NULL)
                        {
                            LogInfo("Failed on creating string for commands metadata\r\n");
                        }
                        else
                        {
                            /* Serialize the commands metadata as a JSON string before sending */
                            if (SchemaSerializer_SerializeCommandMetadata(GET_MODEL_HANDLE(Contoso, Thermostat), commandsMetadata) != SCHEMA_SERIALIZER_OK)
                            {
                                LogInfo("Failed serializing commands metadata\r\n");
                            }
                            else
                            {
                                unsigned char* buffer;
                                size_t bufferSize;
                                thermostat->Commands = (char*)STRING_c_str(commandsMetadata);

                                /* Here is the actual send of the Device Info */
                                if (SERIALIZE(&buffer, &bufferSize, thermostat->ObjectType, thermostat->Version, thermostat->IsSimulatedDevice, thermostat->DeviceProperties, thermostat->Commands) != IOT_AGENT_OK)
                                {
                                    LogInfo("Failed serializing\r\n");
                                }
                                else
                                {
                                    sendMessage(iotHubClientHandle, buffer, bufferSize);
                                }

                            }

                            STRING_delete(commandsMetadata);
                        }

                        thermostat->DeviceId = (char*)deviceId;
                        int sendCycle = 10;
                        int currentCycle = 0;
                        while (1)
                        {
                            if(currentCycle >= sendCycle) {
                                float Temp;
                                float Humi;
                                getNextSample(&Temp, &Humi);
                                thermostat->Temperature = (int)round(Temp);
                                thermostat->ExternalTemperature = 55 + (rand() % 5 + 2);
                                thermostat->Humidity = (int)round(Humi);
                                currentCycle = 0;
                                unsigned char*buffer;
                                size_t bufferSize;

                                LogInfo("Sending sensor value Temperature = %d, Humidity = %d\r\n", thermostat->Temperature, thermostat->Humidity);

                                if (SERIALIZE(&buffer, &bufferSize, thermostat->DeviceId, thermostat->Temperature, thermostat->Humidity, thermostat->ExternalTemperature) != IOT_AGENT_OK)
                                {
                                    LogInfo("Failed sending sensor value\r\n");
                                }
                                else
                                {
                                    sendMessage(iotHubClientHandle, buffer, bufferSize);
                                }
                            }

                            IoTHubClient_LL_DoWork(iotHubClientHandle);
                            ThreadAPI_Sleep(100);
                            currentCycle++;
                        }
                    }

                    DESTROY_MODEL_INSTANCE(thermostat);
                }
                IoTHubClient_LL_Destroy(iotHubClientHandle);
            }
            serializer_deinit();

    }
}

NTPClient.h

C/C++
// Copyright (c) Arduino. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifdef ARDUINO_SAMD_FEATHER_M0
#include <Adafruit_WINC1500.h>
#include <Adafruit_WINC1500Udp.h>
#elif defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000)
#include <WiFi101.h>
#include <WiFiUdp.h>
#endif

#ifndef NTPCLIENT_H
#define NTPCLIENT_H

#define NTP_PACKET_SIZE     48
#define NTP_PORT            123

#define DEFAULT_NTP_TIMEOUT 10000

class NTPClient
{
    public:
        NTPClient();
        int begin();
        uint32_t getEpochTime(const char* host, int port = NTP_PORT, unsigned long timeout = DEFAULT_NTP_TIMEOUT);
        void end();

    private:
        void prepareRequest();
        void sendRequest(const char* host, int port);
        int receiveResponse(unsigned long timeout);
        uint32_t parseResponse();

        char        _buffer[NTP_PACKET_SIZE];
#ifdef ARDUINO_SAMD_FEATHER_M0
        Adafruit_WINC1500UDP     _udp;
#elif defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000)
        WiFiUDP     _udp;
#endif

};

#endif

NTPClient.cpp

C/C++
// Copyright (c) Arduino. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if defined(ARDUINO_ARCH_SAMD)
#include "NTPClient.h"

#define LOCAL_UDP_PORT 2390

NTPClient::NTPClient() :
    _udp()
{
}

int NTPClient::begin()
{
    return _udp.begin(LOCAL_UDP_PORT);
}

uint32_t NTPClient::getEpochTime(const char* host, int port, unsigned long timeout)
{
    if (host == NULL || port < 1) {
        return (uint32_t)-1;
    }

    prepareRequest();
    sendRequest(host, port);

    if (!receiveResponse(timeout)) {
        return (uint32_t)-1;
    }

    return parseResponse();
}

void NTPClient::end()
{
    _udp.stop();
}

void NTPClient::prepareRequest()
{
    memset(_buffer, 0, NTP_PACKET_SIZE);

    // Initialize values needed to form NTP request
    _buffer[0] = 0b11100011;   // LI, Version, Mode
    _buffer[1] = 0;     // Stratum, or type of clock
    _buffer[2] = 6;     // Polling Interval
    _buffer[3] = 0xEC;  // Peer Clock Precision

    // 8 bytes of zero for Root Delay & Root Dispersion

    _buffer[12] = 49;
    _buffer[13] = 0x4E;
    _buffer[14] = 49;
    _buffer[15] = 52;
}

void NTPClient::sendRequest(const char* host, int port)
{
    _udp.beginPacket(host, port);
    _udp.write(_buffer, NTP_PACKET_SIZE);
    _udp.endPacket();
}

int NTPClient::receiveResponse(unsigned long timeout)
{
    long start = millis();
    int size = 0;

    while(size == 0 && (millis() - start) < timeout) {
        size = _udp.parsePacket();
    }

    if (size != NTP_PACKET_SIZE) {
        return 0;
    }

    _udp.read(_buffer, NTP_PACKET_SIZE);

    return 1;
}

uint32_t NTPClient::parseResponse()
{
    uint16_t high = word(_buffer[40], _buffer[41]);
    uint16_t low = word(_buffer[42], _buffer[43]);
    uint32_t ntpTime = high << 16 | low; // since 1900
    uint32_t epoch = ntpTime - 2208988800UL; // since 1970

    return epoch;
}
#endif

dht11.h

C/C++
#ifndef __DHT11_H
#define __DHT11_H


#ifdef __cplusplus
extern "C" {
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////
void initDHT(void);

///////////////////////////////////////////////////////////////////////////////////////////////////
void getNextSample(float* Temperature, float* Humidity);

#ifdef __cplusplus
}
#endif


#endif//__DHT11_H

dht11.cpp

C/C++
#include <Arduino.h>
#include "DHT.h"
#include "dht11.h"

#define DHTPIN 2     // what digital pin we're connected to
#define DHTTYPE DHT11   // DHT 11

DHT dht(DHTPIN, DHTTYPE);

bool DHT_init_result = false;


///////////////////////////////////////////////////////////////////////////////////////////////////
void initDHT(void)
{
dht.begin();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void getNextSample(float* Temperature, float* Humidity)
{
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  *Humidity = dht.readHumidity();
  // Read temperature as Celsius (the default)
  *Temperature = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  // float f = dht.readTemperature(true);

  //printf("Temp=%.2f, Pres=%.2f, Humi=%.2f\n", Temp_c__f, Pres_hPa__f, Humi_pct__f);
  printf("Temp=%.2f, Humi=%.2f\n", *Temperature, *Humidity);
}

RMDevice.c

C/C++
// RMDevice.cpp : Defines the entry point for the console application.
//

#include "iothubtransporthttp.h"
#include "schemalib.h"
#include "iothub_client.h"
#include "serializer.h"
#include "schemaserializer.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"
#include "stdlib.h"
#include <math.h>



static const char* deviceId = "DHL_Cyberjaya";
static const char* deviceKey = "devicekey";
static const char* hubName = "hubname";
static const char* hubSuffix = "azure-devices.net";

struct RandomGeneratorParam {
	double maximumFractionToChangePerTick;
	double minValueToGenerate;
	double maxNonPeakValueToGenerate;
	double minPeakValueToGenerate;
	bool generatePeaks;
	int peakInterval;
	double startValue;
	double nextValue;
	double deltaValue;
	double thresholdWidth;
	long tickCounter;
};

struct RandomGeneratorParam temperatureParam, humidityParam;

void CheckParams(struct RandomGeneratorParam *param) {
	(*param).maximumFractionToChangePerTick = 0.10;

	if ((*param).minValueToGenerate >= (*param).maxNonPeakValueToGenerate) {
		exit(1);
	}
	
	if ((*param).minPeakValueToGenerate != 0 && ((*param).maxNonPeakValueToGenerate >= (*param).minPeakValueToGenerate)) {
		exit(1);
	}

	(*param).generatePeaks = (*param).minPeakValueToGenerate != 0 ? true : false;

	if ((*param).generatePeaks && (*param).peakInterval == 0) {
		exit(1);
	}

	(*param).minPeakValueToGenerate = (*param).minPeakValueToGenerate * 1.01;

	(*param).startValue = (((*param).maxNonPeakValueToGenerate - (*param).minValueToGenerate) / 2.0) + (*param).minValueToGenerate;
	(*param).nextValue = (*param).startValue;

	(*param).deltaValue = ((*param).maxNonPeakValueToGenerate - (*param).minValueToGenerate) * (*param).maximumFractionToChangePerTick;
	(*param).thresholdWidth = (*param).minPeakValueToGenerate - (*param).minValueToGenerate;
	
	(*param).tickCounter = 1;

}

void GetNextRawValue(struct RandomGeneratorParam *param) {
	double val = (double)rand() / RAND_MAX;
	double adjustment = ((2.0 * (*param).deltaValue) * val) - (*param).deltaValue;
	(*param).nextValue += adjustment;

	if ((*param).nextValue < (*param).minValueToGenerate || (*param).nextValue >(*param).maxNonPeakValueToGenerate) {
		(*param).nextValue -= adjustment;

		if ((*param).nextValue < (*param).minValueToGenerate || (*param).nextValue >(*param).maxNonPeakValueToGenerate) {
			(*param).nextValue = (*param).startValue;
		}
	}
}

double GetNextValue(struct RandomGeneratorParam *param) {
	GetNextRawValue(param);
	bool determinePeak = (*param).generatePeaks && ((*param).tickCounter % (*param).peakInterval) == 0;
	++((*param).tickCounter);
	if (determinePeak) {
		return (*param).nextValue + (*param).thresholdWidth;
	}
	return (*param).nextValue;
}


// Define the Model
BEGIN_NAMESPACE(Contoso);

DECLARE_STRUCT(SystemProperties,
ascii_char_ptr, DeviceID,
_Bool, Enabled
);

DECLARE_STRUCT(DeviceProperties,
ascii_char_ptr, DeviceID,
_Bool, HubEnabledState
);

DECLARE_MODEL(Thermostat,

/* Event data (temperature, external temperature and humidity) */
WITH_DATA(double, Temperature),
//WITH_DATA(int, ExternalTemperature),
WITH_DATA(double, Humidity),
WITH_DATA(ascii_char_ptr, DeviceId),

/* Device Info - This is command metadata + some extra fields */
WITH_DATA(ascii_char_ptr, ObjectType),
WITH_DATA(_Bool, IsSimulatedDevice),
WITH_DATA(ascii_char_ptr, Version),
WITH_DATA(DeviceProperties, DeviceProperties),
WITH_DATA(ascii_char_ptr_no_quotes, Commands),

/* Commands implemented by the device */
WITH_ACTION(SetTemperature, int, temperature),
WITH_ACTION(SetHumidity, int, humidity)
);

END_NAMESPACE(Contoso);


EXECUTE_COMMAND_RESULT SetTemperature(Thermostat* thermostat, int temperature)
{
	(void)printf("Received temperature %d\r\n", temperature);
	thermostat->Temperature = temperature;
	return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT SetHumidity(Thermostat* thermostat, int humidity)
{
	(void)printf("Received humidity %d\r\n", humidity);
	thermostat->Humidity = humidity;
	return EXECUTE_COMMAND_SUCCESS;
}


static void sendMessage(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
{
	IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
	if (messageHandle == NULL)
	{
		printf("unable to create a new IoTHubMessage\r\n");
	}
	else
	{
		if (IoTHubClient_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
		{
			printf("failed to hand over the message to IoTHubClient");
		}
		else
		{
			printf("IoTHubClient accepted the message for delivery\r\n");
		}

		IoTHubMessage_Destroy(messageHandle);
	}
	free((void*)buffer);
}



static IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubMessage(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
	IOTHUBMESSAGE_DISPOSITION_RESULT result;
	const unsigned char* buffer;
	size_t size;
	if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK)
	{
		printf("unable to IoTHubMessage_GetByteArray\r\n");
		result = EXECUTE_COMMAND_ERROR;
	}
	else
	{
		/*buffer is not zero terminated*/
		char* temp = malloc(size + 1);
		if (temp == NULL)
		{
			printf("failed to malloc\r\n");
			result = EXECUTE_COMMAND_ERROR;
		}
		else
		{
			memcpy(temp, buffer, size);
			temp[size] = '\0';
			EXECUTE_COMMAND_RESULT executeCommandResult = EXECUTE_COMMAND(userContextCallback, temp);
			result =
				(executeCommandResult == EXECUTE_COMMAND_ERROR) ? IOTHUBMESSAGE_ABANDONED :
				(executeCommandResult == EXECUTE_COMMAND_SUCCESS) ? IOTHUBMESSAGE_ACCEPTED :
				IOTHUBMESSAGE_REJECTED;
			free(temp);
		}
	}
	return result;
}


void remote_monitoring_run(void)
{
	if (serializer_init(NULL) != SERIALIZER_OK)
	{
		printf("Failed on serializer_init\r\n");
	}
	else
	{
		IOTHUB_CLIENT_CONFIG config;
		IOTHUB_CLIENT_HANDLE iotHubClientHandle;

		config.deviceId = deviceId;
		config.deviceKey = deviceKey;
		config.iotHubName = hubName;
		config.iotHubSuffix = hubSuffix;
		config.protocol = HTTP_Protocol;
		config.deviceSasToken = NULL;
		config.protocolGatewayHostName = NULL;
		iotHubClientHandle = IoTHubClient_Create(&config);
		if (iotHubClientHandle == NULL)
		{
			(void)printf("Failed on IoTHubClient_CreateFromConnectionString\r\n");
		}
		else
		{
			Thermostat* thermostat = CREATE_MODEL_INSTANCE(Contoso, Thermostat);
			if (thermostat == NULL)
			{
				(void)printf("Failed on CREATE_MODEL_INSTANCE\r\n");
			}
			else
			{
				STRING_HANDLE commandsMetadata;

				if (IoTHubClient_SetMessageCallback(iotHubClientHandle, IoTHubMessage, thermostat) != IOTHUB_CLIENT_OK)
				{
					printf("unable to IoTHubClient_SetMessageCallback\r\n");
				}
				else
				{

					/* send the device info upon startup so that the cloud app knows
					what commands are available and the fact that the device is up */
					thermostat->ObjectType = "DeviceInfo";
					thermostat->IsSimulatedDevice = false;
					thermostat->Version = "1.0";
					thermostat->DeviceProperties.HubEnabledState = true;
					thermostat->DeviceProperties.DeviceID = (char*)deviceId;

					commandsMetadata = STRING_new();
					if (commandsMetadata == NULL)
					{
						(void)printf("Failed on creating string for commands metadata\r\n");
					}
					else
					{
						/* Serialize the commands metadata as a JSON string before sending */
						if (SchemaSerializer_SerializeCommandMetadata(GET_MODEL_HANDLE(Contoso, Thermostat), commandsMetadata) != SCHEMA_SERIALIZER_OK)
						{
							(void)printf("Failed serializing commands metadata\r\n");
						}
						else
						{
							unsigned char* buffer;
							size_t bufferSize;
							thermostat->Commands = (char*)STRING_c_str(commandsMetadata);

							/* Here is the actual send of the Device Info */
							if (SERIALIZE(&buffer, &bufferSize, thermostat->ObjectType, thermostat->Version, thermostat->IsSimulatedDevice, thermostat->DeviceProperties, thermostat->Commands) != IOT_AGENT_OK)
							{
								(void)printf("Failed serializing\r\n");
							}
							else
							{
								sendMessage(iotHubClientHandle, buffer, bufferSize);
							}

						}

						STRING_delete(commandsMetadata);
					}



					const int REPORT_FREQUENCY_IN_SECONDS = 5;
					const int PEAK_FREQUENCY_IN_SECONDS = 90;

					int peakFrequencyInTicks = ceil((double)PEAK_FREQUENCY_IN_SECONDS / REPORT_FREQUENCY_IN_SECONDS);

					humidityParam.minValueToGenerate = 20;
					humidityParam.maxNonPeakValueToGenerate = 50;
					humidityParam.minPeakValueToGenerate = 0;
					humidityParam.peakInterval = 0;

					CheckParams(&humidityParam);

					temperatureParam.minValueToGenerate = 33;
					temperatureParam.maxNonPeakValueToGenerate = 36;
					temperatureParam.minPeakValueToGenerate = 42;
					temperatureParam.peakInterval = peakFrequencyInTicks;

					CheckParams(&temperatureParam);

					while (1)
					{
						unsigned char*buffer;
						size_t bufferSize;


						//thermostat->ExternalTemperature = 35;

						thermostat->Temperature = GetNextValue(&temperatureParam);
						thermostat->Humidity = GetNextValue(&humidityParam);

						thermostat->DeviceId = (char*)deviceId;

						(void)printf("Sending sensor value Temperature = %lf, Humidity = %lf\r\n", thermostat->Temperature, thermostat->Humidity);

						if (SERIALIZE(&buffer, &bufferSize, thermostat->DeviceId, thermostat->Temperature, thermostat->Humidity) != IOT_AGENT_OK)
						{
							(void)printf("Failed sending sensor value\r\n");
						}
						else
						{
							sendMessage(iotHubClientHandle, buffer, bufferSize);
						}

						ThreadAPI_Sleep(2000);
					}
				}

				DESTROY_MODEL_INSTANCE(thermostat);
			}
			IoTHubClient_Destroy(iotHubClientHandle);
		}
		serializer_deinit();
	}
}



int main()
{
	time_t t;

	/* Intializes random number generator */
	srand((unsigned)time(&t));

	remote_monitoring_run();
	return 0;
}

Credits

vincent wong

vincent wong

80 projects • 202 followers

Comments