1 #include <main-header.h>
3 #include <command-parser.h>
4 #include <command-handler.h>
8 #include "espressif/esp8266_cloud.h"
10 #include <route_command.h>
11 #include "metrics/metrics.h"
13 #define MAX_COM_RETRIES 30
19 #define SEND_BUF_RESERVED1 1
20 #define SEND_BUF_RESERVED2 2
21 #define SEND_NO_CLOUD 3
22 #define SEND_NO_TARGET 5
23 #define SEND_NO_RECIPIENT 6
24 #define SEND_COM_FAILED_TO_ENCODE 7
25 #define SEND_COM_NOT_ENCODED 12
26 #define SEND_COM_INVALID 13
27 #define SEND_COM_STILL_INVALID 14
28 #define SEND_FAILURE_NODEV 16
30 #define SEND_DEVICE_BUSY -113
50 static int command_index = 0;
52 static char queuebuf[256];
53 #define COM_QUEUE_SIZE 50
62 static struct queue_entry out_queue[COM_QUEUE_SIZE];
63 static int send_command_internal(
struct command *com,
int print);
65 static int broadcast_device();
77 #define COMMAND_AGE_BEFORE_GC 120
80 memset(&out_queue, 0,
sizeof(out_queue));
87 printf(
"Outbound command queue cleared.\r\n");
90 void print_outbound_queue() {
92 int elements = get_mpm()->max_commands;
95 for (i = 0; i < elements; i++) {
96 p = &get_mpm()->commem[i];
97 if (p->allocated == 0) {
100 printf(
"------- Queue position %i: ------\r\n", i);
105 struct command *alloc_command_with_minfree(
int minfree) {
109 int elements = get_mpm()->max_commands;
113 for (i = 0; i < elements; i++) {
114 p = &get_mpm()->commem[i];
115 if (p->allocated == 0) {
117 if ( (free>=minfree) && (res!=NULL) ){
128 res->command.
index = -1;
129 res->allocated = mculib_get_seconds_since_boot();
130 return &res->command;
135 printf(
"command buffers are all allocated (reserved %i):\n",minfree);
136 for (i = 0; i < elements; i++) {
137 p = &get_mpm()->commem[i];
138 long now = mculib_get_seconds_since_boot();
139 long age = (now - p->allocated);
140 if (p->allocated != 0) {
155 IPLOG(
"BIG FAT WARNING - No command left to allocate (%i) (reserved %i).\r\n", elements,minfree);
158 printf(
"Reallocated garbage collected command: %p\r\n", &res->command);
160 return &res->command;
172 return alloc_command_with_minfree(0);
182 int elements =
sizeof(get_mpm()->commem) /
sizeof(get_mpm()->commem[0]);
185 for (i = 0; i < elements; i++) {
186 p = &get_mpm()->commem[i];
187 if (p->allocated != 0) {
202 if (p->allocated == 0) {
212 static void garbage_collect_commands() {
215 int elements = get_mpm()->max_commands;
217 long now = mculib_get_seconds_since_boot();
219 for (i = 0; i < elements; i++) {
220 p = &get_mpm()->commem[i];
221 if (p->allocated == 0) {
224 long age = (now - p->allocated);
233 static void garbage_collect_queue_entries() {
234 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
238 for (i = 0; i < elements; i++) {
239 if (out_queue[i].
command == NULL) {
243 if (p->allocated == 0) {
244 out_queue[i].command = NULL;
252 static void set_power_mode_on_com(
struct command *com) {
253 if (config_get_flag(CONFIG_FLAGS_POWER_SAVE)) {
254 com->
flags |= COMFLAGS_POWERSAVE;
256 com->
flags &= ~COMFLAGS_POWERSAVE;
284 dcom->
flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
301 va_start(args, format);
325 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
329 for (i = 0; i < elements; i++) {
331 if (q->command == NULL) {
338 printf(
"That is my command at index %i\r\n", i);
340 struct command *c = q->command;
341 if (c->
target != 0xFFFFFFFF) {
351 static int get_next_command_index() {
352 if ((command_index > 32000) || (command_index < 0)) {
355 return ++command_index;
373 printf(
"Sending command:\r\n");
374 int a = send_command_internal(
com, 1);
377 printf(
"Sending failed (code=%i)\r\n", a);
382 int send_command_quietly(
struct command *
com) {
383 return send_command_internal(
com, 0);
390 static int send_command_internal(
struct command *
com,
int p) {
397 if (com->
index == -1) {
398 com->
index = get_next_command_index();
401 return SEND_NO_TARGET;
405 if (com->
target == CLOUD_SERVER) {
406 if ((esp_cloud_is_connected()) || ((com->local_flags & (1 << COM_LOCAL_FLAG_FORCE_DEVICE)) && (com->
sourcedev == SOURCE_WIFI))) {
413 struct route *r = get_configured_route(com);
422 if (com->
target == BROADCAST) {
425 goto gotdev_no_recipt;
432 if (esp_cloud_is_connected()) {
436 return SEND_NO_CLOUD;
446 return SEND_NO_RECIPIENT;
457 return SEND_FAILURE_NODEV;
462 return SEND_DEVICE_BUSY;
465 if (!is_command_valid(com)) {
466 printf(
"Cannot print at %p\r\n", com);
467 return SEND_COM_INVALID;
471 if (!is_command_valid(com)) {
472 printf(
"print broke stuff at %p (was: %p)\r\n", com, foocom);
473 return SEND_COM_STILL_INVALID;
476 if (!is_command_valid(com)) {
477 printf(
"Cannot encode at %p\r\n", com);
478 return SEND_COM_NOT_ENCODED;
480 set_power_mode_on_com(com);
484 printf(
"Failed to encode packet (%i) at %p.\r\n", len, com);
485 return SEND_COM_FAILED_TO_ENCODE;
489 int i = send_buf_via_device(com->
sourcedev, (
const byte *)&queuebuf, len);
494 printf(
"Failed to sent packet:\r\n");
546 reply->
flags = COMFLAGS_FORWARDED;
604 va_start(args, format);
614 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
617 for (i = 0; i < elements; i++) {
618 if (out_queue[i].
command == NULL) {
619 memset(&out_queue[i], 0,
sizeof(out_queue[0]));
620 out_queue[i].command = com;
621 return &out_queue[i];
624 printf(
"BIG FAT WARNING - no free queue slot found!\r\n");
652 if (!is_command_valid(com)) {
656 q = alloc_free_queue_entry(com);
658 printf(
"No available queue slot\r\n");
662 IncMetric_COM_QUEUE_ADDED;
683 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
687 long now = mculib_get_seconds_since_boot();
690 garbage_collect_commands();
691 garbage_collect_queue_entries();
694 for (i = 0; i < elements; i++) {
696 if (q->command == NULL) {
699 if (!is_command_valid(q->command)) {
700 printf(
"Command %i in queue is invalid\r\n", i);
712 IPLOG(
"Processing queue with %i elements, due elements: %i\r\n", res, x);
713 for (i = 0; i < elements; i++) {
715 if (q->command == NULL) {
727 pretty_node_to_str(c->
target, (
char *)&t);
733 printf(
"Discarded command, No response to command %i (target: %s)\r\n", i, t);
736 printf(
"sending com %i (attempt #%i) to %s\r\n", i, q->
attemptctr, t);
742 printf(
"Queue: temporarily unable to send command %i\r\n", i);
743 }
else if (res > 0) {
746 printf(
"Queue: command #%i (type %i) unsendable (given up) reason: %i\r\n", i, q->command->
com, res);
758 if (c->
flags & (COMFLAGS_ACK | COMFLAGS_FORWARDED | COMFLAGS_DATA)) {
777 printf(
"Requesting route for %N\r\n", nodeid);
783 com->sourcedev = SOURCE_WIFI;
785 com->target = 0xFFFFFFFF;
786 com->recipient = 0xFFFFFFFF;
790 if (!config_get_wifidisable()) {
791 com->sourcedev = SOURCE_WIFI;
795 com->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
797 if (isready_by_type(SOURCE_RADIO)) {
798 com->sourcedev = SOURCE_RADIO;
801 if (isready_by_type(SOURCE_LORA)) {
802 com->sourcedev = SOURCE_LORA;
814 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
817 for (i = 0; i < elements; i++) {
819 if (q->command == NULL) {
822 if ((q->command->
com == 1) || (q->command->
com == 23)) {
830 static int broadcast_device() {
832 int somewhat_good = 0;
841 uint8_t type = nc->source;
842 if (!isonline_by_type(type)) {
845 somewhat_good = type;
846 if ((isready_by_type(type))) {
853 return somewhat_good;
int process_queue_reply(struct command *ack)
process a reply
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...
long nexthop
here the nodeif of the intermediary hop (the proxy)
int send_command_reply_with_args(struct command *com, byte flags, const char *format,...)
send a reply to a command
void free_commands(int index)
free commands by index (-1 for all)
int send_command(struct command *com)
send a command to another module (or broadcast)
void free_command(struct command *com)
free a command
int deliver_command(struct command *com, pkt_callback cb)
deliver a command to a module
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 ...
struct command * alloc_command()
allocate a free command
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
int get_outbound_command_count_important()
return number of commands to be delivered (apart from announce/noop)
struct hostroute * routing_find_host(const long nodeid)
find route to host or NULL if none known
void command_add_varg(struct command *com, const char *format, va_list args)
adds a varg list of parameters to a command
int send_command_reply(struct command *com, byte flags)
send a reply to a command
void command_init(struct command *com)
initialize a command structure with default values
void clear_outbound_queue()
clear the outbound queue any commands within the queue are silently discarded
#define COMMAND_AGE_BEFORE_GC
maximum amount of time a packet may remain allocated
int send_data(struct command *com, const char *format,...)
send the format string as data in response to command "com"
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
void process_command_queue()
this gets called when we got some cpu cycles spare we then send out commands and timeout other comman...
void request_route(long host)
send an arp request (equivalent)
int send_command_fw_info(struct command *com, int err)
send a reply to a command
definitions of routing table structures