Last active
September 26, 2016 18:50
-
-
Save dirkjanfaber/8eff7c6585c3d4cdf732512ddf94ca68 to your computer and use it in GitHub Desktop.
Blink(1) on value increase of thingspeak channel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Program that keeps an eye on a (private) thingspeak channel + field and | |
| acts upon change in value of that field. When the value increases, | |
| a system call to blink1-tool is called to colour the blink(1) led | |
| pumpkin orange. | |
| There are some commandline options: | |
| -v for VERBOSE | |
| -a for the apikey | |
| -c for the thingspeak channel | |
| -f for the field to check | |
| -s for setting the time between checks | |
| Compiling: | |
| gcc -lcurl -O2 -Wall -o blink1speak blink1speak.c | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <ctype.h> | |
| #include <curl/curl.h> | |
| #ifndef VERBOSE | |
| #define VERBOSE 0 | |
| #endif | |
| struct MemoryStruct { | |
| char *memory; | |
| size_t size; | |
| }; | |
| float lastvalue = -1.0; | |
| int verbose = VERBOSE; | |
| static size_t | |
| WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) | |
| { | |
| size_t realsize = size * nmemb; | |
| struct MemoryStruct *mem = (struct MemoryStruct *)userp; | |
| mem->memory = realloc(mem->memory, mem->size + realsize + 1); | |
| if(mem->memory == NULL) { | |
| /* out of memory! */ | |
| printf("not enough memory (realloc returned NULL)\n"); | |
| return 0; | |
| } | |
| memcpy(&(mem->memory[mem->size]), contents, realsize); | |
| mem->size += realsize; | |
| mem->memory[mem->size] = 0; | |
| float tempvalue = atof(contents); | |
| if ( lastvalue < 0 ) { | |
| (verbose) && printf("First run, lastvalue is undefined\n"); | |
| lastvalue = tempvalue; | |
| } | |
| (verbose) && printf("Lastvalue is %0.2f\n", lastvalue); | |
| if ( lastvalue < tempvalue) { | |
| (verbose) && printf("Value increased, blink(1)\n"); | |
| // set the blink(1) colour to pumpkin orange | |
| char command[50]; | |
| strcpy(command, "blink1-tool --rgb '#FF9900'" ); | |
| system(command); | |
| } | |
| return realsize; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| char *channel = "104274"; | |
| char url[256]; | |
| char *apikey; | |
| int field = 1; | |
| int sleeptime = 300; | |
| int index; | |
| int c; | |
| opterr = 0; | |
| while ((c = getopt (argc, argv, "a:c:f:vs:")) != -1) | |
| switch (c) | |
| { | |
| case 'a': | |
| apikey = optarg; | |
| break; | |
| case 'c': | |
| channel = optarg; | |
| break; | |
| case 'f': | |
| field = atoi(optarg); | |
| break; | |
| case 's': | |
| sleeptime = atoi(optarg); | |
| break; | |
| case 'v': | |
| verbose = 1; | |
| break; | |
| case '?': | |
| if (optopt == 'c') | |
| fprintf (stderr, "Option -%c requires an argument.\n", optopt); | |
| else if (isprint (optopt)) | |
| fprintf (stderr, "Unknown option `-%c'.\n", optopt); | |
| else | |
| fprintf (stderr, | |
| "Unknown option character `\\x%x'.\n", | |
| optopt); | |
| return 1; | |
| default: | |
| abort (); | |
| } | |
| (verbose) && printf ("channel = %s, field = %d\n", | |
| channel, field); | |
| for (index = optind; index < argc; index++) | |
| printf ("Non-option argument %s\n", argv[index]); | |
| if ( apikey ) { | |
| sprintf(url, "https://api.thingspeak.com/channels/%s/fields/field%d/last?api_key=%s", channel, field, apikey); | |
| } else { | |
| sprintf(url, "https://api.thingspeak.com/channels/%s/fields/field%d/last", channel, field); | |
| } | |
| (verbose) && printf("Checking url: %s\n", url); | |
| while(1) { | |
| CURL *curl_handle; | |
| CURLcode res; | |
| struct MemoryStruct chunk; | |
| chunk.memory = malloc(1); /* will be grown as needed by the realloc above */ | |
| chunk.size = 0; /* no data at this point */ | |
| curl_global_init(CURL_GLOBAL_ALL); | |
| /* init the curl session */ | |
| curl_handle = curl_easy_init(); | |
| /* specify URL to get */ | |
| curl_easy_setopt(curl_handle, CURLOPT_URL, url); | |
| /* send all data to this function */ | |
| curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); | |
| /* we pass our 'chunk' struct to the callback function */ | |
| curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); | |
| /* some servers don't like requests that are made without a user-agent | |
| field, so we provide one */ | |
| curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); | |
| /* get it! */ | |
| res = curl_easy_perform(curl_handle); | |
| /* check for errors */ | |
| if(res != CURLE_OK) { | |
| fprintf(stderr, "curl_easy_perform() failed: %s\n", | |
| curl_easy_strerror(res)); | |
| } | |
| else { | |
| (verbose) && printf("Current value is %s\n", chunk.memory); | |
| } | |
| /* cleanup curl stuff */ | |
| curl_easy_cleanup(curl_handle); | |
| free(chunk.memory); | |
| /* we're done with libcurl, so clean it up */ | |
| curl_global_cleanup(); | |
| (verbose) && printf("Sleeping %d seconds\n", sleeptime); | |
| sleep(sleeptime); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment