--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bmsd/ispindels.c Fri May 01 16:37:31 2020 +0200 @@ -0,0 +1,241 @@ +/** + * @file ispindels.c + * @brief Handle ispindels data + * @author Michiel Broek <mbroek at mbse dot eu> + * + * Copyright (C) 2019-2020 + * + * This file is part of the bms (Brewery Management System) + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * bms is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ThermFerm; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + + +#include "bms.h" +#include "xutil.h" +#include "ispindels.h" +#include "mysql.h" +#include "nodes.h" + + +sys_ispindel_list *ispindels = NULL; + +extern int debug; +extern sys_config Config; +extern MYSQL *con; +extern MYSQL_RES *res_set; +extern MYSQL_ROW row; + + + +void ispindel_set(char *node, char *payload) +{ + sys_ispindel_list *ispindel, *tmpp; + struct json_object *jobj, *metric, *val; + bool new_ispindel = true; + char *datetime, buf[65], *line, *logfile; + struct tm *mytime; + time_t timestamp; + FILE *fp; + +// if (debug) +// printf("ispindel_set: %s %s\n", node, payload); + + /* + * Search ispindel record in the memory array and use it if found. + */ + if (ispindels) { + for (tmpp = ispindels; tmpp; tmpp = tmpp->next) { + if (strcmp(tmpp->node, node) == 0) { + new_ispindel = false; + ispindel = tmpp; + break; + } + } + } + +// if (debug) +// printf("new_ispindel %s\n", new_ispindel ? "true":"false"); + + /* + * Allocate new ispindel if not yet known. + */ + if (new_ispindel) { + ispindel = (sys_ispindel_list *)malloc(sizeof(sys_ispindel_list)); + memset(ispindel, 0, sizeof(sys_ispindel_list)); + ispindel->node = xstrcpy(node); + ispindel->mode = xstrcpy((char *)"OFF"); + } + + if (! ispindel->online) { + ispindel->online = true; + syslog(LOG_NOTICE, "Online ispindel %s mode %s", node, ispindel->mode); + } + + /* + * Process the JSON formatted payload. + * Update only the fields that are found in the payload. + */ + jobj = json_tokener_parse(payload); + + if (json_object_object_get_ex(jobj, "unit", &metric)) { + if (json_object_object_get_ex(metric, "uuid", &val)) { + if (ispindel->uuid) + free(ispindel->uuid); + ispindel->uuid = xstrcpy((char *)json_object_get_string(val)); + } + if (json_object_object_get_ex(metric, "alias", &val)) { + if (ispindel->alias) + free(ispindel->alias); + ispindel->alias = xstrcpy((char *)json_object_get_string(val)); + } + if (json_object_object_get_ex(metric, "alarm", &val)) { + ispindel->alarm = json_object_get_int(val); + } + if (json_object_object_get_ex(metric, "interval", &val)) { + ispindel->interval = json_object_get_int(val); + } + if (json_object_object_get_ex(metric, "angle", &val)) { + ispindel->angle = json_object_get_double(val); + } + if (json_object_object_get_ex(metric, "temperature", &val)) { + 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)) { + ispindel->gravity = json_object_get_double(val); + } + } + +// ispindel_dump(ispindel); + + if (new_ispindel) { + if (ispindels == NULL) { + ispindels = ispindel; + } else { + for (tmpp = ispindels; tmpp; tmpp = tmpp->next) { + if (tmpp->next == NULL) { + tmpp->next = ispindel; + break; + } + } + } + ispindel_mysql_insert(ispindel); + } else { + ispindel_mysql_update(ispindel); + } + + /* + * The data is complete, see if we can write a log entry. + */ + if (ispindel->beercode && strlen(ispindel->beercode) && ispindel->beername && strlen(ispindel->beername) && + ispindel->online && (strcmp(ispindel->mode, (char *)"ON") == 0)) { + datetime = malloc(72); + timestamp = time(NULL); + 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, "%.4f", ispindel->temperature); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.5f", ispindel->gravity); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); +// snprintf(buf, 64, "%.5f", 1 + (ispindel->gravity / (258.6 - ((ispindel->gravity / 258.2) * 227.1)))); + 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)); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.6f", ispindel->battery); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%.5f", ispindel->angle); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + snprintf(buf, 64, "%d", ispindel->interval); + line = xstrcat(line, buf); + line = xstrcat(line, (char *)","); + line = xstrcat(line, ispindel->uuid); + + /* + * 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; + } +} + + + +/* + * Process iSpindel MQTT message. + */ +void ispindel_birth_data(char *topic, char *payload) +{ + char *message_type, *edge_node; + + strtok(topic, "/"); // ignore namespace + strtok(NULL, "/"); + message_type = strtok(NULL, "/"); + edge_node = strtok(NULL, "/\0"); + + if (strcmp("DBIRTH", message_type) == 0) { + ispindel_set(edge_node, payload); + } +} + + + +void ispindel_dump(sys_ispindel_list *ispindel) +{ + if (debug) { + printf("node/alias %s / %s\n", ispindel->node, ispindel->alias); + printf("uuid %s\n", ispindel->uuid); + printf("online %s\n", ispindel->online ? "yes":"no"); + printf("mode %s\n", ispindel->mode); + printf("product %s / %s\n", ispindel->beercode, ispindel->beername); + printf("tilt %.5f\n", ispindel->angle); + printf("temperature %.4f\n", ispindel->temperature); + printf("battery %.6f\n", ispindel->battery); + printf("gravity %.5f\n", ispindel->gravity); + printf("interval %d\n", ispindel->interval); + } +} + +