Added ispindel logging. Updated the documentation.

Fri, 13 Dec 2019 20:33:38 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 13 Dec 2019 20:33:38 +0100
changeset 568
6f3c24e21deb
parent 567
6bf0afc33e70
child 569
d0e7ab1fc245

Added ispindel logging. Updated the documentation.

bmsd/ispindels.c file | annotate | diff | comparison | revisions
bmsd/ispindels.h file | annotate | diff | comparison | revisions
doc/bms-ch8.sgml file | annotate | diff | comparison | revisions
--- 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 <mbroek at mbse dot eu>
  *
  * 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(&timestamp);
+    	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(&timestamp);
-    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) {
--- 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);
 
--- 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 @@
 <listitem><para><code>fermenters</code> is voor vergisting controllers.</para></listitem>
 <listitem><para><code>co2meters</code> is een drukmeter om bijvoorbeeld hergisting op de fles
 te monitoren.</para></listitem>
+<listitem><para><code>ispindels</code> is een electronische hydrometer die in het gistvat drijft
+en de temperatuur en sg verstuurt.</para></listitem>
 </orderedlist>
 
 <para>De volgende <code>message_type</code> namen zijn gedefinieerd:</para>
@@ -366,4 +368,49 @@
 </programlisting>
 </sect1>
 
+
+<sect1 id="ispindellog">
+<title>Netwerk payload formaat voor de iSpindels.</title>
+<para>
+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:
+</para>
+<programlisting>
+ ispindel/&lt;node&gt;/tilt Tilt
+ ispindel/&lt;node&gt;/temperature 20.1250
+ ispindel/&lt;node&gt;/temp_units C
+ ispindel/&lt;node&gt;/battery Volt
+ ispindel/&lt;node&gt;/gravity Gravity
+ ispindel/&lt;node&gt;/interval 900
+ ispindel/&lt;node&gt;/RSSI WiFi.RSSI()
+</programlisting>
+<para>
+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 <command>bmsd</command>
+</para>
+
+<para>
+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 <code>www/logs/ispindel/</code>.
+De bestandsnamen zijn <code>product_code\ product_name.log</code>.
+Het interne formaat is:</para>
+<programlisting>
+   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 ---------------------------------------------+
+</programlisting>
+</sect1>
+
+
 </chapter>

mercurial