SingingCat 0
application
command-parser.c
Go to the documentation of this file.
1#include "main-header.h"
2#include "coms/coms.h"
3#include "platform-header.h"
5
29#define command_names_size 60
30#ifndef CNWDEBUGCOM
31#define CNWDEBUGCOM(a, ...) noop()
32#endif
33
34// #define CNWDEBUGCOM(a, ...) noop()
35//#define CNWDEBUGCOM printf
36
37// do not change the order!
38// do remember to adjust command_names_size
39// also see command-handler.c "process_packet()" (which is where we jump into once we received one and then decide what to do with it)
40// command->com starts counting at 1 (not 0!)
41const char *const command_names[] = { "noop", // 1
42 "log", // 2
43 "are-you-a-singingcat?", // 3
44 "set-wireless", // 4
45 "set-pin", // 5
46 "reset", // 6
47 "wifireset", // 7
48 "DISradio-ping", // 8
49 "DISradiopingloop", // 9
50 "freeze", // 10
51 "list-modules", // 11
52 "route-request", // 12
53 "strobe", // 13
54 "getpubkey", // 14
55 "setcloudtoken", // 15
56 "set-logging", // 16
57 "set-dac", // 17
58 "set-serial-port",
59 "flash-app", // 19
60 "micro-strobe", // 20
61 "set-server-name", // 21
62 "sensor-value", // 22
63 "announce", // 23
64 "factory-default", // 24
65 "software-info", // 25
66 "button-pressed", // 26
67 "streamsetup", // 27
68 "streamdata", // 28
69 "streamcontrol", // 29
70 "blinkled", // 30
71 "sensor-request", // 31
72 "user", // 32
73 "radio-get-config", // 33
74 "radio-set-config", // 34
75 "startapp", // 35
76 "installed-software", // 36
77 "powerup", // 37
78 "getcloudtoken", // 38
79 "request-radio-forward", // 39
80 "radio-forward", // 40
81 "set-config-flag", // 41
82 "set-config-flags", // 42
83 "set-sensor-server", // 43
84 "wifi-info", // 44
85 "get-config-flags", // 45
86 "wifi-scan", // 46
87 "route", // 47
88 "sensor-list", // 48
89 "sensor-config", // 49
90 "sensor-report", // 50
91 "route-update", //51
92 "setconfig", //52
93 "userapp-info", //53
94 "userapp-control", //54
95 "bt-ble-write-char", //55
96 "metric", // 56
97 "bt-ble-read-char", //57
98 "bt-peers", //58
99 "clock-sync", //59
100 "powerinfo", //60
101 NULL };
102
103static uint8_t command_match[command_names_size];
108 memset(&command_match, 0, sizeof(command_match));
109}
113const char *command_get_name(int num) {
114 if ((num > command_names_size) || (num < 1)) {
115 return "ERROR!";
116 }
117 return command_names[num - 1];
118}
119
120/*
121 * \brief add an encoded arg, that is a buf starting with the 'fieldtype'. return 0 of ok
122 */
123int _command_add_encoded_arg(struct command *com, byte *buf) {
124 return 0;
125}
130void command_add_arg(struct command *com, const char *format, ...) {
131 va_list args;
132
133 va_start(args, format);
134 command_add_varg(com, format, args);
135 va_end(args);
136}
140void command_add_varg(struct command *com, const char *format, va_list args) {
141 char *buf;
142 int r;
143
144 if (com->argctr >= COMMAND_MAXARGS) {
145 printf("ERROR - command has already maximum args\r\n");
146 command_print(com);
147 return;
148 }
149 if (com->argctr == 0) {
150 buf = com->argbuf;
151 r = sizeof(com->argbuf);
152 } else {
153 r = get_arg_size_inmem(com, com->argctr - 1); // end of last arg;
154 buf = (char *)get_arg_new(com, com->argctr - 1); // to last arg
155 buf = buf + r;
156 }
157 vsnprintf(buf + 3, sizeof(com->argbuf) - (buf - com->argbuf) - 3, format, args);
158 buf[0] = com->argctr + 1; // fieldnum
159 buf[1] = 0x81; // byte array field type
160 buf[2] = strlen(buf + 3);
161 com->argctr++;
162}
167int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf) {
168 char *buf;
169 int r;
170
171 if (com->argctr == 0) {
172 buf = com->argbuf;
173 r = sizeof(com->argbuf);
174 } else {
175 r = get_arg_size(com, com->argctr - 1); // end of last arg;
176 buf = (char *)get_arg(com, com->argctr - 1); // to last arg
177 buf = buf + r + 1;
178 r = sizeof(com->argbuf) - (buf - com->argbuf);
179 }
180 int i;
181 int t = 3;
182
183 for (i = 0; i < len; i++) {
184 byte b = srcbuf[i];
185 // if ( (b == ',') || (b == '}')){
186 // buf[t++] = '\\';
187 //}
188 buf[t++] = b;
189 if (t >= r) {
190 IPLOG("buf too long: %i, only got %i bytes left\r\n", len, r);
191 return 1;
192 }
193 }
194 buf[0] = com->argctr + 1;
195 buf[1] = 129;
196 buf[2] = len;
197 com->argctr++;
198 return 0;
199}
200
208int ascii_commandstring_to_num(const byte *buf, int size, int *const newpos) {
209 int i = 0;
210 int j = 0;
211 byte found = 0;
212
213 for (i = 0; i < command_names_size; i++) {
214 const char *com_name = command_names[i];
215 if (strlen(com_name) > size) {
216 continue;
217 }
218 found = 1;
219 for (j = 0; j < strlen(com_name); j++) {
220 if (buf[j] != com_name[j]) {
221 found = 0;
222 break;
223 }
224 }
225 if (!found) {
226 continue;
227 }
228 if ((j < size) && (buf[j] != ',') && (buf[j] != '}')) {
229 continue;
230 }
231 *newpos = strlen(com_name);
232 return i + 1; // (command counting starts at 1 not 0)
233 }
234 *newpos = 0;
235 return 0;
236}
240char *command_get_source_name(byte sourcedev) {
241 if (sourcedev == 1) {
242 return "wifi";
243 } else if (sourcedev == 2) {
244 return "radio";
245 } else if (sourcedev == 3) {
246 return "localtty";
247 } else if (sourcedev == 4) {
248 return "usb";
249 } else if (sourcedev == 5) {
250 return "lora";
251 } else if (sourcedev == 6) {
252 return "bluetooth";
253 } else {
254 return "unknown";
255 }
256}
257char sbuf[10];
258char rbuf[10];
259char tbuf[10];
264void flagstostr(char *buf, int flags) {
265 char *deli;
266
267 deli = "";
268 buf[0] = 0;
269 if (flags == 0) {
270 snprintf(buf + strlen(buf), 20, "NONE");
271 }
272 if (flags & COMFLAGS_ACK) {
273 snprintf(buf + strlen(buf), 20, "%sACK", deli);
274 deli = "|";
275 }
276 if (flags & COMFLAGS_SUCCESS) {
277 snprintf(buf + strlen(buf), 20, "%sSUCCESS", deli);
278 deli = "|";
279 } else if (flags != 0) {
280 snprintf(buf + strlen(buf), 20, "%sFAILURE", deli);
281 deli = "|";
282 }
283 if (flags & COMFLAGS_DATA) {
284 snprintf(buf + strlen(buf), 20, "%sDATA", deli);
285 deli = "|";
286 }
287 if (flags & COMFLAGS_FORWARDED) {
288 snprintf(buf + strlen(buf), 20, "%sFWD", deli);
289 deli = "|";
290 }
291 if (flags & COMFLAGS_POWERSAVE) {
292 snprintf(buf + strlen(buf), 20, "%sPWR", deli);
293 deli = "|";
294 }
295 snprintf(buf + strlen(buf), 20, "(%i)", flags);
296}
300void command_print(struct command *com) {
301 int i;
302 char flagbuf[80];
303
304 if (com == NULL) {
305 return;
306 }
307 if (!is_command_valid(com)) {
308 error_com(com);
309 return;
310 }
311 if ((com->com > command_names_size) || (com->com < 1)) {
312 IPLOG("Command error: %i is out of range (not a valid command!)\r\n", com->com);
313 return;
314 }
315 flagstostr((char *)&flagbuf, com->flags);
316 pretty_node_to_str(com->sender, (char *)&sbuf);
317 pretty_node_to_str(com->recipient, (char *)&rbuf);
318 pretty_node_to_str(com->target, (char *)&tbuf);
319 IPLOG(" [command %p]\r\n device=%s, index=%i, com=%s, flags=%s\r\n sender=%s recipient=%s target=%s\r\n",
320 com,
322 command_get_name(com->com), &flagbuf,
323 (char *)&sbuf, (char *)&rbuf, (char *)&tbuf
324 );
325 if (com->com == 28) { // do not print args of data!
326 IPLOG(" arg: [data]\r\n");
327 return;
328 }
329 for (i = 0; i < com->argctr; i++) {
330 IPLOG(" arg %i: %s\r\n", i, get_arg(com, i));
331 }
332}
333
334/********************************************************
335*********** parse a buffer to a command structure ********
336********************************************************/
337int command_decode_binary(struct command *com, const byte *buf, int size) {
338 // fatal_error("binary commands not yet supported!");
339 return 5;
340}
341
342
343// *buf->first address,second adr, ...
344// (version==1,2,3..) (from packet {1,[version],..}
345// return 0 if ok, otherwise error
346int command_decode_ascii(struct command *com, const byte *buf, int size, int version) {
347 int curpos;
348 int newpos;
349 int num;
350 long h;
351 int i;
352 byte chksum;
353 byte nc;
354
355 CNWDEBUGCOM("Parsing asciibuf \"%s\"\r\n", buf);
357 if (size < 5) {
358 CNWDEBUG("Buf too short: %i\r\n", size);
359 return 1;
360 }
361 curpos = 0;
362 newpos = 0;
363 num = ascii_parse_int(buf + curpos, size - curpos, &newpos);
364 curpos = curpos + newpos;
365 if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
366 CNWDEBUG("started incorrectly: newpos=%i,curpos=%i,b[]=%i\r\n", newpos, curpos, buf[curpos]);
367 return 2;
368 }
369 com->index = num;
370 CNWDEBUGCOM("1. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
371
372 for (i = 0; i < 3; i++) {
373 curpos++; // skip comma
374 h = ascii_parse_hex(buf + curpos, size - curpos, &newpos);
375 curpos = curpos + newpos;
376 if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
377 CNWDEBUG("nodeids invalid: newpos=%i,curpos=%i,b[]=%i\r\n", newpos, curpos, buf[curpos]);
378 return 3;
379 }
380 if (i == 0) {
381 com->sender = h;
382 } else if (i == 1) {
383 com->recipient = h;
384 } else if (i == 2) {
385 com->target = h;
386 }
387 CNWDEBUGCOM("2. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
388 }
389
390 curpos++; // skip comma
391
392 // parse checksum
393 chksum = atoh((const char *)buf + curpos);
394 curpos = curpos + 3;
395
396 // parse index
397 num = ascii_parse_int(buf + curpos, size - curpos, &newpos);
398 curpos = curpos + newpos;
399 if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
400 CNWDEBUG("index invalid: idx=%i, newpos=%i,curpos=%i,b[]=%i\r\n", num, newpos, curpos, buf[curpos]);
401 return 4;
402 }
403 com->index = num;
404
405 curpos++; // skip comma, parse flags
406 com->flags = (byte)ascii_parse_int(buf + curpos, size - curpos, &newpos);
407 curpos = curpos + newpos;
408 if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
409 return 5;
410 }
411
412 CNWDEBUGCOM("3. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
413
414 curpos++; // skip comma, parse command number
415 num = ascii_commandstring_to_num(buf + curpos, size - curpos, &newpos);
416 curpos = curpos + newpos;
417 CNWDEBUGCOM("4. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
418 if ((num < 1) || (newpos <= 0)) {
419 CNWDEBUG("not a command! (result=%i, newpos=%i)\r\n", num, newpos);
420 return 6;
421 }
422 com->com = num;
423 if (size <= curpos) {
424 CNWDEBUG("5. Minimum break, size=%i, curpos=%i\r\n", size, curpos);
425 goto returncommand;
426 }
427
428 // check for args
429 com->argctr = 0;
430
431 if (buf[curpos] == '}') {
432 // no args, com ended
433 goto returncommand;
434 }
435 if (buf[curpos] != ',') {
436 CNWDEBUG("6. break, illegal character at pos %i: \"%s\"\r\n", curpos, &buf[curpos]);
437 return 7;
438 }
439
440 // parse args
441 int argbufpos = 0;
442 byte backslash_detected = 0;
443
444 // we are only parsing byte arrays in ascii decoder!
445 // insert type and length at beginning
446
447 for (;;) {
448 // any args?
449 curpos++; // skip comma
450
451 if (curpos >= size) {
452 break;
453 }
454 int field_header_pos = argbufpos;
455 argbufpos = argbufpos + 3;
456 com->argbuf[field_header_pos] = com->argctr + 1; //fieldnum
457 com->argbuf[field_header_pos + 1] = 129; //array
458
459 backslash_detected = 0;
460 com->argctr++;
461 CNWDEBUGCOM("argctr=%i,buf->%s\n", com->argctr, buf + curpos);
462 if (com->argctr > COMMAND_MAXARGS) {
463 CNWDEBUG("Command has too many arguments: %i (buf->%s)\n", com->argctr, buf + curpos);
464 return 8;
465 }
466 int argsize = 0;
467
468 // repeat until either end of buf (by size) or an unescaped comma is found
469 while ((backslash_detected || (buf[curpos] != ','))
470 && (curpos < size)) {
471 // single backslash?
472 if (((!backslash_detected)) && (buf[curpos] == '\\')) {
473 backslash_detected = 1;
474 curpos++;
475 continue;
476 }
477 if ((!backslash_detected) && (buf[curpos] == '}')) {
478 com->argbuf[field_header_pos + 2] = argsize;
479 CNWDEBUGCOM(" arg length: %i\n", argsize);
480 CNWDEBUGCOM("end of command detected at pos %i (%s)\n", curpos, buf + curpos);
481 goto returncommand;
482 }
483 backslash_detected = 0;
484
485 com->argbuf[argbufpos] = buf[curpos];
486 curpos++;
487 argbufpos++;
488 argsize++;
489 }
490 com->argbuf[field_header_pos + 2] = argsize;
491 CNWDEBUGCOM(" arg length: %i\n", argsize);
492 com->argbuf[argbufpos] = 0;
493 argbufpos++;
494 }
495
496returncommand:
497 nc = command_calc_checksum(com);
498 if (nc > 0xFF) {
499 fatal_error("checksum broken");
500 }
501 nc = nc & 0xFF;
502 if (nc != chksum) {
503 // hexdump(&com->argbuf,60);
504 free_command(com);
505 printf("Command checksum invalid! (calc=%x, received=%x)\r\n", nc, chksum);
506 // printHex("", (uint8_t *)buf, size);
507 // hexdump((uint8_t *)buf, size);
508 return 9;
509 }
510
511 return 0;
512}
513// returns a command or NULL if not a valid command
514struct command *command_parse(const byte *buf, int size) {
515 if (size < 3) {
516 CNWDEBUG("size less than 2! (%i)\n", size);
517 return NULL;
518 }
519 if (buf[0] != '{') {
520 CNWDEBUG("Buf does not start with {\n");
521 return NULL;
522 }
523 // we're trying to find end of buf here (removing superflous stuff)
524 int x = size - 1;
525
526 while ((x > 4) && (buf[x] != '}')) {
527 x--;
528 }
529 if (buf[x] != '}') {
530 CNWDEBUG("Buf does not end with } but with '%i', size=%i\r\n\r\n", buf[size - 1], size);
531 return NULL;
532 }
533
534 struct command *com = alloc_command();
535
536 if (com == NULL) {
537 // cannot parse if we have no command to parse into
538 return NULL;
539 }
540 int res = -10;
541
542 if (buf[1] == 'a') {
543 int version = buf[3] - '0'; // version
544 res = command_decode_ascii(com, buf + 3, x, version);
545 } else if (buf[1] == 'b') {
546 res = command_decode_binary(com, buf + 1, x);
547 } else {
548 CNWDEBUG("buf is neither ascii nor binary (%s)\n", buf);
549 }
550 if (res == 0) {
551 return com;
552 }
553 printf("not a valid command (parse error: %i)\r\n", res);
554 //hexdump(com->argbuf,250);
555 int i;
556
557 for (i = 0; i < com->argctr; i++) {
558 const char *arg = get_arg(com, i);
559 printf("Arg %i: %i (%s)\n", i, (arg - com->argbuf), arg);
560 }
562 return NULL;
563}
564
565/*********************************************************
566*********** turn a command structure to ascii ***********
567*********************************************************/
573int command_encode_ascii(struct command *com, int bufsize, char *buf) {
574 int bctr = 0;
575 int i, j;
576 long id;
577 const char *arg;
578
579 if (!(is_command_valid(com))) {
580 return -3;
581 }
582 memset(buf, 0, bufsize);
583 if ((com->com == 0) || (com->com > command_names_size)) {
584 return -2;
585 }
586 if (bufsize < 5) {
587 printf("Cannot encode ascii to a buffer <5 bytes!\n");
588 return -1;
589 }
590 buf[bctr++] = '{'; // command start
591 buf[bctr++] = 'a'; // com->encoding;
592 snprintf(buf + bctr, bufsize - bctr, ",%i,", PROTOCOL_VERSION_ASCII);
593 bctr = strlen(buf);
594 if (bufsize - bctr < 17) {
595 return -1;
596 }
597 for (i = 0; i < 3; i++) {
598 if (i == 0) {
599 id = com->sender;
600 } else if (i == 1) {
601 id = com->recipient;
602 } else if (i == 2) {
603 id = com->target;
604 }
605 node_to_str(id, buf + bctr);
606 bctr = strlen(buf);
607 buf[bctr++] = ',';
608 buf[bctr] = 0;
609 if (bufsize - bctr < 17) {
610 return -1;
611 }
612 }
613 // add checksum
614 bctr = strlen(buf);
615 int crc = command_calc_checksum(com);
616
617 crc = crc & 0xFF;
618 snprintf(buf + bctr, bufsize - bctr, "%x,", crc);
619
620 // add index, flags and commandname
621 bctr = strlen(buf);
622 snprintf(buf + bctr, bufsize - bctr, "%i,%i,%s", com->index,
623 (int)com->flags,
625 );
626 // add parameters
627 bctr = strlen(buf);
628 for (i = 0; i < com->argctr; i++) {
629 arg = get_arg(com, i);
630 if (arg == NULL) {
631 break;
632 }
633 buf[bctr] = ',';
634 bctr++;
635 j = 0;
636 while (j < get_arg_size(com, i)) {
637 // escape } and ,
638 if ((arg[j] == ',')
639 || (arg[j] == '\\')
640 || (arg[j] == '{')
641 || (arg[j] == '}')) {
642 buf[bctr++] = '\\';
643 }
644 // copy arg to buf
645 buf[bctr++] = arg[j];
646 if (bctr >= bufsize) {
647 return -1;
648 }
649 j++;
650 }
651 buf[bctr] = 0;
652 }
653 buf[bctr++] = '}'; // command end
654 buf[bctr] = 0;
655 return bctr;
656}
660void command_init(struct command *com) {
661 memset(com, 0, sizeof(struct command));
662 com->sender = config_get_ram_struct()->nodeid;
663 com->index = -1;
664 com->sourcedev = 0;
665}
666
671const byte *get_arg_new(const struct command *com, int index) {
672 int i;
673 const byte *buf = (const byte *)com->argbuf;
674
675 if (index >= com->argctr) {
676 return buf;
677 }
678
679 if (index == 0) {
680 return buf;
681 }
682
683 int len;
684
685 for (i = 0; i < index; i++) {
686 len = fieldlen_inmem(buf[1], buf[2]);
687 // printf("arg %i -> %i bytes in memory\n",i,len);
688 buf = buf + len;
689 }
690 // printf("arg %i -> first byte: %i\n",index,buf[0]);
691 return buf;
692}
693
700int get_arg_size_inmem(const struct command *com, int index) {
701 const byte *buf = get_arg_new(com, index);
702
703 if (buf == NULL) {
704 return 0;
705 }
706 int len = fieldlen_inmem(buf[1], buf[2]);
707
708 return len;
709}
710
714int get_arg_size(const struct command *com, int index) {
715 if (index >= com->argctr) {
716 return 0;
717 }
718 const byte *buf = get_arg_new(com, index);
719
720 return fieldlen(buf[1], buf[2]);
721}
722
728const char *get_arg(const struct command *com, int index) {
729 const byte *buf = get_arg_new(com, index);
730
731 if (buf[1] == 129) {
732 return (const char *)buf + 3; // skip fieldnum+type+size
733 }
734 return (const char *)buf + 2; // skip fieldnum+type
735}
736/*
737 * \brief calc checksum of command
738 *
739 */
740byte command_calc_checksum(struct command *com) {
741 int i;
742 int j;
743 uint32_t chk = 0xC5;
744 int r = 0;
745
746 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
747 chk ^= com->index;
748 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
749 chk ^= com->sender;
750 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
751 chk ^= com->recipient;
752 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
753 chk ^= com->target;
754 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
755 chk ^= com->com;
756 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
757 chk ^= com->argctr;
758 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
759 chk ^= com->flags;
760 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
761 for (i = 0; i < com->argctr; i++) {
762 const char *x = get_arg(com, i);
763 for (j = 0; j < get_arg_size(com, i); j++) {
764 chk ^= x[j] & 0xFF;
765 }
766 CNWDEBUGCOM("checksum after arg #%i of size %i: %lx (arg=%s)\r\n", i, get_arg_size(com, i), chk, x);
767 }
768 CNWDEBUGCOM("After paras: Checksum step #%i: %lx\r\n", r++, chk);
769 byte res = 0;
770 byte z;
771
772 for (i = 0; i < 4; i++) {
773 CNWDEBUGCOM("RChecksum step #%i: %x\r\n", r++, res);
774 z = chk >> (i * 8);
775 res ^= z;
776 }
777 chk = res;
778 CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
779 r++; // keep gcc happy
780 //res = res ;
781 res = res & 0xFF;
782 return res;
783}
787const char *namedarg(struct command *com, const char *name) {
788 int i;
789
790 for (i = 0; i < com->argctr; i++) {
791 if (startsWith(get_arg(com, i), name) && (get_arg(com, i)[strlen(name)] == '=')) {
792 return get_arg(com, i) + strlen(name) + 1;
793 }
794 }
795 return NULL;
796}
801int namedarg_uint32(struct command *com, const char *name, uint32_t *value) {
802 const char *v = namedarg(com, name);
803
804 if (v == NULL) {
805 return 1;
806 }
807 uint32_t res = atoi(v);
808
809 *value = res;
810 return 0;
811}
816int namedarg_uint16(struct command *com, const char *name, uint16_t *value) {
817 const char *v = namedarg(com, name);
818
819 if (v == NULL) {
820 return 1;
821 }
822 uint16_t res = atoi(v);
823
824 *value = res;
825 return 0;
826}
827
834int get_arg_int_array(const struct command *com, const int index, int *result, const int arraysize) {
835 if (com->argctr <= index) {
836 printf("asked for more args than we have (req=%i, got=%i)\r\n", index, com->argctr);
837 return 0;
838 }
839 int size = get_arg_size(com, index);
840 int i = 0;
841 int num = 0;
842 const char *buf = get_arg(com, index);
843
844 while (i < size) {
845 if (num >= arraysize) {
846 break;
847 }
848 int r;
849 *(result + num) = ascii_parse_hex((const unsigned char *)&buf[i], size - i, &r);
850 i = i + r + 1;
851 num++;
852 }
853 return num;
854}
855
856// basic sanity check if it's within a minimum sane memory area
857int is_command_valid(struct command *com) {
858#ifdef DEBUG_ON_LINUX
859 return 1;
860#endif
861 if ((void *)com > (void *)0x2000BFFF) {
862 return 0;
863 }
864 return 1;
865}
866void error_com(void *com) {
867 printf("Invalid command at %p\r\n", com);
868}
char * command_get_source_name(byte sourcedev)
returns a human readable text identifying a source device
int namedarg_uint16(struct command *com, const char *name, uint16_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
int command_encode_ascii(struct command *com, int bufsize, char *buf)
encode a command to an ascii blob properly surrounded by '{' and '}' and escaped returns length if ok...
void free_command(struct command *com)
free a command
Definition: queue.c:200
int get_arg_size_inmem(const struct command *com, int index)
given an argument by index [0..n], will returns the number in bytes this argument takes up in memory....
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
void flagstostr(char *buf, int flags)
given a pointer to a buffer and command flags, it will fill the buffer with a human readable text des...
const char * namedarg(struct command *com, const char *name)
get a named arg (key-value pair) or NULL
int ascii_commandstring_to_num(const byte *buf, int size, int *const newpos)
match a string to a command num.
void command_add_varg(struct command *com, const char *format, va_list args)
adds a varg list of parameters to a command
int namedarg_uint32(struct command *com, const char *name, uint32_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
const char * command_get_name(int num)
given a command number returns its name
void command_init(struct command *com)
initialize a command structure with default values
const byte * get_arg_new(const struct command *com, int index)
given an argument by index[0..n], will returns a pointer to it. This will include the fieldnumber and...
int get_arg_int_array(const struct command *com, const int index, int *result, const int arraysize)
given a command and argument index, will attempt to parse the arg as array and return it array syntax...
void command_print(struct command *com)
prints a command in human readable format to serial console
struct command * alloc_command()
allocate a free command
Definition: queue.c:173
int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf)
adds a binary parameter to command returns 0 if ok otherwise errorcode
const char * get_arg(const struct command *com, int index)
given an argument by index[0..n], will return a pointer to the bytearray (excluding the fieldtype) th...
int get_arg_size(const struct command *com, int index)
given an argument by index [0..n], will returns the size of the value in bytes. for a string/array it...
void command_start()
initialization for command parser
int com
Definition: command.h:22
long target
Definition: command.h:16
uint8_t sourcedev
Definition: command.h:17
long recipient
Definition: command.h:15
int index
Definition: command.h:13
uint8_t flags
Definition: command.h:23
uint8_t argctr
Definition: command.h:24
long sender
Definition: command.h:14