# HG changeset patch # User Michiel Broek # Date 1576265618 -3600 # Node ID 6f3c24e21deb7340a7db8054d0bdfb1937e78a74 # Parent 6bf0afc33e70dc4ce3ec084aee6954d8c0db1452 Added ispindel logging. Updated the documentation. diff -r 6bf0afc33e70 -r 6f3c24e21deb bmsd/ispindels.c --- a/bmsd/ispindels.c Fri Dec 13 16:49:50 2019 +0100 +++ b/bmsd/ispindels.c Fri Dec 13 20:33:38 2019 +0100 @@ -1,6 +1,6 @@ /** * @file ispindels.c - * @brief Handle ispindels status + * @brief Handle ispindels data * @author Michiel Broek * * Copyright (C) 2019 @@ -44,9 +44,12 @@ { sys_ispindel_list *ispindel, *tmpp; bool new_ispindel = true, do_update = false; - char *t, *p; + char *t, *p, *datetime, buf[65], *line, *logfile; float temperature = 20; uint8_t temp_units = 'C'; + struct tm *mytime; + time_t timestamp; + FILE *fp; fprintf(stdout, "ispindel_set: %s %s\n", node, payload); @@ -113,8 +116,6 @@ ispindel_dump(ispindel); if (new_ispindel || do_update) { - char buf[21]; - t = xstrcpy((char *)"mbv1.0/ispindels/NBIRTH/"); t = xstrcat(t, node); @@ -142,6 +143,61 @@ } else if (do_update) { ispindel_mysql_update(ispindel); } + + /* + * The data is complete, see if we can write a log entry. + */ + if (do_update && ispindel->beercode && strlen(ispindel->beercode) && ispindel->beername && strlen(ispindel->beername)) { + datetime = malloc(72); + mytime = localtime(×tamp); + snprintf(datetime, 72, "%04d-%02d-%02d %02d:%02d:%02d", + mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, mytime->tm_hour, mytime->tm_min, mytime->tm_sec); + + line = xstrcpy(datetime); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.3f", ispindel->tilt); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.3f", ispindel->temperature); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.3f", ispindel->battery); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.3f", ispindel->gravity); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%d", ispindel->interval); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%d", ispindel->rssi); + line = xstrcat(line, buf); + + /* + * Build logfile name + */ + logfile = xstrcpy(Config.web_root); + logfile = xstrcat(logfile, (char *)"/log/ispindel/"); + logfile = xstrcat(logfile, ispindel->beercode); + logfile = xstrcat(logfile, (char *)" "); + logfile = xstrcat(logfile, ispindel->beername); + logfile = xstrcat(logfile, (char *)".log"); + + fp = fopen(logfile, "a"); + if (fp) { + fprintf(fp, "%s\n", line); + fclose(fp); + } else { + syslog(LOG_NOTICE, "cannot append to `%s'", logfile); + } + + free(logfile); + logfile = NULL; + free(line); + line = NULL; + free(datetime); + datetime = NULL; + } } @@ -167,141 +223,6 @@ -void ispindel_log(char *topic, char *payload) -{ - char *edge_node, *alias, *line, buf[128], *logfile; - struct json_object *jobj, *val, *metric; - co2pressure_log *log; - struct tm *mytime; - time_t timestamp; - FILE *fp; - - strtok(topic, "/"); // ignore namespace - strtok(NULL, "/"); // group_id - strtok(NULL, "/"); // message_type - edge_node = strtok(NULL, "/\0"); - alias = strtok(NULL, "/\0"); - - log = (co2pressure_log *)malloc(sizeof(co2pressure_log)); - memset(log, 0, sizeof(co2pressure_log)); - - log->node = xstrcpy(edge_node); - log->alias = xstrcpy(alias); - jobj = json_tokener_parse(payload); - - timestamp = time(NULL); - log->datetime = malloc(73); - mytime = localtime(×tamp); - snprintf(log->datetime, 72, "%04d-%02d-%02d %02d:%02d:%02d", - mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, mytime->tm_hour, mytime->tm_min, mytime->tm_sec); - - if (json_object_object_get_ex(jobj, "metric", &metric)) { - if (json_object_object_get_ex(metric, "uuid", &val)) { - if (strcmp((char *)"(null)", json_object_get_string(val))) - log->uuid = xstrcpy((char *)json_object_get_string(val)); - } - if (json_object_object_get_ex(metric, "temperature", &val)) { - log->temperature = json_object_get_double(val); - } - if (json_object_object_get_ex(metric, "pressure", &val)) { - log->pressure = json_object_get_double(val); - } - } - json_object_put(jobj); - - /* - * Because ispindels are not so smart and don't hold product information - * search the missing pieces in the database. - */ - snprintf(buf, 127, "SELECT beercode,beername,beeruuid FROM mon_ispindels WHERE uuid='%s'", log->uuid); - if (mysql_query(con, buf)) { - syslog(LOG_NOTICE, "MySQL: %s error %u (%s))", buf, mysql_errno(con), mysql_error(con)); - } else { - res_set = mysql_store_result(con); - if (res_set == NULL) { - syslog(LOG_NOTICE, "MySQL: mysq_store_result error %u (%s))", mysql_errno(con), mysql_error(con)); - } else { - if ((row = mysql_fetch_row(res_set)) != NULL) { - /* - * Ignore when the beer_name or beer_code is not set. - */ - if ((int)strlen(row[0]) == 0 || (int)strlen(row[1]) == 0) { - if (log->datetime) - free(log->datetime); - if (log->uuid) - free(log->uuid); - if (log->node) - free(log->node); - if (log->alias) - free(log->alias); - free(log); - return; - } - log->product_code = xstrcpy(row[0]); - log->product_name = xstrcpy(row[1]); - log->product_uuid = xstrcpy(row[2]); - } - } - } - - /* - * Build csv log line - */ - line = xstrcpy(log->datetime); - line = xstrcat(line, (char *)","); - snprintf(buf, 64, "%.3f", log->temperature); - line = xstrcat(line, buf); - line = xstrcat(line, (char *)","); - snprintf(buf, 64, "%.3f", log->pressure); - line = xstrcat(line, buf); - line = xstrcat(line, (char *)","); - line = xstrcat(line, log->uuid); - - /* - * Build logfile name - */ - logfile = xstrcpy(Config.web_root); - logfile = xstrcat(logfile, (char *)"/log/co2pressure/"); - logfile = xstrcat(logfile, log->product_code); - logfile = xstrcat(logfile, (char *)" "); - logfile = xstrcat(logfile, log->product_name); - logfile = xstrcat(logfile, (char *)".log"); - - if (debug) - fprintf(stdout, "%s %s\n", logfile, line); - - fp = fopen(logfile, "a"); - if (fp) { - fprintf(fp, "%s\n", line); - fclose(fp); - } else { - syslog(LOG_NOTICE, "cannot append to `%s'", logfile); - } - - free(logfile); - logfile = NULL; - free(line); - line = NULL; - - if (log->datetime) - free(log->datetime); - if (log->product_uuid ) - free(log->product_uuid ); - if (log->product_code ) - free(log->product_code ); - if (log->product_name ) - free(log->product_name ); - if (log->uuid) - free(log->uuid); - if (log->node) - free(log->node); - if (log->alias) - free(log->alias); - free(log); -} - - - void ispindel_dump(sys_ispindel_list *ispindel) { if (debug) { diff -r 6bf0afc33e70 -r 6f3c24e21deb bmsd/ispindels.h --- a/bmsd/ispindels.h Fri Dec 13 16:49:50 2019 +0100 +++ b/bmsd/ispindels.h Fri Dec 13 20:33:38 2019 +0100 @@ -8,10 +8,14 @@ void ispindel_dump(sys_ispindel_list *ispindel); /** - * @brief Birth of a ispindel or data update. Create it in the database if - * never seen before, else just update the database entry. - * @param topic The MQTT topic string, contains the ispindel type and name. - * @param payload The JSON formatted payload with the ispindel details. + * @brief Messages received from a iSpindel using the MQTT sender. + * A new node is created if this is the first message of the + * iSpindel, else the last seen time is updated. Then the last + * actual state is recorded. A log line is written when a beer + * is assigned. + * @param topic The MQTT topic string, contains the ispindel name and + * keyword for the data. + * @param payload The value for the selected keyword. */ void ispindel_mqtt(char *topic, char *payload); diff -r 6bf0afc33e70 -r 6f3c24e21deb doc/bms-ch8.sgml --- a/doc/bms-ch8.sgml Fri Dec 13 16:49:50 2019 +0100 +++ b/doc/bms-ch8.sgml Fri Dec 13 20:33:38 2019 +0100 @@ -34,6 +34,8 @@ fermenters is voor vergisting controllers. co2meters is een drukmeter om bijvoorbeeld hergisting op de fles te monitoren. +ispindels is een electronische hydrometer die in het gistvat drijft +en de temperatuur en sg verstuurt. De volgende message_type namen zijn gedefinieerd: @@ -366,4 +368,49 @@ + + +Netwerk payload formaat voor de iSpindels. + +De iSpindel is een extern project en verstuurd een afwijkend en simpel +formaat van MQTT berichten. De berichten die verstuurd worden met iedere +update zien er als volgt uit: + + + ispindel/<node>/tilt Tilt + ispindel/<node>/temperature 20.1250 + ispindel/<node>/temp_units C + ispindel/<node>/battery Volt + ispindel/<node>/gravity Gravity + ispindel/<node>/interval 900 + ispindel/<node>/RSSI WiFi.RSSI() + + +Voor iedere actieve iSpindel wordt bij iedere systeemstart een bericht +gestuurd. Dit is ongeveer iedere 15 minuten. Omdat de iSpindel eenvoudige +controllers zijn is er geen tijd en product informatie beschikbaar. Deze +ontbrekende gegevens worden aangevuld door bmsd + + + +De ontvangen iSpindel gegevens worden niet opgeslagen in de SQL database +maar in platte tekst bestanden. Hierdoor is de gelogde informatie sneller toegankelijk. +Ieder brouw product heeft zijn eigen bestand. +De bestanden staan in www/logs/ispindel/. +De bestandsnamen zijn product_code\ product_name.log. +Het interne formaat is: + + 2019-10-11 16:13:33,70.12,22.250,3.576,1.032,900,-45 + | | | | | | | + 0 datetime + | | | | | | + 1 tilt -----------------+ | | | | | + 2 temperatuur -----------------+ | | | | + 3 batterij spanning -----------------+ | | | + 4 densiteit -------------------------------+ | | + 5 interval -------------------------------------+ | + 6 rssi ---------------------------------------------+ + + + +