|
1 /** |
|
2 * @file ispindels.c |
|
3 * @brief Handle ispindels data |
|
4 * @author Michiel Broek <mbroek at mbse dot eu> |
|
5 * |
|
6 * Copyright (C) 2019-2020 |
|
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 *payload) |
|
44 { |
|
45 sys_ispindel_list *ispindel, *tmpp; |
|
46 struct json_object *jobj, *metric, *val; |
|
47 bool new_ispindel = true; |
|
48 char *datetime, buf[65], *line, *logfile; |
|
49 struct tm *mytime; |
|
50 time_t timestamp; |
|
51 FILE *fp; |
|
52 |
|
53 // if (debug) |
|
54 // printf("ispindel_set: %s %s\n", node, payload); |
|
55 |
|
56 /* |
|
57 * Search ispindel record in the memory array and use it if found. |
|
58 */ |
|
59 if (ispindels) { |
|
60 for (tmpp = ispindels; tmpp; tmpp = tmpp->next) { |
|
61 if (strcmp(tmpp->node, node) == 0) { |
|
62 new_ispindel = false; |
|
63 ispindel = tmpp; |
|
64 break; |
|
65 } |
|
66 } |
|
67 } |
|
68 |
|
69 // if (debug) |
|
70 // printf("new_ispindel %s\n", new_ispindel ? "true":"false"); |
|
71 |
|
72 /* |
|
73 * Allocate new ispindel if not yet known. |
|
74 */ |
|
75 if (new_ispindel) { |
|
76 ispindel = (sys_ispindel_list *)malloc(sizeof(sys_ispindel_list)); |
|
77 memset(ispindel, 0, sizeof(sys_ispindel_list)); |
|
78 ispindel->node = xstrcpy(node); |
|
79 ispindel->mode = xstrcpy((char *)"OFF"); |
|
80 } |
|
81 |
|
82 if (! ispindel->online) { |
|
83 ispindel->online = true; |
|
84 syslog(LOG_NOTICE, "Online ispindel %s mode %s", node, ispindel->mode); |
|
85 } |
|
86 |
|
87 /* |
|
88 * Process the JSON formatted payload. |
|
89 * Update only the fields that are found in the payload. |
|
90 */ |
|
91 jobj = json_tokener_parse(payload); |
|
92 |
|
93 if (json_object_object_get_ex(jobj, "unit", &metric)) { |
|
94 if (json_object_object_get_ex(metric, "uuid", &val)) { |
|
95 if (ispindel->uuid) |
|
96 free(ispindel->uuid); |
|
97 ispindel->uuid = xstrcpy((char *)json_object_get_string(val)); |
|
98 } |
|
99 if (json_object_object_get_ex(metric, "alias", &val)) { |
|
100 if (ispindel->alias) |
|
101 free(ispindel->alias); |
|
102 ispindel->alias = xstrcpy((char *)json_object_get_string(val)); |
|
103 } |
|
104 if (json_object_object_get_ex(metric, "alarm", &val)) { |
|
105 ispindel->alarm = json_object_get_int(val); |
|
106 } |
|
107 if (json_object_object_get_ex(metric, "interval", &val)) { |
|
108 ispindel->interval = json_object_get_int(val); |
|
109 } |
|
110 if (json_object_object_get_ex(metric, "angle", &val)) { |
|
111 ispindel->angle = json_object_get_double(val); |
|
112 } |
|
113 if (json_object_object_get_ex(metric, "temperature", &val)) { |
|
114 ispindel->temperature = json_object_get_double(val); |
|
115 } |
|
116 if (json_object_object_get_ex(metric, "battery", &val)) { |
|
117 ispindel->battery = json_object_get_double(val); |
|
118 } |
|
119 if (json_object_object_get_ex(metric, "gravity", &val)) { |
|
120 ispindel->gravity = json_object_get_double(val); |
|
121 } |
|
122 } |
|
123 |
|
124 // ispindel_dump(ispindel); |
|
125 |
|
126 if (new_ispindel) { |
|
127 if (ispindels == NULL) { |
|
128 ispindels = ispindel; |
|
129 } else { |
|
130 for (tmpp = ispindels; tmpp; tmpp = tmpp->next) { |
|
131 if (tmpp->next == NULL) { |
|
132 tmpp->next = ispindel; |
|
133 break; |
|
134 } |
|
135 } |
|
136 } |
|
137 ispindel_mysql_insert(ispindel); |
|
138 } else { |
|
139 ispindel_mysql_update(ispindel); |
|
140 } |
|
141 |
|
142 /* |
|
143 * The data is complete, see if we can write a log entry. |
|
144 */ |
|
145 if (ispindel->beercode && strlen(ispindel->beercode) && ispindel->beername && strlen(ispindel->beername) && |
|
146 ispindel->online && (strcmp(ispindel->mode, (char *)"ON") == 0)) { |
|
147 datetime = malloc(72); |
|
148 timestamp = time(NULL); |
|
149 mytime = localtime(×tamp); |
|
150 snprintf(datetime, 72, "%04d-%02d-%02d %02d:%02d:%02d", |
|
151 mytime->tm_year + 1900, mytime->tm_mon + 1, mytime->tm_mday, mytime->tm_hour, mytime->tm_min, mytime->tm_sec); |
|
152 |
|
153 line = xstrcpy(datetime); |
|
154 line = xstrcat(line, (char *)","); |
|
155 snprintf(buf, 64, "%.4f", ispindel->temperature); |
|
156 line = xstrcat(line, buf); |
|
157 line = xstrcat(line, (char *)","); |
|
158 snprintf(buf, 64, "%.5f", ispindel->gravity); |
|
159 line = xstrcat(line, buf); |
|
160 line = xstrcat(line, (char *)","); |
|
161 // snprintf(buf, 64, "%.5f", 1 + (ispindel->gravity / (258.6 - ((ispindel->gravity / 258.2) * 227.1)))); |
|
162 snprintf(buf, 64, "%.5f", 1.00001 + (0.0038661 * ispindel->gravity) + (1.3488e-5 * ispindel->gravity * ispindel->gravity) + |
|
163 (4.3074e-8 * ispindel->gravity * ispindel->gravity * ispindel->gravity)); |
|
164 line = xstrcat(line, buf); |
|
165 line = xstrcat(line, (char *)","); |
|
166 snprintf(buf, 64, "%.6f", ispindel->battery); |
|
167 line = xstrcat(line, buf); |
|
168 line = xstrcat(line, (char *)","); |
|
169 snprintf(buf, 64, "%.5f", ispindel->angle); |
|
170 line = xstrcat(line, buf); |
|
171 line = xstrcat(line, (char *)","); |
|
172 snprintf(buf, 64, "%d", ispindel->interval); |
|
173 line = xstrcat(line, buf); |
|
174 line = xstrcat(line, (char *)","); |
|
175 line = xstrcat(line, ispindel->uuid); |
|
176 |
|
177 /* |
|
178 * Build logfile name |
|
179 */ |
|
180 logfile = xstrcpy(Config.web_root); |
|
181 logfile = xstrcat(logfile, (char *)"/log/ispindel/"); |
|
182 logfile = xstrcat(logfile, ispindel->beercode); |
|
183 logfile = xstrcat(logfile, (char *)" "); |
|
184 logfile = xstrcat(logfile, ispindel->beername); |
|
185 logfile = xstrcat(logfile, (char *)".log"); |
|
186 |
|
187 fp = fopen(logfile, "a"); |
|
188 if (fp) { |
|
189 fprintf(fp, "%s\n", line); |
|
190 fclose(fp); |
|
191 } else { |
|
192 syslog(LOG_NOTICE, "cannot append to `%s'", logfile); |
|
193 } |
|
194 |
|
195 free(logfile); |
|
196 logfile = NULL; |
|
197 free(line); |
|
198 line = NULL; |
|
199 free(datetime); |
|
200 datetime = NULL; |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 |
|
206 /* |
|
207 * Process iSpindel MQTT message. |
|
208 */ |
|
209 void ispindel_birth_data(char *topic, char *payload) |
|
210 { |
|
211 char *message_type, *edge_node; |
|
212 |
|
213 strtok(topic, "/"); // ignore namespace |
|
214 strtok(NULL, "/"); |
|
215 message_type = strtok(NULL, "/"); |
|
216 edge_node = strtok(NULL, "/\0"); |
|
217 |
|
218 if (strcmp("DBIRTH", message_type) == 0) { |
|
219 ispindel_set(edge_node, payload); |
|
220 } |
|
221 } |
|
222 |
|
223 |
|
224 |
|
225 void ispindel_dump(sys_ispindel_list *ispindel) |
|
226 { |
|
227 if (debug) { |
|
228 printf("node/alias %s / %s\n", ispindel->node, ispindel->alias); |
|
229 printf("uuid %s\n", ispindel->uuid); |
|
230 printf("online %s\n", ispindel->online ? "yes":"no"); |
|
231 printf("mode %s\n", ispindel->mode); |
|
232 printf("product %s / %s\n", ispindel->beercode, ispindel->beername); |
|
233 printf("tilt %.5f\n", ispindel->angle); |
|
234 printf("temperature %.4f\n", ispindel->temperature); |
|
235 printf("battery %.6f\n", ispindel->battery); |
|
236 printf("gravity %.5f\n", ispindel->gravity); |
|
237 printf("interval %d\n", ispindel->interval); |
|
238 } |
|
239 } |
|
240 |
|
241 |