Upon seeing this project, my first thought -- after the initial wave of excitement -- was thinking of ways I extend the functionality. By using the GridDB and its Grafana plugin, I sought out to visualize my food & pit data. Beyond that, I wished to set up Grafana annotations to seek out any anomalous data points -- can’t have any charred meat!

To get started, I needed to use the C code from the original project to read the data coming in from the wireless thermometer and post that data into my GridDB server. To get this up and running, I spun up a GridDB Server on Azure using a CentOS virtual machine. The easiest way to share data from our edge machine (Raspberry Pi) to our cloud server was via the GridDB Web API. So, on that vm, I set up GridDB’s WebAPI along with Fluentd and the accompanying GridDB connector.

Before actually sending data up to the cloud, I needed to create the basic schema for my BBQ Pi container. The dataset coming in is extremely simple: we have two temperature sensors, one cook id, and of course, the timestamp. So our schema looks like this:

timeseries = gridstore.put_container("bbqpi",[ ("time",griddb.GS_TYPE_TIMESTAMP), ("cookid",griddb.GS_TYPE_INT), ("probe1",griddb.GS_TYPE_INT), ("probe2",griddb.GS_TYPE_INT) ],griddb.GS_CONTAINER_TIME_SERIES)

To create this timeseries container, I simply used the WebAPI (port 8080):

curl -X POST --basic -u admin:admin -H "Content-type:application/json" -d \ '{"container_name":"bbqpi", "container_type":"TIME_SERIES", \ "rowkey":true, "columns":[ \ {"name": "time", "type": "TIMESTAMP" }, \ {"name": "cookid", "type": "INTEGER" },\ {"name": "probe1", "type": "INTEGER" }, \ {"name": "probe2", "type": "INTEGER" }]}' \ http://localhost:8080/griddb/v2/defaultCluster/dbs/public/containers

With the container created, I needed to utilize Fluentd (port 8888) to post actual data into our container. Here’s a CURL command posting some dummy data:

curl -X POST -d 'json={"date":"2020-01-01T12:08:21.112Z","cookid":"1", "probe1":"150", "probe2":"140"}' http://localhost:8888/griddb

From there, I needed to append the original code to send an HTTP POST Request whenever our Pi was reading data from our pit (about once every ~12 seconds).

As a side note: writing this code taught me to appreciate just how verbose the C language can be:

int postData(char time[], int cookid, int probe1, int probe2, char url[]) { CURL *curl; CURLcode res; /* In windows, this will init the winsock stuff */ curl_global_init(CURL_GLOBAL_ALL); char errbuf[CURL_ERROR_SIZE] = { 0, }; char agent[1024] = { 0, }; char json[1000]; snprintf(json,200,"json={\"date\":\"%s.112Z\",\"cookid\":\"%d\", \"probe1\":\"%d\", \"probe2\":\"%d\"}",time,cookid,probe1,probe2); /* get a curl handle */ curl = curl_easy_init(); if(curl) { /* First set the URL that is about to receive our POST. This URL can just as well be a https:// URL if that is what should receive the data. */ snprintf(agent, sizeof agent, "libcurl/%s", curl_version_info(CURLVERSION_NOW)->version); agent[sizeof agent - 1] = 0; curl_easy_setopt(curl, CURLOPT_USERAGENT, agent); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_USERNAME, "admin"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "admin"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); if(res != CURLE_OK) { size_t len = strlen(errbuf); fprintf(stderr, "

libcurl: (%d) ", res); if(len) fprintf(stderr, "%s%s", errbuf, ((errbuf[len - 1] != '

') ? "

" : "")); fprintf(stderr, "%s



", curl_easy_strerror(res)); goto cleanup; } cleanup: curl_easy_cleanup(curl); curl_global_cleanup(); return 0; } }

With this function written, I just needed to have it run at the same time that the sqlite data was being posted:

if (goodData==1) { if (last_db_write==0 || (secs-last_db_write>=10)) { snprintf(sql,100,"INSERT INTO readings (cookid,time,probe1,probe2) VALUES (%d,'%s',%d,%d);",cookID,buff,probe1,probe2); printf("%s

",sql); rc=sqlite3_exec(db,sql,callback,0,&zErrMsg); if (rc!=SQLITE_OK) { printf("SQL error: %s

",zErrMsg); } else { last_db_write=secs; } char url[] = "http://xx.xx.xx.xx:8888/griddb"; postData(buff, cookID, probe1, probe2, url); } }

To make sure your data is actually being inserted into your server, you can run the following command to query your database and view the results:

curl -X POST --basic -u admin:admin -H "Content-type:application/json" -d '{"limit":1000}' http://localhost:8080/griddb/v2/defaultCluster/dbs/public/containers/bbqpi/rows