I have a smart thermostat that allows me to control my heating and cooling system remotely from a smart phone app. This is one of the most commonly used IoT devices. I also have created web interfaces to some of the Raspberry Pi controlled devices in my home - alarm system, lights, sprinklers, hot tub, weather station, security cameras.
I programmed these web interfaces myself, but there are much easier ways that are actually more secure, and these use the services that support the Internet of Things. One of the easiest to use is ThingSpeak.com. Here are the steps to use this service.
Go to the ThingSpeak web site and click on "Get Started." Click on "Sign Up" to create an account and then log in. Now you can create a new "Channel" which includes 1 to 8 fields of data. Once created, the channel is assigned an API_Key which is required to update the channel. You can see this value by clicking on the "API Keys" tab.
I have created a channel named "Example" with a single data field. Data can be uploaded to this field by using the following URL:
https://api.thingspeak.com/update?api_key=JPISWIDBF2CERG24&field1=123
(Yes, that is the actual API key. Feel free to post your own values, but try to keep them between 1-1000 so the chart is usable.)
You can view the public view here: https://thingspeak.com/channels/67033
Note that you can only update once per minute using this method.
Examples in a couple dozen languages, including C and Python are available here:
https://thingspeak.com/docs/examples
Here is an example of real data - temperature and fermentation rate from my home-brewing system.
I decided to create my own API since I had all the necessary code already. This API requires the CURL library to handle the web access. To install this:
sudo apt-get update
sudo apt-get install libcurl4-openssl-dev
Here is the API that I created for updating two fields.
/*********************************************************************** Filename: thingspeak.c send data to ThingSpeak IoT server Uses libcurl to send the data via HTTP 13-Nov-2015 Ted Hale created ************************************************************************/ /* system includes */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <time.h> #include <string.h> #include <curl/curl.h> // Note: this function can be replaced with printf if you like. void Log(char *format, ... ); #define TRUE 1 // the URL structure to update ThingSpeak // https://api.thingspeak.com/update?api_key=YOUR_CHANNEL_API_KEY&field1=7 char *URLtemplate = "https://api.thingspeak.com/update?api_key=%s&%s=%s&%s=%s"; // structure used by the libcurl write callback function struct url_data { size_t size; char* data; }; //===================================================================== // write callback function needed by libCurl size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data) { size_t index = data->size; size_t n = (size * nmemb); char* tmp; data->size += (size * nmemb); tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */ if(tmp) { data->data = tmp; } else { if(data->data) { free(data->data); } Log("wuthread> write_data Failed to allocate memory.\n"); return 0; } memcpy((data->data + index), ptr, n); data->data[data->size] = '\0'; return size * nmemb; } //===================================================================== // upload data to ThingSpeak int UpdateThingSpeak(char *api_key, char *f1, char *v1, char *f2, char *v2) { int error = 1; time_t now; struct tm *dt; char url[256]; CURL *curl; CURLcode res; struct url_data response; time(&now); dt = gmtime(&now); // build the URL string snprintf(url, sizeof(url)-1, URLtemplate, api_key, f1, v1, f2, v2); // guarantee null termination of string url[sizeof(url)-1] = 0; Log("UpdateThingSpeak> send: [%s]",url); curl = curl_easy_init(); if (curl) { response.size = 0; response.data = malloc(4096); /* reasonable size initial buffer */ response.data[0] = '\0'; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); res = curl_easy_perform(curl); if(res != CURLE_OK) { Log("UpdateThingSpeak> curl_easy_perform() failed: %s\n",curl_easy_strerror(res)); Log("URL is: [%s]",url); error = 1; } else { // ThingSpeak returns "0" for error, else returns sample number error = (strcmp(response.data,"0") == 0); } curl_easy_cleanup(curl); free (response.data); } else { Log("UpdateThingSpeak> curl_easy_init failed\n"); error = 1; } return error; }