We would use as a starting point the Smart Fan sample https://ms-iot.github.io/content/SmartFan.htm .
The target is to modify the application to:
- Read the temperature
- Send it to a server
- Execute the server commands to start or stop the fan
We would remove the light sensor part.
How do we communicate with the server, and what server it is?
We open a web page (web server then) and through GET parameters we send the data
https://WebSite/SiteName/Temperatures.aspx?id=2&temp=30&fan=false
The parameters are:
- id – the id of the device
- temp – the temperature
- fan – true if the fan is on otherwise false
The page responds with an invalid html page with 3 commands:
- listen – do nothing
- start – start the fan
- stop – stop the fan
The page is invalid because contains no html markings, just the command text to reduce the bandwidth used. Somethimes you pay for data transfer, and the “dead”, no util information, as the markups are in our case, add up.
2. Developing the Galileo application
The hardware pin wise need to be the same. My colleagues (I do software ) did a simplified version on a Arduino Proto Shield.
Code wise some constants were changed:
// Convert the voltage
double voltage_to_celsius(double voltage) {
//+1 for our schema
return 100 * voltage + 1;
}
void toggle_motor(bool motor_is_on) {
if (motor_is_on) {
// Turn off motor
motor_is_on = false;
analogWrite(MOTOR_PIN, 0);
}
else {
// Turn on motor
motor_is_on = true;
//for our schema
analogWrite(MOTOR_PIN, 250);
//The old code
//delay(1);
//analogWrite(MOTOR_PIN, 50);
}
}
The code to open a web site is a pretty trivial Windows C++ open a page
int SendTempAndGetCommand(int deviceId, double temperature, bool fanRunning)
{
char hostname[] = "169.254.178.34";
WSADATA WsaData;
size_t socketResult;
WSAStartup(0x0101, &WsaData);
socketResult = socket(AF_INET, SOCK_STREAM, 0);
if (socketResult == -1)
{
return -100;
}
struct addrinfo addrinfoHints;
struct addrinfo *pAddrinfo = NULL;
struct addrinfo *pAddrinfoResult = NULL;
int result = -7;
// Setup the addrinfoHints address info structure
// which is passed to the getaddrinfo() function
ZeroMemory(&addrinfoHints, sizeof(addrinfoHints));
addrinfoHints.ai_family = AF_INET;
DWORD dwReturnValue = getaddrinfo(hostname, PORT, &addrinfoHints, &pAddrinfoResult);
if (dwReturnValue != 0)
{
return -101;
}
// loop through all the results and connect to the first we can
for (pAddrinfo = pAddrinfoResult; pAddrinfo != NULL; pAddrinfo = pAddrinfo->ai_next)
{
if ((socketResult = socket(pAddrinfo->ai_family, pAddrinfo->ai_socktype,
pAddrinfo->ai_protocol)) == -1)
{
perror("client: socket");
continue;
}
if (connect(socketResult, pAddrinfo->ai_addr, pAddrinfo->ai_addrlen) == -1) {
perror("client: connect");
DWORD lasterr = WSAGetLastError();
continue;
}
break;
}
if (pAddrinfo == NULL)
{
return -102;
}
freeaddrinfo(pAddrinfoResult);
char msg[500];
sprintf_s(msg, "GET https://WebSite/SiteName/Temperatures.aspx?id=%d&temp=%f&fan=false rnrn ", deviceId, temperature);
if (fanRunning)
sprintf_s(msg, "GET https://WebSite/SiteName/Temperatures.aspx?id=%d&temp=%f&fan=true rnrn ", deviceId, temperature);
send(socketResult, msg, (int)strlen(msg), 0);
char buffer[10000];
recv(socketResult, buffer, 10000, 0);
char listen[] = "Listen";
char start[] = "Start";
char stop[] = "Stop";
if (strstr(buffer, listen) != NULL)
{
result = -1;
}
else
if (strstr(buffer, start) != NULL)
{
result = 1;
}
else
if (strstr(buffer, stop) != NULL)
{
result = 0;
}
closesocket(socketResult);
WSACleanup();
return result;
}
And the motor is commanded using the result of this method
int result = SendTempAndGetCommand(3, temp_in_c, motor_is_on);
if (result==1) {
if (!motor_is_on) //super sure
{
toggle_motor(motor_is_on);
motor_is_on = true;
Log(L"Motor Onrn");
}
}
else if (result==0) {
if (motor_is_on) //super sure
{
toggle_motor(motor_is_on);
motor_is_on = false;
Log(L"Motor Offrn");
}
}
The code is attached to the article, bear in mind that you need to adapt it to your specific hardware.
3. Developing the server applications
The server app is an ASP.Net web site but could be anything (this is why I do not put the full code for it in the article ).
The aspx is “empty”:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Temperatures.aspx.cs" Inherits="FanTemperature.Temperatures" %>
And on .cs on the Page_Load is all the code.
This is how the paramethers are read.
int deviceId = 0;
double curentTemperature = 0;
bool fanRunning = false;
int commandFanToRun = -1;
if (this.Request["ID"] != null)
{
deviceId = Convert.ToInt32(this.Request["ID"], CultureInfo.InvariantCulture);
if (this.Request["temp"] != null)
{
curentTemperature = Convert.ToDouble(this.Request["temp"], CultureInfo.InvariantCulture);
}
if (this.Request["fan"] != null)
{
fanRunning = Convert.ToBoolean(this.Request["fan"], CultureInfo.InvariantCulture);
}
}
And to suppress the headers the adding of the markups, this is the code used, the result string is the command.
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Write(result);
Response.ClearHeaders();
About the rest of the code could be a simple if, switch or a decision workflow etc. Also the data could be written into the database, and get a report from it using Reporting Services for example.
3. Run all 
Depending on the sensor temperature (by touching the sensor is enough to change it) the fan will start
or stop
The temperature report is set to auto refresh each second.
4. Security consideration
I would admit that we use this communication through GET parameters in our solutions for years, our company was in IoT before the term was coined. But because our clients are in manufacturing the networks we use with our apps and sensors are private.
My point, the GET method is not secure, bear this in mind, is a solution in the cases when data is not sensitive or the network is private. As a plus the traffic is very easy to debug.
So if security is a concern POST, https, Azure and so is something that you should think of.
And there are some interesting Azure offerings that could be used in this IoT scenarios (for sure you can connect from Windows Galileo since the C++ method surface is almost all of a “big” Windows)
- Intelligent Systems Services https://www.microsoft.com/windowsembedded/en-us/intelligent-systems-service.aspx
- Azure Service Bus https://azure.microsoft.com/en-us/services/service-bus/
- Azure Notification Hubs https://azure.microsoft.com/en-us/documentation/services/notification-hubs/
And I’m naming just a few Azure offerings that could fit in an IoT solution.
5. Conclusions
I hope that I was able to fill the gaps of the Windows Developer Program for IoT (https://dev.windows.com/en-us/featured/windows-developer-program-for-iot) documentation and tutorials and show you that running Windows on Galileo is an option.
Also there (https://ms-iot.github.io/content/AdvancedUsage.htm) are answers to some advanced questions, how to do not use the USB network card, how to ensure that my application runs on the device without using Visual Studio debug, how to kill a Galileo task and so on.