Sun, 06 Jan 2019 17:28:48 +0100
When importing from brouwhulp use 0 and 1 instead of false and true for boolean variables. Added Export button to the recipe editor. Added beerxml recipe export.
0 | 1 | /** |
2 | * @file fermenters.c | |
3 | * @brief Handle fermenters status | |
4 | * @author Michiel Broek <mbroek at mbse dot eu> | |
5 | * | |
6 | * Copyright (C) 2018 | |
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 "fermenters.h" | |
29 | #include "mysql.h" | |
30 | ||
31 | ||
32 | sys_fermenter_list *fermenters = NULL; | |
33 | ||
34 | extern int debug; | |
35 | ||
36 | ||
37 | ||
38 | ||
39 | void fermenter_set(char *edge_node, char *alias, bool birth, char *payload) | |
40 | { | |
41 | struct json_object *jobj, *val, *sensor, *temp; | |
42 | sys_fermenter_list *fermenter, *tmpp; | |
43 | bool new_fermenter = true; | |
44 | ||
45 | // fprintf(stdout, "fermenter_set: %s/%s %s %s\n", edge_node, alias, birth ? "BIRTH":"DATA", payload); | |
46 | ||
47 | /* | |
48 | * Search fermenter record in the memory array and use it if found. | |
49 | */ | |
50 | if (fermenters) { | |
51 | for (tmpp = fermenters; tmpp; tmpp = tmpp->next) { | |
52 | if ((strcmp(tmpp->alias, alias) == 0) && (strcmp(tmpp->node, edge_node) == 0)) { | |
53 | new_fermenter = false; | |
54 | fermenter = tmpp; | |
55 | break; | |
56 | } | |
57 | } | |
58 | } | |
59 | ||
60 | if (! birth && new_fermenter) { | |
61 | printf("ERROR got DDATA and fermenter %s/%s doesn't exist\n", edge_node, alias); | |
62 | return; | |
63 | } | |
64 | //printf("new_fermenter %s\n", new_fermenter ? "true":"false"); | |
65 | ||
66 | /* | |
67 | * Allocate new fermenter if not yet known. | |
68 | */ | |
69 | if (new_fermenter) { | |
70 | fermenter = (sys_fermenter_list *)malloc(sizeof(sys_fermenter_list)); | |
71 | memset(fermenter, 0, sizeof(sys_fermenter_list)); | |
72 | fermenter->alias = xstrcpy(alias); | |
73 | fermenter->node = xstrcpy(edge_node); | |
74 | fermenter->mode = xstrcpy((char *)"OFF"); | |
75 | fermenter->stage = xstrcpy((char *)"PRIMARY"); | |
76 | } | |
77 | ||
78 | fermenter->online = true; | |
79 | if (birth) { | |
80 | syslog(LOG_NOTICE, "Online fermenter %s/%s mode %s", edge_node, alias, fermenter->mode); | |
81 | } | |
82 | ||
83 | /* | |
84 | * Process the JSON formatted payload. | |
85 | * Update only the fields that are found in the payload. | |
86 | */ | |
87 | jobj = json_tokener_parse(payload); | |
88 | ||
89 | if (json_object_object_get_ex(jobj, "uuid", &val)) { | |
90 | if (fermenter->uuid) | |
91 | free(fermenter->uuid); | |
92 | fermenter->uuid = xstrcpy((char *)json_object_get_string(val)); | |
93 | } | |
94 | if (json_object_object_get_ex(jobj, "mode", &val)) { | |
95 | if (fermenter->mode) { | |
96 | if (strcmp(fermenter->mode, (char *)json_object_get_string(val))) { | |
97 | syslog(LOG_NOTICE, "Change mode fermenter %s/%s: %s to %s", edge_node, alias, fermenter->mode, (char *)json_object_get_string(val)); | |
98 | } | |
99 | free(fermenter->mode); | |
100 | } | |
101 | fermenter->mode = xstrcpy((char *)json_object_get_string(val)); | |
102 | } | |
103 | if (json_object_object_get_ex(jobj, "stage", &val)) { | |
104 | if (fermenter->stage) { | |
105 | if (strcmp(fermenter->stage, (char *)json_object_get_string(val))) { | |
106 | syslog(LOG_NOTICE, "Change stage fermenter %s/%s: %s to %s", edge_node, alias, fermenter->stage, (char *)json_object_get_string(val)); | |
107 | } | |
108 | free(fermenter->stage); | |
109 | } | |
110 | fermenter->stage = xstrcpy((char *)json_object_get_string(val)); | |
111 | } | |
112 | if (json_object_object_get_ex(jobj, "alarm", &val)) { | |
113 | if (fermenter->alarm != json_object_get_int(val)) { | |
114 | syslog(LOG_NOTICE, "Change alarm fermenter %s/%s: %d to %d", edge_node, alias, fermenter->alarm, json_object_get_int(val)); | |
115 | } | |
116 | fermenter->alarm = json_object_get_int(val); | |
117 | } | |
118 | if (json_object_object_get_ex(jobj, "product", &sensor)) { | |
119 | if (json_object_object_get_ex(sensor, "code", &val)) { | |
120 | if (fermenter->beercode) | |
121 | free(fermenter->beercode); | |
122 | fermenter->beercode = xstrcpy((char *)json_object_get_string(val)); | |
123 | } | |
124 | if (json_object_object_get_ex(sensor, "name", &val)) { | |
125 | if (fermenter->beername) | |
126 | free(fermenter->beername); | |
127 | fermenter->beername = xstrcpy((char *)json_object_get_string(val)); | |
128 | } | |
129 | } | |
130 | if (json_object_object_get_ex(jobj, "air", &sensor)) { | |
131 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
132 | if (fermenter->air_address) | |
133 | free(fermenter->air_address); | |
134 | fermenter->air_address= xstrcpy((char *)json_object_get_string(val)); | |
135 | } | |
136 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
137 | if (fermenter->air_state) | |
138 | free(fermenter->air_state); | |
139 | fermenter->air_state= xstrcpy((char *)json_object_get_string(val)); | |
140 | } | |
141 | if (json_object_object_get_ex(sensor, "temperature", &val)) { | |
142 | fermenter->air_temperature = json_object_get_double(val); | |
143 | } | |
144 | } | |
145 | if (json_object_object_get_ex(jobj, "beer", &sensor)) { | |
146 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
147 | if (fermenter->beer_address) | |
148 | free(fermenter->beer_address); | |
149 | fermenter->beer_address= xstrcpy((char *)json_object_get_string(val)); | |
150 | } | |
151 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
152 | if (fermenter->beer_state) | |
153 | free(fermenter->beer_state); | |
154 | fermenter->beer_state= xstrcpy((char *)json_object_get_string(val)); | |
155 | } | |
156 | if (json_object_object_get_ex(sensor, "temperature", &val)) { | |
157 | fermenter->beer_temperature = json_object_get_double(val); | |
158 | } | |
159 | } | |
160 | if (json_object_object_get_ex(jobj, "chiller", &sensor)) { | |
161 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
162 | if (fermenter->chiller_address) | |
163 | free(fermenter->chiller_address); | |
164 | fermenter->chiller_address= xstrcpy((char *)json_object_get_string(val)); | |
165 | } | |
166 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
167 | if (fermenter->chiller_state) | |
168 | free(fermenter->chiller_state); | |
169 | fermenter->chiller_state= xstrcpy((char *)json_object_get_string(val)); | |
170 | } | |
171 | if (json_object_object_get_ex(sensor, "temperature", &val)) { | |
172 | fermenter->chiller_temperature = json_object_get_double(val); | |
173 | } | |
174 | } | |
175 | if (json_object_object_get_ex(jobj, "heater", &sensor)) { | |
176 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
177 | if (fermenter->heater_address) | |
178 | free(fermenter->heater_address); | |
179 | fermenter->heater_address= xstrcpy((char *)json_object_get_string(val)); | |
180 | } | |
181 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
182 | fermenter->heater_state = json_object_get_int(val); | |
183 | } | |
184 | if (json_object_object_get_ex(sensor, "usage", &val)) { | |
185 | fermenter->heater_usage = json_object_get_int(val); | |
186 | } | |
187 | } | |
188 | if (json_object_object_get_ex(jobj, "cooler", &sensor)) { | |
189 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
190 | if (fermenter->cooler_address) | |
191 | free(fermenter->cooler_address); | |
192 | fermenter->cooler_address= xstrcpy((char *)json_object_get_string(val)); | |
193 | } | |
194 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
195 | fermenter->cooler_state = json_object_get_int(val); | |
196 | } | |
197 | if (json_object_object_get_ex(sensor, "usage", &val)) { | |
198 | fermenter->cooler_usage = json_object_get_int(val); | |
199 | } | |
200 | } | |
201 | if (json_object_object_get_ex(jobj, "fan", &sensor)) { | |
202 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
203 | if (fermenter->fan_address) | |
204 | free(fermenter->fan_address); | |
205 | fermenter->fan_address= xstrcpy((char *)json_object_get_string(val)); | |
206 | } | |
207 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
208 | fermenter->fan_state = json_object_get_int(val); | |
209 | } | |
210 | if (json_object_object_get_ex(sensor, "usage", &val)) { | |
211 | fermenter->fan_usage = json_object_get_int(val); | |
212 | } | |
213 | } | |
214 | if (json_object_object_get_ex(jobj, "light", &sensor)) { | |
215 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
216 | if (fermenter->light_address) | |
217 | free(fermenter->light_address); | |
218 | fermenter->light_address= xstrcpy((char *)json_object_get_string(val)); | |
219 | } | |
220 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
221 | fermenter->light_state = json_object_get_int(val); | |
222 | } | |
223 | if (json_object_object_get_ex(sensor, "usage", &val)) { | |
224 | fermenter->light_usage = json_object_get_int(val); | |
225 | } | |
226 | } | |
227 | if (json_object_object_get_ex(jobj, "door", &sensor)) { | |
228 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
229 | if (fermenter->door_address) | |
230 | free(fermenter->door_address); | |
231 | fermenter->door_address= xstrcpy((char *)json_object_get_string(val)); | |
232 | } | |
233 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
234 | fermenter->door_state = json_object_get_int(val); | |
235 | } | |
236 | } | |
237 | if (json_object_object_get_ex(jobj, "psu", &sensor)) { | |
238 | if (json_object_object_get_ex(sensor, "address", &val)) { | |
239 | if (fermenter->psu_address) | |
240 | free(fermenter->psu_address); | |
241 | fermenter->psu_address= xstrcpy((char *)json_object_get_string(val)); | |
242 | } | |
243 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
244 | fermenter->psu_state = json_object_get_int(val); | |
245 | } | |
246 | } | |
247 | if (json_object_object_get_ex(jobj, "setpoint", &sensor)) { | |
248 | if (json_object_object_get_ex(sensor, "low", &val)) { | |
249 | fermenter->setpoint_low = json_object_get_double(val); | |
250 | } | |
251 | if (json_object_object_get_ex(sensor, "high", &val)) { | |
252 | fermenter->setpoint_high = json_object_get_double(val); | |
253 | } | |
254 | } | |
255 | if (json_object_object_get_ex(jobj, "profile", &sensor)) { | |
256 | if (strcmp(json_object_to_json_string_ext(sensor, 0), "null")) { | |
257 | // printf("profile: %s\n", json_object_to_json_string_ext(sensor, 0)); | |
258 | ||
259 | if (json_object_object_get_ex(sensor, "uuid", &val)) { | |
260 | if (fermenter->profile_uuid) | |
261 | free(fermenter->profile_uuid); | |
262 | fermenter->profile_uuid = xstrcpy((char *)json_object_get_string(val)); | |
263 | } | |
264 | if (json_object_object_get_ex(sensor, "name", &val)) { | |
265 | if (fermenter->profile_name) | |
266 | free(fermenter->profile_name); | |
267 | fermenter->profile_name = xstrcpy((char *)json_object_get_string(val)); | |
268 | } | |
269 | if (json_object_object_get_ex(sensor, "state", &val)) { | |
270 | if (fermenter->profile_state) | |
271 | free(fermenter->profile_state); | |
272 | fermenter->profile_state = xstrcpy((char *)json_object_get_string(val)); | |
273 | } | |
274 | if (json_object_object_get_ex(sensor, "inittemp", &temp)) { | |
275 | if (json_object_object_get_ex(temp, "low", &val)) { | |
276 | fermenter->profile_inittemp_low = json_object_get_double(val); | |
277 | } | |
278 | if (json_object_object_get_ex(temp, "high", &val)) { | |
279 | fermenter->profile_inittemp_high = json_object_get_double(val); | |
280 | } | |
281 | } | |
282 | if (json_object_object_get_ex(sensor, "steps", &val)) { | |
283 | if (fermenter->profile_steps) | |
284 | free(fermenter->profile_steps); | |
285 | fermenter->profile_steps = xstrcpy((char *)json_object_to_json_string_ext(val, 0)); | |
286 | } | |
287 | ||
288 | ||
289 | } else { | |
290 | if (fermenter->profile_uuid) | |
291 | free(fermenter->profile_uuid); | |
292 | if (fermenter->profile_name) | |
293 | free(fermenter->profile_name); | |
294 | if (fermenter->profile_state) | |
295 | free(fermenter->profile_state); | |
296 | if (fermenter->profile_steps) | |
297 | free(fermenter->profile_steps); | |
298 | fermenter->profile_uuid = fermenter->profile_name = fermenter->profile_state = fermenter->profile_steps = NULL; | |
299 | fermenter->profile_percent = 0; | |
300 | fermenter->profile_inittemp_high = fermenter->profile_inittemp_low = 0.0; | |
301 | } | |
302 | } | |
303 | json_object_put(jobj); | |
304 | ||
305 | // fermenter_dump(fermenter); | |
306 | ||
307 | if (new_fermenter) { | |
308 | if (fermenters == NULL) { | |
309 | fermenters = fermenter; | |
310 | } else { | |
311 | for (tmpp = fermenters; tmpp; tmpp = tmpp->next) { | |
312 | if (tmpp->next == NULL) { | |
313 | tmpp->next = fermenter; | |
314 | break; | |
315 | } | |
316 | } | |
317 | } | |
318 | fermenter_mysql_insert(fermenter); | |
319 | } else { | |
320 | fermenter_mysql_update(fermenter); | |
321 | } | |
322 | ||
323 | } | |
324 | ||
325 | ||
326 | ||
327 | /* | |
328 | * With DBIRTH all active fermenters are publishd in an array. | |
329 | * With DDATA only one fermenter is published in the payload. | |
330 | */ | |
331 | void fermenter_birth_data(char *topic, char *payload) | |
332 | { | |
333 | char *message_type, *edge_node, *alias; | |
334 | struct json_object *jobj, *val, *metric, *units, *unit; | |
335 | int arraylen; | |
336 | ||
337 | strtok(topic, "/"); // ignore namespace | |
338 | strtok(NULL, "/"); | |
339 | message_type = strtok(NULL, "/"); | |
340 | edge_node = strtok(NULL, "/\0"); | |
341 | alias = strtok(NULL, "/\0"); | |
342 | ||
343 | if ((alias == NULL) && (strcmp("DBIRTH", message_type) == 0)) { | |
344 | /* | |
345 | * Global initial DBIRTH message with array of fermenters. | |
346 | */ | |
347 | jobj = json_tokener_parse(payload); | |
348 | ||
349 | if (json_object_object_get_ex(jobj, "metric", &metric)) { | |
350 | if (json_object_object_get_ex(metric, "units", &units)) { | |
351 | arraylen = json_object_array_length(units); | |
352 | for (int i = 0; i < arraylen; i++) { | |
353 | /* | |
354 | * Parse the array of units | |
355 | */ | |
356 | unit = json_object_array_get_idx(units, i); | |
357 | ||
358 | if (json_object_object_get_ex(unit, "alias", &val)) { | |
359 | if (alias) | |
360 | free(alias); | |
361 | alias = xstrcpy((char *)json_object_get_string(val)); | |
362 | fermenter_set(edge_node, alias, true, (char *)json_object_to_json_string_ext(unit, 0)); | |
363 | free(alias); | |
364 | alias = NULL; | |
365 | } | |
366 | } | |
367 | } | |
368 | } | |
369 | json_object_put(jobj); | |
370 | return; | |
371 | } | |
372 | ||
373 | if (strcmp("DBIRTH", message_type) == 0) { | |
374 | /* | |
375 | * DBIRTH for just one fermenter. | |
376 | */ | |
377 | jobj = json_tokener_parse(payload); | |
378 | ||
379 | if (json_object_object_get_ex(jobj, "metric", &metric)) { | |
380 | fermenter_set(edge_node, alias, true, (char *)json_object_to_json_string_ext(metric, 0)); | |
381 | } | |
382 | json_object_put(jobj); | |
383 | return; | |
384 | } | |
385 | ||
386 | if (strcmp("DDATA", message_type) == 0) { | |
387 | /* | |
388 | * DDATA update messages for each fermenter. | |
389 | */ | |
390 | jobj = json_tokener_parse(payload); | |
391 | ||
392 | if (json_object_object_get_ex(jobj, "metric", &metric)) { | |
393 | fermenter_set(edge_node, alias, false, (char *)json_object_to_json_string_ext(metric, 0)); | |
394 | } | |
395 | json_object_put(jobj); | |
396 | return; | |
397 | } | |
398 | ||
399 | /* | |
400 | * The rest are errors. | |
401 | */ | |
402 | printf("ERROR fermenter_birth_data: %s %s %s\n", message_type, edge_node, alias); | |
403 | } | |
404 | ||
405 | ||
406 | ||
407 | void fermenter_log(char *topic, char *payload) | |
408 | { | |
409 | char *edge_node, *alias; | |
410 | struct json_object *jobj, *val, *metric, *metric2; | |
411 | fermentation_log *log; | |
412 | struct tm *mytime; | |
413 | time_t timestamp; | |
414 | ||
415 | strtok(topic, "/"); // ignore namespace | |
416 | strtok(NULL, "/"); // group_id | |
417 | strtok(NULL, "/"); // message_type | |
418 | edge_node = strtok(NULL, "/\0"); | |
419 | alias = strtok(NULL, "/\0"); | |
420 | ||
421 | log = (fermentation_log *)malloc(sizeof(fermentation_log)); | |
422 | memset(log, 0, sizeof(fermentation_log)); | |
423 | ||
424 | log->fermenter_node = xstrcpy(edge_node); | |
425 | log->fermenter_alias = xstrcpy(alias); | |
426 | jobj = json_tokener_parse(payload); | |
427 | ||
428 | if (json_object_object_get_ex(jobj, "timestamp", &val)) { | |
429 | timestamp = json_object_get_int(val); | |
430 | log->datetime = malloc(21); | |
431 | mytime = localtime(×tamp); | |
432 | snprintf(log->datetime, 20, "%04d-%02d-%02d %02d:%02d:%02d", | |
433 | mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, mytime->tm_hour, mytime->tm_min, mytime->tm_sec); | |
434 | } | |
435 | ||
436 | if (json_object_object_get_ex(jobj, "metric", &metric)) { | |
437 | ||
438 | if (json_object_object_get_ex(metric, "product", &metric2)) { | |
439 | if (json_object_object_get_ex(metric2, "uuid", &val)) { | |
440 | if (strcmp((char *)"(null)", json_object_get_string(val))) | |
441 | log->product_uuid = xstrcpy((char *)json_object_get_string(val)); | |
442 | } | |
443 | if (json_object_object_get_ex(metric2, "code", &val)) { | |
444 | if (strcmp((char *)"(null)", json_object_get_string(val))) | |
445 | log->product_code = xstrcpy((char *)json_object_get_string(val)); | |
446 | } | |
447 | if (json_object_object_get_ex(metric2, "name", &val)) { | |
448 | if (strcmp((char *)"(null)", json_object_get_string(val))) | |
449 | log->product_name = xstrcpy((char *)json_object_get_string(val)); | |
450 | } | |
451 | } | |
452 | if (json_object_object_get_ex(metric, "stage", &val)) { | |
453 | log->stage = xstrcpy((char *)json_object_get_string(val)); | |
454 | } | |
455 | if (json_object_object_get_ex(metric, "mode", &val)) { | |
456 | log->mode = xstrcpy((char *)json_object_get_string(val)); | |
457 | } | |
458 | if (json_object_object_get_ex(metric, "event", &val)) { | |
459 | if (strcmp((char *)"(null)", json_object_get_string(val))) | |
460 | log->event = xstrcpy((char *)json_object_get_string(val)); | |
461 | } | |
462 | if (json_object_object_get_ex(metric, "fermenter_uuid", &val)) { | |
463 | if (strcmp((char *)"(null)", json_object_get_string(val))) | |
464 | log->fermenter_uuid = xstrcpy((char *)json_object_get_string(val)); | |
465 | } | |
466 | if (json_object_object_get_ex(metric, "temperature", &metric2)) { | |
467 | if (json_object_object_get_ex(metric2, "air", &val)) { | |
468 | log->temperature_air = json_object_get_double(val); | |
469 | } | |
470 | if (json_object_object_get_ex(metric2, "beer", &val)) { | |
471 | log->temperature_beer = json_object_get_double(val); | |
472 | } | |
473 | if (json_object_object_get_ex(metric2, "chiller", &val)) { | |
474 | log->temperature_chiller = json_object_get_double(val); | |
475 | } | |
476 | if (json_object_object_get_ex(metric2, "room", &val)) { | |
477 | log->temperature_room = json_object_get_double(val); | |
478 | } | |
479 | } | |
480 | if (json_object_object_get_ex(metric, "setpoint", &metric2)) { | |
481 | if (json_object_object_get_ex(metric2, "low", &val)) { | |
482 | log->setpoint_low = json_object_get_double(val); | |
483 | } | |
484 | if (json_object_object_get_ex(metric2, "high", &val)) { | |
485 | log->setpoint_high = json_object_get_double(val); | |
486 | } | |
487 | } | |
488 | if (json_object_object_get_ex(metric, "heater", &metric2)) { | |
489 | if (json_object_object_get_ex(metric2, "power", &val)) { | |
490 | log->heater_power = json_object_get_int(val); | |
491 | } | |
492 | if (json_object_object_get_ex(metric2, "usage", &val)) { | |
493 | log->heater_usage = json_object_get_int(val); | |
494 | } | |
495 | } | |
496 | if (json_object_object_get_ex(metric, "cooler", &metric2)) { | |
497 | if (json_object_object_get_ex(metric2, "power", &val)) { | |
498 | log->cooler_power = json_object_get_int(val); | |
499 | } | |
500 | if (json_object_object_get_ex(metric2, "usage", &val)) { | |
501 | log->cooler_usage = json_object_get_int(val); | |
502 | } | |
503 | } | |
504 | if (json_object_object_get_ex(metric, "fan", &metric2)) { | |
505 | if (json_object_object_get_ex(metric2, "power", &val)) { | |
506 | log->fan_power = json_object_get_int(val); | |
507 | } | |
508 | if (json_object_object_get_ex(metric2, "usage", &val)) { | |
509 | log->fan_usage = json_object_get_int(val); | |
510 | } | |
511 | } | |
512 | // printf("%s\n", (char *)json_object_to_json_string_ext(metric, 0)); | |
513 | } | |
514 | json_object_put(jobj); | |
515 | ||
516 | fermentation_mysql_log(log); | |
517 | /* | |
518 | printf("datetime %s\n", log->datetime); | |
519 | printf("product %s %s\n", log->product_code, log->product_name); | |
520 | printf("stage/mode %s %s\n", log->stage, log->mode); | |
521 | printf("temp air %.3f\n", log->temperature_air); | |
522 | printf("temp beer %.3f\n", log->temperature_beer); | |
523 | printf("temp chiller %.3f\n", log->temperature_chiller); | |
524 | printf("temp room %.3f\n", log->temperature_room); | |
525 | printf("setpoint %.1f %.1f\n", log->setpoint_low, log->setpoint_high); | |
526 | printf("heater %3d %ld\n", log->heater_power, log->heater_usage); | |
527 | printf("cooler %3d %ld\n", log->cooler_power, log->cooler_usage); | |
528 | printf("fan %3d %ld\n", log->fan_power, log->fan_usage); | |
529 | printf("event %s\n", log->event); | |
530 | printf("fermenter %s\n", log->fermenter_uuid); | |
531 | */ | |
532 | if (log->datetime) | |
533 | free(log->datetime); | |
534 | if (log->product_uuid ) | |
535 | free(log->product_uuid ); | |
536 | if (log->product_code ) | |
537 | free(log->product_code ); | |
538 | if (log->product_name ) | |
539 | free(log->product_name ); | |
540 | if (log->stage) | |
541 | free(log->stage); | |
542 | if (log->mode) | |
543 | free(log->mode); | |
544 | if (log->event) | |
545 | free(log->event); | |
546 | if (log->fermenter_uuid) | |
547 | free(log->fermenter_uuid); | |
548 | if (log->fermenter_node) | |
549 | free(log->fermenter_node); | |
550 | if (log->fermenter_alias) | |
551 | free(log->fermenter_alias); | |
552 | free(log); | |
553 | } | |
554 | ||
555 | ||
556 | ||
557 | void fermenter_dump(sys_fermenter_list *fermenter) | |
558 | { | |
559 | if (debug) { | |
560 | printf("uuid %s\n", fermenter->uuid); | |
561 | printf("alias %s\n", fermenter->alias); | |
562 | printf("node %s\n", fermenter->node); | |
563 | printf("online %s\n", fermenter->online ? "yes":"no"); | |
564 | printf("product %s / %s\n", fermenter->beercode, fermenter->beername); | |
565 | if (fermenter->air_address) | |
566 | printf("Air %-36s %10s %8.3f\n", fermenter->air_address, fermenter->air_state, fermenter->air_temperature); | |
567 | if (fermenter->beer_address) | |
568 | printf("Beer %-36s %10s %8.3f\n", fermenter->beer_address, fermenter->beer_state, fermenter->beer_temperature); | |
569 | if (fermenter->chiller_address) | |
570 | printf("Chiller %-36s %10s %8.3f\n", fermenter->chiller_address, fermenter->chiller_state, fermenter->chiller_temperature); | |
571 | if (fermenter->heater_address) | |
572 | printf("Heater %-36s %9d%% %8lu\n", fermenter->heater_address, fermenter->heater_state, fermenter->heater_usage); | |
573 | if (fermenter->cooler_address) | |
574 | printf("Cooler %-36s %9d%% %8lu\n", fermenter->cooler_address, fermenter->cooler_state, fermenter->cooler_usage); | |
575 | if (fermenter->fan_address) | |
576 | printf("Fan %-36s %9d%% %8lu\n", fermenter->fan_address, fermenter->fan_state, fermenter->fan_usage); | |
577 | if (fermenter->light_address) | |
578 | printf("Light %-36s %9d%% %8lu\n", fermenter->light_address, fermenter->light_state, fermenter->light_usage); | |
579 | if (fermenter->door_address) | |
580 | printf("Door %-36s %10d\n", fermenter->door_address, fermenter->door_state); | |
581 | if (fermenter->psu_address) | |
582 | printf("PSU %-36s %10d\n", fermenter->psu_address, fermenter->psu_state); | |
583 | printf("mode %s\n", fermenter->mode); | |
584 | printf("alarm %04x\n", fermenter->alarm); | |
585 | printf("sp high %8.3f\n", fermenter->setpoint_high); | |
586 | printf("sp low %8.3f\n", fermenter->setpoint_low); | |
587 | if (fermenter->profile_uuid) { | |
588 | printf("profile uuid %s\n", fermenter->profile_uuid); | |
589 | printf("profile name %s\n", fermenter->profile_name); | |
590 | printf("profile state %s\n", fermenter->profile_state); | |
591 | printf("profile percent %d\n", fermenter->profile_percent); | |
592 | printf("profile sp high %.3f\n", fermenter->profile_inittemp_high); | |
593 | printf("profile sp low %.3f\n", fermenter->profile_inittemp_low); | |
594 | printf("profile steps %s\n", fermenter->profile_steps); | |
595 | } | |
596 | } | |
597 | } | |
598 | ||
599 | ||
600 | ||
601 | void fermenter_death(char *topic) | |
602 | { | |
603 | char *edge_node, *alias; | |
604 | sys_fermenter_list *tmpp; | |
605 | ||
606 | printf("fermenter_death: %s\n", topic); | |
607 | strtok(topic, "/"); // ignore namespace | |
608 | strtok(NULL, "/"); // ignore group_id | |
609 | strtok(NULL, "/"); // ignore message_type | |
610 | edge_node = strtok(NULL, "/\0"); | |
611 | alias = strtok(NULL, "/\0"); | |
612 | ||
613 | fermenter_mysql_death(edge_node, alias); | |
614 | ||
615 | if (alias) { | |
616 | for (tmpp = fermenters; tmpp; tmpp = tmpp->next) { | |
617 | if ((strcmp(tmpp->node, edge_node) == 0) && (strcmp(tmpp->alias, alias) == 0)) { | |
618 | if (tmpp->online) | |
619 | syslog(LOG_NOTICE, "Offline fermenter %s/%s", tmpp->node, tmpp->alias); | |
620 | tmpp->online = false; | |
621 | break; | |
622 | } | |
623 | } | |
624 | } else { | |
625 | for (tmpp = fermenters; tmpp; tmpp = tmpp->next) { | |
626 | if (strcmp(tmpp->node, edge_node) == 0) { | |
627 | if (tmpp->online) | |
628 | syslog(LOG_NOTICE, "Offline fermenter %s/%s", tmpp->node, tmpp->alias); | |
629 | tmpp->online = false; | |
630 | } | |
631 | } | |
632 | } | |
633 | } | |
634 | ||
635 |