SingingCat 0
application
command-handler.c
Go to the documentation of this file.
1#include <main-header.h>
2#include <loader-api.h>
3#include <user_app_exe.h>
4#include <constants.h>
5#include <function-instr.h>
6#include "sc_time.h"
7#include <baseinfo.h>
8#include <streams.h>
9#include <flashapp.h>
10#include <fets.h>
11#include <led.h>
12#include <sensors/sensor.h>
13#include <sensors/sensor_command.h>
14#include <routing.h>
15#include <route_command.h>
16#include <forwarding.h>
17#include "ti1101.h"
18#include "user_app_info.h"
19#include "user_app_exe.h"
20#include "coms/coms.h"
21//#include <bare-metal.h>
22
23static int dac_toggle_high = 0;
24static int dac_toggle_low = 0;
25static int dac_toggle_speed;
26static int dac_toggle_cur;
27static int dac_cur_value = 0;
28static int dac_toggle_step = 0;
29static byte dac_cur_dir = 0;
30
31static int strobe_relay = 0;
32static int strobe_cur = 0;
33static int strobe_repeat = 0;
34static int strobe_timeout_on = 0;
35static int strobe_timeout_off = 0;
36static int strobe_state = 0;
37#define MAX_PIN_STATES 5
38static uint16_t pinstates[MAX_PIN_STATES]; // max 5 pins may be
53// the delivery queue
54
55
57extern int ack_ctr;
58
59static void restore_pin(int pin);
60static void store_pin(int pin);
61void list_modules(struct command *com);
62void process_strobe_command(struct command *com);
63void check_strobe();
64void start_strobe(int relay, int ton, int toff, int repeat);
65static void software_info(struct command *com);
66static void installed_info(struct command *com);
67static void button_pressed(struct command *com);
68static void set_server_name(struct command *com);
69static void set_sensor_server_name(struct command *com);
70static void set_config(struct command *com);
71static void powerinfo_command_received(struct command *com);
79 memset(&pinstates, 0, sizeof(pinstates));
80}
81void setpin(struct command *com) {
82 int r;
83 int pin = atoi(get_arg(com, 0));
84 int state = atoi(get_arg(com, 1));
85
86 if ((pin == 100) || (pin == 101)) {
87 fets_set_com(com);
88 return;
89 }
90 printf("setting pin %i to %i\r\n", pin, state);
91 if ((r = mculib_pin_out(MAIN_MCULIBHANDLE, pin, HAL_PIN_FASTEST))) {
92 printf("set-pin: failed to set pin %i to out: %i\r\n", pin, r);
93 return;
94 }
95 r = mculib_pin_set(MAIN_MCULIBHANDLE, pin, state);
96 if (r != 0) {
97 printf("set-pin: failed to set pin: %i\r\n", r);
98 }
99}
103static int completion(struct command *com, int result) {
104 if (result == 1) {
105 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
106 } else if (result == 2) {
107 send_command_reply(com, COMFLAGS_ACK);
108 }
109 return result;
110}
111
120int is_packet_for_us(struct command *com) {
121 char ownnode[10];
122 char othernode[10];
123
124 node_to_str(config_get_ram_struct()->nodeid, ownnode);
125 if (!adr_isvalid(com->sender)) {
126 node_to_str(com->sender, othernode);
127 printf("Dropping packet: Invalid sender ID: %s\r\n", othernode);
128 return 0;
129 }
130 if (!adr_isvalid(com->recipient)) {
131 node_to_str(com->recipient, othernode);
132 printf("Dropping packet: Invalid recipient ID: %s\r\n", othernode);
133 return 0;
134 }
135 if (!adr_isvalid(com->target)) {
136 node_to_str(com->target, othernode);
137 printf("Dropping packet: Invalid target ID: %s\r\n", othernode);
138 return 0;
139 }
140 // check if packet is for ourselves
141 if (
142 (com->recipient == 0xFFFFFFFF)
143 || (com->target == 0xFFFFFFFF)
144 || (com->recipient == get_my_node_id())
145 ) {
146 return 1;
147 }
148
149
150 // not for ourselves - but to forward
151 node_to_str(com->recipient, othernode);
152 printf("comhandler: Forwarding packet to %s...\r\n", othernode);
153 int i = forward_packet(com);
154
155 printf("forward result: %i\r\n", i);
156 return 0;
157}
158
159void set_logging(struct command *com) {
160 int enable;
161 int newpos;
162
163 enable = 0;
164 if (com->argctr > 0) {
165 enable = atoi(get_arg(com, 0));
166 }
167 if (com->argctr > 1) {
168 long node = ascii_parse_hex((const byte *)get_arg(com, 1), 8, &newpos);
169 logging_set_node(node);
170 config_set_log_node(node);
171 config_commit();
172 IPLOG("logging enabled\r\n");
173 }
174 if (enable) {
175 logging_on();
176 } else {
177 IPLOG("Disabling logging\r\n");
178 logging_off();
179 config_set_log_node(0);
180 config_commit();
181 }
182}
183void static inline xdelay_us(int us, int timeout) {
184 int jc = 0;
185 int x = us * timeout;
186
187 while (jc < x) {
188 jc++;
189 }
190}
191
192
197void micro_strobe(struct command *com) {
198 int pin = atoi(get_arg(com, 0));
199 int timeout_on = atoi(get_arg(com, 1));
200 int timeout_off = atoi(get_arg(com, 2));
201 int repeat = atoi(get_arg(com, 3));
202 int us = atoi(get_arg(com, 4));
203 int i = 0;
204
205 //long t = mculib_get_seconds_since_boot();
206 for (i = 0; i < repeat; i++) {
207 // long x = mculib_get_seconds_since_boot();
208 //if ( (x-t) > 10) {
209 // break;
210 //}
211 //avoid_watchdog();
212 mculib_pin_set(MAIN_MCULIBHANDLE, pin, 1);
213 xdelay_us(us, timeout_on);
214 mculib_pin_set(MAIN_MCULIBHANDLE, pin, 0);
215 xdelay_us(us, timeout_off);
216 }
217 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
218 printf("Did strobe timeout_on=%i,timeout_off=%i...\r\n", timeout_on, timeout_off);
219}
223void factory_default(struct command *com) {
224 printf("Erasing config...\r\n");
225 config_erase();
226 loader_erase_config();
227 printf("Rebooting...\r\n");
228 reboot_fast();
229}
230
231
232
239 long res = config_get_ram_struct()->nodeid;
240
241 if (!adr_isvalid(res)) {
242 return 0;
243 }
244 res = res & 0xFFFFFFFF; // ensure 32bit
245 return res;
246}
247
254void setcloudtoken(struct command *com) {
255 if (com->argctr != 1) {
256 printf("Missing cloud token!\r\n");
257 send_command_reply(com, COMFLAGS_ACK);
258 return;
259 }
260 const char *token = get_arg(com, 0);
261
262 if (token == NULL) {
263 printf("cloud token must not be NULL!\r\n");
264 send_command_reply(com, COMFLAGS_ACK);
265 return;
266 }
267 printf("Setting a cloud token\r\n");
268 config_set_cloud_token(token);
269 config_commit();
270 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
271 //esp_cloudconnect("module-in.singingcat.net");
273}
274void forward_radio(struct command *com) {
275 int newpos;
276 long node = ascii_parse_hex((const byte *)get_arg(com, 0), 8, &newpos);
277
279 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
280}
284static void set_server_name(struct command *com) {
285 config_set_cloud_server(get_arg(com, 0));
286 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
287 //send_command_reply(com, COMFLAGS_ACK);
288 printf("Command-handler: set new cloud server to %s\r\n", get_arg(com, 0));
289 esp_init();
290}
294static void set_sensor_server_name(struct command *com) {
295 if (com->argctr != 2) {
296 IPLOG("Error - need exactly 2 arguments to set_server_name, not %i\r\n", com->argctr);
297 send_command_reply(com, COMFLAGS_ACK);
298 return;
299 }
300 const char *srv = get_arg(com, 0);
301
302 printf("Setting sensor server to \"%s\"\r\n", srv);
303 config_set_sensor_server(srv);
304 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
305 config_commit();
306}
310void set_config_flag(struct command *com) {
311 if (com->argctr != 2) {
312 IPLOG("Error - need exactly 2 arguments to set_config_flag, not %i\r\n", com->argctr);
313 send_command_reply(com, COMFLAGS_ACK);
314 return;
315 }
316 int flag = atoi(get_arg(com, 0));
317 int value = atoi(get_arg(com, 1));
318
319 config_set_flag(flag, value);
320 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
321 config_commit();
322}
326void get_config_flags(struct command *com) {
327 struct command *reply;
328
329 reply = alloc_command();
330 if (reply == NULL) {
331 printf("cannot reply.\r\n");
332 return;
333 }
334 command_add_arg(reply, "flags1=%i", config_get_ram_struct()->flags1);
335 command_add_arg(reply, "flags2=%i", config_get_ram_struct()->flags2);
336 command_add_arg(reply, "flags=%N", config_get_flags());
337 reply->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
338 reply->index = com->index;
339 reply->target = com->sender;
340 reply->encoding = 'a';
341 reply->connid = com->connid;
342 reply->com = com->com;
343
344 deliver_command(reply, NULL);
345}
346
350void wifi_info(struct command *com) {
351 struct ipv4address *ip;
352 struct command *reply;
353
355 reply = alloc_command();
356 if (reply == NULL) {
357 printf("cannot reply.\r\n");
358 return;
359 }
360 command_add_arg(reply, "ws=%i", esp8266_get_firmware_version());
361 if (ip != NULL) {
362 command_add_arg(reply, "ip=%i.%i.%i.%i", ip->ip1, ip->ip2, ip->ip3, ip->ip4);
363 }
364 const char *ssid = esp_get_last_ssid();
365
366 if (ssid != NULL) {
367 command_add_arg(reply, "ssid=%s", ssid);
368 }
369 const char *pw = esp_get_last_pw();
370
371 if (pw != NULL) {
372 command_add_arg(reply, "pw=%s", pw);
373 }
374 command_add_arg(reply, "rsctr=%i", get_esp_reboot_ctr());
375 reply->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
376 reply->index = com->index;
377 reply->target = com->sender;
378 reply->encoding = 'a';
379 reply->connid = com->connid;
380 reply->com = com->com;
381
382 deliver_command(reply, NULL);
383}
384
388void getcloudtoken(struct command *com) {
389 struct command *reply;
390
391 reply = alloc_command();
392 if (reply == NULL) {
393 printf("cannot reply.\r\n");
394 return;
395 }
396 const char *tok = config_get_cloud_token();
397
398 if (tok != NULL) {
399 command_add_arg(reply, "key=%s", tok);
400 reply->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
401 } else {
402 reply->flags = COMFLAGS_ACK;
403 }
404 reply->index = com->index;
405 reply->target = com->sender;
406 reply->encoding = 'a';
407 reply->connid = com->connid;
408 reply->com = com->com;
409
410 deliver_command(reply, NULL);
411}
412
417void getpubkey(struct command *com) {
418 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
419}
420
421static void gpio_set_dac(int dac, int val) {
422 printf("gpio_set_dac not implemented in command-handler.c\r\n");
423}
424
425void setdac(struct command *com) {
426 if (com->argctr == 2) {
427 int dac = atoi(get_arg(com, 0));
428 int val = atoi(get_arg(com, 1));
429 dac_toggle_step = 0;
430 gpio_set_dac(dac, val);
431 } else if (com->argctr == 5) {
432 dac_toggle_high = atoi(get_arg(com, 1));
433 dac_toggle_low = atoi(get_arg(com, 2));
434 dac_toggle_step = atoi(get_arg(com, 3));
435 dac_toggle_speed = atoi(get_arg(com, 4));
436 if (dac_toggle_low > dac_toggle_high) {
437 int x = dac_toggle_low;
438 dac_toggle_low = dac_toggle_high;
439 dac_toggle_high = x;
440 }
441 dac_cur_value = dac_toggle_low;
442 dac_toggle_cur = 0;
443 if (dac_toggle_step == 0) {
444 gpio_set_dac(0, 0);
445 }
446 }
447 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
448}
452void list_modules(struct command *com) {
453 printf("Listing modules...\r\n");
454 struct command *dcom;
455 int nodes;
456 struct hostroute *host;
457 int i;
458
459 dcom = alloc_command();
460 if (dcom == NULL) {
461 send_command_reply(com, COMFLAGS_ACK);
462 return;
463 }
464 nodes = routing_count_nodes();
465 printf("Got %i nodes\r\n", nodes);
466 for (i = 0; i < nodes; i++) {
468 if (host != NULL) {
469 printf("%p\r\n", (void *)host->host);
470 command_init(dcom);
471 //dcom->recipient = com->sender; // WRONG!! next hop!
472 dcom->target = com->sender;
473 dcom->encoding = 'a';
474 dcom->index = com->index;
475 dcom->sourcedev = com->sourcedev;
476 dcom->connid = com->connid;
477 dcom->com = com->com;
478 dcom->flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
479 command_add_arg(dcom, "%N", host->host);
480 command_add_arg(dcom, "%i", host->hosttype);
481 command_add_arg(dcom, "%i", host->device);
482 send_command(dcom);
483 free_command(dcom);
484 }
485 }
486 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
487}
488
489static void button_pressed(struct command *com) {
490 // do what here exactly?
491}
492
493static uint8_t installed_info_to_flags(int active, int valid) {
494 uint8_t res = 0;
495
496 if (active) {
497 res |= (1 << 0);
498 }
499 if (valid) {
500 res |= (1 << 1);
501 }
502 return res;
503}
504
505static void installed_info(struct command *com) {
506 int version = atoi(get_arg(com, 0));
507
508 printf("getting installed info Version #%i\r\n", version);
509 if (version == 0) {
510 char buf[100];
511 int max = loader_get_app_base_address_count();
512 int i;
513
514 for (i = 0; i < max; i++) {
515 struct app_header *app = loader_get_app_base_address(i);
516 if (app == NULL) {
517 continue;
518 }
519 struct meta_header *header = loader_get_app_meta_address(i);
520 int seq = 0;
521 if (header != NULL) {
522 seq = header->meta_seq;
523 }
524 snprintf(buf, 99, "av=%i,ad=%p,ab=%p,repo=%i,seq=%i,idx=%i",
525 app->version,
526 app->buildtime,
527 app,
528 app->repoid,
529 seq,
530 i
531 );
532 printf("INSTALLED: %s\r\n", buf);
533 if (send_data(com, "%s", buf) != 0) {
534 goto fail;
535 }
536 }
537 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
538 return;
539 } else if ( (version == 1) || (version == 2)){
540 // version 1 of installed software
541 // byte: version,max_installed_firmware
542 // adding uint16 type, uint32 of version, uint32 repo, uint64 baseaddress,uint32 timestamp flags "0=is_active,1=isvalid"
543 byte buf[100];
544 buf[0] = 2;//version
545 int max = loader_get_app_base_address_count();
546 int i;
547
548 int extra = 1;
549 struct userapp_info *ua = get_user_app();
550
551 if (ua != NULL) {
552 extra++;
553 }
554 buf[1] = max + extra; // installed firmware +wifi +userapp
555 int offset = 2;
556
557 if (ua != NULL) {
558 add_uint16(buf, 100, &offset, 3); // SC_APP_STM32L15X=3
559 add_uint32(buf, 100, &offset, ua->version);
560 add_uint32(buf, 100, &offset, ua->repoid);
561 add_uint64(buf, 100, &offset, (uint64_t)((uint32_t)ua->base));
562 if (version == 2) add_uint32(buf, 100, &offset, 0); // userapp has no buildtime
563 add_uint8(buf, 100, &offset, installed_info_to_flags(user_app_is_enabled(), user_app_is_valid()));
564 }
565
566 // add userapp
567 // add wifi software
568 if (esp8266_get_chip() == 1) {
569 add_uint16(buf, 100, &offset, 4); // ESP8266_AS_COPROCESSOR=4;
570 } else if (esp8266_get_chip() == 2) {
571 add_uint16(buf, 100, &offset, 5); // ESP32_AS_COPROCESSOR=5;
572 } else {
573 add_uint16(buf, 100, &offset, 0); // unknown chip
574 }
575 add_uint32(buf, 100, &offset, esp8266_get_firmware_version());
576 add_uint32(buf, 100, &offset, esp8266_get_firmware_repo());
577 add_uint64(buf, 100, &offset, esp8266_get_firmware_base());
578 if (version == 2) add_uint32(buf, 100, &offset,0); // esp32 firmware has no buildtime
579 add_uint8(buf, 100, &offset, installed_info_to_flags(1, 1));
580
581 //add firmware
582 for (i = 0; i < max; i++) {
583 struct app_header *app = loader_get_app_base_address(i);
584 if (app == NULL) {
585 continue;
586 }
587 add_uint16(buf, 100, &offset, 1); // SC_FIRMWARE_STM32L15x
588 add_uint32(buf, 100, &offset, app->version);
589 add_uint32(buf, 100, &offset, app->repoid);
590 add_uint64(buf, 100, &offset, (uint64_t)((uint32_t)app));
591 if (version == 2) add_uint32(buf, 100, &offset, app->buildtime);
592 byte active = 0;
593 if (get_app_header() == app) {
594 active = 1;
595 }
596 //TODO: calculate checksum
597 add_uint8(buf, 100, &offset, installed_info_to_flags(active, 1));
598 }
599 struct command *dcom;
600 dcom = get_data_reply(com);
601 if (dcom == NULL) {
602 goto fail;
603 }
604 command_add_binary_arg(dcom, offset, buf);
605 send_command(dcom);
606 free_command(dcom);
607 } else {
608 // unknown version
609 goto fail;
610 }
611fail:
612 send_command_reply(com, COMFLAGS_ACK);
613}
614
615
616static void software_info(struct command *com) {
617 struct command *dcom;
618
619 dcom = get_data_reply(com);
620 if (dcom == NULL) {
621 goto fail;
622 }
623
624 command_add_arg(dcom, "av=%i", CNW_BUILD_VERSION);
625 command_add_arg(dcom, "ad=%p", CNW_BUILD_TIMESTAMP);
626 command_add_arg(dcom, "ab=%p", get_app_header());
627 command_add_arg(dcom, "repo=%i", get_app_header()->repoid);
628 command_add_arg(dcom, "ws=%i", esp8266_get_firmware_version());
629 command_add_arg(dcom, "ua=%p", config_get_userapp());
630 if (config_get_userapp() != 0) {
631 struct userapp_info *ua = get_user_app();
632 command_add_arg(dcom, "uv=%i", ua->version);
633 command_add_arg(dcom, "ur=%i", ua->repoid);
634 }
635
636 send_command(dcom);
637 free_command(dcom);
638
639 dcom = get_data_reply(com);
640 if (dcom == NULL) {
641 goto fail;
642 }
643 command_add_arg(dcom, "lv=%i", loader_get_version());
644 command_add_arg(dcom, "lpc=%p", constants()->last_return_address);
645 command_add_arg(dcom, "fadr=%p", constants()->failing_address);
646 command_add_arg(dcom, "cfsr=%p", constants()->CFSR);
647 command_add_arg(dcom, "curts=%i", mculib_get_seconds_since_boot());
648 command_add_arg(dcom, "rc=%p", loader_get_last_reset_cause());
649 send_command(dcom);
650 free_command(dcom);
651
652
653 if (send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS)) {
654 goto fail;
655 }
656 printf("sent data for software info\r\n");
657 return;
658fail:
659 send_command_reply(com, COMFLAGS_ACK);
660 printf("Failed to sent data for software info\r\n");
661}
662
663
664void dac_timer() {
665 check_strobe();
666 if (dac_toggle_step == 0) {
667 return;
668 }
669 if (dac_toggle_cur < dac_toggle_speed) {
670 dac_toggle_cur++;
671 return;
672 }
673 dac_toggle_cur = 0;
674 if (dac_cur_dir == 0) {
675 dac_cur_value = dac_cur_value + dac_toggle_step;
676 if (dac_cur_value >= dac_toggle_high) {
677 dac_cur_dir = 1;
678 }
679 } else {
680 dac_cur_value = dac_cur_value - dac_toggle_step;
681 if (dac_cur_value <= dac_toggle_low) {
682 dac_cur_dir = 0;
683 }
684 }
685 gpio_set_dac(0, dac_cur_value);
686}
687
688
689void check_strobe() {
690 if (strobe_timeout_on == 0) {
691 return;
692 }
693 int max = 0;
694
695 if (strobe_state == 1) {
696 max = strobe_timeout_off;
697 } else {
698 max = strobe_timeout_on;
699 }
700 if (strobe_cur < max) {
701 strobe_cur++;
702 return;
703 }
704 strobe_cur = 1;
705 if (strobe_state == 0) {
706 mculib_pin_set(MAIN_MCULIBHANDLE, strobe_relay, 0);
707 strobe_state = 1;
708 } else {
709 strobe_repeat--;
710 mculib_pin_set(MAIN_MCULIBHANDLE, strobe_relay, 1);
711 strobe_state = 0;
712 }
713 if (strobe_repeat <= 0) {
714 strobe_timeout_on = 0;
715 restore_pin(strobe_relay);
716 }
717}
718
719void start_strobe(int relay, int ton, int toff, int repeat) {
720 int r;
721
722 if ((r = mculib_pin_out(MAIN_MCULIBHANDLE, relay, HAL_PIN_FASTEST))) {
723 printf("Strobe: failed to set pin %i to out: %i\r\n", relay, r);
724 return;
725 }
726 store_pin(relay);
727 strobe_state = 0;
728 strobe_relay = relay;
729 strobe_timeout_on = ton;
730 strobe_timeout_off = toff;
731 strobe_repeat = repeat;
732 strobe_cur = 1;
733 mculib_pin_set(MAIN_MCULIBHANDLE, strobe_relay, 1);
734}
735
736
737static void sensorrequest(struct command *com) {
738 int x;
739
740 if (com->argctr != 3) {
741 printf("Need exactly 3 args for sensorrequest, not %i\r\n", com->argctr);
742 // send fail?
743 return;
744 }
745 const void *sensorname = get_arg(com, 0);
746 long idx = ascii_parse_hex(sensorname, strlen(sensorname), NULL);
747 const void *nodeid = get_arg(com, 1);
748 long h = ascii_parse_hex(nodeid, strlen(nodeid), NULL);
749
750 printf("nodeid: %s (%p)\r\n", nodeid, h);
751 int paras[3];
752
753 if ((x = get_arg_int_array(com, 2, (int *)paras, 3)) != 3) {
754 printf("Too few arguments (need 3, got %i\r\n)", x);
755 completion(com, 2);
756 return;
757 }
758
759 completion(com, sensor_submit_request(h, (int)idx, paras[0], paras[1], paras[2]));
760}
761static void blinkled(struct command *com) {
762 if (com->argctr < 3) {
763 printf("Need at least 3 args for blinkled, not %i\r\n", com->argctr);
764 // send fail?
765 return;
766 }
767 led_set_user_managed();
768 int col = atoi(get_arg(com, 0));
769 int on = atoi(get_arg(com, 1));
770 int off = atoi(get_arg(com, 2));
771 int brightness = 256;
772
773 if (com->argctr > 3) {
774 brightness = atoi(get_arg(com, 3));
775 }
776 uint32_t flags = 0;
777
778 if (com->argctr > 4) {
779 flags = atoi(get_arg(com, 4));
780 }
781 printf("Led blink in colour %i, brightness=%i, on=%i, off=%i\r\n", col, brightness, on, off);
782 if (col == 0) {
783 led_off(LED_USER);
784 led_set_machine_managed();
785 } else {
786 led_blink_flags(LED_USER, col, brightness, on, off, flags);
787 }
788 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
789 led_print_status();
790}
791void process_strobe_command(struct command *com) {
792 if (com->argctr != 4) {
793 return;
794 }
795
796 start_strobe(atoi(get_arg(com, 0)), atoi(get_arg(com, 1)), atoi(get_arg(com, 2)), atoi(get_arg(com, 3)));
797}
798
799
800
808void process_command(struct command *com) {
809 int i;
810
811 if (!is_packet_for_us(com)) {
812 return;
813 }
814 if (com->flags & COMFLAGS_ACK) {
815 // do not send this via log! - log will be ack'ed
816 printf("ack received for %i (com=%i)\r\n", com->index, com->com);
817 // packet is an ack
818 i = process_queue_reply(com);
819 if (i > 0) {
820 IPLOG("ack processed for %i (com=%i)\r\n", com->index, com->com);
821 return;
822 }
823 if (i == 0) {
824 // we received a reply, but we (no longer) know which command triggered it!
825 printf("ack received for %i (com=%i), but no trigger command found?\r\n", com->index, com->com);
826 if (com->com == 12) {
827 routing_request_reply(com); // update routing table
828 }
829 }
830 if (i < 0) {
831 printf("ack received for %i (com=%i), but failed to process it.\r\n", com->index, com->com);
832 }
833 return;
834 }
835 if (com->flags & COMFLAGS_DATA) {
836 printf("data received for %i (com=%i)\r\n", com->index, com->com);
837 // packet is data
838 return;
839 }
840
841
842 if (com->com != 28) {
843 // skip printing streamdata - too many!
844 IPLOG("Processing incoming command.:\r\n");
845 command_print(com);
846 }
847
848 /****************************************************
849 * some commands will be executed prior to userhook
850 * to ensure we can recover from broken userhooks
851 ****************************************************/
852
853 if (com->com == 6) {
854 if (com->argctr == 0) {
855 reboot_hard();
856 } else {
857 reboot(atoi(get_arg(com, 0)));
858 }
859 } else if (com->com == 23) {
860 // routing update
861 send_routing_update_now();
862 } else if (com->com == 24) {
863 // factory default
864 factory_default(com);
865 } else if (com->com == 25) {
866 software_info(com); // software info
867 } else if (com->com == 26) {
868 // button pressed
869 button_pressed(com);
870 } else if (com->com == 27) {
871 streamsetup(com);
872 } else if (com->com == 28) {
873 streamdata(com);
874 } else if (com->com == 19) {
875 flashcom(com);
876 } else if (com->com == 36) {
877 installed_info(com);
878 } else if (com->com == 35) {
879 // start app is super important - perhaps we fuck up flashing?
880 restart_app_adr(atoi(get_arg(com, 0)));
881 }
882
883
884 /****************************************************
885 * now we call the userhook and may or may not
886 * continue normal processing, depending on return value
887 ****************************************************/
888
889 // we call the userhook
890 if (user_app_executable()) {
891 if (completion(com, invoke_on_command_received(com)) > 0) {
892 // usercommand did handle it, do not process further
893 free_command(com);
894 return;
895 }
896 }
897
898 /****************************************************
899 * normal processing of commands
900 * (unless command is superimportant - implement here)
901 ****************************************************/
902
903 if (com->com == 1) {
904 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
905 } else if (com->com == 4) { // set-wireless
906 esp8266_add_ap(get_arg(com, 0), get_arg(com, 1));
907 } else if (com->com == 5) {
908 setpin(com);
909 } else if (com->com == 7) {
911 } else if (com->com == 8) { // radio-ping
912 //
913 } else if (com->com == 9) { // radiopingloop
914 //
915 } else if (com->com == 10) {
916 printf("Freezing...\r\n");
917 for (;;) {
918 ; // I am frozen ;)
919 }
920 } else if (com->com == 11) {
921 list_modules(com);
922 } else if (com->com == 13) {
923 process_strobe_command(com);
924 } else if (com->com == 14) {
925 getpubkey(com);
926 } else if (com->com == 15) {
927 setcloudtoken(com);
928 } else if (com->com == 16) {
929 set_logging(com);
930 send_command_reply(com, COMFLAGS_ACK);
931 } else if (com->com == 17) {
932 setdac(com);
933 } else if (com->com == 18) {
934 printf("Set serial port not implemented\r\n");
935 } else if (com->com == 20) {
936 micro_strobe(com);
937 } else if (com->com == 30) {
938 blinkled(com);
939 } else if (com->com == 31) {
940 sensorrequest(com);
941 } else if (com->com == 33) {
942 completion(com, received_radio_get_config(com));
943 } else if (com->com == 34) {
944 completion(com, received_radio_set_config(com));
945 } else if (com->com == 21) {
946 set_server_name(com);
947 } else if (com->com == 38) {
948 getcloudtoken(com);
949 } else if (com->com == 39) {
950 forward_radio(com);
951 } else if (com->com == 41) {
952 set_config_flag(com);
953 } else if (com->com == 43) {
954 set_sensor_server_name(com);
955 } else if (com->com == 44) {
956 wifi_info(com);
957 } else if (com->com == 45) {
958 get_config_flags(com);
959 } else if (com->com == 46) {
960 esp8266_wifi_scan(com);
961 } else if (com->com == 47) {
962 route_command(com);
963 } else if (com->com == 48) {
964 sensor_com_list(com);
965 } else if (com->com == 49) {
966 sensor_com_config(com);
967 } else if (com->com == 52) {
968 set_config(com);
969 } else if (com->com == 53) {
970 user_app_info(com);
971 } else if (com->com == 54) {
972 user_app_control(com);
973 } else if (com->com == 57) {
974 completion(com, esp32_bt_trigger_read_characteristic_com(com));
975 } else if (com->com == 55) {
976 completion(com, esp32_bt_set_characteristic_com(com));
977 } else if (com->com == 58) {
978 completion(com, esp32_bt_peers(com));
979 } else if (com->com == 59) {
980 completion(com, time_command_received(com)); // clock-sync
981 } else if (com->com == 60) { // powerinfo
982 powerinfo_command_received(com);
983 }
984
985
986 if ((com->com == 3)
987 || (com->com == 4)
988 || (com->com == 8)
989 || (com->com == 9)
990 || (com->com == 10)
991 || (com->com == 13)
992 || (com->com == 5)) {
993 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
994 }
995
996 free_command(com);
997}
998
999// command 60 powerinfo
1000static void powerinfo_command_received(struct command *com) {
1001 struct command *reply;
1002 byte buf[100];
1003
1004 reply = alloc_command();
1005 if (reply == NULL) {
1006 printf("cannot reply.\r\n");
1007 return;
1008 }
1009 reply->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
1010 reply->index = com->index;
1011 reply->target = com->sender;
1012 reply->encoding = 'a';
1013 reply->connid = com->connid;
1014 reply->com = com->com;
1015 struct cnw_config *cfg = config_get_ram_struct();
1016
1017 if (cfg == NULL) {
1018 reply->flags = COMFLAGS_ACK;
1019 deliver_command(reply, NULL);
1020 return;
1021 }
1022 command_add_arg(reply, "pi=1"); // version 1, increment if layout changes
1023 int offset = 0;
1024
1025 add_uint8(buf, 100, &offset, config_get_flag(CONFIG_FLAGS_POWER_SAVE));
1026 add_uint16(buf, 100, &offset, config_get_wifioff_duration());
1027 add_uint16(buf, 100, &offset, config_get_radiooff_duration());
1028 add_uint32(buf, 100, &offset, config_get_powermode_flags());
1029 add_uint16(buf, 100, &offset, cfg->sleep_duration);
1030 add_uint16(buf, 100, &offset, cfg->nonsleep_duration);
1031 int len = 30;
1032
1033 command_add_binary_arg(reply, len, buf);
1034 deliver_command(reply, NULL);
1035}
1036
1037// command 52 "setconfig"
1038static void set_config(struct command *com) {
1039 const char *na = namedarg(com, "modid");
1040
1041 if (na != NULL) {
1042 uint64_t modid = atoi(na);
1043 config_set_moduleid(modid);
1044 }
1045 uint32_t v;
1046
1047 if (namedarg_uint32(com, "powermode", &v) == 0) {
1048 if (v) {
1049 config_set_flag(CONFIG_FLAGS_POWER_SAVE, 1);
1050 } else {
1051 config_set_flag(CONFIG_FLAGS_POWER_SAVE, 0);
1052 }
1053 }
1054 if (namedarg_uint32(com, "powermodeflags", &v) == 0) {
1055 config_set_powermode_flags(v);
1056 }
1057 uint16_t f;
1058
1059 if (namedarg_uint16(com, "wifioffdur", &f) == 0) {
1060 config_set_wifioff_duration(f);
1061 }
1062 if (namedarg_uint16(com, "radiooffdur", &f) == 0) {
1063 config_set_radiooff_duration(f);
1064 }
1065 struct cnw_config *cfg = config_get_ram_struct();
1066
1067 if (cfg != NULL) {
1068 if (namedarg_uint16(com, "sd", &f) == 0) {
1069 cfg->sleep_duration = f;
1070 }
1071 if (namedarg_uint16(com, "nsd", &f) == 0) {
1072 cfg->nonsleep_duration = f;
1073 }
1074 }
1075 config_commit();
1076 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
1077}
1078
1079/***************************** store/restore pin status *******************************/
1080// for after strobe..
1081static void store_pin(int pin) {
1082 int i = 0;
1083 int r;
1084 int t = 0;
1085
1086 r = mculib_pin_get(MAIN_MCULIBHANDLE, pin);
1087 if (r == 0) {
1088 // noop
1089 } else if (r == 1) {
1090 t = (1 << 9);
1091 } else {
1092 printf("failed to get pin state: %i\r\n", r);
1093 return;
1094 }
1095 for (i = 0; i < MAX_PIN_STATES; i++) {
1096 if (((pinstates[i] & 0xFF) == pin) && (pinstates[i] & (1 << 8))) {
1097 // do not overwrite value
1098 return;
1099 }
1100 if ((pinstates[i] & (1 << 8)) && ((pinstates[i] & 0xFF) != pin)) {
1101 continue;
1102 }
1103 pinstates[i] = (uint16_t)(((uint8_t)pin) | (1 << 8)) | t;
1104 printf("Stored pin %i: %i\r\n", pin, (int)pinstates[i]);
1105 return;
1106 }
1107 printf("Unable to store pin %i: out of free slots\r\n", pin);
1108}
1109
1110// runs in IRQ!
1111static void restore_pin(int pin) {
1112 int i = 0;
1113 int r;
1114 uint16_t p;
1115
1116 for (i = 0; i < MAX_PIN_STATES; i++) {
1117 p = pinstates[i];
1118 if ((p & (1 << 8)) == 0) {
1119 continue;
1120 }
1121 if ((p & 0xFF) != pin) {
1122 continue;
1123 }
1124 r = 0;
1125 if (p & (1 << 9)) {
1126 r = 1;
1127 }
1128 mculib_pin_set(MAIN_MCULIBHANDLE, pin, r);
1129 pinstates[i] = 0;
1130 break;
1131 }
1132}
definitions of routing table structures
void getcloudtoken(struct command *com)
get the opaque cloud token
int is_packet_for_us(struct command *com)
check if a command needs to be routed
int process_queue_reply(struct command *com)
process a reply
Definition: queue.c:326
void logging_set_node(long nodeid)
log to a given node. Usually this would be an app or a server
Definition: logging.c:27
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 ,...
void list_modules(struct command *com)
we received a list-modules command
void streamdata(struct command *com)
called when we receive a stream data packet TODO: this is a really simplistic, memory-consumption opt...
Definition: streams.c:451
int received_radio_set_config(struct command *com)
called when we received radio_set_config command modified the current radio config
Definition: ti1101.c:905
void getpubkey(struct command *com)
request the public key of this module
void set_config_flag(struct command *com)
set a single config flag
void logging_off()
disable logging and logging processing. guarantees that no buffers are used for logging
Definition: logging.c:34
int send_command(struct command *com)
send a command to another module (or broadcast)
Definition: queue.c:374
void free_command(struct command *com)
free a command
Definition: queue.c:200
int deliver_command(struct command *com, pkt_callback)
deliver a command to a module
Definition: queue.c:651
void ti1101_forward_radio(long node)
forward all radio packets to this node mostly useful to debug and decode and sniff 3rd party protocol...
Definition: ti1101.c:928
void factory_default(struct command *com)
set the module back to factory default
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
void streamsetup(struct command *com)
called when we receive a stream setup packet
Definition: streams.c:305
const char * namedarg(struct command *com, const char *name)
get a named arg (key-value pair) or NULL
long get_my_node_id()
get the id of my node
long host
Definition: routing.h:21
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 ,...
struct hostroute * routing_get_node_by_index(const int index)
finds a nodeid by index. [0...n]
Definition: routing.c:219
int received_radio_get_config(struct command *com)
called when we received radio_get_config command sends back an answer with the current radio config
Definition: ti1101.c:860
void micro_strobe(struct command *com)
do a nano strobe
void esp8266_reset()
reset state machine and esp8266
Definition: esp8266.c:387
int send_command_reply(struct command *com, byte flags)
send a reply to a command
Definition: queue.c:562
int routing_count_nodes()
determine number of nodes known
Definition: routing.c:203
void command_init(struct command *com)
initialize a command structure with default values
int ack_ctr
void process_command(struct command *com)
command is parsed, now execute it
void logging_on()
enable logging and logging processing. buffers are used for logging
Definition: logging.c:42
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...
struct command * get_data_reply(struct command *com)
allocates and initializes a packet to be send as "data" to the command typically you'd add some data ...
Definition: queue.c:271
void get_config_flags(struct command *com)
get config flags
int send_data(struct command *com, const char *format,...)
send the format string as data in response to command "com"
Definition: queue.c:294
void command_print(struct command *com)
prints a command in human readable format to serial console
void flashcom(struct command *com)
set up a flash connection, associate with stream, called by command-handler for command "flash-app"
Definition: flashapp.c:224
void esp_init()
call this ONCE before calling anything else
Definition: esp8266.c:883
struct command * alloc_command()
allocate a free command
Definition: queue.c:173
void wifi_info(struct command *com)
get some information about our currentwifi connection
void setcloudtoken(struct command *com)
set a token to connect to the cloud
struct ipv4address * esp8266_get_current_ip()
return last ip (null if none)
Definition: esp8266.c:1229
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 forward_packet(struct command *com)
a command is forwarded to target based on our hostroutes
Definition: forwarding.c:31
void esp8266_add_ap(const char *ssid, const char *pw)
add an ap to the list of known ap
Definition: esp8266.c:424
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...
void init_command_handler()
resets the command handler
void esp8266_send_instructions()
send our nodeid and other goodies to the esp8266 chip
Definition: esp8266.c:1311
void routing_request_reply(const struct command *com)
we call this when we receive a reply to a routing request this adds or updates a new route
Definition: routing.c:359
definitions of routing table structures
int com
Definition: command.h:22
long target
Definition: command.h:16
uint8_t connid
Definition: command.h:18
uint8_t sourcedev
Definition: command.h:17
uint8_t encoding
Definition: command.h:11
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
this must be implemented by the userapp, stored in flash at the beginning of the file (offset 0)
user application interface