Table des matières:

BBQ Pi (avec visualisation des données !) : 4 étapes (avec photos)
BBQ Pi (avec visualisation des données !) : 4 étapes (avec photos)

Vidéo: BBQ Pi (avec visualisation des données !) : 4 étapes (avec photos)

Vidéo: BBQ Pi (avec visualisation des données !) : 4 étapes (avec photos)
Vidéo: Introduction à la visualisation des données avec Matplotlib de Python 2024, Novembre
Anonim
BBQ Pi (avec visualisation des données !)
BBQ Pi (avec visualisation des données !)
BBQ Pi (avec visualisation des données !)
BBQ Pi (avec visualisation des données !)
BBQ Pi (avec visualisation des données !)
BBQ Pi (avec visualisation des données !)

introduction

Le barbecue fait généralement référence au processus lent d'utilisation de la chaleur indirecte pour cuire vos viandes préférées. Bien que cette méthode de cuisson soit extrêmement populaire, en particulier aux États-Unis, elle présente ce que certains peuvent considérer comme une faiblesse plutôt sérieuse: elle nécessite des heures d'attention semi-lucide pour surveiller la température de votre noyau et de vos aliments. Entrez: Raspberry Pi.

Le projet d'origine

La source originale de ce projet peut être trouvée ici: https://old.reddit.com/r/raspberry_pi/comments/a0… L'essentiel est que l'utilisateur de reddit Produkt a pu relayer les données de température des aliments et des fosses à partir de données relativement bon marché., des thermomètres sans fil disponibles dans le commerce à un Raspberry Pi (qui avait attaché à ses broches GPIO un petit module RF). Dans le projet d'origine (lié ci-dessus), Produkt avait ses données stockées dans une base de données sqlite et affichées sur un site Web Apache2 php hébergé localement.

Cette solution résout déjà le problème initial évoqué dans l'introduction de ce blog: vous pouvez désormais surveiller à distance la température de vos aliments et de vos fosses à l'aide d'un navigateur Web. Mais et si nous voulions développer cela? Entrez: GridDB.

Fournitures

Framboise Pi4

Module récepteur sans fil superhétérodyne SUNKEE 433Mhz

Étape 1: API Web GridDB et FluentD

API Web GridDB et FluentD
API Web GridDB et FluentD

En voyant ce projet, ma première pensée - après la vague initiale d'enthousiasme - a été de réfléchir aux moyens d'étendre la fonctionnalité. En utilisant GridDB et son plugin Grafana, j'ai cherché à visualiser mes données sur les aliments et les noyaux. Au-delà de cela, je souhaitais configurer des annotations Grafana pour rechercher des points de données anormaux - ne peut pas avoir de viande carbonisée !

Pour commencer, je devais utiliser le code C du projet d'origine pour lire les données provenant du thermomètre sans fil et publier ces données sur mon serveur GridDB. Pour que cela soit opérationnel, j'ai créé un serveur GridDB sur Azure à l'aide d'une machine virtuelle CentOS. Le moyen le plus simple de partager des données de notre machine périphérique (Raspberry Pi) vers notre serveur cloud était via l'API Web GridDB. Ainsi, sur cette machine virtuelle, j'ai configuré la WebAPI de GridDB avec Fluentd et le connecteur GridDB qui l'accompagne.

Avant d'envoyer des données vers le cloud, je devais créer le schéma de base de mon conteneur BBQ Pi. L'ensemble de données entrant est extrêmement simple: nous avons deux capteurs de température, un identifiant de cuisson et, bien sûr, l'horodatage. Notre schéma ressemble donc à ceci:

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)

Pour créer ce conteneur de séries temporelles, j'ai simplement utilisé la WebAPI (port 8080):

curl -X POST --basic -u admin:admin -H "Type de contenu: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" }]}'

Une fois le conteneur créé, je devais utiliser Fluentd (port 8888) pour publier des données réelles dans notre conteneur. Voici une commande CURL affichant des données factices:

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

À partir de là, je devais ajouter le code d'origine pour envoyer une requête HTTP POST chaque fois que notre Pi lisait les données de notre fosse (environ une fois toutes les ~ 12 secondes).

En passant: écrire ce code m'a appris à apprécier à quel point le langage C peut être verbeux:

int postData(char time, int cookid, int probe1, int probe2, char url)

{ CURL *curl; CURLcode res; /* Dans Windows, cela initialisera le contenu de winsock */ curl_global_init(CURL_GLOBAL_ALL); car errbuf[CURL_ERROR_SIZE] = { 0, }; agent de caractère[1024] = { 0, }; char json[1000]; snprintf(json, 200, "json={"date\":\"%s.112Z\", \"cookid\":\"%d\", \"probe1\":\"%d\", \"probe2\":\"%d\"}", time, cookid, probe1, probe2); /* obtient un handle curl */ curl = curl_easy_init(); if(curl) { /* Définissez d'abord l'URL qui est sur le point de recevoir notre POST. Cette URL peut tout aussi bien être une URL https:// si c'est elle qui doit recevoir les données. */ snprintf(agent, taille de l'agent, "libcurl/%s", curl_version_info(CURLVERSION_NOW)->version); agent[taille de l'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); /* Exécuter la requête, res obtiendra le code retour */ res = curl_easy_perform(curl); if(res != CURLE_OK) { size_t len = strlen(errbuf); fprintf(stderr, "\nlibcurl: (%d) ", res); if(len) fprintf(stderr, "%s%s", errbuf, ((errbuf[len - 1] != '\n') ? "\n": "")); fprintf(stderr, "%s\n\n", curl_easy_strerror(res)); aller au nettoyage; } nettoyage: curl_easy_cleanup(curl); curl_global_cleanup(); renvoie 0; } }

Avec cette fonction écrite, j'avais juste besoin de la faire fonctionner en même temps que les données sqlite étaient publiées:

si (bonneDonnée==1) {

if (last_db_write==0 || (secs-last_db_write>=10)) { snprintf(sql, 100, "INSERT INTO lectures (cookid, time, probe1, probe2) VALEURS (%d, '%s', %d, %d);", cookID, buff, probe1, probe2); printf("%s\n", sql); rc=sqlite3_exec(db, sql, rappel, 0, &zErrMsg); if (rc!=SQLITE_OK) { printf("Erreur SQL: %s\n", zErrMsg); } else { last_db_write=secs; } char url = "https://xx.xx.xx.xx:8888/griddb"; postData(buff, cookID, probe1, probe2, url); } }

Pour vous assurer que vos données sont bien insérées dans votre serveur, vous pouvez exécuter la commande suivante pour interroger votre base de données et afficher les résultats:

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

Étape 2: Grafana

Grafana
Grafana
Grafana
Grafana

Avec le code en place, maintenant, lorsque nous utiliserons le portail Web d'origine pour démarrer un « cuisinier », nous stockerons simultanément nos données de température sur notre serveur GridDB.

La prochaine étape sera de visualiser nos données à l'aide de Grafana. Pour ce faire, nous avons suivi les informations de ce blog: ici. La bonne chose à propos de cette implémentation est qu'il est extrêmement facile de voir nos données dans un joli graphique. Il ajoute également des annotations.

Les annotations abordées dans le blog nous permettent de surveiller extrêmement facilement les problèmes liés à notre nourriture ou à la fosse elle-même. Dans mon cas, je cuisinais des côtes levées de bœuf. Avec ceux-ci, je ne voulais pas que la température dans la fosse dépasse les 275 degrés Fahrenheit. Si je voyais la température dépasser, je pourrais éteindre un brûleur et laisser la chaleur redescendre:

J'avais une règle similaire pour le capteur gardant un œil sur la nourriture elle-même: si la nourriture atteignait une température interne de 203 degrés Fahrenheit, les côtes étaient prêtes. Vous pouvez voir l'annotation solitaire à la fin de la cuisson ici:

Dans l'ensemble, le cuisinier ne m'a pris qu'environ 4 heures environ, mais ce type de configuration serait vraiment excellent si je cuisinais quelque chose qui aurait nécessité encore plus de temps dans le gril (pensez à une fumée lente qui dure ~ 12 les heures). Malgré cela, je pense que la valeur de cet outil est facilement évidente: être capable d'enregistrer les résultats de vos aliments, puis de les comparer aux cuisiniers précédents, signifie que votre barbecue s'améliorera lentement avec le temps, car vous pouvez utiliser des données pour voir ce qui fonctionne et ce qui ne fonctionne pas. 't.

Étape 3: La nourriture

La nourriture
La nourriture
La nourriture
La nourriture
La nourriture
La nourriture

C'était la première fois que je faisais des côtes levées de bœuf; pour l'assaisonnement, j'ai simplement utilisé du sel, du poivre noir et de la poudre d'ail. Malgré quelques problèmes avec le brûleur qui est devenu un peu trop élevé au début, les côtes sont sorties fantastiques. S'il vous plaît, jetez un oeil:

Étape 4: Conclusion

En fin de compte, la nourriture est sortie formidable, les capteurs, GridDB et Grafana ont tous fonctionné de concert à merveille, et nous avons obtenu des données précieuses sur la façon de cuisiner à nouveau ces choses pour la prochaine fois que nous voulons impressionner des amis.

Conseillé: