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!)
41 const 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 
103 static uint8_t command_match[command_names_size];
108  memset(&command_match, 0, sizeof(command_match));
109 }
113 const 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  */
123 int _command_add_encoded_arg(struct command *com, byte *buf) {
124  return 0;
125 }
130 void 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 }
140 void 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 }
167 int 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 
208 int 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 }
240 char *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 }
257 char sbuf[10];
258 char rbuf[10];
259 char tbuf[10];
264 void 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 }
300 void 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 ********************************************************/
337 int 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 // return 0 if ok, otherwise error
345 int command_decode_ascii(struct command *com, const byte *buf, int size) {
346  int curpos;
347  int newpos;
348  int num;
349  long h;
350  int i;
351  byte chksum;
352  byte nc;
353 
354  CNWDEBUGCOM("Parsing asciibuf \"%s\"\r\n", buf);
355  command_start();
356  if (size < 5) {
357  CNWDEBUG("Buf too short: %i\r\n", size);
358  return 1;
359  }
360  curpos = 0;
361  newpos = 0;
362  num = ascii_parse_int(buf + curpos, size - curpos, &newpos);
363  curpos = curpos + newpos;
364  if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
365  CNWDEBUG("started incorrectly: newpos=%i,curpos=%i,b[]=%i\r\n", newpos, curpos, buf[curpos]);
366  return 2;
367  }
368  com->index = num;
369  CNWDEBUGCOM("1. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
370 
371  for (i = 0; i < 3; i++) {
372  curpos++; // skip comma
373  h = ascii_parse_hex(buf + curpos, size - curpos, &newpos);
374  curpos = curpos + newpos;
375  if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
376  CNWDEBUG("nodeids invalid: newpos=%i,curpos=%i,b[]=%i\r\n", newpos, curpos, buf[curpos]);
377  return 3;
378  }
379  if (i == 0) {
380  com->sender = h;
381  } else if (i == 1) {
382  com->recipient = h;
383  } else if (i == 2) {
384  com->target = h;
385  }
386  CNWDEBUGCOM("2. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
387  }
388 
389  curpos++; // skip comma
390 
391  // parse checksum
392  chksum = atoh((const char *)buf + curpos);
393  curpos = curpos + 3;
394 
395  // parse index
396  num = ascii_parse_int(buf + curpos, size - curpos, &newpos);
397  curpos = curpos + newpos;
398  if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
399  CNWDEBUG("index invalid: idx=%i, newpos=%i,curpos=%i,b[]=%i\r\n", num, newpos, curpos, buf[curpos]);
400  return 4;
401  }
402  com->index = num;
403 
404  curpos++; // skip comma, parse flags
405  com->flags = (byte)ascii_parse_int(buf + curpos, size - curpos, &newpos);
406  curpos = curpos + newpos;
407  if ((newpos <= 0) || (curpos >= size) || (buf[curpos] != ',')) {
408  return 5;
409  }
410 
411  CNWDEBUGCOM("3. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
412 
413  curpos++; // skip comma, parse command number
414  num = ascii_commandstring_to_num(buf + curpos, size - curpos, &newpos);
415  curpos = curpos + newpos;
416  CNWDEBUGCOM("4. size=%i,newpos=%i,curpos=%i,buf->%s\r\n", size, newpos, curpos, buf + curpos);
417  if ((num < 1) || (newpos <= 0)) {
418  CNWDEBUG("not a command! (result=%i, newpos=%i)\r\n", num, newpos);
419  return 6;
420  }
421  com->com = num;
422  if (size <= curpos) {
423  CNWDEBUG("5. Minimum break, size=%i, curpos=%i\r\n", size, curpos);
424  goto returncommand;
425  }
426 
427  // check for args
428  com->argctr = 0;
429 
430  if (buf[curpos] == '}') {
431  // no args, com ended
432  goto returncommand;
433  }
434  if (buf[curpos] != ',') {
435  CNWDEBUG("6. break, illegal character at pos %i: \"%s\"\r\n", curpos, &buf[curpos]);
436  return 7;
437  }
438 
439  // parse args
440  int argbufpos = 0;
441  byte backslash_detected = 0;
442 
443  // we are only parsing byte arrays in ascii decoder!
444  // insert type and length at beginning
445 
446  for (;;) {
447  // any args?
448  curpos++; // skip comma
449 
450  if (curpos >= size) {
451  break;
452  }
453  int field_header_pos = argbufpos;
454  argbufpos = argbufpos + 3;
455  com->argbuf[field_header_pos] = com->argctr + 1; //fieldnum
456  com->argbuf[field_header_pos + 1] = 129; //array
457 
458  backslash_detected = 0;
459  com->argctr++;
460  CNWDEBUGCOM("argctr=%i,buf->%s\n", com->argctr, buf + curpos);
461  if (com->argctr > COMMAND_MAXARGS) {
462  CNWDEBUG("Command has too many arguments: %i (buf->%s)\n", com->argctr, buf + curpos);
463  return 8;
464  }
465  int argsize = 0;
466 
467  // repeat until either end of buf (by size) or an unescaped comma is found
468  while ((backslash_detected || (buf[curpos] != ','))
469  && (curpos < size)) {
470  // single backslash?
471  if (((!backslash_detected)) && (buf[curpos] == '\\')) {
472  backslash_detected = 1;
473  curpos++;
474  continue;
475  }
476  if ((!backslash_detected) && (buf[curpos] == '}')) {
477  com->argbuf[field_header_pos + 2] = argsize;
478  CNWDEBUGCOM(" arg length: %i\n", argsize);
479  CNWDEBUGCOM("end of command detected at pos %i (%s)\n", curpos, buf + curpos);
480  goto returncommand;
481  }
482  backslash_detected = 0;
483 
484  com->argbuf[argbufpos] = buf[curpos];
485  curpos++;
486  argbufpos++;
487  argsize++;
488  }
489  com->argbuf[field_header_pos + 2] = argsize;
490  CNWDEBUGCOM(" arg length: %i\n", argsize);
491  com->argbuf[argbufpos] = 0;
492  argbufpos++;
493  }
494 
495 returncommand:
496  nc = command_calc_checksum(com);
497  if (nc > 0xFF) {
498  fatal_error("checksum broken");
499  }
500  nc = nc & 0xFF;
501  if (nc != chksum) {
502  // hexdump(&com->argbuf,60);
503  free_command(com);
504  printf("Command checksum invalid! (calc=%x, received=%x)\r\n", nc, chksum);
505  // printHex("", (uint8_t *)buf, size);
506  // hexdump((uint8_t *)buf, size);
507  return 9;
508  }
509 
510  return 0;
511 }
512 // returns a command or NULL if not a valid command
513 struct command *command_parse(const byte *buf, int size) {
514  if (size < 3) {
515  CNWDEBUG("size less than 2! (%i)\n", size);
516  return NULL;
517  }
518  if (buf[0] != '{') {
519  CNWDEBUG("Buf does not start with {\n");
520  return NULL;
521  }
522  // we're trying to find end of buf here (removing superflous stuff)
523  int x = size - 1;
524 
525  while ((x > 4) && (buf[x] != '}')) {
526  x--;
527  }
528  if (buf[x] != '}') {
529  CNWDEBUG("Buf does not end with } but with '%i', size=%i\r\n\r\n", buf[size - 1], size);
530  return NULL;
531  }
532 
533  struct command *com = alloc_command();
534 
535  if (com == NULL) {
536  // cannot parse if we have no command to parse into
537  return NULL;
538  }
539  int res = -10;
540 
541  if (buf[1] == 'a') {
542  res = command_decode_ascii(com, buf + 3, x);
543  } else if (buf[1] == 'b') {
544  res = command_decode_binary(com, buf + 1, x);
545  } else {
546  CNWDEBUG("buf is neither ascii nor binary (%s)\n", buf);
547  }
548  if (res == 0) {
549  return com;
550  }
551  printf("not a valid command (parse error: %i)\r\n", res);
552  //hexdump(com->argbuf,250);
553  int i;
554 
555  for (i = 0; i < com->argctr; i++) {
556  const char *arg = get_arg(com, i);
557  printf("Arg %i: %i (%s)\n", i, (arg - com->argbuf), arg);
558  }
559  free_command(com);
560  return NULL;
561 }
562 
563 /*********************************************************
564 *********** turn a command structure to ascii ***********
565 *********************************************************/
571 int command_encode_ascii(struct command *com, int bufsize, char *buf) {
572  int bctr = 0;
573  int i, j;
574  long id;
575  const char *arg;
576 
577  if (!(is_command_valid(com))) {
578  return -3;
579  }
580  memset(buf, 0, bufsize);
581  if ((com->com == 0) || (com->com > command_names_size)) {
582  return -2;
583  }
584  if (bufsize < 5) {
585  printf("Cannot encode ascii to a buffer <5 bytes!\n");
586  return -1;
587  }
588  buf[bctr++] = '{'; // command start
589  buf[bctr++] = 'a'; // com->encoding;
590  snprintf(buf + bctr, bufsize - bctr, ",%i,", PROTOCOL_VERSION_ASCII);
591  bctr = strlen(buf);
592  if (bufsize - bctr < 17) {
593  return -1;
594  }
595  for (i = 0; i < 3; i++) {
596  if (i == 0) {
597  id = com->sender;
598  } else if (i == 1) {
599  id = com->recipient;
600  } else if (i == 2) {
601  id = com->target;
602  }
603  node_to_str(id, buf + bctr);
604  bctr = strlen(buf);
605  buf[bctr++] = ',';
606  buf[bctr] = 0;
607  if (bufsize - bctr < 17) {
608  return -1;
609  }
610  }
611  // add checksum
612  bctr = strlen(buf);
613  int crc = command_calc_checksum(com);
614 
615  crc = crc & 0xFF;
616  snprintf(buf + bctr, bufsize - bctr, "%x,", crc);
617 
618  // add index, flags and commandname
619  bctr = strlen(buf);
620  snprintf(buf + bctr, bufsize - bctr, "%i,%i,%s", com->index,
621  (int)com->flags,
622  command_get_name(com->com)
623  );
624  // add parameters
625  bctr = strlen(buf);
626  for (i = 0; i < com->argctr; i++) {
627  arg = get_arg(com, i);
628  if (arg == NULL) {
629  break;
630  }
631  buf[bctr] = ',';
632  bctr++;
633  j = 0;
634  while (j < get_arg_size(com, i)) {
635  // escape } and ,
636  if ((arg[j] == ',')
637  || (arg[j] == '\\')
638  || (arg[j] == '{')
639  || (arg[j] == '}')) {
640  buf[bctr++] = '\\';
641  }
642  // copy arg to buf
643  buf[bctr++] = arg[j];
644  if (bctr >= bufsize) {
645  return -1;
646  }
647  j++;
648  }
649  buf[bctr] = 0;
650  }
651  buf[bctr++] = '}'; // command end
652  buf[bctr] = 0;
653  return bctr;
654 }
658 void command_init(struct command *com) {
659  memset(com, 0, sizeof(struct command));
660  com->sender = config_get_ram_struct()->nodeid;
661  com->index = -1;
662  com->sourcedev = 0;
663 }
664 
669 const byte *get_arg_new(const struct command *com, int index) {
670  int i;
671  const byte *buf = (const byte *)com->argbuf;
672 
673  if (index >= com->argctr) {
674  return buf;
675  }
676 
677  if (index == 0) {
678  return buf;
679  }
680 
681  int len;
682 
683  for (i = 0; i < index; i++) {
684  len = fieldlen_inmem(buf[1], buf[2]);
685  // printf("arg %i -> %i bytes in memory\n",i,len);
686  buf = buf + len;
687  }
688  // printf("arg %i -> first byte: %i\n",index,buf[0]);
689  return buf;
690 }
691 
698 int get_arg_size_inmem(const struct command *com, int index) {
699  const byte *buf = get_arg_new(com, index);
700 
701  if (buf == NULL) {
702  return 0;
703  }
704  int len = fieldlen_inmem(buf[1], buf[2]);
705 
706  return len;
707 }
708 
712 int get_arg_size(const struct command *com, int index) {
713  if (index >= com->argctr) {
714  return 0;
715  }
716  const byte *buf = get_arg_new(com, index);
717 
718  return fieldlen(buf[1], buf[2]);
719 }
720 
726 const char *get_arg(const struct command *com, int index) {
727  const byte *buf = get_arg_new(com, index);
728 
729  if (buf[1] == 129) {
730  return (const char *)buf + 3; // skip fieldnum+type+size
731  }
732  return (const char *)buf + 2; // skip fieldnum+type
733 }
734 /*
735  * \brief calc checksum of command
736  *
737  */
738 byte command_calc_checksum(struct command *com) {
739  int i;
740  int j;
741  uint32_t chk = 0xC5;
742  int r = 0;
743 
744  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
745  chk ^= com->index;
746  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
747  chk ^= com->sender;
748  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
749  chk ^= com->recipient;
750  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
751  chk ^= com->target;
752  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
753  chk ^= com->com;
754  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
755  chk ^= com->argctr;
756  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
757  chk ^= com->flags;
758  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
759  for (i = 0; i < com->argctr; i++) {
760  const char *x = get_arg(com, i);
761  for (j = 0; j < get_arg_size(com, i); j++) {
762  chk ^= x[j] & 0xFF;
763  }
764  CNWDEBUGCOM("checksum after arg #%i of size %i: %lx (arg=%s)\r\n", i, get_arg_size(com, i), chk, x);
765  }
766  CNWDEBUGCOM("After paras: Checksum step #%i: %lx\r\n", r++, chk);
767  byte res = 0;
768  byte z;
769 
770  for (i = 0; i < 4; i++) {
771  CNWDEBUGCOM("RChecksum step #%i: %x\r\n", r++, res);
772  z = chk >> (i * 8);
773  res ^= z;
774  }
775  chk = res;
776  CNWDEBUGCOM("Checksum step #%i: %lx\r\n", r++, chk);
777  r++; // keep gcc happy
778  //res = res ;
779  res = res & 0xFF;
780  return res;
781 }
785 const char *namedarg(struct command *com, const char *name) {
786  int i;
787 
788  for (i = 0; i < com->argctr; i++) {
789  if (startsWith(get_arg(com, i), name) && (get_arg(com, i)[strlen(name)] == '=')) {
790  return get_arg(com, i) + strlen(name) + 1;
791  }
792  }
793  return NULL;
794 }
799 int namedarg_uint32(struct command *com, const char *name, uint32_t *value) {
800  const char *v = namedarg(com, name);
801 
802  if (v == NULL) {
803  return 1;
804  }
805  uint32_t res = atoi(v);
806 
807  *value = res;
808  return 0;
809 }
814 int namedarg_uint16(struct command *com, const char *name, uint16_t *value) {
815  const char *v = namedarg(com, name);
816 
817  if (v == NULL) {
818  return 1;
819  }
820  uint16_t res = atoi(v);
821 
822  *value = res;
823  return 0;
824 }
825 
832 int get_arg_int_array(const struct command *com, const int index, int *result, const int arraysize) {
833  if (com->argctr <= index) {
834  printf("asked for more args than we have (req=%i, got=%i)\r\n", index, com->argctr);
835  return 0;
836  }
837  int size = get_arg_size(com, index);
838  int i = 0;
839  int num = 0;
840  const char *buf = get_arg(com, index);
841 
842  while (i < size) {
843  if (num >= arraysize) {
844  break;
845  }
846  int r;
847  *(result + num) = ascii_parse_hex((const unsigned char *)&buf[i], size - i, &r);
848  i = i + r + 1;
849  num++;
850  }
851  return num;
852 }
853 
854 // basic sanity check if it's within a minimum sane memory area
855 int is_command_valid(struct command *com) {
856 #ifdef DEBUG_ON_LINUX
857  return 1;
858 #endif
859  if ((void *)com > (void *)0x2000BFFF) {
860  return 0;
861  }
862  return 1;
863 }
864 void error_com(void *com) {
865  printf("Invalid command at %p\r\n", com);
866 }
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:198
struct command * alloc_command()
allocate a free command
Definition: queue.c:171
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....
const char * command_get_name(int num)
given a command number returns its name
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...
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 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...
void command_init(struct command *com)
initialize a command structure with default values
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...
const char * namedarg(struct command *com, const char *name)
get a named arg (key-value pair) or NULL
char * command_get_source_name(byte sourcedev)
returns a human readable text identifying a source device
void command_print(struct command *com)
prints a command in human readable format to serial console
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 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
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