# HG changeset patch # User Michiel Broek # Date 1697113186 -7200 # Node ID 16079aef4c4cf37644206504437eaaf7ee1f2d27 # Parent 542bdc7f65222df2d31d9ea53fabbae498a09de4 Version 0.3.44. Moved iSpindel Plato calculation from the php script to bmsd. This uses calibration data in the mon_ispindels table. Setup of this data will be done by the bmsapp applications. Default settings are stored in MySQL. From now on you don't need to store calibration data in the iSpindel. diff -r 542bdc7f6522 -r 16079aef4c4c bmsd/bms.h --- a/bmsd/bms.h Wed Aug 23 10:30:09 2023 +0200 +++ b/bmsd/bms.h Thu Oct 12 14:19:46 2023 +0200 @@ -332,6 +332,8 @@ float og_gravity; ///< OG gravity in Plato detected float yeast_lo; ///< Yeast low temperature limit float yeast_hi; ///< Yeast high temperature limit + char *calibrate; ///< Calibration data + time_t lastseen; ///< iSpindel last seen } sys_ispindel_list; diff -r 542bdc7f6522 -r 16079aef4c4c bmsd/ispindels.c --- a/bmsd/ispindels.c Wed Aug 23 10:30:09 2023 +0200 +++ b/bmsd/ispindels.c Thu Oct 12 14:19:46 2023 +0200 @@ -40,6 +40,14 @@ extern MYSQL_ROW row; + +double plato_to_sg(double plato) +{ + return 1.00001 + (0.0038661 * plato) + (1.3488e-5 * pow(plato, 2)) + (4.3074e-8 * pow(plato, 3)); +} + + + void ispindel_ws_send(sys_ispindel_list *ispindel) { char *msg = NULL, buf[65]; @@ -225,7 +233,7 @@ time_t timestamp; FILE *fp; - // syslog(LOG_NOTICE, "ispindel_set: %s %s", node, payload); + syslog(LOG_NOTICE, "ispindel_set: %s %s", node, payload); /* * Search ispindel record in the memory array and use it if found. @@ -265,6 +273,7 @@ jobj = json_tokener_parse(payload); if (json_object_object_get_ex(jobj, "unit", &metric)) { + ispindel->lastseen = time(NULL); if (json_object_object_get_ex(metric, "uuid", &val)) { if (ispindel->uuid) free(ispindel->uuid); @@ -285,16 +294,15 @@ ispindel->temperature = json_object_get_double(val); if (json_object_object_get_ex(metric, "battery", &val)) ispindel->battery = json_object_get_double(val); - if (json_object_object_get_ex(metric, "gravity", &val)) { + if (json_object_object_get_ex(metric, "gravity", &val)) ispindel->gravity = json_object_get_double(val); - if (ispindel->gravity > ispindel->og_gravity) - ispindel->og_gravity = ispindel->gravity; - } } -// ispindel_dump(ispindel); + //ispindel_dump(ispindel); - + /* + * If a new iSpindel, insert record. + */ if (new_ispindel) { if (ispindels == NULL) { ispindels = ispindel; @@ -307,9 +315,16 @@ } } ispindel_mysql_insert(ispindel); - } else { - ispindel_mysql_update(ispindel); } + + /* + * Calculate Plato using the calibration data. + * Then update again and make it available. + */ + ispindel->gravity = ispindel_mysql_plato(ispindel->uuid, ispindel->angle); + if (ispindel->gravity > ispindel->og_gravity) + ispindel->og_gravity = ispindel->gravity; + ispindel_mysql_update(ispindel); ispindel_ws_send(ispindel); /* @@ -331,8 +346,7 @@ snprintf(buf, 64, "%.5f", ispindel->gravity); line = xstrcat(line, buf); line = xstrcat(line, (char *)","); - snprintf(buf, 64, "%.5f", 1.00001 + (0.0038661 * ispindel->gravity) + (1.3488e-5 * ispindel->gravity * ispindel->gravity) + - (4.3074e-8 * ispindel->gravity * ispindel->gravity * ispindel->gravity)); + snprintf(buf, 64, "%.5f", plato_to_sg(ispindel->gravity)); line = xstrcat(line, buf); line = xstrcat(line, (char *)","); snprintf(buf, 64, "%.6f", ispindel->battery); @@ -349,9 +363,7 @@ snprintf(query, 511, "INSERT IGNORE INTO log_ispindel SET code='%s', datetime='%s', " \ "temperature='%.4f', plato='%.5f', sg='%.5f', battery='%.6f', " \ "angle='%.5f', refresh='%d', uuid='%s'", - ispindel->beercode, datetime, ispindel->temperature, ispindel->gravity, - 1.00001 + (0.0038661 * ispindel->gravity) + (1.3488e-5 * ispindel->gravity * ispindel->gravity) + - (4.3074e-8 * ispindel->gravity * ispindel->gravity * ispindel->gravity), + ispindel->beercode, datetime, ispindel->temperature, ispindel->gravity, plato_to_sg(ispindel->gravity), ispindel->battery, ispindel->angle, ispindel->interval, ispindel->uuid); //syslog(LOG_NOTICE, "%s", query); bms_mysql_query(query); @@ -416,8 +428,12 @@ printf("temperature %.4f\n", ispindel->temperature); printf("battery %.6f\n", ispindel->battery); printf("gravity %.5f\n", ispindel->gravity); + printf("last seen %ld\n", ispindel->lastseen); printf("interval %d\n", ispindel->interval); printf("og_gravity %.5f\n", ispindel->og_gravity); + printf("yeast_lo %.1f\n", ispindel->yeast_lo); + printf("yeast_hi %.1f\n", ispindel->yeast_hi); + printf("calibrate %s\n", ispindel->calibrate); } } diff -r 542bdc7f6522 -r 16079aef4c4c bmsd/mysql.c --- a/bmsd/mysql.c Wed Aug 23 10:30:09 2023 +0200 +++ b/bmsd/mysql.c Thu Oct 12 14:19:46 2023 +0200 @@ -308,6 +308,8 @@ ispindel->og_gravity = atof(row[15]); ispindel->yeast_lo = atof(row[16]); ispindel->yeast_hi = atof(row[17]); + ispindel->calibrate = xstrcpy(row[18]); + ispindel->lastseen = datetime_to_time_t(row[19]); if (ispindels == NULL) { ispindels = ispindel; @@ -360,6 +362,8 @@ free(tmpi->beeruuid); if (tmpi->mode) free(tmpi->mode); + if (tmpi->calibrate) + free(tmpi->calibrate); free(tmpi); } @@ -710,17 +714,63 @@ +/* + * Update the gravity calculated from the calibrate data. + */ +double ispindel_mysql_plato(char *uuid, double angle) +{ + char *query = malloc(1024), *cal; + struct json_object *jobj, *metric, *val; + double poly[4], plato = 0; + + snprintf(query, 1023, "SELECT uuid,calibrate FROM mon_ispindels WHERE uuid='%s'", uuid); + if (mysql_query(con, query)) { + syslog(LOG_NOTICE, "MySQL: %s error %u (%s))", query, mysql_errno(con), mysql_error(con)); + free(query); + return 0.0; + } + + 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)); + free(query); + return 0.0; + } + free(query); + + if ((row = mysql_fetch_row(res_set)) != NULL) { + cal = xstrcpy(row[1]); + jobj = json_tokener_parse(cal); + if (json_object_object_get_ex(jobj, "polyData", &metric)) { + int arraylen = json_object_array_length(metric); + for (int i = 0; i < arraylen; i++) { + val = json_object_array_get_idx(metric, i); + poly[i] = json_object_get_double(val); + } + plato = (poly[0] * pow(angle, 3)) + (poly[1] * pow(angle, 2)) + (poly[2] * angle) + poly[3]; + } + free(cal); + } + return plato; +} + + void ispindel_mysql_insert(sys_ispindel_list *ispindel) { - char *query = malloc(2560); + char *query = malloc(2560), last[73]; + struct tm *mytime; + + mytime = localtime(&ispindel->lastseen); + snprintf(last, 64, "%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); snprintf(query, 2559, "INSERT INTO mon_ispindels SET uuid='%s', alias='%s', node='%s', online='%d', mode='%s', alarm='%d', " \ "angle='%.6f', temperature='%.4f', battery='%.6f', gravity='%.6f', up_interval='%d', og_gravity='0.0', " \ - "yeast_lo='%.1f', yeast_hi='%.1f'", + "yeast_lo='%.1f', yeast_hi='%.1f', lastseen='%s'", ispindel->uuid, ispindel->alias, ispindel->node, ispindel->online ? 1:0, ispindel->mode, ispindel->alarm, ispindel->angle, ispindel->temperature, ispindel->battery, ispindel->gravity, ispindel->interval, - ispindel->yeast_lo, ispindel->yeast_hi); + ispindel->yeast_lo, ispindel->yeast_hi, last); if (bms_mysql_query(query) == 0) { syslog(LOG_NOTICE, "MySQL: insert new ispindel %s", ispindel->node); @@ -732,15 +782,23 @@ void ispindel_mysql_update(sys_ispindel_list *ispindel) { - char *query = malloc(2560); + char *query = malloc(2560), last[73]; + struct tm *mytime; + mytime = localtime(&ispindel->lastseen); + snprintf(last, 64, "%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); + + /* + * Do not update the calibrate field with regular updates. + */ snprintf(query, 2559, "UPDATE mon_ispindels SET online='%d', mode='%s', alias='%s', alarm='%d', " \ "angle='%.6f', temperature='%.4f', battery='%.6f', gravity='%.6f', up_interval='%d', og_gravity=GREATEST(og_gravity, '%.6f'), " \ - "yeast_lo='%.1f', yeast_hi='%.1f' WHERE uuid='%s'", + "yeast_lo='%.1f', yeast_hi='%.1f', lastseen='%s' WHERE uuid='%s'", ispindel->online ? 1:0, ispindel->mode, ispindel->alias, ispindel->alarm, ispindel->angle, ispindel->temperature, ispindel->battery, ispindel->gravity, ispindel->interval, ispindel->gravity, - ispindel->yeast_lo, ispindel->yeast_hi, ispindel->uuid); + ispindel->yeast_lo, ispindel->yeast_hi, last, ispindel->uuid); bms_mysql_query(query); free(query); } diff -r 542bdc7f6522 -r 16079aef4c4c bmsd/mysql.h --- a/bmsd/mysql.h Wed Aug 23 10:30:09 2023 +0200 +++ b/bmsd/mysql.h Thu Oct 12 14:19:46 2023 +0200 @@ -36,6 +36,7 @@ void co2meter_mysql_update(sys_co2meter_list *co2meter); void co2meter_mysql_death(char *node, char *alias); +double ispindel_mysql_plato(char *uuid, double angle); void ispindel_mysql_insert(sys_ispindel_list *ispindel); void ispindel_mysql_update(sys_ispindel_list *ispindel); void ispindel_mysql_death(char *alias); diff -r 542bdc7f6522 -r 16079aef4c4c config.status --- a/config.status Wed Aug 23 10:30:09 2023 +0200 +++ b/config.status Thu Oct 12 14:19:46 2023 +0200 @@ -433,7 +433,7 @@ This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." -ac_pwd='/home/mbroek/MyProjects/bms' +ac_pwd='/mnt/home/mbroek/MyProjects/bms' srcdir='.' test -n "$AWK" || AWK=awk # The default lists apply if the user does not specify any file. @@ -621,7 +621,7 @@ S["CC"]="gcc" S["CYEARS"]="2016-2023" S["COPYRIGHT"]="Copyright (C) 2016-2023 Michiel Broek, All Rights Reserved" -S["VERSION"]="0.3.43" +S["VERSION"]="0.3.44" S["PACKAGE"]="bms" S["SUBDIRS"]="bmsd doc script tools www" S["target_alias"]="" @@ -709,7 +709,7 @@ D["PACKAGE_STRING"]=" \"\"" D["PACKAGE_BUGREPORT"]=" \"\"" D["PACKAGE_URL"]=" \"\"" -D["VERSION"]=" \"0.3.43\"" +D["VERSION"]=" \"0.3.44\"" D["COPYRIGHT"]=" \"Copyright (C) 2016-2023 Michiel Broek, All Rights Reserved\"" D["STDC_HEADERS"]=" 1" D["HAVE_SYS_TYPES_H"]=" 1" diff -r 542bdc7f6522 -r 16079aef4c4c configure --- a/configure Wed Aug 23 10:30:09 2023 +0200 +++ b/configure Thu Oct 12 14:19:46 2023 +0200 @@ -2031,7 +2031,7 @@ PACKAGE="bms" -VERSION="0.3.43" +VERSION="0.3.44" COPYRIGHT="Copyright (C) 2016-2023 Michiel Broek, All Rights Reserved" CYEARS="2016-2023" diff -r 542bdc7f6522 -r 16079aef4c4c configure.ac --- a/configure.ac Wed Aug 23 10:30:09 2023 +0200 +++ b/configure.ac Thu Oct 12 14:19:46 2023 +0200 @@ -8,7 +8,7 @@ dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="bms" -VERSION="0.3.43" +VERSION="0.3.44" COPYRIGHT="Copyright (C) 2016-2023 Michiel Broek, All Rights Reserved" CYEARS="2016-2023" AC_SUBST(PACKAGE) diff -r 542bdc7f6522 -r 16079aef4c4c www/ispindel/index.php --- a/www/ispindel/index.php Wed Aug 23 10:30:09 2023 +0200 +++ b/www/ispindel/index.php Thu Oct 12 14:19:46 2023 +0200 @@ -17,11 +17,6 @@ $tempC = floatval($data['temperature']); } - /* The rounding in the tilt using less digits results in a 0.25 plato difference. Calculate here again using the calibration data. */ - $tilt = $data['angle']; - $plato = (0.00028548 * $tilt * $tilt * $tilt) + (-0.03492272 * $tilt * $tilt) + (1.617106176 * $tilt) + -21.412976092; - syslog(LOG_NOTICE, "ispindel " . $input . " plato ".$plato); - $node = 'ispindel-' . sprintf("%06x", floatval($data['ID'])); $alarm = 0; @@ -49,7 +44,7 @@ $uuid = 'c0ffeeee-cafe-dead-bee0-' . sprintf("%06x", 0xffffff - floatval($data['ID'])) . sprintf("%06x", floatval($data['ID'])); $topic = 'mbv1.0/ispindels/DBIRTH/' . $node; $payload = '{"unit":{"uuid":"' . $uuid .'","alias":"' . $data['name'] . '","alarm":' . $alarm . ',"interval":' . $interval; - $payload .= ',"angle":' . $data['angle'] . ',"temperature":' . $tempC . ',"battery":' . $data['battery'] . ',"gravity":' . $plato . '}}'; + $payload .= ',"angle":' . $data['angle'] . ',"temperature":' . $tempC . ',"battery":' . $data['battery'] . ',"gravity":' . $data['gravity'] . '}}'; $pub = $publisher . $topic . ' -m \'' .$payload . '\''; exec($pub); }