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
50static int command_index = 0;
52static char queuebuf[256];
54#define COM_QUEUE_SIZE 80
64static int send_command_internal(
struct command *com,
int print);
66static int broadcast_device();
78#define COMMAND_AGE_BEFORE_GC 120
81 memset(&out_queue, 0,
sizeof(out_queue));
88 printf(
"Outbound command queue cleared.\r\n");
91void print_outbound_queue() {
93 int elements = get_mpm()->max_commands;
96 for (i = 0; i < elements; i++) {
97 p = &get_mpm()->commem[i];
98 if (p->allocated == 0) {
101 printf(
"------- Queue position %i: ------\r\n", i);
106struct command *alloc_command_with_minfree(
int minfree) {
110 int elements = get_mpm()->max_commands;
115 for (i = 0; i < elements; i++) {
116 p = &get_mpm()->commem[i];
117 if (p->allocated == 0) {
119 if ((free >= minfree) && (res != NULL)) {
130 res->command.
index = -1;
131 res->allocated = mculib_get_seconds_since_boot();
132 return &res->command;
137 printf(
"command buffers are all allocated (reserved %i):\n", minfree);
138 for (i = 0; i < elements; i++) {
139 p = &get_mpm()->commem[i];
140 long now = mculib_get_seconds_since_boot();
141 long age = (now - p->allocated);
142 if (p->allocated != 0) {
157 IPLOG(
"BIG FAT WARNING - No command left to allocate (%i) (reserved %i).\r\n", elements, minfree);
160 printf(
"Reallocated garbage collected command: %p\r\n", &res->command);
162 return &res->command;
174 return alloc_command_with_minfree(0);
184 int elements =
sizeof(get_mpm()->commem) /
sizeof(get_mpm()->commem[0]);
187 for (i = 0; i < elements; i++) {
188 p = &get_mpm()->commem[i];
189 if (p->allocated != 0) {
204 if (p->allocated == 0) {
214static void garbage_collect_commands() {
217 int elements = get_mpm()->max_commands;
219 long now = mculib_get_seconds_since_boot();
221 for (i = 0; i < elements; i++) {
222 p = &get_mpm()->commem[i];
223 if (p->allocated == 0) {
226 long age = (now - p->allocated);
235static void garbage_collect_queue_entries() {
236 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
240 for (i = 0; i < elements; i++) {
241 if (out_queue[i].
command == NULL) {
245 if (p->allocated == 0) {
246 out_queue[i].command = NULL;
254static void set_power_mode_on_com(
struct command *com) {
255 if (config_get_flag(CONFIG_FLAGS_POWER_SAVE)) {
256 com->
flags |= COMFLAGS_POWERSAVE;
258 com->
flags &= ~COMFLAGS_POWERSAVE;
286 dcom->
flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
303 va_start(args, format);
327 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
331 for (i = 0; i < elements; i++) {
333 if (q->command == NULL) {
340 printf(
"That is my command at index %i\r\n", i);
342 struct command *c = q->command;
343 if (c->
target != 0xFFFFFFFF) {
353static int get_next_command_index() {
354 if ((command_index > 32000) || (command_index < 0)) {
357 return ++command_index;
375 printf(
"Sending command:\r\n");
376 int a = send_command_internal(
com, 1);
379 printf(
"Sending failed (code=%i)\r\n", a);
384int send_command_quietly(
struct command *
com) {
385 return send_command_internal(
com, 0);
392static int send_command_internal(
struct command *
com,
int p) {
399 if (com->
index == -1) {
400 com->
index = get_next_command_index();
403 return SEND_NO_TARGET;
407 if (com->
target == CLOUD_SERVER) {
408 if ((esp_cloud_is_connected()) || ((com->local_flags & (1 << COM_LOCAL_FLAG_FORCE_DEVICE)) && (com->
sourcedev == SOURCE_WIFI))) {
415 struct route *r = get_configured_route(com);
424 if (com->
target == BROADCAST) {
427 goto gotdev_no_recipt;
434 if (esp_cloud_is_connected()) {
438 return SEND_NO_CLOUD;
448 return SEND_NO_RECIPIENT;
459 return SEND_FAILURE_NODEV;
464 return SEND_DEVICE_BUSY;
467 if (!is_command_valid(com)) {
468 printf(
"Cannot print at %p\r\n", com);
469 return SEND_COM_INVALID;
473 if (!is_command_valid(com)) {
474 printf(
"print broke stuff at %p (was: %p)\r\n", com, foocom);
475 return SEND_COM_STILL_INVALID;
478 if (!is_command_valid(com)) {
479 printf(
"Cannot encode at %p\r\n", com);
480 return SEND_COM_NOT_ENCODED;
482 set_power_mode_on_com(com);
486 printf(
"Failed to encode packet (%i) at %p.\r\n", len, com);
487 return SEND_COM_FAILED_TO_ENCODE;
491 int i = send_buf_via_device(com->
sourcedev, (
const byte *)&queuebuf, len);
496 printf(
"Failed to sent packet:\r\n");
548 reply->
flags = COMFLAGS_FORWARDED;
606 va_start(args, format);
616 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
619 for (i = 0; i < elements; i++) {
620 if (out_queue[i].
command == NULL) {
621 memset(&out_queue[i], 0,
sizeof(out_queue[0]));
622 out_queue[i].command = com;
623 return &out_queue[i];
626 printf(
"BIG FAT WARNING - no free queue slot found!\r\n");
654 if (!is_command_valid(com)) {
658 q = alloc_free_queue_entry(com);
660 printf(
"No available queue slot\r\n");
664 IncMetric_COM_QUEUE_ADDED;
685 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
689 long now = mculib_get_seconds_since_boot();
692 garbage_collect_commands();
693 garbage_collect_queue_entries();
696 for (i = 0; i < elements; i++) {
698 if (q->command == NULL) {
701 if (!is_command_valid(q->command)) {
702 printf(
"Command %i in queue is invalid\r\n", i);
714 IPLOG(
"Processing queue with %i elements, due elements: %i\r\n", res, x);
715 for (i = 0; i < elements; i++) {
717 if (q->command == NULL) {
729 pretty_node_to_str(c->
target, (
char *)&t);
735 printf(
"Discarded command, No response to command %i (target: %s)\r\n", i, t);
738 printf(
"sending com %i (attempt #%i) to %s\r\n", i, q->
attemptctr, t);
744 printf(
"Queue: temporarily unable to send command %i\r\n", i);
745 }
else if (res > 0) {
748 printf(
"Queue: command #%i (type %i) unsendable (given up) reason: %i\r\n", i, q->command->
com, res);
760 if (c->
flags & (COMFLAGS_ACK | COMFLAGS_FORWARDED | COMFLAGS_DATA)) {
779 printf(
"Requesting route for %N\r\n", nodeid);
785 com->sourcedev = SOURCE_WIFI;
787 com->target = 0xFFFFFFFF;
788 com->recipient = 0xFFFFFFFF;
792 if (!config_get_wifidisable()) {
793 com->sourcedev = SOURCE_WIFI;
797 com->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
799 if (isready_by_type(SOURCE_RADIO)) {
800 com->sourcedev = SOURCE_RADIO;
803 if (isready_by_type(SOURCE_LORA)) {
804 com->sourcedev = SOURCE_LORA;
816 int elements =
sizeof(out_queue) /
sizeof(out_queue[0]);
819 for (i = 0; i < elements; i++) {
821 if (q->command == NULL) {
824 if ((q->command->
com == 1) || (q->command->
com == 23)) {
832static int broadcast_device() {
834 int somewhat_good = 0;
843 uint8_t type = nc->source;
844 if (!isonline_by_type(type)) {
847 somewhat_good = type;
848 if ((isready_by_type(type))) {
855 return somewhat_good;
char * command_get_source_name(byte sourcedev)
returns a human readable text identifying a source device
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
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
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
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
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 ...
int send_data(struct command *com, const char *format,...)
send the format string as data in response to command "com"
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...
struct command * alloc_command()
allocate a free command
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