Nyx Node
Loading...
Searching...
No Matches
utils.c
1/* NyxNode
2 * Author: Jérôme ODIER <jerome.odier@lpsc.in2p3.fr>
3 * SPDX-License-Identifier: GPL-2.0-only (Mongoose backend) or GPL-3.0+
4 */
5
6/*--------------------------------------------------------------------------------------------------------------------*/
7
8#include <time.h>
9#include <stdio.h>
10#include <string.h>
11
12#include "../nyx_node_internal.h"
13
14/*--------------------------------------------------------------------------------------------------------------------*/
15/* STATE */
16/*--------------------------------------------------------------------------------------------------------------------*/
17
18STR_t nyx_state_to_str(nyx_state_t state)
19{
20 switch(state)
21 {
22 case NYX_STATE_IDLE:
23 return "Idle";
24 case NYX_STATE_OK:
25 return "Ok";
26 case NYX_STATE_BUSY:
27 return "Busy";
28 case NYX_STATE_ALERT:
29 return "Alert";
30 }
31
32 NYX_LOG_FATAL("Internal error");
33}
34
35/*--------------------------------------------------------------------------------------------------------------------*/
36
37nyx_state_t nyx_str_to_state(STR_t state)
38{
39 if(strcmp("Idle", state) == 0) {
40 return NYX_STATE_IDLE;
41 }
42 if(strcmp("Ok", state) == 0) {
43 return NYX_STATE_OK;
44 }
45 if(strcmp("Busy", state) == 0) {
46 return NYX_STATE_BUSY;
47 }
48 if(strcmp("Alert", state) == 0) {
49 return NYX_STATE_ALERT;
50 }
51
52 NYX_LOG_FATAL("Internal error");
53}
54
55/*--------------------------------------------------------------------------------------------------------------------*/
56/* PERM */
57/*--------------------------------------------------------------------------------------------------------------------*/
58
59STR_t nyx_perm_to_str(nyx_perm_t perm)
60{
61 switch(perm)
62 {
63 case NYX_PERM_RO:
64 return "ro";
65 case NYX_PERM_WO:
66 return "wo";
67 case NYX_PERM_RW:
68 return "rw";
69 }
70
71 NYX_LOG_FATAL("Internal error");
72}
73
74/*--------------------------------------------------------------------------------------------------------------------*/
75
76nyx_perm_t nyx_str_to_perm(STR_t perm)
77{
78 if(strcmp("ro", perm) == 0) {
79 return NYX_PERM_RO;
80 }
81 if(strcmp("wo", perm) == 0) {
82 return NYX_PERM_WO;
83 }
84 if(strcmp("rw", perm) == 0) {
85 return NYX_PERM_RW;
86 }
87
88 NYX_LOG_FATAL("Internal error");
89}
90
91/*--------------------------------------------------------------------------------------------------------------------*/
92/* RULE */
93/*--------------------------------------------------------------------------------------------------------------------*/
94
95STR_t nyx_rule_to_str(nyx_rule_t rule)
96{
97 switch(rule)
98 {
100 return "OneOfMany";
102 return "AtMostOne";
104 return "AnyOfMany";
105 }
106
107 NYX_LOG_FATAL("Internal error");
108}
109
110/*--------------------------------------------------------------------------------------------------------------------*/
111
112nyx_rule_t nyx_str_to_rule(STR_t rule)
113{
114 if(strcmp("OneOfMany", rule) == 0) {
116 }
117 if(strcmp("AtMostOne", rule) == 0) {
119 }
120 if(strcmp("AnyOfMany", rule) == 0) {
122 }
123 NYX_LOG_FATAL("Internal error");
124}
125
126/*--------------------------------------------------------------------------------------------------------------------*/
127/* ONOFF */
128/*--------------------------------------------------------------------------------------------------------------------*/
129
130STR_t nyx_onoff_to_str(nyx_onoff_t onoff)
131{
132 switch(onoff)
133 {
134 case NYX_ONOFF_ON:
135 return "On";
136 case NYX_ONOFF_OFF:
137 return "Off";
138 }
139
140 NYX_LOG_FATAL("Internal error");
141}
142
143/*--------------------------------------------------------------------------------------------------------------------*/
144
145nyx_onoff_t nyx_str_to_onoff(STR_t onoff)
146{
147 if(strcmp("On", onoff) == 0) {
148 return NYX_ONOFF_ON;
149 }
150 if(strcmp("Off", onoff) == 0) {
151 return NYX_ONOFF_OFF;
152 }
153
154 NYX_LOG_FATAL("Internal error");
155}
156
157/*--------------------------------------------------------------------------------------------------------------------*/
158/* BLOB */
159/*--------------------------------------------------------------------------------------------------------------------*/
160
161STR_t nyx_blob_state_to_str(nyx_blob_state_t blob)
162{
163 switch(blob)
164 {
165 case NYX_BLOB_STATE_DISABLED:
166 return "Never";
167 case NYX_BLOB_STATE_ENABLED:
168 return "Also";
169 }
170
171 NYX_LOG_FATAL("Internal error");
172}
173
174/*--------------------------------------------------------------------------------------------------------------------*/
175
176nyx_blob_state_t nyx_str_to_blob_state(STR_t blob)
177{
178 if(strcmp("Never", blob) == 0) {
179 return NYX_BLOB_STATE_DISABLED;
180 }
181 if(strcmp("Also", blob) == 0
182 ||
183 strcmp("Only", blob) == 0
184 ) {
185 return NYX_BLOB_STATE_ENABLED;
186 }
187
188 NYX_LOG_FATAL("Internal error");
189}
190
191/*--------------------------------------------------------------------------------------------------------------------*/
192/* STREAM */
193/*--------------------------------------------------------------------------------------------------------------------*/
194
195STR_t nyx_stream_state_to_str(nyx_stream_state_t stream)
196{
197 switch(stream)
198 {
199 case NYX_STREAM_STATE_DISABLED:
200 return "Never";
201 case NYX_STREAM_STATE_ENABLED:
202 return "Also";
203 }
204
205 NYX_LOG_FATAL("Internal error");
206}
207
208/*--------------------------------------------------------------------------------------------------------------------*/
209
210nyx_stream_state_t nyx_str_to_stream_state(STR_t stream)
211{
212 if(strcmp("Never", stream) == 0) {
213 return NYX_STREAM_STATE_DISABLED;
214 }
215 if(strcmp("Also", stream) == 0
216 ||
217 strcmp("Only", stream) == 0
218 ) {
219 return NYX_STREAM_STATE_ENABLED;
220 }
221
222 NYX_LOG_FATAL("Internal error");
223}
224
225/*--------------------------------------------------------------------------------------------------------------------*/
226/* HELPERS */
227/*--------------------------------------------------------------------------------------------------------------------*/
228
229bool nyx_dict_set_boolean_unref(nyx_dict_t *dict, STR_t key, bool value)
230{
231 nyx_boolean_t *boolean = nyx_boolean_from(value);
232
233 bool result = nyx_dict_set(dict, key, boolean);
234
235 nyx_object_unref(boolean);
236
237 return result;
238}
239
240/*--------------------------------------------------------------------------------------------------------------------*/
241
242bool nyx_dict_set_number_unref(nyx_dict_t *dict, STR_t key, double value)
243{
244 nyx_number_t *number = nyx_number_from(value);
245
246 bool result = nyx_dict_set(dict, key, number);
247
248 nyx_object_unref(number);
249
250 return result;
251}
252
253/*--------------------------------------------------------------------------------------------------------------------*/
254
255bool nyx_dict_set_string_unref(nyx_dict_t *dict, STR_t key, STR_t value, bool managed)
256{
257 nyx_string_t *string = nyx_string_from(value, managed);
258
259 bool result = nyx_dict_set(dict, key, string);
260
261 nyx_object_unref(string);
262
263 return result;
264}
265
266/*--------------------------------------------------------------------------------------------------------------------*/
267
268bool nyx_dict_set_buff_unref(nyx_dict_t *dict, STR_t key, size_t size, BUFF_t buff, bool managed)
269{
270 nyx_string_t *string = nyx_string_from_buff(size, buff, managed);
271
272 bool result = nyx_dict_set(dict, key, string);
273
274 nyx_object_unref(string);
275
276 return result;
277}
278
279/*--------------------------------------------------------------------------------------------------------------------*/
280
281bool internal_copy(nyx_dict_t *dst, const nyx_dict_t *src, STR_t key)
282{
283 nyx_object_t *src_object = nyx_dict_get(src, key);
284
285 if(src_object != NULL)
286 {
287 /*------------------------------------------------------------------------------------------------------------*/
288
289 switch(src_object->type)
290 {
291 /*--------------------------------------------------------------------------------------------------------*/
292
293 case NYX_TYPE_NULL:
294 return src_object->type == NYX_TYPE_NULL;
295
296 /*--------------------------------------------------------------------------------------------------------*/
297
298 case NYX_TYPE_NUMBER:
299 return nyx_dict_set_number_unref(dst, key, nyx_number_get((nyx_number_t *) src_object));
300
301 /*--------------------------------------------------------------------------------------------------------*/
302
303 case NYX_TYPE_BOOLEAN:
304 return nyx_dict_set_boolean_unref(dst, key, nyx_boolean_get((nyx_boolean_t *) src_object));
305
306 /*--------------------------------------------------------------------------------------------------------*/
307
308 case NYX_TYPE_STRING:
309 return nyx_dict_set_string_unref(dst, key, nyx_string_dup(nyx_string_get((nyx_string_t *) src_object)), true);
310
311 /*--------------------------------------------------------------------------------------------------------*/
312
313 default:
314 NYX_LOG_ERROR("Invalid object");
315 break;
316
317 /*--------------------------------------------------------------------------------------------------------*/
318 }
319
320 /*------------------------------------------------------------------------------------------------------------*/
321 }
322
323 return false;
324}
325
326/*--------------------------------------------------------------------------------------------------------------------*/
327
328int internal_get_timestamp(size_t len, str_t str)
329{
330 struct tm tm_now;
331
332 time_t now = time(NULL);
333
334 localtime_r(&now, &tm_now);
335
336 return snprintf(
337 str,
338 len,
339 "%04d-%02d-%02dT%02d:%02d:%02d",
340 tm_now.tm_year + 1900,
341 tm_now.tm_mon + 1,
342 tm_now.tm_mday,
343 tm_now.tm_hour,
344 tm_now.tm_min,
345 tm_now.tm_sec
346 );
347}
348
349/*--------------------------------------------------------------------------------------------------------------------*/
350
351void internal_set_opts(nyx_dict_t *dict, const nyx_opts_t *opts)
352{
353 /*----------------------------------------------------------------------------------------------------------------*/
354
355 char timestamp[36];
356
357 internal_get_timestamp(sizeof(timestamp), timestamp);
358
359 nyx_dict_set_string_unref(dict, "@timestamp", nyx_string_dup(timestamp), true);
360
361 /*----------------------------------------------------------------------------------------------------------------*/
362
363 STR_t group = "Main";
364
365 if(opts != NULL)
366 {
367 /*------------------------------------------------------------------------------------------------------------*/
368
369 if(opts->group != NULL && opts->group[0] != '\0')
370 {
371 group = opts->group;
372 }
373
374 /*------------------------------------------------------------------------------------------------------------*/
375
376 if(opts->label != NULL && opts->label[0] != '\0') {
377 nyx_dict_set_string_unref(dict, "@label", nyx_string_dup(opts->label), true);
378 }
379
380 if(opts->hints != NULL && opts->hints[0] != '\0') {
381 nyx_dict_set_string_unref(dict, "@hints", nyx_string_dup(opts->hints), true);
382 }
383
384 if(opts->message != NULL && opts->message[0] != '\0') {
385 nyx_dict_set_string_unref(dict, "@message", nyx_string_dup(opts->message), true);
386 }
387
388 /*------------------------------------------------------------------------------------------------------------*/
389
390 if(opts->timeout > 0.0) {
391 nyx_dict_set_number_unref(dict, "@timeout", opts->timeout);
392 }
393
394 /*------------------------------------------------------------------------------------------------------------*/
395 }
396
397 /*----------------------------------------------------------------------------------------------------------------*/
398
399 nyx_dict_set_string_unref(dict, "@group", nyx_string_dup(group), true);
400
401 /*----------------------------------------------------------------------------------------------------------------*/
402}
403
404/*--------------------------------------------------------------------------------------------------------------------*/
405
406bool internal_blob_is_compressed(const nyx_dict_t *def)
407{
408 nyx_string_t *format = (nyx_string_t *) /* NOSONAR */ nyx_dict_get(def, "@format");
409
410 return format != NULL && format->base.type == NYX_TYPE_STRING && format->length > 2 && format->value[format->length - 2] == '.' && format->value[format->length - 1] == 'z';
411}
412
413/*--------------------------------------------------------------------------------------------------------------------*/
414
415static void internal_copy_blob(nyx_dict_t *dst_dict, const nyx_dict_t *src_dict)
416{
417 /*----------------------------------------------------------------------------------------------------------------*/
418
419 internal_copy(dst_dict, src_dict, "@size");
420 internal_copy(dst_dict, src_dict, "@format");
421
422 /*----------------------------------------------------------------------------------------------------------------*/
423
424 nyx_object_t *src_payload = nyx_dict_get(src_dict, "$");
425
426 if(src_payload != NULL && src_payload->type == NYX_TYPE_STRING)
427 {
428 /*------------------------------------------------------------------------------------------------------------*/
429
430 size_t src_size;
431 buff_t src_buff;
432
433 nyx_string_get_buff((nyx_string_t *) src_payload, &src_size, &src_buff);
434
435 /*------------------------------------------------------------------------------------------------------------*/
436
437 size_t dst_len;
438 str_t dst_str;
439
440 if(internal_blob_is_compressed(src_dict)) {
441 dst_str = nyx_zlib_base64_deflate(&dst_len, src_size, src_buff);
442 }
443 else {
444 dst_str = nyx_base64_encode(&dst_len, src_size, src_buff);
445 }
446
447 /*------------------------------------------------------------------------------------------------------------*/
448
449 nyx_dict_set(dst_dict, "$", nyx_string_from_buff(dst_len, dst_str, true));
450
451 /*------------------------------------------------------------------------------------------------------------*/
452 }
453
454 /*----------------------------------------------------------------------------------------------------------------*/
455}
456
457/*--------------------------------------------------------------------------------------------------------------------*/
458
459nyx_dict_t *internal_prop_to_set_vector(const nyx_dict_t *vector, STR_t set_tag, STR_t one_tag)
460{
461 /*----------------------------------------------------------------------------------------------------------------*/
462
463 nyx_dict_t *result = nyx_dict_new();
464
465 nyx_list_t *children = nyx_list_new();
466
467 /*----------------------------------------------------------------------------------------------------------------*/
468
469 nyx_dict_set_string_unref(result, "<>", set_tag, false);
470
471 /*----------------------------------------------------------------------------------------------------------------*/
472
473 internal_copy(result, vector, "@client");
474 internal_copy(result, vector, "@device");
475 internal_copy(result, vector, "@name");
476 internal_copy(result, vector, "@state");
477 internal_copy(result, vector, "@timeout");
478 internal_copy(result, vector, "@timestamp");
479 internal_copy(result, vector, "@message");
480
481 /*----------------------------------------------------------------------------------------------------------------*/
482
483 nyx_dict_set(result, "children", children);
484
485 /*----------------------------------------------------------------------------------------------------------------*/
486
487 size_t idx;
488
489 nyx_object_t *object;
490
491 nyx_object_t *list = nyx_dict_get(vector, "children");
492
493 if(list != NULL && list->type == NYX_TYPE_LIST)
494 {
495 for(nyx_list_iter_t iter = NYX_LIST_ITER(list); nyx_list_iterate(&iter, &idx, &object);)
496 {
497 if(object->type == NYX_TYPE_DICT)
498 {
499 /*----------------------------------------------------------------------------------------------------*/
500
501 nyx_dict_t *src_dict = (nyx_dict_t *) /* NOSONAR */ object, *dst_dict = nyx_dict_new();
502
503 /*----------------------------------------------------------------------------------------------------*/
504
505 nyx_dict_set_string_unref(dst_dict, "<>", one_tag, false);
506
507 internal_copy(dst_dict, src_dict, "@name");
508
509 if(strcmp(one_tag, "oneBLOB") == 0) {
510 internal_copy_blob(dst_dict, src_dict);
511 }
512 else {
513 internal_copy(dst_dict, src_dict, "$");
514 }
515
516 /*----------------------------------------------------------------------------------------------------*/
517
518 nyx_list_push(children, dst_dict);
519
520 nyx_object_unref(dst_dict);
521
522 /*----------------------------------------------------------------------------------------------------*/
523 }
524 }
525 }
526
527 /*----------------------------------------------------------------------------------------------------------------*/
528
529 nyx_object_unref(children);
530
531 /*----------------------------------------------------------------------------------------------------------------*/
532
533 return result;
534}
535
536/*--------------------------------------------------------------------------------------------------------------------*/
Struct describing a JSON boolean object.
Definition nyx_node.h:821
Struct describing a JSON dict object.
#define NYX_LIST_ITER(list)
Initializes a JSON list iterator.
Definition nyx_node.h:1457
Struct describing a JSON list iterator.
Definition nyx_node.h:1443
Struct describing a JSON list object.
#define NYX_LOG_FATAL(fmt,...)
Logs a fatal message.
Definition nyx_node.h:208
#define NYX_LOG_ERROR(fmt,...)
Logs an error message.
Definition nyx_node.h:219
#define STR_t
Alias for const char *.
Definition nyx_node.h:71
#define buff_t
Alias for void *.
Definition nyx_node.h:67
#define BUFF_t
Alias for const void *.
Definition nyx_node.h:68
__NYX_NULLABLE__ str_t nyx_string_dup(__NYX_NULLABLE__ STR_t s)
Similar to libc strdup.
#define str_t
Alias for char *.
Definition nyx_node.h:70
Struct describing a JSON number object.
Definition nyx_node.h:726
__NYX_ZEROABLE__ double timeout
Worst-case time [sec] to apply, 0 by default, N/A for RO.
Definition nyx_node.h:2054
__NYX_NULLABLE__ STR_t label
GUI label, if NULL, replaced by the device name.
Definition nyx_node.h:2051
__NYX_NULLABLE__ STR_t hints
GUI Markdown description.
Definition nyx_node.h:2052
__NYX_NULLABLE__ STR_t message
Free comment.
Definition nyx_node.h:2053
__NYX_NULLABLE__ STR_t group
GUI group membership, if NULL, replaced by "Main".
Definition nyx_node.h:2050
nyx_perm_t
Vector permission hint.
Definition nyx_node.h:1948
nyx_state_t
Vector state hint.
Definition nyx_node.h:1913
nyx_onoff_t
Switch state.
Definition nyx_node.h:2016
nyx_rule_t
Switch vector rule hint.
Definition nyx_node.h:1982
@ NYX_PERM_RW
Read & write.
Definition nyx_node.h:1951
@ NYX_PERM_WO
Write only.
Definition nyx_node.h:1950
@ NYX_PERM_RO
Read only.
Definition nyx_node.h:1949
@ NYX_STATE_IDLE
State is idle.
Definition nyx_node.h:1914
@ NYX_STATE_BUSY
State is busy.
Definition nyx_node.h:1916
@ NYX_STATE_OK
State is ok.
Definition nyx_node.h:1915
@ NYX_STATE_ALERT
State is alert.
Definition nyx_node.h:1917
@ NYX_ONOFF_ON
Switch is ON.
Definition nyx_node.h:2017
@ NYX_ONOFF_OFF
Switch is OFF.
Definition nyx_node.h:2018
@ NYX_RULE_ONE_OF_MANY
Only one switch of many can be ON (e.g., radio buttons).
Definition nyx_node.h:1983
@ NYX_RULE_ANY_OF_MANY
Any number of switches can be ON (e.g., check boxes).
Definition nyx_node.h:1985
@ NYX_RULE_AT_MOST_ONE
At most one switch can be ON, but all switches can be OFF.
Definition nyx_node.h:1984
Struct describing the options for INDI / Nyx vectors.
Definition nyx_node.h:2049
@ NYX_TYPE_DICT
Dict object.
Definition nyx_node.h:438
@ NYX_TYPE_LIST
List object.
Definition nyx_node.h:439
@ NYX_TYPE_BOOLEAN
Boolean object.
Definition nyx_node.h:435
@ NYX_TYPE_NUMBER
Number object.
Definition nyx_node.h:436
@ NYX_TYPE_NULL
Null object.
Definition nyx_node.h:434
@ NYX_TYPE_STRING
String object.
Definition nyx_node.h:437
Struct describing a JSON object.
str_t value
C string payload.
Definition nyx_node.h:919
nyx_object_t base
Common object header for JSON objects.
Definition nyx_node.h:915
size_t length
C string length excluding NULL.
Definition nyx_node.h:918
Struct describing a JSON string object.
Definition nyx_node.h:914
__NYX_NULLABLE__ str_t nyx_base64_encode(__NYX_NULLABLE__ size_t *result_len, __NYX_ZEROABLE__ size_t size, __NYX_NULLABLE__ BUFF_t buff)
Encodes a buffer using the Base64 algorithm.
__NYX_NULLABLE__ str_t nyx_zlib_base64_deflate(__NYX_NULLABLE__ size_t *result_len, __NYX_ZEROABLE__ size_t size, __NYX_NULLABLE__ BUFF_t buff)
Compresses a buffer using the ZLib+Base64 algorithm.