Project tutorial
Event Monitor for Independent Senior Citizens

Event Monitor for Independent Senior Citizens © LGPL

Cost and availability of retirement villages cause aging people to stay in their own homes. This system monitors their daily events.

  • 3,959 views
  • 4 comments
  • 26 respects

Components and supplies

About this project

About this project

The aging population of the world presents enormous financial challenges. There are not enough retirement facilities to cater the needs of the elderly and costs are high. The tendency is that elderly people prefer staying in their own homes for longer. That makes the elderly more independent and happier, but risks are higher when they fall or experience health or security problems. Sometimes that is only discovered hours or days after the incident.

With this non-invasive system daily events can be monitored and recorded and a set of rules can be applied to generate an alarm condition. This includes:

  • opening and closing doors
  • switching lights on or off
  • using electrical appliances
  • movement in various locations in the house
  • temperature measurement
  • panic button
  • fall detection (monitor worn by elderly)

A summary of this information will be sent to the cloud. With the monitor app users with access to the service will be able to monitor various statuses and will be alerted of emergency situations. These users may include family, friends, emergency services and health services.


Infrastructure Needed to Provide the Service:

  • one or more wifi sensor nodes to collect relevant data
  • wifi network infrastructure
  • data cloud storage and service infrastructure
  • client app to display cloud collected data and control sensor nodes via the cloud

A number of different sensors are used to accumulate data for a rules based system, which will send alerts when events do not follow a normal pattern. These include, but are not restricted to:

  • a) accelerometer - vibration (eg. fridge running), orientation or fall detection (where the device is worn by the person), objects being moved (sensor device attached to the object)
  • b) light sensor - to determine whether lights are on and/or sun is shining (curtains drawn of not)
  • c) temperature - to measure room temperature (too hot or too cold)
  • d) magnetic switch OR motion monitor contact - to determine when a door is opened or closed (when not supposed to) OR lack thereof (which may be an abnormal condition) OR lack of motion (for a period of time in a specific time slot)

All these events are time stamped, so that rules can include time of day, time slots and time span.

A bi-color LED and buzzer is used to communicate remote messages and as local alarm when the internet is not available. Messages may include reminders like medication, time to feed the cat, time for a meal, etc.

The assumption is that a wifi router, which is connected to the internet, will be available. The wifi sensor node makes use of DHCP to obtain an IP address.

Cloud Environment

The wifi sensor node currently makes use of a free subscription to the Microsoft Azure IoT Hub to store data. Setup and tools will be described in the software section.

As a proof of concept I used the Azure Device Monitor software to analyze data and to send commands to my MKR1000 sensor node via Azure IoT Hub.

I also installed the Azure IoT Suite and had a look at their example application (more under software).

In future a Windows 10 app will be used to display data (light level, temperature) and alerts (fall, door open) from Azure IoT Hub and to send signal commands to wifi sensor nodes via the hub. 

Hardware Setup

Initially I did my prototype on a breadboard, as shown in the first picture. The second picture shows the schematic. Towards the end I decided to do a more permanent setup for testing and I built the circuit on prototype board, as seen in the project picture. The Fritzing file is available under uploaded files.


Software Development Setup

If you are not currently running Arduino IDE version 1.6.7, download it from here 

https://www.arduino.cc/en/Main/OldSoftwareReleases 

and install. The MKR1000 forum will help to set up the board

http://forum.arduino.cc/index.php?topic=380369.msg2622600#msg2622600

Upgrade to MKR1000 core version 1.6.4-mkr02, which contains a crucial fix for a condition that destroys the bootloader. Install the latest Arduino Wifi101 library.

Setup the Arduino IDE for MKR1000, plug the module into a usb port and ensure that the correct serial port is selected. There are good example sketches in Wifi101 to turn the module into a webclient or webserver. Try these out to ensure that your board is working properly. Change ssid and pass to connect to your own wifi router.

Refer to the hardware schematics and component list to prepare the wifi sensor node. The pinouts are well documented in the Arduino sketch. 

Initially I planned on using Windows Remote Arduino, which is a Windows 10 environment that uses firmata protocol to "take over" the Arduino. This would poll remote sensors from a Windows app. Due to the unpredictable nature of accelerometer data I decided against this method, in favor of pushing sensor data to the cloud. The obvious choice was Microsoft Azure IoT Hub.

MKR1000 Sensor Node Sketch

I am thrilled to be in the group of 1000 to familiarize myself with the MKR1000. Initially I worked through example sketches in the Wifi101 library. After I defined the goal of my project I made a decision on the sensors and other components I would use, preferably in stock items. I collected libraries and examples for LDR light dependent resistor, DS18B20 temperature sensor, ADXL345 accelerometer, switch, bi-color LED, buzzer and tested them individually on a breadboard. I had to quickly learn Fritzing to do the schematic and breadboard layout (see hardware setup).

I received lots of help from members on the MKR1000 forum, as well as other hobbyists (see references). At this stage I had only heard about Azure, but I decided to use it for cloud data storage anyway. The vast capabilities of the Azure cloud platform was quite confusing. Fortunately Mohan Palanisami (mohanp) did a good article on connecting to Azure IoT Hub. A "simple C" sample on azure-iot-sdks looked promising, but it was not that simple after all and I did not like the 100k+ size of my sketch. I noticed that mohanp only used around 30k, so I decided to use his sketch as basis. Initially I used the JSON structure in the connect the dots library examples, but now I am using a very neat JSON library for generating strings.

In the main loop there are basic local rules for determining an event condition (temperature changing x degrees, light level changing y lumens, accelerometer events, battery voltage falling under 3.3V). When an event occurs the data gets sent to Azure IoT Hub, where a secondary set of rules is applied on the data to decide on an alarm condition (abnormal events in specific time slots or time spans). Currently this is not implemented, but the Azure IoT Suite example shows how it can be done. 

 Further work needs to be done to decode combinations of accelerometer "words" (INACTIVITY, ACTIVITY, TAP, DOUBLE TAP, FALL DETECT) into real life events (like fall, object moved, vibration stopped). 

With the extension of the deadline I managed to add more functionality:

  • JSON generation is simplified by using JSON library calls. The JSON string is also simplified.
  • Commands received from Azure IoT Hub via the Device Explorer "messages to device" tab are executed on the MKR1000.  Examples are beepon/beepoff to turn the buzzer on of off. Similarly this could in future be used to turn a relay on/off to control electrical devices.
  • I moved from the Arduino IDE environment to Visual Studio with Visual Micro, Azure IoT Hub and Github extensions. I posted my local library to Github from here.

Azure Hub Setup

If you are not already using Azure you can subscribe to a free account. Use the Azure portal to create you own IoT Hub (mine is called MKR1000hub)

https://azure.microsoft.com/en-in/documentation/articles/iot-hub-csharp-csharp-getstarted/

To enable you to create and explore devices on Azure install Device Explorer for IoT Hub devices 

https://github.com/Azure/azure-iot-sdks/blob/master/tools/DeviceExplorer/doc/how_to_use_device_explorer.md

Configure the Device Explorer by using the IoT Hub Connection String and Protocol Gateway Hostname from Azure portal.  Go to the Management tab to create a device. Use this connection string in the MKR1000 sensor node sketch. The Data tab enables you to display the JSON messages sent to Azure. The Messages to Device tab enable you to send messages to the MKR1000 sensor node (as described in the sketch section).

Azure IoT Suite

An excellent example application monitors and displays temperature and humidity. That together with the ease of registering new devices and the rules engine makes it ideal for my project. I adapted my sketch to send data to the sample Azure IoT Hub, which according to Device Explorer worked. The device showed up in the IoT Device Portal, but the status stayed "pending". More people complained about getting the same results sending from Arduino, but could not get any clarity on solving the problem. I could also not find documentation on the JSON schema they use. I tried to reverse engineer it by looking at the sample data in Device Explorer, but I may still be missing something.

References

1. MKR1000 Azure IoT Hub Interface Using HTTP

 http://mohanp.com/mkr1000-azure-iot-hub-how-to/ 

2. Connect the Dots libraries examples of JSON structures

https://github.com/Azure/connectthedots/tree/master/Devices/GatewayConnectedDevices/Arduino%20UNO 

3. Detecting Human Falls with a 3-Axis Digital Accelerometer

http://www.analog.com/library/analogdialogue/archives/43-07/fall_detector.html 

4. ADXL345 accelerometer plus Arduino - tap, double tap, fall, activity, inactivity

http://bildr.org/2011/03/adxl345-arduino/ 

5. Run a simple C sample on Arduino WiFi Shield 101 and MKR1000 device

https://github.com/Azure/azure-iot-sdks/blob/master/doc/get_started/arduinoide-arduino-wifi101-c.md 

6. IoT device management using Azure IoT Suite and Azure IoT Hub

https://github.com/Azure/azure-content/blob/master/articles/iot-hub/iot-hub-device-management.md 

7. Arduino JSON library

https://github.com/bblanchon/ArduinoJson 

Code

MKR1000 Azure Sensor Node SketchArduino
This sketch runs on the MKR1000 and is used to collect sensor data which an essential part of my project. This will be used determine when abnormal events occur in the daily routine of the elderly who whom I have developed this system. This version simplifies JSON generation by the use of library calls. Extra functionality was also added to receive and execute commands from Device Explorer.
/* MKR1000Azure.ino - MKR1000 Azure IoT HTTP client with sensors sending data to Azure IoT Suit example

Tested joepvanwyk 11 Mar 2016 - adapted from MKRAzure.ino written by Mohan Palanisamy (http://mohanp.com)
Instructions are here to properly set up the MKR1000 for SSL connections http://mohanp.com/mkr1000-azure-iot-hub-how-to/

Additional code used from sample sketches:
------------------------------------------
Connectthedots - DS18B20.ino					// temperature sensor code outputs degrees Centigrade
Bildr		  - ADXL345_Example.ino			// ADXL345 accelerometer statuses INACTIVITY, ACTIVITY, FALL DETECT, TAP, DOUBLE TAP
Github		  - JsonGeneratorExample.ino	// Benoit Blanchon's Json library example simplifies JSON generation parts of mohanp's code

MKR1000 pinouts:
----------------
LDR analog			A0		2
Battery voltage		A1		3
LED red				D0		9
LED green			D1		10
DS18B20 signal		D2		11
ADXL345 INT1			?
Buzzer				D3		12
Switch				D4		13
MKR1000_LED			D6		15				// internal LED
ADXL345 SDA			D11		21
ADXL345 SCL			D12		22

GND							25
Vcc							26
Vin							27

Rules for posting data to Azure:
--------------------------------
1. Temperature changes by more than 0.5 degrees C
2. Accelerometer combination of statuses defines action
3. Light level changes by more than 100 units
4. Battery voltage falls below 3.3V
5. Switch status changes (door open or close)


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

*/

#include <SPI.h>
#include <WiFi101.h>
#include <Wire.h>
#include <ADXL345.h>
#include <OneWire.h> 
#include <avr/dtostrf.h>
#include <ArduinoJson.h>

// WiFi Network Config 
char ssid[] = "wlan-ap"; 		//  your network SSID (name)
char pass[] = "qwerty123";		// your network password (use for WPA, or use as key for WEP)

								// Device Explorer - Protocol Gateway Hostname
char hostname[] = "RethinkAzureSensorNode.azure-devices.net";
// IoT Hub Connection String: HostName=RethinkAzureSensorNode.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=yypCMvmAHIZDSKN2CYxVilHeliTau42EvlBd/QmSC9o= 

// Device Explorer - Generated SAS
char authSAS[] = "SharedAccessSignature sr=RethinkAzureSensorNode.azure-devices.net&sig=g%2bQHMLYInsPrvbmyeC9QRsA6kutL8dQTpz5ruR%2b%2fiY0%3d&se=1490453142&skn=iothubowner";

char feeduri[] = "/devices/RethinkAzureSuite01/messages/devicebound?api-version=2016-02-03"; // feed URI
char azurePOST_Uri[] = "/devices/RethinkAzureSuite01/messages/events?api-version=2016-02-03"; // feed POST Uri

																							  // message Complete/Reject/Abandon URIs.  "etag" will be replaced with the message id E-Tag recieved from recieve call.
String azureComplete = "/devices/RethinkAzureSuite01/messages/devicebound/etag?api-version=2016-02-03";
String azureReject = "/devices/RethinkAzureSuite01/messages/devicebound/etag?reject&api-version=2016-02-03";
String azureAbandon = "/devices/RethinkAzureSuite01/messages/devicebound/etag/abandon?&api-version=2016-02-03";

char DeviceID[] = "RethinkAzureSuite01";

char buffer[256];		// JSON data buffer


						// Sensor stuff
#define ldrPin		A0			// light sensor
#define batPin		A1			// battery voltage
#define LED_red		0			// red status led
#define LED_green	1			// green status led
#define DS18S20_Pin 2 			// DS18S20 Signal pin
#define Buzzer		3			// sound output
#define swPin		4			// switch input
#define MKR1000_LED 6			// internal LED

float prevtemp = 0;
float prevacc = 0;
float prevlight = 0;
float prevbattery = 0;
int prevswitch = 0;

unsigned long time_last = millis();
unsigned long time_new = millis();
int polltime = 5;						// minimum time between sending to Azure

int status = WL_IDLE_STATUS;

OneWire ds(DS18S20_Pin); 				// instantiate temperature object	 
ADXL345 adxl; 							// variable adxl is an instance of the ADXL345 library
WiFiSSLClient client;					// instantiate wifi object
void setup()
{

	/* serial is for debugging  */
	Serial.begin(9600);
	int i;
	while (!Serial) { if (i++ >= 512) break; }			// wait for serial to connect

														// setup I/Os
	pinMode(LED_red, OUTPUT);			// status LED red
	digitalWrite(LED_red, HIGH);		// high is off
	pinMode(LED_green, OUTPUT); 		// status LED green
	digitalWrite(LED_green, HIGH);	// high is off
	pinMode(Buzzer, OUTPUT);			// sound out
	digitalWrite(Buzzer, LOW);		// low is off
	pinMode(MKR1000_LED, OUTPUT);		// internal LED
	pinMode(swPin, INPUT);			// external switch


									// ADXL345 accelerometer setup
	adxl.powerOn();
	//set activity/ inactivity thresholds (0-255)
	adxl.setActivityThreshold(75); //62.5mg per increment
	adxl.setInactivityThreshold(75); //62.5mg per increment
	adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
								//look of activity movement on this axes - 1 == on; 0 == off 
	adxl.setActivityX(1);
	adxl.setActivityY(1);
	adxl.setActivityZ(1);
	//look of inactivity movement on this axes - 1 == on; 0 == off
	adxl.setInactivityX(1);
	adxl.setInactivityY(1);
	adxl.setInactivityZ(1);
	//look of tap movement on this axes - 1 == on; 0 == off
	adxl.setTapDetectionOnX(0);
	adxl.setTapDetectionOnY(0);
	adxl.setTapDetectionOnZ(1);
	//set values for what is a tap, and what is a double tap (0-255)
	adxl.setTapThreshold(50); //62.5mg per increment
	adxl.setTapDuration(15); //625s per increment
	adxl.setDoubleTapLatency(80); //1.25ms per increment
	adxl.setDoubleTapWindow(200); //1.25ms per increment
								  //set values for what is considered freefall (0-255)
	adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
	adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
								  //setting all interupts to take place on int pin 1
								  //I had issues with int pin 2, was unable to reset it
	adxl.setInterruptMapping(ADXL345_INT_SINGLE_TAP_BIT, ADXL345_INT1_PIN);
	adxl.setInterruptMapping(ADXL345_INT_DOUBLE_TAP_BIT, ADXL345_INT1_PIN);
	adxl.setInterruptMapping(ADXL345_INT_FREE_FALL_BIT, ADXL345_INT1_PIN);
	adxl.setInterruptMapping(ADXL345_INT_ACTIVITY_BIT, ADXL345_INT1_PIN);
	adxl.setInterruptMapping(ADXL345_INT_INACTIVITY_BIT, ADXL345_INT1_PIN);
	//register interupt actions - 1 == on; 0 == off  
	adxl.setInterrupt(ADXL345_INT_SINGLE_TAP_BIT, 1);
	adxl.setInterrupt(ADXL345_INT_DOUBLE_TAP_BIT, 1);
	adxl.setInterrupt(ADXL345_INT_FREE_FALL_BIT, 1);
	adxl.setInterrupt(ADXL345_INT_ACTIVITY_BIT, 1);
	adxl.setInterrupt(ADXL345_INT_INACTIVITY_BIT, 1);

	//check for the presence of the shield:
	if (WiFi.status() == WL_NO_SHIELD) {
		// don't continue:
		while (true);
	}

	// attempt to connect to Wifi network:
	while (status != WL_CONNECTED) {
		status = WiFi.begin(ssid, pass);
		// wait 10 seconds for connection:
		delay(10000);
	}

}

void loop()
	{
		// Check for messages from Azure IoT Hub and process them
		azureHttpMessage();

		// Read accelerometer and send to Azure
		int acc = getAccelerometer();
		if (acc > 0) {					    // acceleration action sensed
			if (wifiConnect()) {
				prevacc = acc;
				LED_blink(LED_red, 50, 1);
				httpRequest("POST", azurePOST_Uri, "", buffer); 			// buffer contains JSON data
				delay(polltime);
			}
		}

		// Read temperature and send to Azure
		float temp = getTemp();
		float temp1 = (temp - prevtemp);
		if (abs(temp1) > 1) {				// temperature changed by more than 1 degrees C
			if (wifiConnect()) {
				prevtemp = temp;
				LED_blink(LED_red, 50, 2);
				httpRequest("POST", azurePOST_Uri, "", buffer); 			// buffer contains JSON data
				delay(polltime);				// minimum poll time in seconds
			}
		}

		// Read lightlevel and send to Azure
		float light = getLight();
		float light1 = (light - prevlight);
		if (abs(light1) > 100) {				// light level changed more than 100 units
			if (wifiConnect()) {
				prevlight = light;
				LED_blink(LED_red, 50, 3);
				httpRequest("POST", azurePOST_Uri, "", buffer); 			// buffer contains JSON data
				delay(polltime);				// minimum poll time in seconds
			}
		}

		// Read battery voltage and send to Azure
		float battery = getBatteryV();
		float battery1 = (battery - prevbattery);
		if (abs(battery1) > 100) {			// battery voltage changed more than 0.5V
			if (wifiConnect()) {
				prevbattery = battery;
				LED_blink(LED_red, 50, 4);
				httpRequest("POST", azurePOST_Uri, "", buffer); 			// buffer contains JSON data
				delay(polltime);				// minimum poll time in seconds
			}
		}

		int switchstatus = getSwitch();
		if (!(switchstatus == prevswitch)) {
			if (wifiConnect()) {
				prevswitch = switchstatus;
				LED_blink(LED_red, 50, 5);
				httpRequest("POST", azurePOST_Uri, "", buffer); 			// buffer contains JSON data
				delay(polltime);				// minimum poll time in seconds
			}
		}

		time_new = millis();
		if ((time_new - time_last) > 20000) {
			LED_blink(LED_green, 50, 2);
			time_last = millis();
			azureIoTReceiveMessage();			// send Azure request for message
		}
	}


/************ Read temperature ************/

float getTemp() {
	//returns the temperature from one DS18S20 in Centigrade
	byte data1[12];
	byte addr[8];

	if (!ds.search(addr)) {
		//no more sensors on chain, reset search
		ds.reset_search();
		return -1000;
	}

	if (OneWire::crc8(addr, 7) != addr[7]) {
		return -1000;
	}

	if (addr[0] == 0x10) {
		//Sensor is a DS18S20
	}
	else if (addr[0] == 0x28) {
		//Sensor is a DS18BS20
	}
	else
	{
		return -1000;
	}

	ds.reset();
	ds.select(addr);
	ds.write(0x44, 1); // start conversion, with parasite power on at the end

	byte present = ds.reset();
	ds.select(addr);
	ds.write(0xBE); // Read Scratchpad


	for (int i = 0; i < 9; i++) { // we need 9 bytes
		data1[i] = ds.read();
	}

	ds.reset_search();

	byte MSB = data1[1];
	byte LSB = data1[0];

	float tempRead = ((MSB << 8) | LSB); //using two's compliment
	float TemperatureSum = tempRead / 16;
	// JSON buffer created
	// Create the root of the object tree.
	StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.createObject();
	root["DeviceID"] = DeviceID;
	root["Temperature"] = double_with_n_digits(TemperatureSum, 2);
	// Print to buffer
	root.printTo(buffer, sizeof(buffer));

	return TemperatureSum;

}

/************ Read accelerometer ************/

int getAccelerometer() {
	char action[50];                        // strcat needs a character array
	memset(action, '\0', sizeof(action));
	int interrupt = 0;

	int x, y, z;
	adxl.readAccel(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
								//read interrupts source and look for triggerd actions
	byte interrupts = adxl.getInterruptSource();

	// freefall
	if (adxl.triggered(interrupts, ADXL345_FREE_FALL)) {
		strcat(action, "freefall ");
		interrupt = 1;
		//add code here to do when freefall is sensed
	}

	//inactivity
	if (adxl.triggered(interrupts, ADXL345_INACTIVITY)) {
		strcat(action, "inactivity ");
		interrupt = 0;
		//add code here to do when inactivity is sensed
	}

	//activity
	if (adxl.triggered(interrupts, ADXL345_ACTIVITY)) {
		strcat(action, "activity ");
		interrupt = 1;
		//add code here to do when activity is sensed
	}

	//double tap
	if (adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)) {
		strcat(action, "double tap ");
		interrupt = 1;
		//add code here to do when a 2X tap is sensed
	}

	//tap
	if (adxl.triggered(interrupts, ADXL345_SINGLE_TAP)) {
		strcat(action, "tap ");
		interrupt = 1;
		//add code here to do when a tap is sensed
	}

	// JSON buffer created
	// Create the root of the object tree.
	StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.createObject();
	root["DeviceID"] = DeviceID;
	root["Accelerometer"] = action;
	// Print to buffer
	root.printTo(buffer, sizeof(buffer));

	return interrupt;
}

/************ Read lightlevel ************/

float getLight() {
	float lightlevel = analogRead(ldrPin);

	// Create the root of the object tree.
	StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.createObject();
	// JSON buffer created
	root["DeviceID"] = DeviceID;
	root["Lightlevel"] = double_with_n_digits(lightlevel, 2);
	// Print to buffer
	root.printTo(buffer, sizeof(buffer));

	return lightlevel;
}

/************ Read battery voltage ************/

float getBatteryV() {
	float batteryV = analogRead(batPin);

	// Create the root of the object tree.
	StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.createObject();
	// JSON buffer created
	root["DeviceID"] = DeviceID;
	root["Batvolts"] = double_with_n_digits(batteryV, 2);
	// Print to buffer
	root.printTo(buffer, sizeof(buffer));

	return batteryV;
}

/************ Read switch ************/

int getSwitch() {
	int swStatus = digitalRead(swPin);
	char truefalse[5];                        // strcat needs a character array
	memset(truefalse, '\0', sizeof(truefalse));

	if (swStatus == 0) {
		strcat(truefalse, "OFF");
	}
	else
	{
		strcat(truefalse, "ON");
	}

	// Create the root of the object tree.
	StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.createObject();
	// JSON buffer created
	root["DeviceID"] = DeviceID;
	root["Switch"] = truefalse;
	// Print to buffer
	root.printTo(buffer, sizeof(buffer));

	return swStatus;
}

/********************* Blink ***********************/

void LED_blink(int portnum, int timedelay, int flashnum) {
	for (int i = 0; i < flashnum; i++) {
		digitalWrite(portnum, LOW);
		delay(timedelay);
		digitalWrite(portnum, HIGH);
		delay(timedelay);
	}

}

//******************* Open WiFi connection ****************/

int wifiConnect() {
	// attempt to connect to Wifi network:
	while (status != WL_CONNECTED) {
		status = WiFi.begin(ssid, pass);
		// wait 1 seconds for connection:
		delay(1000);
	}
	return 1;
}

/**************************** Azure related methods **************************/


/************* this method checks for messages from the Aure IoT Hub and processes them ***************/

void azureHttpMessage() {
	String response = "";
	char c;
	///read response if WiFi Client is available
	while (client.available()) {
		c = client.read();
		response.concat(c);
	}

	if (!response.equals(""))
	{
		//if there are no messages in the IoT Hub Device queue, Azure will return 204 status code. 
		if (response.startsWith("HTTP/1.1 204"))
		{
			//turn off onboard LED
			digitalWrite(MKR1000_LED, LOW);
		}
		else
		{
			//turn on onboard LED
			digitalWrite(MKR1000_LED, HIGH);

			// get the ETag from the received message response 
			String eTag = getHeaderValue(response, "ETag");

			// get the payload from the message response
			String command = getResponsePayload(response);

			azureIoTCompleteMessage(eTag);

			if (command == "beepon") {
				//turn on buzzer
				digitalWrite(Buzzer, HIGH);
			}

			if (command == "beepoff") {
				//turn off buzzer
				digitalWrite(Buzzer, LOW);
			}
		}
	}
}

/************* Receive Azure IoT Hub "cloud-to-device" message ***************/

void azureIoTReceiveMessage()
{
	httpRequest("GET", feeduri, "", "");
}

/************* Tells Azure IoT Hub that the message with the msgLockId is handled and it can be removed from the queue ***************/

void azureIoTCompleteMessage(String eTag)
{
	String uri = azureComplete;
	uri.replace("etag", trimETag(eTag));

	httpRequest("DELETE", uri, "", "");
}

/************* Azure POST, GET, DELETE requests ***************/

void httpRequest(String verb, String uri, String contentType, String content)
{
	if (verb.equals("")) return;
	if (uri.equals("")) return;

	// close any connection before send a new request.
	// This will free the socket on the WiFi shield
	// client.stop();

	// if there's a successful connection:
	if (client.connect(hostname, 443)) {
		client.print(verb); //send POST, GET or DELETE
		client.print(" ");
		client.print(uri);  // any of the URI
		client.println(" HTTP/1.1");
		client.print("Host: ");
		client.println(hostname);  					//with hostname header
		client.print("Authorization: ");
		client.println(authSAS);  					//Authorization SAS token obtained from Azure IoT device explorer
		client.println("Connection: close");

		if (verb.equals("POST"))
		{
			client.print("Content-Type: ");
			client.println(contentType);
			client.print("Content-Length: ");
			client.println(content.length());
			client.println();
			client.println(content);

		}
		else
		{
			client.println();
		}
	}
}

/************* To get only the message header from http response ***************/

String getHeaderValue(String response, String headerName)
{
	String headerSection = getHeaderSection(response);
	String headerValue = "";

	int idx = headerSection.indexOf(headerName);

	if (idx >= 0)
	{
		int skip = 0;
		if (headerName.endsWith(":"))
			skip = headerName.length() + 1;
		else
			skip = headerName.length() + 2;

		int idxStart = idx + skip;
		int idxEnd = headerSection.indexOf("\r\n", idxStart);
		headerValue = response.substring(idxStart, idxEnd);
	}

	return headerValue;
}

/********** Azure IoT sets ETag string enclosed in double quotes, not in sync with its other endpoints - need to remove the double quotes ************/

String trimETag(String value)
{
	String retVal = value;

	if (value.startsWith("\""))
		retVal = value.substring(1);

	if (value.endsWith("\""))
		retVal = retVal.substring(0, retVal.length() - 1);

	return retVal;
}

/************* To get all the headers from the HTTP Response ***************/

String getHeaderSection(String response)
{
	int idxHdrEnd = response.indexOf("\r\n\r\n");

	return response.substring(0, idxHdrEnd);
}

/************* To get only the message payload from http response ***************/

String getResponsePayload(String response)
{
	int idxHdrEnd = response.indexOf("\r\n\r\n");

	return response.substring(idxHdrEnd + 4);
}
Azure sensor dataPlain text
This is a real set of data and represents the various event conditions generated by the MKR1000 sensor node, with the exception of battery voltage. The second part shows commands being sent from Device Explorer.
Azure JSON data as viewed in Device Explorer

Receiving events...
26 Mar 2016 10:44:14 PM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":24.44}]
27 Mar 2016 8:40:50 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":85.00}]
27 Mar 2016 8:40:50 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":18.62}]
27 Mar 2016 8:43:49 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":19.69}]
27 Mar 2016 8:49:26 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":20.75}]
27 Mar 2016 8:51:44 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":451.00}]
27 Mar 2016 9:06:44 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":21.81}]
27 Mar 2016 9:07:31 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":364.00}]
27 Mar 2016 9:11:16 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":376.00}]
27 Mar 2016 9:11:59 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":477.00}]
27 Mar 2016 9:13:11 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":335.00}]
27 Mar 2016 9:26:48 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":420.00}]
27 Mar 2016 9:27:24 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":521.00}]
27 Mar 2016 9:39:31 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Temperature":20.75}]
27 Mar 2016 9:51:58 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Lightlevel":398.00}]
27 Mar 2016 9:52:25 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Switch":"OFF"}]
27 Mar 2016 9:52:34 AM> Device: [RethinkAzureSuite01], Data:[{"DeviceID":"RethinkAzureSuite01","Switch":"ON"}]

Commands sent from Device Explorer

Started monitoring feedback for device RethinkAzureSuite01.
Sent to Device ID: [RethinkAzureSuite01], Message:"beepon", message Id: 737786cd-50e5-4bca-bc80-7aeddcc78466
Sent to Device ID: [RethinkAzureSuite01], Message:"beepoff", message Id: 748fb613-8f06-4bdd-b228-256d1cfefef2
Hackster Arduino MKR1000 project
Contains the source files for the MKR1000Azure project in Visual Studio with Visual Micro extension

Schematics

MKR1000 Sensor Node Fritzing File
In my story I have used exported image files of my Fritzing breadboard and schematic designs, but if you need to edit these I suggest that you download the latest version of Fritzing.
MKR1000AzureNode.fzz

Comments

Similar projects you might like

Wi-Fi Power Toggler

Project tutorial by Khalid Abdulla

  • 2,807 views
  • 2 comments
  • 14 respects

Make a Gas Leak Monitor

Project tutorial by Jasper

  • 4,176 views
  • 3 comments
  • 15 respects

Azure Stream Analytics saving lives!

Project tutorial by Asad Zia

  • 6,415 views
  • 3 comments
  • 26 respects

Monitor fridge with Arduino MKR1000 and thethings.iO

Project tutorial by thethings.iO

  • 2,052 views
  • 1 comment
  • 5 respects

Adding Bluetooth to Your Arduino (+Light Sensor)

Project tutorial by IoTaLabs

  • 4,705 views
  • 0 comments
  • 20 respects

I'm Fine

Project in progress by Peter F. Jørgensen

  • 4,361 views
  • 5 comments
  • 29 respects
Add projectSign up / Login