Added design notes for the csv log format from fermenters. In bmsd configuration added the web_root entry. Switched fermenter DLOG messages to store the log in flat csv files instead of the database. This is much faster and the graphs look better.

Mon, 21 Jan 2019 20:45:18 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 21 Jan 2019 20:45:18 +0100
changeset 194
d202777ebae5
parent 193
3cbd81ea9391
child 195
2ac491548d8d

Added design notes for the csv log format from fermenters. In bmsd configuration added the web_root entry. Switched fermenter DLOG messages to store the log in flat csv files instead of the database. This is much faster and the graphs look better.

.hgignore file | annotate | diff | comparison | revisions
README.design file | annotate | diff | comparison | revisions
bmsd/Makefile file | annotate | diff | comparison | revisions
bmsd/bms.c file | annotate | diff | comparison | revisions
bmsd/bms.h file | annotate | diff | comparison | revisions
bmsd/fermenters.c file | annotate | diff | comparison | revisions
bmsd/mysql.c file | annotate | diff | comparison | revisions
bmsd/mysql.h file | annotate | diff | comparison | revisions
bmsd/rdconfig.c file | annotate | diff | comparison | revisions
www/Makefile file | annotate | diff | comparison | revisions
www/getfermentlog.php file | annotate | diff | comparison | revisions
www/js/log_fermentation.js file | annotate | diff | comparison | revisions
--- a/.hgignore	Sat Jan 19 20:42:11 2019 +0100
+++ b/.hgignore	Mon Jan 21 20:45:18 2019 +0100
@@ -16,4 +16,5 @@
 *.o
 */filelist
 tools/*
+www/log/*
 Makefile.bak
--- a/README.design	Sat Jan 19 20:42:11 2019 +0100
+++ b/README.design	Mon Jan 21 20:45:18 2019 +0100
@@ -120,3 +120,35 @@
 	  Recipes Beerxml import.
 
 Een cronjob om de Stage bij te werken in geval van Package .. Taste. 
+
+-----------------------------------------------------------------------------
+
+	Formaat csv vergisting logs.
+
+Directory:	www/logs/fermentation
+Filenaam:	product_code\ product_name.log
+
+   2014-11-15 18:39,BEER,PRIMARY,20.312,19.750,-1.500,20.5,18.6,18.8,35,12345,0,67890,Whatsup,Fermenter
+            |         |     |      |      |      |      |    |    |   |   |   |   |      |        |
+ 0 datetime +         |     |      |      |      |      |    |    |   |   |   |   |      |        |
+ 1 mode --------------+     |      |      |      |      |    |    |   |   |   |   |      |        |
+ 2 stage -------------------+      |      |      |      |    |    |   |   |   |   |      |        |
+ 3 temp air -----------------------+      |      |      |    |    |   |   |   |   |      |        |
+ 4 temp beer -----------------------------+      |      |    |    |   |   |   |   |      |        |
+ 5 temp chiller ---------------------------------+      |    |    |   |   |   |   |      |        |
+ 6 temp room -------------------------------------------+    |    |   |   |   |   |      |        |
+ 7 setpoint low ---------------------------------------------+    |   |   |   |   |      |        |
+ 8 setpoint high -------------------------------------------------+   |   |   |   |      |        |
+ 9 heater power ------------------------------------------------------+   |   |   |      |        |
+10 heater usage ----------------------------------------------------------+   |   |      |        |
+11 cooler power --------------------------------------------------------------+   |      |        |
+12 cooler usage ------------------------------------------------------------------+      |        |
+13 event --------------------------------------------------------------------------------+        |
+14 fermenter uuid --------------------------------------------------------------------------------+
+
+De oude logs zijn geimporteerd en geconverteerd. Nieuwe worden geschreven
+door bmsd welke de log gegevens ontvangt via MQTT DLOG berichten.
+Vanwege de snelheid van verwerken staan de logs niet in de database.
+
+-----------------------------------------------------------------------------
+
--- a/bmsd/Makefile	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/Makefile	Mon Jan 21 20:45:18 2019 +0100
@@ -55,12 +55,13 @@
 
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
-mqtt.o: bms.h xutil.h mqtt.h nodes.h
+mqtt.o: bms.h xutil.h mqtt.h nodes.h fermenters.h
+lock.o: lock.h bms.h futil.h
 nodes.o: bms.h xutil.h nodes.h mysql.h
 futil.o: bms.h futil.h
-lock.o: lock.h bms.h futil.h
-bms.o: bms.h xutil.h rdconfig.h lock.h mqtt.h mysql.h
+fermenters.o: bms.h xutil.h fermenters.h mysql.h
+bms.o: bms.h xutil.h futil.h rdconfig.h lock.h mqtt.h mysql.h
 xutil.o: bms.h xutil.h
 rdconfig.o: bms.h xutil.h futil.h rdconfig.h
-mysql.o: bms.h xutil.h mysql.h
+mysql.o: bms.h xutil.h mysql.h nodes.h
 # End of generated dependencies
--- a/bmsd/bms.c	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/bms.c	Mon Jan 21 20:45:18 2019 +0100
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2017-2018
+ * Copyright (C) 2017-2019
  *   
  * Michiel Broek <mbroek at mbse dot eu>
  *
@@ -22,6 +22,7 @@
 
 #include "bms.h"
 #include "xutil.h"
+#include "futil.h"
 #include "rdconfig.h"
 #include "lock.h"
 #include "mqtt.h"
@@ -32,9 +33,8 @@
 int			debug = FALSE;
 static pid_t		pgrp, mypid;
 char			*Private_Path = NULL;	/* Users data path		*/
-//char			*resource_path = NULL;	/* Webserver root		*/
 
-//extern struct lws_context *context;
+extern sys_config       Config;
 
 
 void help(void)
@@ -71,6 +71,7 @@
     uid_t               myuid;
     struct passwd       *mypwd;
     int			rc = 0;
+    char		*tmppath = NULL;
 
     myuid = getuid();
     mypwd = getpwuid(myuid);
@@ -92,6 +93,31 @@
 	goto endit1;
     }
 
+    if (! Config.web_root) {
+	rc = 5;
+	syslog(LOG_NOTICE, "Configuration `web_root' is not set"); 
+	goto endit1;
+    }
+
+    /*
+     * Make sure the needed log paths exist.
+     */
+    tmppath = xstrcpy(Config.web_root);
+    tmppath = xstrcat(tmppath, (char *)"/log/fermentation/");
+    if (! mkdirs(tmppath, 0755)) {
+	rc = 5;
+	goto endit1;
+    }
+    free(tmppath);
+    tmppath = xstrcpy(Config.web_root);
+    tmppath = xstrcat(tmppath, (char *)"/log/brews/");
+    if (! mkdirs(tmppath, 0755)) {
+	rc = 5;
+	goto endit1;
+    }
+    free(tmppath);
+    tmppath = NULL;
+
     if (bms_mysql_init()) {
 	rc = 3;
 	goto endit1;
--- a/bmsd/bms.h	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/bms.h	Mon Jan 21 20:45:18 2019 +0100
@@ -71,6 +71,7 @@
     int				mqtt_port;		///< MQTT port
     char			*mqtt_user;		///< MQTT username of NULL
     char			*mqtt_pass;		///< MQTT password of NULL
+    char			*web_root;		///< WWW root directory
 } sys_config;
 
 
--- a/bmsd/fermenters.c	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/fermenters.c	Mon Jan 21 20:45:18 2019 +0100
@@ -32,7 +32,7 @@
 sys_fermenter_list	*fermenters = NULL;
 
 extern int		debug;
-
+extern sys_config       Config;
 
 
 
@@ -414,11 +414,12 @@
 
 void fermenter_log(char *topic, char *payload)
 {
-    char                *edge_node, *alias;
+    char                *edge_node, *alias, *line, buf[65], *logfile;
     struct json_object  *jobj, *val, *metric, *metric2;
     fermentation_log	*log;
     struct tm		*mytime;
     time_t		timestamp;
+    FILE		*fp;
 
     strtok(topic, "/"); // ignore namespace
     strtok(NULL, "/");	// group_id
@@ -517,26 +518,80 @@
 		log->fan_usage = json_object_get_int(val);
 	    }
 	}
-//	printf("%s\n", (char *)json_object_to_json_string_ext(metric, 0));
     }
     json_object_put(jobj);
 
-    fermentation_mysql_log(log);
-/*
-    printf("datetime      %s\n", log->datetime);
-    printf("product       %s %s\n", log->product_code, log->product_name);
-    printf("stage/mode    %s %s\n", log->stage, log->mode);
-    printf("temp air      %.3f\n", log->temperature_air);
-    printf("temp beer     %.3f\n", log->temperature_beer);
-    printf("temp chiller  %.3f\n", log->temperature_chiller);
-    printf("temp room     %.3f\n", log->temperature_room);
-    printf("setpoint      %.1f %.1f\n", log->setpoint_low, log->setpoint_high);
-    printf("heater        %3d %ld\n", log->heater_power, log->heater_usage);
-    printf("cooler        %3d %ld\n", log->cooler_power, log->cooler_usage);
-    printf("fan           %3d %ld\n", log->fan_power, log->fan_usage);
-    printf("event         %s\n", log->event);
-    printf("fermenter     %s\n", log->fermenter_uuid);
-*/
+    /*
+     * Build csv log line
+     */
+    line = xstrcpy(log->datetime);
+    line = xstrcat(line, (char *)",");
+    line = xstrcat(line, log->mode);
+    line = xstrcat(line, (char *)",");
+    line = xstrcat(line, log->stage);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.3f", log->temperature_air);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.3f", log->temperature_beer);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.3f", log->temperature_chiller);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.3f", log->temperature_room);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.1f", log->setpoint_low);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%.1f", log->setpoint_high);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%d", log->heater_power);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%ld", log->heater_usage);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%d", log->cooler_power);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    snprintf(buf, 64, "%ld", log->cooler_usage);
+    line = xstrcat(line, buf);
+    line = xstrcat(line, (char *)",");
+    if (log->event)
+	line = xstrcat(line, log->event);
+    line = xstrcat(line, (char *)",");
+    if (log->fermenter_uuid)
+	line = xstrcat(line, log->fermenter_uuid);
+
+    /*
+     * Build logfile name
+     */
+    logfile = xstrcpy(Config.web_root);
+    logfile = xstrcat(logfile, (char *)"/log/fermentation/");
+    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 )
--- a/bmsd/mysql.c	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/mysql.c	Mon Jan 21 20:45:18 2019 +0100
@@ -512,94 +512,3 @@
 }
 
 
-
-void fermentation_mysql_log(fermentation_log *log)
-{
-    char	*query, buf[65];
-
-    query = xstrcpy((char *)"INSERT INTO log_fermentation SET datetime='");
-    query = xstrcat(query, log->datetime);
-    query = xstrcat(query, (char *)":00");
-    if (log->product_uuid) {
-	query = xstrcat(query, (char *)"', product_uuid='");
-	query = xstrcat(query, log->product_uuid);
-    }
-    if (log->product_code) {
-	query = xstrcat(query, (char *)"', product_code='");
-	query = xstrcat(query, log->product_code);
-    }
-    if (log->product_name) {
-	query = xstrcat(query, (char *)"', product_name='");
-	query = xstrcat(query, log->product_name);
-    }
-    query = xstrcat(query, (char *)"', stage='");
-    query = xstrcat(query, log->stage);
-    query = xstrcat(query, (char *)"', mode='");
-    query = xstrcat(query, log->mode);
-    query = xstrcat(query, (char *)"', temperature_beer='");
-    snprintf(buf, 64, "%.3f", log->temperature_beer);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', temperature_air='");
-    snprintf(buf, 64, "%.3f", log->temperature_air);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', temperature_chiller='");
-    snprintf(buf, 64, "%.3f", log->temperature_chiller);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', temperature_room='");
-    snprintf(buf, 64, "%.3f", log->temperature_room);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', target_low='");
-    snprintf(buf, 64, "%.1f", log->setpoint_low);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', target_high='");
-    snprintf(buf, 64, "%.1f", log->setpoint_high);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', heater_power='");
-    snprintf(buf, 64, "%d", log->heater_power);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', heater_usage='");
-    snprintf(buf, 64, "%ld", log->heater_usage);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', cooler_power='");
-    snprintf(buf, 64, "%d", log->cooler_power);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', cooler_usage='");
-    snprintf(buf, 64, "%ld", log->cooler_usage);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', fan_power='");
-    snprintf(buf, 64, "%d", log->fan_power);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"', fan_usage='");
-    snprintf(buf, 64, "%ld", log->fan_usage);
-    query = xstrcat(query, buf);
-    query = xstrcat(query, (char *)"'");
-    // sg
-    if (log->event) {
-	query = xstrcat(query, (char *)", event='");
-	query = xstrcat(query, log->event);
-	query = xstrcat(query, (char *)"'");
-    }
-    if (log->fermenter_uuid) {
-	query = xstrcat(query, (char *)", fermenter_uuid='");
-	query = xstrcat(query, log->fermenter_uuid);
-	query = xstrcat(query, (char *)"'");
-    }
-    if (log->fermenter_node) {
-	query = xstrcat(query, (char *)", fermenter_node='");
-	query = xstrcat(query, log->fermenter_node);
-	query = xstrcat(query, (char *)"'");
-    }
-    if (log->fermenter_alias) {
-	query = xstrcat(query, (char *)", fermenter_alias='");
-	query = xstrcat(query, log->fermenter_alias);
-	query = xstrcat(query, (char *)"'");
-    }
-
-    if (mysql_real_query(con, query, strlen(query))) {
-	syslog(LOG_NOTICE, "MySQL: `%s' error %u (%s)\n)", query, mysql_errno(con), mysql_error(con));
-    }
-
-    free(query);
-}
-
-
--- a/bmsd/mysql.h	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/mysql.h	Mon Jan 21 20:45:18 2019 +0100
@@ -30,6 +30,5 @@
 void fermenter_mysql_update(sys_fermenter_list *fermenter);
 void fermenter_mysql_death(char *node, char *alias);
 
-void fermentation_mysql_log(fermentation_log *log);
 
 #endif
--- a/bmsd/rdconfig.c	Sat Jan 19 20:42:11 2019 +0100
+++ b/bmsd/rdconfig.c	Mon Jan 21 20:45:18 2019 +0100
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2017-2018
+ * Copyright (C) 2017-2019
  *   
  * Michiel Broek <mbroek at mbse dot eu>
  *
@@ -53,6 +53,7 @@
     {(char *)"mqtt_port",		getint,		(char **)&Config.mqtt_port},
     {(char *)"mqtt_user",		getstr,		(char **)&Config.mqtt_user},
     {(char *)"mqtt_pass",		getstr,		(char **)&Config.mqtt_pass},
+    {(char *)"web_root",		getstr,		(char **)&Config.web_root},
     {NULL,				NULL,		NULL}
 };
 
@@ -94,6 +95,10 @@
     if (Config.mqtt_pass)
 	free(Config.mqtt_pass);
     Config.mqtt_pass = NULL;
+
+    if (Config.web_root)
+	free(Config.web_root);
+    Config.web_root = NULL;
 }
 
 
@@ -150,7 +155,12 @@
 	fprintf(fp, "mqtt_pass             %s\n", Config.mqtt_pass);
     else
 	fprintf(fp, "#mqtt_pwd              <passwd>\n");
+    fprintf(fp, "#\n");
 
+    if (Config.web_root)
+	fprintf(fp, "web_root              %s\n", Config.web_root);
+    else
+	fprintf(fp, "#web_root              </path/to/webroot>\n");
     fprintf(fp, "#\n");
     fprintf(fp, "# End of generated configuration\n");
     fclose(fp);
--- a/www/Makefile	Sat Jan 19 20:42:11 2019 +0100
+++ b/www/Makefile	Mon Jan 21 20:45:18 2019 +0100
@@ -34,6 +34,9 @@
 			${WWWDIR}/fpdf/font \
 			${WWWDIR}/jqwidgets ${WWWDIR}/js ${WWWDIR}/images/ ${WWWDIR}/includes/
 		${INSTALL} -d -g 314 -o 314 -m 0777 ${WWWDIR}/run
+		${INSTALL} -d -g 314 -o 314 ${WWWDIR}/log
+		${INSTALL} -d -g 314 -o 314 ${WWWDIR}/log/brews
+		${INSTALL} -d -g 314 -o 314 ${WWWDIR}/log/fermentation
 		${INSTALL} -g 314 -o 314 ${SRC} ${WWWDIR}/
 		${INSTALL} -g 314 -o 314 version.php ${WWWDIR}/
 		${INSTALL} -g 314 -o 314 css/* ${WWWDIR}/css/
--- a/www/getfermentlog.php	Sat Jan 19 20:42:11 2019 +0100
+++ b/www/getfermentlog.php	Mon Jan 21 20:45:18 2019 +0100
@@ -3,57 +3,116 @@
 require_once('config.php');
 
 if (isset($_GET["code"]))
-	$code = $_GET["code"];
+	$code = $_GET["code"] . ' ' . $_GET["name"];
 else
-	$code = "TB0015";
+	$code = "TB0015 Winterbier-2";
 
-$query = "SELECT datetime,temperature_air,temperature_beer,temperature_chiller,temperature_room,target_low,target_high,heater_usage,cooler_usage FROM log_fermentation WHERE product_code='".$code."'";
-$connect = mysqli_connect(DBASE_HOST,DBASE_USER,DBASE_PASS,DBASE_NAME);
-if (! $connect) {
-	echo "[]";
-	return;
+$filename = 'log/fermentation/' . $code . '.log';
+/*
+ * From Stackoverflow, the fastest way to count the lines in a file.
+ */
+$file = new \SplFileObject($filename, 'r');
+$file->seek(PHP_INT_MAX);
+// $file->key() = lines in the file.
+
+define ('MAX_INTERVALS', 10);
+$GRAPH_INTERVAL = array ( 0, 1, 5, 15, 30, 60, 120, 240, 480, 720 );
+$GRAPH_DATALINES = array ( 0, 800, 3200, 12000, 24000, 48000, 96000, 192000, 384000, 768000 );
+
+
+for ($graphstep = 1; $graphstep <= MAX_INTERVALS; $graphstep++) {
+	if ($file->key() < $GRAPH_DATALINES[$graphstep])
+		break;
 }
-$step = 600; // Must be a multiple of 300
-$ld = 0;
-$lh = 0;
-$ch = 0;
-$lc = 0;
-$cc = 0;
-$result = mysqli_query($connect, $query);
-while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
+if ($graphstep > MAX_INTERVALS)
+	$graphstep = MAX_INTERVALS;
+
+//echo $code . '.log lines=' . $file->key() . ' interval=' . $GRAPH_INTERVAL[$graphstep] . ' graphstep=' . $graphstep . PHP_EOL;
 
-	$dt = new DateTime($row['datetime'], new DateTimeZone('Europe/Amsterdam'));
-	$ts = $dt->getTimestamp();
-	$diff = $ts - $ld;
+/*
+ * 2014-11-15 18:39,BEER,PRIMARY,20.312,19.750,-1.500,20.5,18.6,18.8,35,12345,0,67890,Whatsup
+ *          |         |     |      |      |      |      |    |    |   |   |   |   |      |
+ * datetime +         |     |      |      |      |      |    |    |   |   |   |   |      |
+ * mode --------------+     |      |      |      |      |    |    |   |   |   |   |      |
+ * stage -------------------+      |      |      |      |    |    |   |   |   |   |      |
+ * temp air -----------------------+      |      |      |    |    |   |   |   |   |      |
+ * temp beer -----------------------------+      |      |    |    |   |   |   |   |      |
+ * temp chiller ---------------------------------+      |    |    |   |   |   |   |      |
+ * temp room -------------------------------------------+    |    |   |   |   |   |      |
+ * setpoint low ---------------------------------------------+    |   |   |   |   |      |
+ * setpoint high -------------------------------------------------+   |   |   |   |      |
+ * heater power ------------------------------------------------------+   |   |   |      |
+ * heater usage ----------------------------------------------------------+   |   |      |
+ * cooler power --------------------------------------------------------------+   |      |
+ * cooler usage ------------------------------------------------------------------+      |
+ * event --------------------------------------------------------------------------------+
+ */
+
+$heater_l = 0;
+$cooler_l = 0;
+
+$handle = @fopen($filename, "r");
+if ($handle) {
+	$lines = 0;
+	while (($buffer = fgets($handle, 4096)) !== false) {
+
+		$buffer = preg_replace( "/\r|\n/", "", $buffer);
+		$row = explode(",", $buffer);
+		if ($row[1] != 'Mode') {
 
-	if ($diff < $step) {
-		// Read on
-	} else if ($diff > $step) {
-		// Reset, out of sync.
-		$ld = $ts;
-		$lh = $ch = $row['heater_usage'];
-		$lc = $cc = $row['cooler_usage'];
-	} else {
-		// This is a valid timeframe.
-		$ch = $row['heater_usage'];
-		$cc = $row['cooler_usage'];
-		$heat = round(($ch - $lh) / ($step / 100));
-		$cool = round(($cc - $lc) / ($step / 100));
-//		echo $heat . ' ' . $cool . PHP_EOL;
-		$logs[] = array(
-			'date' => $row['datetime'],
-			'air' => $row['temperature_air'],
-			'beer' => $row['temperature_beer'],
-			'chiller' => $row['temperature_chiller'],
-			'room' => $row['temperature_room'],
-			'tlo' => $row['target_low'],
-			'thi' => $row['target_high'],
-			'heater' => $heat,
-			'cooler' => $cool
-		);
-		$ld = $ts;
-		$lh = $ch;
-		$lc = $cc;
+			$hr = intval(substr($buffer, 11, 2));
+			if ((($graphstep == 1)) ||
+			    (($graphstep == 2) && ((substr($buffer, 15, 1) == '0') || (substr($buffer, 15, 1) == '5'))) ||
+			    (($graphstep == 3) && ((substr($buffer, 14, 2) == '00') || (substr($buffer, 14, 2) == '15') ||
+						   (substr($buffer, 14, 2) == '30') || (substr($buffer, 14, 2) == '45'))) ||
+			    (($graphstep == 4) && ((substr($buffer, 14, 2) == '00') || (substr($buffer, 14, 2) == '30'))) ||
+			    (($graphstep == 5) && (substr($buffer, 14, 2) == '00')) ||
+			    (($graphstep == 6) && (substr($buffer, 14, 2) == '00') && (($hr % 2) == 0)) ||
+			    (($graphstep == 7) && (substr($buffer, 14, 2) == '00') && (($hr % 4) == 0)) ||
+			    (($graphstep == 8) && (substr($buffer, 14, 2) == '00') && (($hr % 8) == 0)) ||
+			    (($graphstep == 9) && (substr($buffer, 14, 2) == '00') && (($hr % 12) == 0))) {
+//				echo $hr . ' ' . $row[1] . ' ' . $buffer;
+				$lines++;
+
+				$heat_used = $cool_used = 0;
+				if ($row[10] && ($row[10] != "NA") && ($heater_l > 0)) {
+					$heat_used = round((intval($row[10]) - $heater_l) * 100 / ($GRAPH_INTERVAL[$graphstep] * 60));
+				}
+				if ($row[12] && ($row[12] != "NA") && ($cooler_l > 0)) {
+					$cool_used = round((intval($row[12]) - $cooler_l) * 100 / ($GRAPH_INTERVAL[$graphstep] * 60));
+				}
+
+
+//				echo $GRAPH_INTERVAL[$graphstep] . ' ' . $heat_used . ' ' . $cool_used . PHP_EOL;
+
+				if (($heat_used <= 100) && ($cool_used <= 100)) {
+					$logs[] = array(
+						'date' => $row[0],
+						'air' => $row[3],
+						'beer' => $row[4],
+						'chiller' => $row[5],
+						'room' => $row[6],
+						'tlo' => $row[7],
+						'thi' => $row[8],
+						'heater' => $heat_used,
+						'cooler' => $cool_used,
+						'event' => $row[13]
+					);
+				}
+
+				if ($row[10] && ($row[10] != "NA"))
+					$heater_l = intval($row[10]);
+				if ($row[12] && ($row[12] != "NA"))
+					$cooler_l = intval($row[12]);
+			}
+		}
+
 	}
+	if (!feof($handle)) {
+		echo "Error: unexpected fgets() fail\n";
+	}
+	fclose($handle);
 }
+
 echo json_encode($logs);
+//echo $lines . ' lines' . PHP_EOL;
--- a/www/js/log_fermentation.js	Sat Jan 19 20:42:11 2019 +0100
+++ b/www/js/log_fermentation.js	Mon Jan 21 20:45:18 2019 +0100
@@ -42,14 +42,15 @@
 			{ name: "date", type: "date", format: "yyyy-MM-dd HH:mm" },
 			{ name: "air", type: "float" },
 			{ name: "beer", type: "float" },
+			{ name: "chiller", type: "float" },
+			{ name: "room", type: "float" },
 			{ name: "tlo", type: "float" },
 			{ name: "thi", type: "float" },
 			{ name: "heater", type: "int" },
 			{ name: "cooler", type: "int" },
-			{ name: "room", type: "float" },
-			{ name: "chiller", type: "float" }
+			{ name: "event", type: "string" }
 		],
-		url: 'getfermentlog.php?code=' + my_code
+		url: 'getfermentlog.php?code=' + my_code + '&name=' + my_name
 	};
 	var dataAdapter = new $.jqx.dataAdapter(sourceA, {
 		autoBind: true,

mercurial