bmsd/ispindels.c

changeset 567
6bf0afc33e70
child 568
6f3c24e21deb
equal deleted inserted replaced
566:e526dc911bc1 567:6bf0afc33e70
1 /**
2 * @file ispindels.c
3 * @brief Handle ispindels status
4 * @author Michiel Broek <mbroek at mbse dot eu>
5 *
6 * Copyright (C) 2019
7 *
8 * This file is part of the bms (Brewery Management System)
9 *
10 * This is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
13 * later version.
14 *
15 * bms is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ThermFerm; see the file COPYING. If not, write to the Free
22 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25
26 #include "bms.h"
27 #include "xutil.h"
28 #include "ispindels.h"
29 #include "mysql.h"
30 #include "nodes.h"
31
32
33 sys_ispindel_list *ispindels = NULL;
34
35 extern int debug;
36 extern sys_config Config;
37 extern MYSQL *con;
38 extern MYSQL_RES *res_set;
39 extern MYSQL_ROW row;
40
41
42
43 void ispindel_set(char *node, char *key, char *payload)
44 {
45 sys_ispindel_list *ispindel, *tmpp;
46 bool new_ispindel = true, do_update = false;
47 char *t, *p;
48 float temperature = 20;
49 uint8_t temp_units = 'C';
50
51 fprintf(stdout, "ispindel_set: %s %s\n", node, payload);
52
53 /*
54 * Search ispindel record in the memory array and use it if found.
55 */
56 if (ispindels) {
57 for (tmpp = ispindels; tmpp; tmpp = tmpp->next) {
58 if (strcmp(tmpp->node, node) == 0) {
59 new_ispindel = false;
60 ispindel = tmpp;
61 break;
62 }
63 }
64 }
65
66 printf("new_ispindel %s\n", new_ispindel ? "true":"false");
67
68 /*
69 * Allocate new ispindel if not yet known.
70 */
71 if (new_ispindel) {
72 ispindel = (sys_ispindel_list *)malloc(sizeof(sys_ispindel_list));
73 memset(ispindel, 0, sizeof(sys_ispindel_list));
74 ispindel->node = xstrcpy(node);
75 }
76
77 if (! ispindel->online) {
78 ispindel->online = true;
79 syslog(LOG_NOTICE, "Online ispindel %s", node);
80 }
81
82 /*
83 * Process the simple iSpindel MQTT payload.
84 */
85 if (strcmp(key, "tilt") == 0) {
86 ispindel->tilt = atof(payload);
87 } else if (strcmp(key, "temperature") == 0) {
88 temperature = atof(payload);
89 } else if (strcmp(key, "temp_units") == 0) {
90 temp_units = payload[0];
91 } else if (strcmp(key, "battery") == 0) {
92 ispindel->battery = atof(payload);
93 } else if (strcmp(key, "gravity") == 0) {
94 ispindel->gravity = atof(payload);
95 } else if (strcmp(key, "interval") == 0) {
96 ispindel->interval = atoi(payload);
97 } else if (strcmp(key, "RSSI") == 0) {
98 ispindel->rssi = atoi(payload);
99 do_update = true;
100 if (temp_units == 'C') {
101 ispindel->temperature = temperature;
102 } else if (temp_units == 'F') {
103 ispindel->temperature = temperature / 1.8 - 32;
104 } else if (temp_units == 'K') {
105 ispindel->temperature = temperature - 273.15;
106 } else {
107 ispindel->temperature = temperature;
108 }
109 } else {
110 syslog(LOG_NOTICE, "Unknown keyword `%s' from `%s'", key, node);
111 }
112
113 ispindel_dump(ispindel);
114
115 if (new_ispindel || do_update) {
116 char buf[21];
117
118 t = xstrcpy((char *)"mbv1.0/ispindels/NBIRTH/");
119 t = xstrcat(t, node);
120
121 p = xstrcpy((char *)"{\"metric\":{\"properties\":{\"hardwaremake\":\"MBSE\",\"hardwaremodel\":\"Wemos D1 mini\"},\"net\":{\"rssi\":");
122 sprintf(buf, "%d", ispindel->rssi);
123 p = xstrcat(p, buf);
124 p = xstrcat(p, (char *)"}}}");
125 node_birth_data(t, p);
126 free(t);
127 free(p);
128 }
129
130 if (new_ispindel) {
131 if (ispindels == NULL) {
132 ispindels = ispindel;
133 } else {
134 for (tmpp = ispindels; tmpp; tmpp = tmpp->next) {
135 if (tmpp->next == NULL) {
136 tmpp->next = ispindel;
137 break;
138 }
139 }
140 }
141 ispindel_mysql_insert(ispindel);
142 } else if (do_update) {
143 ispindel_mysql_update(ispindel);
144 }
145 }
146
147
148
149 /*
150 * Process iSpindel MQTT message.
151 */
152 void ispindel_mqtt(char *topic, char *payload)
153 {
154 char *namespace, *node, *keyword;
155
156 namespace = strtok(topic, "/"); // must be ispindel
157 node = strtok(NULL, "/");
158 keyword = strtok(NULL, "/\0");
159
160 if (strcmp(namespace, "ispindels")) {
161 syslog(LOG_NOTICE, "ispindel_mqtt(%s, %s) error", topic, payload);
162 return;
163 }
164
165 ispindel_set(node, keyword, payload);
166 }
167
168
169
170 void ispindel_log(char *topic, char *payload)
171 {
172 char *edge_node, *alias, *line, buf[128], *logfile;
173 struct json_object *jobj, *val, *metric;
174 co2pressure_log *log;
175 struct tm *mytime;
176 time_t timestamp;
177 FILE *fp;
178
179 strtok(topic, "/"); // ignore namespace
180 strtok(NULL, "/"); // group_id
181 strtok(NULL, "/"); // message_type
182 edge_node = strtok(NULL, "/\0");
183 alias = strtok(NULL, "/\0");
184
185 log = (co2pressure_log *)malloc(sizeof(co2pressure_log));
186 memset(log, 0, sizeof(co2pressure_log));
187
188 log->node = xstrcpy(edge_node);
189 log->alias = xstrcpy(alias);
190 jobj = json_tokener_parse(payload);
191
192 timestamp = time(NULL);
193 log->datetime = malloc(73);
194 mytime = localtime(&timestamp);
195 snprintf(log->datetime, 72, "%04d-%02d-%02d %02d:%02d:%02d",
196 mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, mytime->tm_hour, mytime->tm_min, mytime->tm_sec);
197
198 if (json_object_object_get_ex(jobj, "metric", &metric)) {
199 if (json_object_object_get_ex(metric, "uuid", &val)) {
200 if (strcmp((char *)"(null)", json_object_get_string(val)))
201 log->uuid = xstrcpy((char *)json_object_get_string(val));
202 }
203 if (json_object_object_get_ex(metric, "temperature", &val)) {
204 log->temperature = json_object_get_double(val);
205 }
206 if (json_object_object_get_ex(metric, "pressure", &val)) {
207 log->pressure = json_object_get_double(val);
208 }
209 }
210 json_object_put(jobj);
211
212 /*
213 * Because ispindels are not so smart and don't hold product information
214 * search the missing pieces in the database.
215 */
216 snprintf(buf, 127, "SELECT beercode,beername,beeruuid FROM mon_ispindels WHERE uuid='%s'", log->uuid);
217 if (mysql_query(con, buf)) {
218 syslog(LOG_NOTICE, "MySQL: %s error %u (%s))", buf, mysql_errno(con), mysql_error(con));
219 } else {
220 res_set = mysql_store_result(con);
221 if (res_set == NULL) {
222 syslog(LOG_NOTICE, "MySQL: mysq_store_result error %u (%s))", mysql_errno(con), mysql_error(con));
223 } else {
224 if ((row = mysql_fetch_row(res_set)) != NULL) {
225 /*
226 * Ignore when the beer_name or beer_code is not set.
227 */
228 if ((int)strlen(row[0]) == 0 || (int)strlen(row[1]) == 0) {
229 if (log->datetime)
230 free(log->datetime);
231 if (log->uuid)
232 free(log->uuid);
233 if (log->node)
234 free(log->node);
235 if (log->alias)
236 free(log->alias);
237 free(log);
238 return;
239 }
240 log->product_code = xstrcpy(row[0]);
241 log->product_name = xstrcpy(row[1]);
242 log->product_uuid = xstrcpy(row[2]);
243 }
244 }
245 }
246
247 /*
248 * Build csv log line
249 */
250 line = xstrcpy(log->datetime);
251 line = xstrcat(line, (char *)",");
252 snprintf(buf, 64, "%.3f", log->temperature);
253 line = xstrcat(line, buf);
254 line = xstrcat(line, (char *)",");
255 snprintf(buf, 64, "%.3f", log->pressure);
256 line = xstrcat(line, buf);
257 line = xstrcat(line, (char *)",");
258 line = xstrcat(line, log->uuid);
259
260 /*
261 * Build logfile name
262 */
263 logfile = xstrcpy(Config.web_root);
264 logfile = xstrcat(logfile, (char *)"/log/co2pressure/");
265 logfile = xstrcat(logfile, log->product_code);
266 logfile = xstrcat(logfile, (char *)" ");
267 logfile = xstrcat(logfile, log->product_name);
268 logfile = xstrcat(logfile, (char *)".log");
269
270 if (debug)
271 fprintf(stdout, "%s %s\n", logfile, line);
272
273 fp = fopen(logfile, "a");
274 if (fp) {
275 fprintf(fp, "%s\n", line);
276 fclose(fp);
277 } else {
278 syslog(LOG_NOTICE, "cannot append to `%s'", logfile);
279 }
280
281 free(logfile);
282 logfile = NULL;
283 free(line);
284 line = NULL;
285
286 if (log->datetime)
287 free(log->datetime);
288 if (log->product_uuid )
289 free(log->product_uuid );
290 if (log->product_code )
291 free(log->product_code );
292 if (log->product_name )
293 free(log->product_name );
294 if (log->uuid)
295 free(log->uuid);
296 if (log->node)
297 free(log->node);
298 if (log->alias)
299 free(log->alias);
300 free(log);
301 }
302
303
304
305 void ispindel_dump(sys_ispindel_list *ispindel)
306 {
307 if (debug) {
308 printf("node %s\n", ispindel->node);
309 printf("online %s\n", ispindel->online ? "yes":"no");
310 printf("product %s / %s\n", ispindel->beercode, ispindel->beername);
311 printf("tilt %.3f\n", ispindel->tilt);
312 printf("temperature %.3f\n", ispindel->temperature);
313 printf("battery %.3f\n", ispindel->battery);
314 printf("gravity %.3f\n", ispindel->gravity);
315 printf("interval %d\n", ispindel->interval);
316 printf("rssi %d\n", ispindel->rssi);
317 }
318 }
319
320

mercurial