1#include "main-header.h"
4#include "espressif/esp8266_flash.h"
6#include "espressif/esp32_bluetooth.h"
7#include "proto-esp-usart.h"
8#include "platform-header.h"
9#include "wireless_state_machine.h"
12#include "metrics/metrics.h"
13#include "ringbuffer.h"
19static byte isupdating = 0;
20static uint32_t sc_boot_version = 0;
22static long valid_commands = 0;
23static long invalid_commands = 0;
24long wifi_state_since = 0;
25static long timedout_state = 0;
26static byte contbridge = 0;
27static byte comctr = 0;
28static long comctrts = 0;
29static byte esp8266_usart_mode = 0;
30static byte esp8266_debug = 0;
31static byte esp8266_mode;
32static byte gpio4_prev_state = 0;
33static int default_baudrate = 115200;
34static int esp8266_reboots = 0;
35static long last_request_for_core = 0;
36static long core_info_age = 0;
38static uint32_t core_version = 0;
39static uint32_t core_base;
40static uint8_t core_chip;
41static uint32_t core_repo;
43static byte core_after_reset = 0;
44static const char *lastssid;
45static byte esp_reset_detect = 0;
48static uint8_t com_state = 0;
55#define ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE 9600
61#define AT_COMMAND_OK 2
62#define AT_COMMAND_TIMEOUT 7
66#define MAX_SECS_BETWEEN_WIFI_DETECT 600
72#define SECONDS_BEFORE_ESP_FAIL 30
77#define SECONDS_BEFORE_ESP_RESET_FAIL 30
84#define SECONDS_BEFORE_ATTEMPTING_TO_RECONNECT 600
87static byte next_reset_ap = 0;
88static byte esplogin = 0;
89static void request_core_info();
91static void wireless_queue_event(
int event);
92void enter_esp_passthrough_mode();
94static char esplinebuf[80];
95static char espline_received[190];
96static int espline_received_valid;
98static long ip_age = 0;
100static byte gotmac = 0;
105static void check_espusart_and_send_to_terminal();
106static int esp8266_ison();
107static void esp8266_off();
108static void esp8266_on();
109static const char *translate_baudrate(
int baudrate);
110static void scanComplete();
111static void scanUpdate(
const uint8_t *buf);
114static byte baud_verify = 0;
115const char *BAUD_CHANGE_INDICATOR =
"NEW BAUDRATE: [";
116static long new_baud = 0;
157static int is_ready_for_commands() {
158 if (is_hijacked_esp32()) {
163 (wireless_get_current_state() == WIRELESS_STATE_DEFAULTSOFTAP)
164 || (wireless_get_current_state() == WIRELESS_STATE_CONNECTED)
165 || (wireless_get_current_state() == WIRELESS_STATE_CONNECTINGCLOUD)
172static int pin_set(
int pin,
int onoff) {
173 int r = mculib_pin_set(ESP8266_MCULIBHANDLE, pin, onoff);
176 if (pin == PIN_ESP8266_GPIO0) {
177 mculib_pin_set(ESP8266_MCULIBHANDLE, DEBUG_SYNC_PIN, onoff);
182 printf(
"esp8266: Failed to set pin %i to %i: %i\r\n", pin, onoff, r);
190 return lastip.ip1 | lastip.ip2 | lastip.ip3 | lastip.ip4;
192int get_esp_reboot_ctr() {
193 return esp8266_reboots;
196long esp8266_get_valid_commands() {
197 return valid_commands;
199long esp8266_get_invalid_commands() {
200 return invalid_commands;
202void esp8266_reset_command_validity_ctrs() {
203 invalid_commands = 0;
206void esp8266_set_operational_baudrate(
int baudrate) {
207 if (default_baudrate == baudrate) {
210 if (translate_baudrate(baudrate) == NULL) {
211 printf(
"esp8266: Cannot set baudrate %i\r\n", baudrate);
214 default_baudrate = baudrate;
217int esp8266_get_operational_baudrate() {
218 return default_baudrate;
222static void esp_indicate_terminal_ready(
int ready) {
223 if (config_get_flag(CONFIG_FLAGS_ESP_COMSYNC) == 0) {
236 pin_set(PIN_ESP8266_GPIO0, ready?1:0);
239static void esp8266_set_baudrate(
int baudrate) {
243 res = mculib_serialport_enable(ESP8266_MCULIBHANDLE, USART_ESP8266, baudrate);
245 printf(
"esp8266: Failed to set esp8266 usart to %i baud: %i\r\n", baudrate, res);
247 printf(
"esp8266: Set esp8266 usart to %i baud\r\n", baudrate);
249 write_serial_string(USART_ESP8266,
"AT\r");
257 esp8266_set_baudrate(esp8266_get_operational_baudrate());
258 printf(
"esp8266: Switching esp8266 off and on in write-to-flash mode...\r\n");
259 pin_set(PIN_ESP8266_GPIO0, 0);
264 long started = mculib_get_seconds_since_boot();
266 while ((mculib_get_seconds_since_boot() - started) < 2) {
267 check_espusart_and_send_to_terminal();
269 printf(
"esp8266: Attempting sync to flash protocol...\r\n");
270 int res = espflash_sync();
273 printf(
"esp8266: Sync failed (%i)\r\n", res);
276 printf(
"esp8266: Sync ok\r\n");
278 res = espflash_prepare((
void *)0x40000, 152648);
280 printf(
"esp8266: Prepare failed (%i)\r\n", res);
283 printf(
"esp8266: Prepare ok\r\n");
284 res = espflash_write_block(0, 0);
286 printf(
"Write failed (%i)\r\n", res);
289 printf(
"esp8266: Write ok\r\n");
291 res = espflash_finish();
293 printf(
"esp8266: Finish failed (%i)\r\n", res);
295 printf(
"esp8266: Finish ok\r\n");
297 pin_set(PIN_ESP8266_GPIO0, 1);
299 printf(
"esp8266: Switching esp8266 off and on in boot-from-flash mode...\r\n");
303 started = mculib_get_seconds_since_boot();
304 while ((mculib_get_seconds_since_boot() - started) < 2) {
305 check_espusart_and_send_to_terminal();
308 printf(
"esp8266: Done.\r\n");
311void set_esp8266_debug(
byte b) {
312 printf(
"esp8266: Set esp8266 debug to %i\r\n", (
int)b);
316static int esp8266_ison() {
317 return mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD);
319static void esp8266_off() {
320 printf(
"esp8266: esp8266 off\r\n");
321 esp_cloud_deactivate();
322 pin_set(PIN_ESP8266_CHPD, 0);
325 esp_reset_detect = 0;
327static void esp8266_on() {
329 esp_reset_detect = 0;
330 core_after_reset = 0;
331 printf(
"esp8266: esp8266 on\r\n");
333 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
334 pin_set(PIN_ESP8266_CHPD, 1);
341static void esp8266_trigger_reset_normal() {
342 esp_indicate_terminal_ready(1);
343 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
344 printf(
"esp8266: Resetting esp8266 to normal mode\r\n");
345 if (esp8266_ison()) {
346 printf(
"esp8266: ESP8266 is already enabled!\r\n");
350 pin_set(PIN_ESP8266_GPIO0, 1);
353 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
358void esp8266_dodebug(
const char *paras) {
359 pin_set(PIN_ESP8266_GPIO0, 1);
361 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
362 if (strlen(paras) > 0) {
363 if (paras[0] ==
'c') {
365 esp8266_set_baudrate(74800);
367 if (strlen(paras) > 2) {
368 const char *bs = ¶s[0];
371 printf(
"esp8266: wifidebug: Invalid baudrate: %i (%s)\r\n", br, bs);
374 printf(
"esp8266: Wifidebug, requested baudrate %i...\r\n", br);
375 esp8266_set_baudrate(br);
389 wireless_queue_event(WIRELESS_EVENT_ONRESET);
392static char *get_ap_credentials() {
393 return config_get_ram_struct()->apcredentials;
398static int get_ap_count() {
399 if (get_ap_credentials()[0] == 0) {
407static const char *get_ssid(
int num) {
408 return (
const char *)get_ap_credentials();
413static const char *get_ssid_pw(
int num) {
414 const char *p = get_ssid(num);
427 byte *p = (
byte *)get_ap_credentials();
430 for (i = 0; i < strlen(ssid); i++) {
435 for (i = 0; i < strlen(pw); i++) {
440 wireless_queue_event(WIRELESS_EVENT_GOTNEWAP);
444static void check_espusart_and_send_to_terminal() {
447 while ((esp = ringbuffer_get_byte(&esp_ringbuffer)) >= 256) {
448 if ((esp == 0x12) || (esp < 9) || (esp > 127)) {
451 write_serial_char(USART_CONSOLE, esp);
455static void esp8266_cfg_entry(
char type,
const char *txt) {
457 printf(
"esp8266: Sent Config: %c == \"%s\"\r\n", type, txt);
459 write_serial_char(USART_ESP8266, type);
460 write_serial_string(USART_ESP8266, txt);
461 write_serial_char(USART_ESP8266, 1);
463static const char *translate_baudrate(
int baudrate) {
464 const char *c = NULL;
466 if (baudrate == 9600) {
468 }
else if (baudrate == 19200) {
470 }
else if (baudrate == 38400) {
472 }
else if (baudrate == 57600) {
474 }
else if (baudrate == 115200) {
476 }
else if (baudrate == 230400) {
478 }
else if (baudrate == 460800) {
480 }
else if (baudrate == 921600) {
482 }
else if (baudrate == 74880) {
487static void set_common_parameters() {
488 esp_indicate_terminal_ready(0);
490 esp8266_cfg_entry(
'd', (esp8266_debug & 0x02) ?
"1" :
"0");
491 if (config_get_flag(CONFIG_FLAGS_UDP_ENABLED)) {
492 esp8266_cfg_entry(
'L',
"7234");
494 esp8266_cfg_entry(
'L',
"0");
496 if (config_get_flag(CONFIG_FLAGS_ESP_COMSYNC)) {
497 esp8266_cfg_entry(
's',
"1");
500 const char *tok = config_get_cloud_token();
502 if ((tok != NULL) && (strlen(tok) > 0)) {
503 esp8266_cfg_entry(
'T', tok);
507 node_to_str(config_get_ram_struct()->nodeid, buf);
508 esp8266_cfg_entry(
'N', buf);
509 esp8266_cfg_entry(
'I',
"5");
511 const char *sn = config_get_sensor_server();
513 if (strlen(sn) > 0) {
514 esp8266_cfg_entry(
'D', sn);
516 char *c = (
char *)translate_baudrate(esp8266_get_operational_baudrate());
518 esp8266_cfg_entry(
'B', c);
521static void set_station_mode(
int num) {
522 const char *ssid = get_ssid(num);
525 led_indicate(LED_WIFI_STATION);
526 write_serial_string(USART_ESP8266,
"\rAT+CFG=");
527 esp8266_cfg_entry(
'M',
"1");
528 esp8266_cfg_entry(
'S', ssid);
529 esp8266_cfg_entry(
'P', get_ssid_pw(num));
531 set_common_parameters();
532 write_serial_string(USART_ESP8266,
"\r\r\r");
533 esp8266_set_baudrate(esp8266_get_operational_baudrate());
535 esp8266_mode = esp8266_mode & ~ESPMODE_ISAP;
538 printf(
"esp8266: Esp8266 connecting to %s with pw %s\r\n", ssid, get_ssid_pw(num));
539 set_esp8266_usart_mode(ESP8266_USART_PACKET_ONLY);
544void esp8266_send_config() {
548static byte got_ap_pw() {
549 const char *c = config_get_cloud_token();
551 if ((c == NULL) || (strlen(c) < 1)) {
557static void set_ap_mode() {
559 led_indicate(LED_WIFI_APMODE);
560 write_serial_string(USART_ESP8266,
"\rAT+CFG=");
561 esp8266_cfg_entry(
'M',
"2");
562 set_common_parameters();
565 snprintf(buf, 63,
"singingcat_%N", config_get_ram_struct()->nodeid);
566 esp8266_cfg_entry(
'S', buf);
568 strncpy(buf, config_get_cloud_token(), 11);
569 esp8266_cfg_entry(
'P', buf);
571 esp8266_cfg_entry(
'P',
"singingcat");
573 write_serial_string(USART_ESP8266,
"\r\r\r");
574 esp8266_set_baudrate(esp8266_get_operational_baudrate());
577 printf(
"esp8266: Esp8266 set to accesspoint\r\n");
578 set_esp8266_usart_mode(ESP8266_USART_PACKET_ONLY);
584 return (esp8266_mode & ESPMODE_ISAP) ? 1 : 0;
593 ringbuffer_init(&esp_ringbuffer);
596static int cat_is_control_byte(uint8_t b) {
597 return (b == PKT_START_BYTE)
598 || (b == PKT_END_BYTE)
599 || (b == PKT_ESC_BYTE)
603static void transmit_to_esp(
const byte *buf,
int len) {
604 if (is_hijacked_esp32()) {
609 for (i = 0; i < len; i++) {
610 write_serial_char(USART_ESP8266, buf[i]);
622 if (!is_ready_for_commands()) {
624 printf(
"esp8266: Not sending to esp - not ready yet\r\n");
629 if (cat_is_control_byte(type)) {
631 printf(
"esp8266: invalid packet type\r\n");
634 b[0] = PKT_START_BYTE;
636 transmit_to_esp((
const byte *)&b, 2);
639 for (tl = 0; tl < len; tl++) {
640 if (cat_is_control_byte(buf[tl])) {
641 transmit_to_esp((
const byte *)&buf[startpos], tl - startpos);
642 transmit_to_esp((
const byte *)&b, 1);
647 transmit_to_esp((
const byte *)&buf[startpos], tl - startpos);
651 transmit_to_esp((
const byte *)&b, 1);
652 IncMetric_PKTS_WIFI_CTR_OUT;
655static void do_gpio4() {
656 int b = mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO4);
658 if (b == gpio4_prev_state) {
661 gpio4_prev_state = b;
664 printf(
"esp8266: ESP8266 gpio4: high\r\n");
665 printf(
"esp8266: ESP8266 reset detected\r\n");
666 wireless_queue_event(WIRELESS_EVENT_ONRESET);
667 IncMetric_WIFI_RESTARTS;
669 printf(
"esp8266: ESP8266 gpio4: low\r\n");
676 int res = espflash_sync();
679 printf(
"esp8266: FAIL: failed to sync to esp8266. Is it connected and powered up?\r\n");
683 wireless_queue_event(WIRELESS_EVENT_ONRESETDETECTED);
685static void do_com_while_bridged(
const char c) {
687 led_blink(LED_WIFI_BRIDGE, 0xFF0000, 255, 10, 1);
689 comctrts = mculib_get_seconds_since_boot();
693 if ((c !=
'\r') && (c !=
'\n')) {
694 led_blink(LED_WIFI_BRIDGE, 0x0000FF, 255, 10, 1);
699static void scan_esp_output_while_bridged(
const char c) {
700 if (BAUD_CHANGE_INDICATOR[baud_verify] == 0) {
702 if ((c >=
'0') && (c <=
'9')) {
703 new_baud = new_baud * 10 + (c -
'0');
705 printf(
"esp8266: *** SingingCat firmware detected baudrate change: %i (%c)\r\n", (
int)new_baud, c);
706 esp8266_set_baudrate(new_baud);
710 if (c == BAUD_CHANGE_INDICATOR[baud_verify]) {
719static int com_mode_bridged() {
721 printf(
"\r\n(ato|atq|atc|atC|atp|atr|atscan)\r\nOK\r\n");
727 int x = console_get_line((
char *)&esptmpbuf, 50);
732 if (strcmp(esptmpbuf,
"ato") == 0) {
733 printf(
"esp8266: reconnecting...\r\n");
736 if (strcmp(esptmpbuf,
"atscan") == 0) {
737 printf(
"esp8266: starting scan...\r\n");
741 if (strcmp(esptmpbuf,
"atq") == 0) {
742 printf(
"esp8266: quitting\r\n");
745 if (strcmp(esptmpbuf,
"atp") == 0) {
747 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
750 if (strcmp(esptmpbuf,
"atC") == 0) {
751 printf(
"esp8266: sending quick update config...\r\n");
752 write_serial_string(USART_ESP8266,
"\rAT+CFG=");
753 esp8266_cfg_entry(
'M',
"1");
754 esp8266_cfg_entry(
'u',
"1");
755 esp8266_cfg_entry(
'S', get_ssid(0));
756 esp8266_cfg_entry(
'P', get_ssid_pw(0));
758 set_common_parameters();
759 write_serial_string(USART_ESP8266,
"\r\r\r");
760 esp8266_set_baudrate(esp8266_get_operational_baudrate());
763 if (strcmp(esptmpbuf,
"atc") == 0) {
764 printf(
"esp8266: sending config...\r\n");
765 write_serial_string(USART_ESP8266,
"\rAT+CFG=");
766 esp8266_cfg_entry(
'M',
"1");
767 esp8266_cfg_entry(
'S', get_ssid(0));
768 esp8266_cfg_entry(
'P', get_ssid_pw(0));
770 set_common_parameters();
771 write_serial_string(USART_ESP8266,
"\r\r\r");
772 esp8266_set_baudrate(esp8266_get_operational_baudrate());
775 if (strcmp(esptmpbuf,
"atr") == 0) {
778 printf(
"esp8266: ESP8266 on & return\r\n");
792 printf(
"esp8266: Bridging esp2866 & debug console...\r\n");
796 led_indicate(LED_WIFI_BRIDGE);
798 printf(
"esp8266: contbridge==%i\r\n", contbridge);
799 printf(
"esp8266: Entering passthrough mode\r\n");
800 printf(
"[BRIDGE ACTIVE]\r\n");
801 esp8266_usart_mode = ESP8266_USART_PASSTHROUGH;
802 reset_delay_counter(DELAY_ESP2SERIAL);
803 reset_delay_counter(DELAY_DEFAULT);
810 if (get_delay_counter(DELAY_DEFAULT) > 20) {
811 reset_delay_counter(DELAY_DEFAULT);
812 }
else if (get_delay_counter(DELAY_DEFAULT) > 10) {
815 if ((comctr >= 3) && (mculib_get_seconds_since_boot() - comctrts) >= 2) {
817 if (com_mode_bridged()) {
823 if ((x = console_get_byte()) < 256) {
826 write_serial_char(USART_ESP8266, x);
827 reset_delay_counter(DELAY_ESP2SERIAL);
830 do_com_while_bridged(x);
832 led_blink(LED_WIFI_BRIDGE, 0xFFFFFF, 255, 10, 1);
838 if ((x = ringbuffer_get_byte(&esp_ringbuffer)) < 256) {
839 write_char_to_console(x);
841 scan_esp_output_while_bridged(x);
846 if ((contbridge == 0) && (get_delay_counter(DELAY_ESP2SERIAL) > to)) {
847 printf(
"esp8266: Leaving passthrough mode.\r\n");
848 esp8266_usart_mode = ESP8266_USART_PACKET_ONLY;
849 printf(
"[BRIDGE MODE FINISHED]\r\n");
853 led_indicate(LED_WIFI_BRIDGE2);
860 if (is_hijacked_esp32()) {
861 return "userapp_control";
865 return "Updating Firmware";
867 if (config_get_wifidisable()) {
871 return "Accesspoint";
874 return "Client (No IP)";
876 return "Connected to AP (Got IP)";
886 ringbuffer_init(&esp_ringbuffer);
887 espline_received[0] = 0;
888 espline_received_valid = 0;
889 if (config_get_wifidisable()) {
891 if ((r = mculib_pin_out(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD, HAL_PIN_FASTEST))) {
892 printf(
"esp8266: Failed to set pin: %i\r\n", r);
902 esp8266_usart_mode = ESP8266_USART_PACKET_ONLY;
905 if ((r = mculib_pin_out(ESP8266_MCULIBHANDLE, DEBUG_SYNC_PIN, HAL_PIN_FASTEST))) {
906 printf(
"esp8266: Failed to set pin: %i\r\n", r);
909 if ((r = mculib_pin_out(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD, HAL_PIN_FASTEST))) {
910 printf(
"esp8266: Failed to set pin: %i\r\n", r);
912 if ((r = mculib_pin_out(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO0, HAL_PIN_FASTEST))) {
913 printf(
"esp8266: Failed to set pin: %i\r\n", r);
915 if ((r = mculib_pin_in(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO4, HAL_PIN_SLOWEST, HAL_PUSHPULL_DOWN))) {
916 printf(
"esp8266: Failed to set pin: %i\r\n", r);
920 if (!config_get_wifidisable()) {
923 CNWDEBUG(
"esp_init() complete\n");
932 if ((bufsize == 0) || (buf == NULL)) {
939 snprintf(buf, bufsize,
"18:FE:34:%x:%x:%x",
940 (
int)((mac1 >> 8) & 0xff),
941 (
int)((mac1) & 0xff),
942 (
int)((mac0 >> 24) & 0xff));
953 printf(
"esp8266: Syncing to esp8266...\r\n");
954 if ((res = espflash_sync()) != 0) {
958 espflash_read_register(0x3ff00050, &mac0);
959 espflash_read_register(0x3ff00054, &mac1);
967void set_esp8266_usart_mode(
int i) {
968 esp8266_usart_mode = i;
970int get_esp8266_usart_mode() {
971 return esp8266_usart_mode;
974void print_esp_core_info() {
975 long now = mculib_get_seconds_since_boot();
976 long ago = now - core_info_age;
978 printf(
"esp8266 firmware chip : %i\r\n", (
int)core_chip);
979 printf(
"esp8266 firmware version : %i (from %is ago)\r\n", (
int)core_version, ago);
980 printf(
"esp8266 firmware repository : %i\r\n", (
int)core_repo);
981 printf(
"esp8266 firmware base : %p\r\n", (
int)core_base);
986static void esp_core_update(
int code,
byte *buf,
int size) {
987 printf(
"esp firmware version update received (%i bytes)\r\n", size);
988 printf(
"esp-fw-buf: ");
989 printHex(
"esp-fw-buf: ", buf, size);
992 if ((size < 8) || (buf[0] != 0)) {
993 printf(
"esp firmware - Old style\r\n");
994 uint16_t v = (((uint16_t)buf[0]) << 8) | (((uint16_t)buf[1]) << 0);
995 core_version = (uint32_t)v;
999 core_info_age = mculib_get_seconds_since_boot();
1000 core_after_reset = 1;
1004 printf(
"esp firmware - New style\r\n");
1007 printf(
"esp firmware - unknown structure %i\r\n", buf[0]);
1011 get_uint8(buf, size, &pos, &core_chip);
1012 get_uint32(buf, size, &pos, &core_version);
1013 get_uint32(buf, size, &pos, &core_repo);
1014 get_uint32(buf, size, &pos, &core_base);
1015 core_info_age = mculib_get_seconds_since_boot();
1016 core_after_reset = 1;
1019void wifi_new_creds(
char *buf) {
1021 const char *pw = NULL;
1022 const char *ssid = NULL;
1024 for (i = 0; i < strlen(buf); i++) {
1025 if ((ssid == NULL) && ((buf[i] == 13) || (buf[i] == 10))) {
1033 pw = (
const char *)(buf + i + 1);
1038 printf(
"esp8266 - got new wifi SSID (%s), but no password\r\n", ssid);
1041 printf(
"esp8266 - got new wifi credentials: %s %s\r\n", ssid, pw);
1046static void request_core_info() {
1050void wifi_update_started() {
1051 printf(
"esp8266: wifi_update started\r\n");
1054void wifi_update_completed() {
1056 printf(
"esp8266: wifi_update completed\r\n");
1058void wifi_update_progress(
const uint8_t *buf) {
1059 printf(
"esp8266: wifi_update: %s\r\n", buf);
1072 esp_indicate_terminal_ready(1);
1078 if (buf[0] == PKT_COMMAND) {
1080 com = command_parse(buf + 1, size - 1);
1083 printf(
"esp8266: Invalid command from espserialport (%i): \r\n \"%s\"\r\n", buf[0], buf + 1);
1084 printHex(
"", buf + 1, size - 1);
1085 IncMetric_PKTS_WIFI_INVALID;
1088 com->sourcedev = SOURCE_WIFI;
1090 IncMetric_PKTS_WIFI_CTR_IN;
1092 }
else if (buf[0] == PKT_IP_UPDATE) {
1093 lastip.ip1 = buf[1];
1094 lastip.ip2 = buf[2];
1095 lastip.ip3 = buf[3];
1096 lastip.ip4 = buf[4];
1097 ip_age = mculib_get_seconds_since_boot();
1098 const char *statestr;
1099 if (esp_cloud_is_connected()) {
1100 statestr =
"CONNECTED";
1102 statestr =
"NOT CONNECTED";
1105 wireless_queue_event(WIRELESS_EVENT_IPASSIGNED);
1107 printf(
"esp8266: WIFI IP: %i.%i.%i.%i (%s)\r\n", lastip.ip1, lastip.ip2, lastip.ip3, lastip.ip4, statestr);
1108 if ((esplogin == 1) || (esplogin == 2)) {
1111 }
else if (buf[0] == PKT_LOG) {
1112 printf(
"esp8266: WIFI LOG: %s\r\n", buf + 1);
1113 }
else if (buf[0] == PKT_STATE_UPDATE) {
1114 int subsystem = buf[1];
1116 printf(
"esp8266: ESP state update: subsystem=%i, code=%i\r\n", subsystem, code);
1117 if ((subsystem == SUBSYS_AP) && (code == STATE_AP_CONNECTED)) {
1118 wireless_queue_event(WIRELESS_EVENT_APCONNECTED);
1120 if ((subsystem == SUBSYS_AP) && (code == STATE_AP_FAILED)) {
1121 wireless_queue_event(WIRELESS_EVENT_APFAILURE);
1123 if ((subsystem == SUBSYS_CLOUD) && (code == STATE_CLOUD_CONNECTED)) {
1124 wireless_queue_event(WIRELESS_EVENT_CLOUDISOK);
1126 if ((subsystem == SUBSYS_CLOUD) && (
1127 (code == STATE_CLOUD_DISCONNECTED)
1128 || (code == STATE_CLOUD_CONNECTFAILURE)
1129 || (code == STATE_CLOUD_AUTORECONNECT)
1131 wireless_queue_event(WIRELESS_EVENT_CLOUDDISCONNECTED);
1133 if ((subsystem == PKT_IP_UPDATE) && (code == STATE_AP_CONNECTED)) {
1134 wireless_queue_event(WIRELESS_EVENT_APCONNECTED);
1136 if (subsystem == SUBSYS_CORE) {
1137 esp_core_update(code, (
byte *)(buf + 3), size - 3);
1141 }
else if (size > 3) {
1143 }
else if (size > 2) {
1146 printf(
"esp8266: WIFI state update: no subsystem\r\n");
1148 }
else if (buf[0] == PKT_LOCAL_INSTRUCTION) {
1149 printf(
"esp8266: Local instruction received: ");
1151 for (i = 0; i < size; i++) {
1152 printf(
" %i", buf[i]);
1155 }
else if (buf[0] == PKT_WIFI_SCAN_UPDATE) {
1156 scanUpdate(buf + 1);
1157 }
else if (buf[0] == PKT_WIFI_SCAN_COMPLETE) {
1159 }
else if (buf[0] == PKT_WIFI_UPDATE_STARTED) {
1160 wifi_update_started();
1161 }
else if (buf[0] == PKT_WIFI_UPDATE_COMPLETED) {
1162 wifi_update_completed();
1163 }
else if (buf[0] == PKT_WIFI_UPDATE_PROGRESS) {
1164 wifi_update_progress(buf + 1);
1165 }
else if (buf[0] == PKT_BT_PEER_UPDATE) {
1166 bt_peer_update(buf + 1, size - 1);
1167 }
else if (buf[0] == PKT_WIFI_NEW_CREDS) {
1168 wifi_new_creds((
char *)buf + 1);
1170 printf(
"invalid esp8266 packet type (%i: \"%s\")!\r\n", buf[0], buf);
1171 printHex(
"packet: ", buf, size);
1178int esp8266_get_chip() {
1181int esp8266_get_firmware_version() {
1182 return core_version;
1184int esp8266_get_firmware_repo() {
1187uint64_t esp8266_get_firmware_base() {
1194 int data = (((int)d1) << 8) | ((
int)d2);
1196 if (subsystem == SUBSYS_AP) {
1197 printf(
"SUBSYSTEM: Accesspoint Code: ");
1198 if (code == STATE_AP_IDLE) {
1200 }
else if (code == STATE_AP_CONNECTING) {
1201 printf(
"Connecting\r\n");
1202 }
else if (code == STATE_AP_CONNECTED) {
1203 printf(
"Connected\r\n");
1204 }
else if (code == STATE_AP_FAILED) {
1205 printf(
"Logon to accesspoint failed\r\n");
1206 }
else if (code == PKT_WIFI_AP_NOT_FOUND) {
1207 printf(
"SSID not found\r\n");
1208 }
else if (code == PKT_WIFI_AP_REJECTED) {
1209 printf(
"accesspoint rejected auth\r\n");
1210 }
else if (code == PKT_WIFI_AP_DISCONNECT_UNKNOWN_REASON) {
1211 printf(
"disconnected from accesspoint, reason unspecified\r\n");
1213 printf(
"%i\r\n", code);
1215 }
else if (subsystem == SUBSYS_CLOUD) {
1217 }
else if (subsystem == SUBSYS_CORE) {
1218 printf(
"esp core update\n");
1220 printf(
"SUBSYSTEM: %i Code: %i\r\n", subsystem, code);
1230 if ((lastip.ip1 | lastip.ip2 | lastip.ip3 | lastip.ip4) == 0) {
1235long esp8266_get_time_of_last_ip() {
1239static const char *eob =
"csum";
1242static void esp8266_afterreset(
byte read) {
1243 ringbuffer_add_byte(&esp_ringbuffer, read);
1244 if (read == eob[det]) {
1248 if (read == eob[det]) {
1253 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
1254 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
1263 if (get_esp8266_usart_mode() == ESP8266_USART_IGNORE) {
1266 byte read = 0xFF & val;
1268 int state = wireless_get_current_state();
1270 if ((com_state == 0) && (val ==
'{')) {
1272 esp_indicate_terminal_ready(0);
1274 if (state == WIRELESS_STATE_RESETTING) {
1275 ringbuffer_add_byte(&esp_ringbuffer, read);
1278 if (get_esp8266_usart_mode() == ESP8266_USART_PACKET_ONLY) {
1280 if (esp8266_debug) {
1282 ringbuffer_add_byte(&esp_ringbuffer, read);
1286 }
else if (get_esp8266_usart_mode() == ESP8266_USART_SMART) {
1289 ringbuffer_add_byte(&esp_ringbuffer, read);
1292 }
else if (get_esp8266_usart_mode() == ESP8266_USART_PASSTHROUGH) {
1293 ringbuffer_add_byte(&esp_ringbuffer, read);
1295 }
else if (get_esp8266_usart_mode() == ESP8266_USART_AFTERRESET) {
1296 esp8266_afterreset(read);
1301static void write_serial_buffer(
int USART,
const uint8_t *buf,
int length) {
1304 for (i = 0; i < length; i++) {
1305 write_serial_char(USART, buf[i]);
1314 if (esp8266_debug) {
1315 printf(
"esp8266 - sending extra instructions\r\n");
1317 node_to_str(config_get_ram_struct()->nodeid, buf);
1319 const char *tok = config_get_cloud_token();
1321 if ((tok != NULL) && (strlen(tok) > 0)) {
1332 if (esp8266_debug) {
1333 printf(
"esp8266 - asking for ota\r\n");
1348 if (cat_is_control_byte(type)) {
1350 printf(
"invalid packet type\r\n");
1353 write_serial_char(USART_ESP8266, PKT_START_BYTE);
1354 write_serial_char(USART_ESP8266, PKT_LOCAL_INSTRUCTION);
1355 write_serial_char(USART_ESP8266, type);
1358 for (tl = 0; tl < len; tl++) {
1359 if (cat_is_control_byte(buf[tl])) {
1360 write_serial_buffer(USART_ESP8266, &buf[startpos], tl - startpos);
1361 write_serial_char(USART_ESP8266, PKT_ESC_BYTE);
1365 if (startpos < tl) {
1366 write_serial_buffer(USART_ESP8266, &buf[startpos], tl - startpos);
1368 b[0] = PKT_END_BYTE;
1370 write_serial_buffer(USART_ESP8266, (
const uint8_t *)&b, 2);
1374void start_wifi_scan() {
1380static void scanComplete() {
1383 printf(
"Wifi scan finished\r\n");
1385static void scanUpdate(
const uint8_t *buf) {
1396 printf(
"Cannot send wifi update - no free command\r\n");
1407 dcom->
flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
1413 printf(
"Channel=%i, rssi=%i, SSID: %s\r\n", buf[0], buf[1], &buf[8]);
1426const char *esp_get_last_pw() {
1427 return get_ssid_pw(0);
1429const char *esp_get_last_ssid() {
1434int esp8266_is_enabled() {
1435 if (config_get_wifidisable()) {
1443 printf(
"esp8266 enable\r\n");
1444 wireless_queue_event(WIRELESS_EVENT_WIFIENABLED);
1447 printf(
"esp8266 disable\r\n");
1448 wireless_queue_event(WIRELESS_EVENT_ONWIFIDISABLE);
1450 esp8266_event_loop();
1457static void check_esp_core() {
1458 int state = wireless_get_current_state();
1462 if ((state != WIRELESS_STATE_CONNECTED)
1463 && (state != WIRELESS_STATE_CONNECTINGAP)
1464 && (state != WIRELESS_STATE_CONNECTINGIP)
1465 && (state != WIRELESS_STATE_CONNECTINGCLOUD)
1469 long now = mculib_get_seconds_since_boot();
1472 if (core_info_age > now) {
1473 core_info_age = now;
1477 if (core_after_reset && ((now - core_info_age) < 600)) {
1481 if (last_request_for_core > now) {
1482 last_request_for_core = now;
1485 if ((now - last_request_for_core) < 2) {
1488 last_request_for_core = now;
1490 printf(
"esp8266: Requesting core info...\r\n");
1491 request_core_info();
1494static void check_boot_firmware() {
1495 if (!espline_received_valid) {
1498 const char *x =
"Singingcat Firmware Version: ";
1500 if (strlen(x) > strlen(espline_received)) {
1505 for (i = 0; i < strlen(x); i++) {
1506 if (espline_received[i] != x[i]) {
1510 sc_boot_version = atoi(&espline_received[strlen(x)]);
1511 printf(
"esp8226: singingcat firmware version: \"%s\" (%i)\r\n", &espline_received[strlen(x)], sc_boot_version);
1514static void read_esp_serial_line() {
1515 if (espline_received_valid) {
1516 espline_received_valid = 0;
1517 espline_received[0] = 0;
1522 int nb = ringbuffer_get_byte(&esp_ringbuffer);
1526 int l = strlen(espline_received);
1527 if (l >
sizeof(espline_received) - 5) {
1530 if ((nb ==
'\r') || (nb ==
'\n')) {
1532 espline_received_valid = 1;
1536 espline_received[l++] = (byte)nb;
1537 espline_received[l] = 0;
1545static void wireless_process_event_queue();
1546static long lastloop = 0;
1547static int laststate = 0;
1549void esp8266_event_loop() {
1550 if (config_get_wifidisable()) {
1554 read_esp_serial_line();
1556 if (espline_received_valid) {
1557 if (esp8266_debug) {
1558 printf(
"esp8266: buf: \"%s\"\r\n", &espline_received);
1561 mculib_serialport_transferbuffer(USART_ESP8266);
1567 int state = wireless_get_current_state();
1570#ifdef DEBUG_ON_LINUX
1571 if (state == WIRELESS_STATE_RESETTING) {
1572 wireless_queue_event(WIRELESS_EVENT_RESETSUCCEEDED);
1576 if (state != WIRELESS_STATE_RESETTING) {
1581 long now = mculib_get_seconds_since_boot();
1585 if (state != laststate) {
1586 printf(
"esp8266: State: %s\r\n", wireless_state_to_string(state));
1592 if (state == WIRELESS_STATE_IDLE) {
1593 wireless_queue_event(WIRELESS_EVENT_WIFIENABLED);
1596 if (state == WIRELESS_STATE_ROMCHECK) {
1597#ifdef DEBUG_ON_LINUX
1598 wireless_queue_event(WIRELESS_EVENT_ONROMCHECKED);
1601 wireless_queue_event(WIRELESS_EVENT_ONROMFAILED);
1603 wireless_queue_event(WIRELESS_EVENT_ONROMCHECKED);
1608 if (state == WIRELESS_STATE_RESETTING) {
1609 check_boot_firmware();
1611 if (esp_reset_detect == 0) {
1612 if ((espline_received_valid) && (strcmp(espline_received,
"[BOOTDONE]") == 0)) {
1613 printf(
"esp8266: detected [BOOTDONE] message\r\n");
1614 esp_reset_detect = 1;
1622 }
else if (esp_reset_detect == 1) {
1624 gpio4_prev_state = mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO4);
1625 if (gpio4_prev_state == 1) {
1627 printf(
"esp8266: gpio high detected\r\n");
1628 wireless_queue_event(WIRELESS_EVENT_RESETSUCCEEDED);
1629 esp_reset_detect = 0;
1635 if (state == WIRELESS_STATE_CONNECTED) {
1638 wireless_process_event_queue();
1640 if (wifi_state_since > now) {
1641 wifi_state_since = now;
1643 int to = wireless_get_current_timeout();
1644 if ((to != 0) && ((now - wifi_state_since) >= to) && (state != timedout_state)) {
1645 timedout_state = state;
1646 if (state != WIRELESS_STATE_CONNECTED) {
1647 printf(
"esp8266: Wireless state: %s timed out (%i secs, max=%i secs)\r\n",
1648 wireless_state_to_string(state),
1649 (
int)(now - wifi_state_since),
1662 wireless_queue_event(WIRELESS_EVENT_CLOUDDISCONNECTED);
1668static int wireless_queue[10];
1672static void wireless_queue_event(
int event) {
1676 if ((!esp8266_is_enabled()) && (event != WIRELESS_EVENT_WIFIENABLED)) {
1680 if (esp8266_debug) {
1681 printf(
"esp8266: [wireless-statemachine] Queued wireless event: %s\r\n", wireless_event_to_string(event));
1683 for (i = 0; i < (
sizeof(wireless_queue) /
sizeof(wireless_queue[0])); i++) {
1684 if (wireless_queue[i] != 0) {
1688 if ((max + 1) >=
sizeof(wireless_queue) /
sizeof(wireless_queue[0])) {
1689 printf(
"esp8266: [wireless-statemachine] ERROR -> Out of event buffers!!\r\n");
1692 wireless_queue[max + 1] = event;
1695static void wireless_process_event_queue() {
1698 for (i = 0; i < (
sizeof(wireless_queue) /
sizeof(wireless_queue[0])); i++) {
1699 if (wireless_queue[i] != 0) {
1700 wireless_new_event(wireless_queue[i]);
1701 wireless_queue[i] = 0;
1707void wireless_callback_state_change(
int newstate,
int oldstate) {
1708 printf(
"esp8266: [wireless-statemachine] State change: %s(%i) to %s(%i)\r\n",
1709 wireless_state_to_string(oldstate), oldstate,
1710 wireless_state_to_string(newstate), newstate);
1711 wifi_state_since = mculib_get_seconds_since_boot();
1712 timedout_state = -1;
1714 if (newstate == WIRELESS_STATE_RESETTING) {
1715 esp8266_trigger_reset_normal();
1717 if (newstate == WIRELESS_STATE_READY) {
1718 if ((get_ap_count() == 0) || (next_reset_ap)) {
1720 wireless_queue_event(WIRELESS_EVENT_GOTNOAP);
1722 wireless_queue_event(WIRELESS_EVENT_GOTAP);
1725 if (newstate == WIRELESS_STATE_DEFAULTSOFTAP) {
1726 led_set_wifi_managed();
1729 if (newstate == WIRELESS_STATE_TRIGGERDEFAULTSOFTAP) {
1730 led_set_wifi_managed();
1734 if (newstate == WIRELESS_STATE_CONNECTINGAP) {
1735 set_station_mode(0);
1737 if (newstate == WIRELESS_STATE_CONNECTED) {
1738 led_indicate(LED_WIFI_CONNECTED);
1743 if (oldstate == WIRELESS_STATE_CONNECTED) {
1745 esp_cloud_deactivate();
1749 if (newstate == WIRELESS_STATE_NEXTAP) {
1754 wireless_queue_event(WIRELESS_EVENT_ONNOMOREAPS);
1764int write_char_to_console(
char b) {
1767 i = write_serial_char(USART_CONSOLE, b);
1768 mculib_usb_send(ESP8266_MCULIBHANDLE, 1, (uint8_t *)&b);
void esp8266_enable()
enable the esp8266 (switch it on)
void esp8266_wififlash_bridge(void)
set esp8266 to flash mode, sync and then bridge ("startflash")
byte esp8266_is_in_packet()
returns 1 if currently parsing a packet
void esp8266_cloud_loop()
called from esp8266 event loop if we are connected
void decode_esp_packet_init()
int send_command(struct command *com)
send a command to another module (or broadcast)
void free_command(struct command *com)
free a command
void esp_cloud_init()
this resets the cloud state
char * esp8266_status_string()
returns a human readable status string of the wifi connection
void esp8266_read_byte_from_serialport(int val)
this is called directly from the usart IRQ. be quick. and do not use printf()
void esp_cloud_activate()
activate the cloud.
void wifi_send_data(const PACKET_TYPE type, const byte *buf, const int len)
send a command via wifi
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
int is_last_ip_valid()
return true if IP is set and valid
void esp8266_ota()
tell the esp to do an OTA
void esp_cloud_state_update(int code, int data)
whenever the esp chip sends us an update about the cloud state this gets called by the event handler ...
void esp8266_reset()
reset state machine and esp8266
int esp8266_is_accespoint()
returns !=0 if we are currently an accesspoint
int send_command_reply(struct command *com, byte flags)
send a reply to a command
const char * esp_cloud_get_desired_server()
returns server we want to connect to
void cat_send_local_instruction(const PACKET_TYPE type, const uint8_t *buf, const int len)
send a packet to the esp8266 wifi chip
void esp_empty_ringbuffer()
empties the ringbuffer.
void command_init(struct command *com)
initialize a command structure with default values
void esp8266_got_packet(const byte *buf, int size)
int esp8266_add_byte(byte b)
feed this with one byte at a time
int esp_get_mac(char *buf, int bufsize)
get the esp8266 mac address.
byte got_new_packet(struct command *com, uint8_t signal_indicator)
stack received a new packet (signal indicator is a 0-255 byte value, interface specific)
void esp8266_disable()
disable the esp8266 (switch it off)
void esp_init()
call this ONCE before calling anything else
struct command * alloc_command()
allocate a free command
void led_blink(LED_USAGE_TYPE lut, uint32_t colour, uint8_t brightness, uint32_t on, uint32_t off)
will keep blinking until told otherwise will repeat endlessly.
void print_pkt_state_update(int subsystem, int code, uint8_t d1, uint8_t d2)
struct ipv4address * esp8266_get_current_ip()
return last ip (null if none)
void esp8266_add_ap(const char *ssid, const char *pw)
add an ap to the list of known ap
void esp8266_bridge()
bridge debug serialport and esp8266 (e.g. "wifidebug")
void esp8266_cloud_connection_failed()
called if the cloud connection failed
void esp8266_send_instructions()
send our nodeid and other goodies to the esp8266 chip
void esp8266_reset_buf()
reset buf, e.g. after packet was processed