SingingCat 0
application
esp8266.c
1#include "main-header.h"
2#include "loader-api.h"
3#include "addressing.h"
4#include "espressif/esp8266_flash.h"
5#include "coms/coms.h"
6#include "espressif/esp32_bluetooth.h"
7#include "proto-esp-usart.h"
8#include "platform-header.h"
9#include "wireless_state_machine.h"
10//#include "bare-metal.h"
11#include "led.h"
12#include "metrics/metrics.h"
13#include "ringbuffer.h"
14#include "hijack.h"
15
19static byte isupdating = 0;
20static uint32_t sc_boot_version = 0;
21//static long total_update_bytes=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;
37
38static uint32_t core_version = 0;
39static uint32_t core_base;
40static uint8_t core_chip;
41static uint32_t core_repo;
42
43static byte core_after_reset = 0; // esp8266_on sets it to '0'. upon receipt will be reset to '1';
44static const char *lastssid;
45static byte esp_reset_detect = 0;
46// command to which wifi scan results will be replied...
47static struct command *scan_com;
48static uint8_t com_state = 0;
49struct ringbuffer esp_ringbuffer;
50
51// #define DEBUG_SYNC_PIN 110
52
53#define ESPMODE_ISAP 1
54
55#define ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE 9600
56
61#define AT_COMMAND_OK 2
62#define AT_COMMAND_TIMEOUT 7
66#define MAX_SECS_BETWEEN_WIFI_DETECT 600
67
72#define SECONDS_BEFORE_ESP_FAIL 30
77#define SECONDS_BEFORE_ESP_RESET_FAIL 30
84#define SECONDS_BEFORE_ATTEMPTING_TO_RECONNECT 600
85
86
87static byte next_reset_ap = 0; // if 1, after next reset will go into AP instead of Statio node
88static byte esplogin = 0; //0=no need, 1=attempting, 2=failed, 3=ok
89static void request_core_info();
90void print_pkt_state_update(int subsystem, int code, uint8_t d1, uint8_t d2);
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;
97struct ipv4address lastip;
98static long ip_age = 0;
99
100static byte gotmac = 0;
101static long mac0;
102static long mac1;
103
104
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);
112
113char esptmpbuf[128];
114static byte baud_verify = 0;
115const char *BAUD_CHANGE_INDICATOR = "NEW BAUDRATE: [";
116static long new_baud = 0;
117
118/********************************************************************
119* Boot sequence:
120* esp8266_reset:
121* pin CHPD: low
122* decode_esp_packet_init()
123* queue_event(wireless_event_onreset) (-> state "IDLE")
124*
125* event_loop() (called by main each iteration, ~20k per second)
126* [LOOP] if STATE=="IDLE" -> send event "WIFIENABLED" => state "ROMCHECK"
127* [LOOP] if STATE=="ROMCHECK" -> send event "ONROMCHECKED" => state "INIT"
128* [LOOP] state INIT timesout after 1 second and becomes "RESETTING"
129* [CALLBACK "RESETTING"]: esp8266_trigger_reset_normal(); (toggle CHPD and set baud 74800)
130* [LOOP] if STATE=="RESETTING" -> if "[BOOTDONE]"&GPIO4=1 -> send event "RESETSUCCEEDED" => state READY
131* [CALLBACK "READY"]: send event "GOTAP" => state CONNECTINGAP
132* [CALLBACK "CONNECTINGAP"]: set_station_mode (send config, change baudrate to configured)
133*
134* at any time: if GPIO4 toggles from low->high: send event "ONRESET(DETECTED)"
135********************************************************************/
136
137/*
138 * static void set_wifi_led(int colour) {
139 * printf("*** WIFILED: %i *** \r\n", colour);
140 * led_blink(LED_WIFI, colour, 255, 20, 100);
141 * }
142 * static void led_connected() {
143 * set_wifi_led(0x00FF00);
144 * Delay(100);
145 * led_set_machine_managed();
146 * }
147 */
148
152//static long wifidetect = 0;
157static int is_ready_for_commands() {
158 if (is_hijacked_esp32()) {
159 return 0;
160 }
161
162 if (
163 (wireless_get_current_state() == WIRELESS_STATE_DEFAULTSOFTAP)
164 || (wireless_get_current_state() == WIRELESS_STATE_CONNECTED)
165 || (wireless_get_current_state() == WIRELESS_STATE_CONNECTINGCLOUD)
166 ) {
167 return 1;
168 }
169 return 0;
170}
171
172static int pin_set(int pin, int onoff) {
173 int r = mculib_pin_set(ESP8266_MCULIBHANDLE, pin, onoff);
174
175#ifdef DEBUG_SYNC_PIN
176 if (pin == PIN_ESP8266_GPIO0) {
177 mculib_pin_set(ESP8266_MCULIBHANDLE, DEBUG_SYNC_PIN, onoff);
178 }
179#endif
180
181 if (r) {
182 printf("esp8266: Failed to set pin %i to %i: %i\r\n", pin, onoff, r);
183 }
184 return r;
185}
190 return lastip.ip1 | lastip.ip2 | lastip.ip3 | lastip.ip4;
191}
192int get_esp_reboot_ctr() {
193 return esp8266_reboots;
194}
195
196long esp8266_get_valid_commands() {
197 return valid_commands;
198}
199long esp8266_get_invalid_commands() {
200 return invalid_commands;
201}
202void esp8266_reset_command_validity_ctrs() {
203 invalid_commands = 0;
204 valid_commands = 0;
205}
206void esp8266_set_operational_baudrate(int baudrate) {
207 if (default_baudrate == baudrate) {
208 return;
209 }
210 if (translate_baudrate(baudrate) == NULL) {
211 printf("esp8266: Cannot set baudrate %i\r\n", baudrate);
212 return;
213 }
214 default_baudrate = baudrate;
216}
217int esp8266_get_operational_baudrate() {
218 return default_baudrate;
219}
220
221// indicate to esp32 wether or not we are ready to receive. 1==ready,0==not ready
222static void esp_indicate_terminal_ready(int ready) {
223 if (config_get_flag(CONFIG_FLAGS_ESP_COMSYNC) == 0) {
224 return;
225 }
226 /*
227 * int ec = get_esp8266_usart_mode();
228 * if ( (ec != ESP8266_USART_PACKET_ONLY) && ( ec != ESP8266_USART_SMART ) ) {
229 * return;
230 * }
231 * int state = wireless_get_current_state();
232 * if (state == WIRELESS_STATE_RESETTING) {
233 * return;
234 * }
235 */
236 pin_set(PIN_ESP8266_GPIO0, ready?1:0);
237}
238
239static void esp8266_set_baudrate(int baudrate) {
240 int res;
241
242 //write_serial_string(USART_ESP8266, "\r"); // ensure all transmits are done
243 res = mculib_serialport_enable(ESP8266_MCULIBHANDLE, USART_ESP8266, baudrate);
244 if (res) {
245 printf("esp8266: Failed to set esp8266 usart to %i baud: %i\r\n", baudrate, res);
246 } else {
247 printf("esp8266: Set esp8266 usart to %i baud\r\n", baudrate);
248 }
249 write_serial_string(USART_ESP8266, "AT\r"); // ensure all transmits are done
250}
251
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);
260 Delay(50);
261 esp8266_off();
262 Delay(100);
263 esp8266_on();
264 long started = mculib_get_seconds_since_boot();
265
266 while ((mculib_get_seconds_since_boot() - started) < 2) {
267 check_espusart_and_send_to_terminal();
268 }
269 printf("esp8266: Attempting sync to flash protocol...\r\n");
270 int res = espflash_sync();
271
272 if (res != 0) {
273 printf("esp8266: Sync failed (%i)\r\n", res);
274 goto failure;
275 }
276 printf("esp8266: Sync ok\r\n");
277 goto skipflashtest;
278 res = espflash_prepare((void *)0x40000, 152648);
279 if (res != 0) {
280 printf("esp8266: Prepare failed (%i)\r\n", res);
281 goto failure;
282 }
283 printf("esp8266: Prepare ok\r\n");
284 res = espflash_write_block(0, 0);
285 if (res != 0) {
286 printf("Write failed (%i)\r\n", res);
287 goto failure;
288 }
289 printf("esp8266: Write ok\r\n");
290skipflashtest:
291 res = espflash_finish();
292 if (res != 0) {
293 printf("esp8266: Finish failed (%i)\r\n", res);
294 } else {
295 printf("esp8266: Finish ok\r\n");
296 }
297 pin_set(PIN_ESP8266_GPIO0, 1);
298 Delay(50);
299 printf("esp8266: Switching esp8266 off and on in boot-from-flash mode...\r\n");
300 esp8266_off();
301 Delay(100);
302 esp8266_on();
303 started = mculib_get_seconds_since_boot();
304 while ((mculib_get_seconds_since_boot() - started) < 2) {
305 check_espusart_and_send_to_terminal();
306 }
307failure:
308 printf("esp8266: Done.\r\n");
309}
310
311void set_esp8266_debug(byte b) {
312 printf("esp8266: Set esp8266 debug to %i\r\n", (int)b);
313 esp8266_debug = b;
314}
315
316static int esp8266_ison() {
317 return mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD);
318}
319static void esp8266_off() {
320 printf("esp8266: esp8266 off\r\n");
321 esp_cloud_deactivate();
322 pin_set(PIN_ESP8266_CHPD, 0);
323 Delay(50);
325 esp_reset_detect = 0;
326}
327static void esp8266_on() {
328 sc_boot_version = 0; // detect at boot. 0 == not found
329 esp_reset_detect = 0;
330 core_after_reset = 0; // it's a reset, we got to ask for firmware version again
331 printf("esp8266: esp8266 on\r\n");
333 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
334 pin_set(PIN_ESP8266_CHPD, 1);
335 Delay(50);
336 esp8266_reboots++;
337}
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");
347 esp8266_off();
348 Delay(10);
349 }
350 pin_set(PIN_ESP8266_GPIO0, 1);
351 Delay(50);
352 //esp8266_set_baudrate( 74800);
353 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
354 esp8266_on();
355}
356
357// on "wifidebug"
358void esp8266_dodebug(const char *paras) {
359 pin_set(PIN_ESP8266_GPIO0, 1);
360 Delay(50);
361 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
362 if (strlen(paras) > 0) {
363 if (paras[0] == 'c') {
364 contbridge = 1;
365 esp8266_set_baudrate(74800);
366 }
367 if (strlen(paras) > 2) {
368 const char *bs = &paras[0];
369 int br = atoi(bs);
370 if (br == 0) {
371 printf("esp8266: wifidebug: Invalid baudrate: %i (%s)\r\n", br, bs);
372 return;
373 }
374 printf("esp8266: Wifidebug, requested baudrate %i...\r\n", br);
375 esp8266_set_baudrate(br);
376 contbridge = 1;
377 }
378 }
380 esp8266_on();
382 contbridge = 0;
383}
388 esp8266_off();
389 wireless_queue_event(WIRELESS_EVENT_ONRESET);
390}
391
392static char *get_ap_credentials() {
393 return config_get_ram_struct()->apcredentials;
394}
398static int get_ap_count() {
399 if (get_ap_credentials()[0] == 0) {
400 return 0;
401 }
402 return 1;
403}
407static const char *get_ssid(int num) {
408 return (const char *)get_ap_credentials();
409}
413static const char *get_ssid_pw(int num) {
414 const char *p = get_ssid(num);
415
416 while (*p++ != 0) {
417 }
418 //p++;
419 return p;
420}
424void esp8266_add_ap(const char *ssid, const char *pw) {
425 int i;
426 int t;
427 byte *p = (byte *)get_ap_credentials();
428
429 t = 0;
430 for (i = 0; i < strlen(ssid); i++) {
431 p[t++] = ssid[i];
432 p[t] = 0;
433 }
434 p[t++] = 0;
435 for (i = 0; i < strlen(pw); i++) {
436 p[t++] = pw[i];
437 p[t] = 0;
438 }
439 config_commit();
440 wireless_queue_event(WIRELESS_EVENT_GOTNEWAP);
441}
442
443
444static void check_espusart_and_send_to_terminal() {
445 int esp;
446
447 while ((esp = ringbuffer_get_byte(&esp_ringbuffer)) >= 256) {
448 if ((esp == 0x12) || (esp < 9) || (esp > 127)) {
449 esp = ' ';
450 }
451 write_serial_char(USART_CONSOLE, esp);
452 }
453}
454
455static void esp8266_cfg_entry(char type, const char *txt) {
456 if (esp8266_debug) {
457 printf("esp8266: Sent Config: %c == \"%s\"\r\n", type, txt);
458 }
459 write_serial_char(USART_ESP8266, type);
460 write_serial_string(USART_ESP8266, txt);
461 write_serial_char(USART_ESP8266, 1);
462}
463static const char *translate_baudrate(int baudrate) {
464 const char *c = NULL;
465
466 if (baudrate == 9600) {
467 c = "0";
468 } else if (baudrate == 19200) {
469 c = "1";
470 } else if (baudrate == 38400) {
471 c = "2";
472 } else if (baudrate == 57600) {
473 c = "3";
474 } else if (baudrate == 115200) {
475 c = "4";
476 } else if (baudrate == 230400) {
477 c = "5";
478 } else if (baudrate == 460800) {
479 c = "6";
480 } else if (baudrate == 921600) {
481 c = "7";
482 } else if (baudrate == 74880) {
483 c = "8";
484 }
485 return c;
486}
487static void set_common_parameters() {
488 esp_indicate_terminal_ready(0);
489 com_state = 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");
493 } else {
494 esp8266_cfg_entry('L', "0");
495 }
496 if (config_get_flag(CONFIG_FLAGS_ESP_COMSYNC)) {
497 esp8266_cfg_entry('s', "1");
498 }
499
500 const char *tok = config_get_cloud_token();
501
502 if ((tok != NULL) && (strlen(tok) > 0)) {
503 esp8266_cfg_entry('T', tok);
504 }
505 char buf[16];
506
507 node_to_str(config_get_ram_struct()->nodeid, buf);
508 esp8266_cfg_entry('N', buf);
509 esp8266_cfg_entry('I', "5");
510 // esp8266_cfg_entry('E', "0"); // obsolete
511 const char *sn = config_get_sensor_server();
512
513 if (strlen(sn) > 0) {
514 esp8266_cfg_entry('D', sn);
515 }
516 char *c = (char *)translate_baudrate(esp8266_get_operational_baudrate());
517
518 esp8266_cfg_entry('B', c);
519}
520
521static void set_station_mode(int num) {
522 const char *ssid = get_ssid(num);
523
524 lastssid = ssid;
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));
530 esp8266_cfg_entry('C', esp_cloud_get_desired_server());
531 set_common_parameters();
532 write_serial_string(USART_ESP8266, "\r\r\r");
533 esp8266_set_baudrate(esp8266_get_operational_baudrate());
534
535 esp8266_mode = esp8266_mode & ~ESPMODE_ISAP;
536 Delay(10);
537 // send_nodeid();
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);
540 //request_core_info();
541 //printf("Enabling esp8266 DMA\r\n");
542 //mculib_serialport_enable_dma(USART_ESP8266,serialbuf,sizeof(serialbuf));
543}
544void esp8266_send_config() {
545 set_station_mode(0);
546}
547
548static byte got_ap_pw() {
549 const char *c = config_get_cloud_token();
550
551 if ((c == NULL) || (strlen(c) < 1)) {
552 return 0;
553 }
554 return 1;
555}
556
557static void set_ap_mode() {
558 lastssid = NULL;
559 led_indicate(LED_WIFI_APMODE);
560 write_serial_string(USART_ESP8266, "\rAT+CFG=");
561 esp8266_cfg_entry('M', "2");
562 set_common_parameters();
563 char buf[63];
564
565 snprintf(buf, 63, "singingcat_%N", config_get_ram_struct()->nodeid);
566 esp8266_cfg_entry('S', buf);
567 if (got_ap_pw()) {
568 strncpy(buf, config_get_cloud_token(), 11);
569 esp8266_cfg_entry('P', buf);
570 } else {
571 esp8266_cfg_entry('P', "singingcat");
572 }
573 write_serial_string(USART_ESP8266, "\r\r\r");
574 esp8266_set_baudrate(esp8266_get_operational_baudrate());
575 Delay(10);
577 printf("esp8266: Esp8266 set to accesspoint\r\n");
578 set_esp8266_usart_mode(ESP8266_USART_PACKET_ONLY);
579}
584 return (esp8266_mode & ESPMODE_ISAP) ? 1 : 0;
585}
586
593 ringbuffer_init(&esp_ringbuffer);
594}
595
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)
600 ;
601}
602
603static void transmit_to_esp(const byte *buf, int len) {
604 if (is_hijacked_esp32()) {
605 return;
606 }
607 int i;
608
609 for (i = 0; i < len; i++) {
610 write_serial_char(USART_ESP8266, buf[i]);
611 }
612}
617void wifi_send_data(const PACKET_TYPE type, const byte *buf, const int len) {
618 int tl;
619 int startpos;
620 byte b[3];
621
622 if (!is_ready_for_commands()) { // includes check for hijack
623 if (esp8266_debug) {
624 printf("esp8266: Not sending to esp - not ready yet\r\n");
625 }
626 return;
627 }
628
629 if (cat_is_control_byte(type)) {
630 // big error!
631 printf("esp8266: invalid packet type\r\n");
632 return;
633 }
634 b[0] = PKT_START_BYTE;
635 b[1] = type;
636 transmit_to_esp((const byte *)&b, 2);
637 startpos = 0;
638 b[0] = PKT_ESC_BYTE;
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);
643 startpos = tl;
644 }
645 }
646 if (startpos < tl) {
647 transmit_to_esp((const byte *)&buf[startpos], tl - startpos);
648 }
649 b[0] = PKT_END_BYTE;
650 b[1] = '\n';
651 transmit_to_esp((const byte *)&b, 1);
652 IncMetric_PKTS_WIFI_CTR_OUT;
653}
654
655static void do_gpio4() {
656 int b = mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO4);
657
658 if (b == gpio4_prev_state) {
659 return;
660 }
661 gpio4_prev_state = b;
662 if (b) {
663 // wireless_queue_event(WIRELESS_EVENT_ONRESETDETECTED);
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;
668 } else {
669 printf("esp8266: ESP8266 gpio4: low\r\n");
670 }
671}
676 int res = espflash_sync();
677
678 if (res) {
679 printf("esp8266: FAIL: failed to sync to esp8266. Is it connected and powered up?\r\n");
680 return;
681 }
683 wireless_queue_event(WIRELESS_EVENT_ONRESETDETECTED);
684}
685static void do_com_while_bridged(const char c) {
686 if (c == '+') {
687 led_blink(LED_WIFI_BRIDGE, 0xFF0000, 255, 10, 1);
688 comctr++;
689 comctrts = mculib_get_seconds_since_boot();
690 //printf("+ received (%i)\r\n",comctr);
691 } else {
692 //printf("non-+ received (%i)\r\n",c);
693 if ((c != '\r') && (c != '\n')) {
694 led_blink(LED_WIFI_BRIDGE, 0x0000FF, 255, 10, 1);
695 comctr = 0;
696 }
697 }
698}
699static void scan_esp_output_while_bridged(const char c) {
700 if (BAUD_CHANGE_INDICATOR[baud_verify] == 0) {
701 // found baud rate indicator
702 if ((c >= '0') && (c <= '9')) {
703 new_baud = new_baud * 10 + (c - '0');
704 } else {
705 printf("esp8266: *** SingingCat firmware detected baudrate change: %i (%c)\r\n", (int)new_baud, c);
706 esp8266_set_baudrate(new_baud);
707 baud_verify = 0;
708 }
709 } else {
710 if (c == BAUD_CHANGE_INDICATOR[baud_verify]) {
711 baud_verify++;
712 new_baud = 0;
713 } else {
714 baud_verify = 0;
715 }
716 }
717}
718
719static int com_mode_bridged() {
720 //return/quit/config/ap/reset/scan
721 printf("\r\n(ato|atq|atc|atC|atp|atr|atscan)\r\nOK\r\n");
722 comctrts = 0;
723 comctr = 0;
724 esptmpbuf[0] = 0;
725 for (;;) {
726 avoid_watchdog();
727 int x = console_get_line((char *)&esptmpbuf, 50);
728 if (x <= 0) {
729 continue;
730 }
731 console_reset();
732 if (strcmp(esptmpbuf, "ato") == 0) {
733 printf("esp8266: reconnecting...\r\n");
734 break;
735 }
736 if (strcmp(esptmpbuf, "atscan") == 0) {
737 printf("esp8266: starting scan...\r\n");
738 start_wifi_scan();
739 break;
740 }
741 if (strcmp(esptmpbuf, "atq") == 0) {
742 printf("esp8266: quitting\r\n");
743 return 1;
744 }
745 if (strcmp(esptmpbuf, "atp") == 0) {
746 set_ap_mode();
747 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
748 break;
749 }
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"); // if debug, update immediately
755 esp8266_cfg_entry('S', get_ssid(0));
756 esp8266_cfg_entry('P', get_ssid_pw(0));
757 esp8266_cfg_entry('C', esp_cloud_get_desired_server());
758 set_common_parameters();
759 write_serial_string(USART_ESP8266, "\r\r\r");
760 esp8266_set_baudrate(esp8266_get_operational_baudrate());
761 break;
762 }
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));
769 esp8266_cfg_entry('C', esp_cloud_get_desired_server());
770 set_common_parameters();
771 write_serial_string(USART_ESP8266, "\r\r\r");
772 esp8266_set_baudrate(esp8266_get_operational_baudrate());
773 break;
774 }
775 if (strcmp(esptmpbuf, "atr") == 0) {
776 esp8266_off();
777 Delay(2);
778 printf("esp8266: ESP8266 on & return\r\n");
779 // reset_ringbuffer(USART_CONSOLE);
780 esp8266_on();
781 return 0;
782 }
783 }
784 // reset_ringbuffer(USART_CONSOLE);
785 return 0;
786}
787
792 printf("esp8266: Bridging esp2866 & debug console...\r\n");
793 comctr = 0;
794 comctrts = 0;
795 console_reset();
796 led_indicate(LED_WIFI_BRIDGE);
797 baud_verify = 0;
798 printf("esp8266: contbridge==%i\r\n", contbridge);
799 printf("esp8266: Entering passthrough mode\r\n");
800 printf("[BRIDGE ACTIVE]\r\n"); // easy parse ;)
801 esp8266_usart_mode = ESP8266_USART_PASSTHROUGH;
802 reset_delay_counter(DELAY_ESP2SERIAL);
803 reset_delay_counter(DELAY_DEFAULT);
804 avoid_watchdog();
805 int to = 20000;
806
807 for (;;) {
808 avoid_watchdog();
809 do_gpio4();
810 if (get_delay_counter(DELAY_DEFAULT) > 20) {
811 reset_delay_counter(DELAY_DEFAULT);
812 } else if (get_delay_counter(DELAY_DEFAULT) > 10) {
813 }
814 // check for +++ and some time passed thereafter
815 if ((comctr >= 3) && (mculib_get_seconds_since_boot() - comctrts) >= 2) {
816 // check for commands (after +++)
817 if (com_mode_bridged()) {
818 break;
819 }
820 }
821 // deal with chars from console while bridged
822 uint16_t x;
823 if ((x = console_get_byte()) < 256) {
824 to = 500;
825 avoid_watchdog();
826 write_serial_char(USART_ESP8266, x);
827 reset_delay_counter(DELAY_ESP2SERIAL);
828 if (contbridge) {
829 // count '+' (increases variable comctr, each time one is received)
830 do_com_while_bridged(x);
831 } else {
832 led_blink(LED_WIFI_BRIDGE, 0xFFFFFF, 255, 10, 1);
833 }
834 } else {
835 led_blink(LED_WIFI_BRIDGE, 0, 0, 0, 0);
836 }
837 // deal with chars from esp8266 while bridged
838 if ((x = ringbuffer_get_byte(&esp_ringbuffer)) < 256) {
839 write_char_to_console(x);
840 if (contbridge) {
841 scan_esp_output_while_bridged(x);
842 }
843 }
844
845 // if no traffic for some time, leave debug mode
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"); // easy parse ;)
850 break;
851 }
852 }
853 led_indicate(LED_WIFI_BRIDGE2);
854}
860 if (is_hijacked_esp32()) {
861 return "userapp_control";
862 }
863
864 if (isupdating) {
865 return "Updating Firmware";
866 }
867 if (config_get_wifidisable()) {
868 return "Disabled";
869 }
870 if (esp8266_is_accespoint()) {
871 return "Accesspoint";
872 }
873 if (!is_last_ip_valid()) {
874 return "Client (No IP)";
875 }
876 return "Connected to AP (Got IP)";
877}
878
883void esp_init() {
884 int r;
885
886 ringbuffer_init(&esp_ringbuffer);
887 espline_received[0] = 0;
888 espline_received_valid = 0;
889 if (config_get_wifidisable()) {
890 // even if wifi is disabled, enable pin for output, so we can turn wifi off
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);
893 }
894 esp8266_off();
895 return;
896 }
897 lastssid = NULL;
898 core_version = 0;
899 core_chip = 0;
900 core_base = 0;
901 core_repo = 0;
902 esp8266_usart_mode = ESP8266_USART_PACKET_ONLY;
903
904#ifdef DEBUG_SYNC_PIN
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);
907 }
908#endif
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);
911 }
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);
914 }
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);
917 }
918 esp8266_off();
919 wireless_init();
920 if (!config_get_wifidisable()) {
922 }
923 CNWDEBUG("esp_init() complete\n");
924}
925
931int esp_get_mac(char *buf, int bufsize) {
932 if ((bufsize == 0) || (buf == NULL)) {
933 return 2;
934 }
935 buf[0] = 0;
936 if (!gotmac) {
937 return 1;
938 }
939 snprintf(buf, bufsize, "18:FE:34:%x:%x:%x",
940 (int)((mac1 >> 8) & 0xff),
941 (int)((mac1) & 0xff),
942 (int)((mac0 >> 24) & 0xff));
943 return 0;
944}
949 avoid_watchdog();
950 int res;
951
952 res = 0;
953 printf("esp8266: Syncing to esp8266...\r\n");
954 if ((res = espflash_sync()) != 0) {
955 res = 1;
956 goto failure;
957 }
958 espflash_read_register(0x3ff00050, &mac0);
959 espflash_read_register(0x3ff00054, &mac1);
960 gotmac = 1;
961failure:
962 avoid_watchdog();
963 esp8266_off();
964 return res;
965}
966
967void set_esp8266_usart_mode(int i) {
968 esp8266_usart_mode = i;
969}
970int get_esp8266_usart_mode() {
971 return esp8266_usart_mode;
972}
973
974void print_esp_core_info() {
975 long now = mculib_get_seconds_since_boot();
976 long ago = now - core_info_age;
977
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);
982}
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);
990 int pos = 0;
991
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;
996 core_chip = 1; // we don't know any better. but it's old, so probably an esp8266
997 core_repo = 0; // we just don't know ;(
998 core_base = 0; // we just don't know ;(
999 core_info_age = mculib_get_seconds_since_boot();
1000 core_after_reset = 1;
1001 return;
1002 }
1003 // new style:
1004 printf("esp firmware - New style\r\n");
1005 //uint8_t version, uint8_t chip, uint32_t version, uint32_t repo, uint32_t baseadr
1006 if (buf[1] != 1) {
1007 printf("esp firmware - unknown structure %i\r\n", buf[0]);
1008 return;
1009 }
1010 pos = 2;
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;
1017}
1018
1019void wifi_new_creds(char *buf) {
1020 int i;
1021 const char *pw = NULL;
1022 const char *ssid = NULL;
1023
1024 for (i = 0; i < strlen(buf); i++) {
1025 if ((ssid == NULL) && ((buf[i] == 13) || (buf[i] == 10))) {
1026 continue;
1027 }
1028 if (ssid == NULL) {
1029 ssid = &buf[i];
1030 }
1031 if (buf[i] == 1) {
1032 buf[i] = 0;
1033 pw = (const char *)(buf + i + 1);
1034 break;
1035 }
1036 }
1037 if (pw == NULL) {
1038 printf("esp8266 - got new wifi SSID (%s), but no password\r\n", ssid);
1039 return;
1040 }
1041 printf("esp8266 - got new wifi credentials: %s %s\r\n", ssid, pw);
1042 esp8266_add_ap(ssid, pw);
1043 esp8266_reset();
1044}
1045
1046static void request_core_info() {
1047 cat_send_local_instruction(INSTRUCTION_GET_CORE_INFO, (const uint8_t *)esplinebuf, 0);
1048}
1049/************************ wifi update handler ***************************/
1050void wifi_update_started() {
1051 printf("esp8266: wifi_update started\r\n");
1052 isupdating = 1;
1053}
1054void wifi_update_completed() {
1055 isupdating = 0;
1056 printf("esp8266: wifi_update completed\r\n");
1057}
1058void wifi_update_progress(const uint8_t *buf) {
1059 printf("esp8266: wifi_update: %s\r\n", buf);
1060}
1061
1069void esp8266_got_packet(const byte *buf, int size) {
1070 // tell esp that we received the packet.
1071 com_state = 2;
1072 esp_indicate_terminal_ready(1);
1073 if (size == 0) {
1075 com_state = 0;
1076 return; // empty packet? ;)
1077 }
1078 if (buf[0] == PKT_COMMAND) {
1079 struct command *com;
1080 com = command_parse(buf + 1, size - 1);
1081 if (com == NULL) {
1082 invalid_commands++;
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;
1086 } else {
1087 valid_commands++;
1088 com->sourcedev = SOURCE_WIFI;
1089 got_new_packet(com, 255);
1090 IncMetric_PKTS_WIFI_CTR_IN;
1091 }
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";
1101 } else {
1102 statestr = "NOT CONNECTED";
1103 }
1104 if (is_last_ip_valid()) {
1105 wireless_queue_event(WIRELESS_EVENT_IPASSIGNED);
1106 }
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)) {
1109 esplogin = 3;
1110 }
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];
1115 int code = buf[2];
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);
1119 }
1120 if ((subsystem == SUBSYS_AP) && (code == STATE_AP_FAILED)) {
1121 wireless_queue_event(WIRELESS_EVENT_APFAILURE);
1122 }
1123 if ((subsystem == SUBSYS_CLOUD) && (code == STATE_CLOUD_CONNECTED)) {
1124 wireless_queue_event(WIRELESS_EVENT_CLOUDISOK);
1125 }
1126 if ((subsystem == SUBSYS_CLOUD) && (
1127 (code == STATE_CLOUD_DISCONNECTED)
1128 || (code == STATE_CLOUD_CONNECTFAILURE)
1129 || (code == STATE_CLOUD_AUTORECONNECT)
1130 )) {
1131 wireless_queue_event(WIRELESS_EVENT_CLOUDDISCONNECTED);
1132 }
1133 if ((subsystem == PKT_IP_UPDATE) && (code == STATE_AP_CONNECTED)) {
1134 wireless_queue_event(WIRELESS_EVENT_APCONNECTED);
1135 }
1136 if (subsystem == SUBSYS_CORE) {
1137 esp_core_update(code, (byte *)(buf + 3), size - 3);
1138 }
1139 if (size > 4) {
1140 print_pkt_state_update(subsystem, code, buf[3], buf[4]);
1141 } else if (size > 3) {
1142 print_pkt_state_update(subsystem, code, buf[3], 0);
1143 } else if (size > 2) {
1144 print_pkt_state_update(subsystem, code, 0, 0);
1145 } else {
1146 printf("esp8266: WIFI state update: no subsystem\r\n");
1147 }
1148 } else if (buf[0] == PKT_LOCAL_INSTRUCTION) {
1149 printf("esp8266: Local instruction received: ");
1150 int i;
1151 for (i = 0; i < size; i++) {
1152 printf(" %i", buf[i]);
1153 }
1154 printf("\r\n");
1155 } else if (buf[0] == PKT_WIFI_SCAN_UPDATE) {
1156 scanUpdate(buf + 1);
1157 } else if (buf[0] == PKT_WIFI_SCAN_COMPLETE) {
1158 scanComplete();
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);
1169 } else {
1170 printf("invalid esp8266 packet type (%i: \"%s\")!\r\n", buf[0], buf);
1171 printHex("packet: ", buf, size);
1172 }
1174 com_state = 0; // allow esp to send next packet
1175}
1176
1177// 1==esp8266, 2=esp32
1178int esp8266_get_chip() {
1179 return core_chip;
1180}
1181int esp8266_get_firmware_version() {
1182 return core_version;
1183}
1184int esp8266_get_firmware_repo() {
1185 return core_repo;;
1186}
1187uint64_t esp8266_get_firmware_base() {
1188 return core_base;
1189}
1193void print_pkt_state_update(int subsystem, int code, uint8_t d1, uint8_t d2) {
1194 int data = (((int)d1) << 8) | ((int)d2);
1195
1196 if (subsystem == SUBSYS_AP) {
1197 printf("SUBSYSTEM: Accesspoint Code: ");
1198 if (code == STATE_AP_IDLE) {
1199 printf("Idle\r\n");
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");
1212 } else {
1213 printf("%i\r\n", code);
1214 }
1215 } else if (subsystem == SUBSYS_CLOUD) {
1216 esp_cloud_state_update(code, data);
1217 } else if (subsystem == SUBSYS_CORE) {
1218 printf("esp core update\n");
1219 } else {
1220 printf("SUBSYSTEM: %i Code: %i\r\n", subsystem, code);
1221 }
1222}
1223
1224
1230 if ((lastip.ip1 | lastip.ip2 | lastip.ip3 | lastip.ip4) == 0) {
1231 return NULL;
1232 }
1233 return &lastip;
1234}
1235long esp8266_get_time_of_last_ip() {
1236 return ip_age;
1237}
1238
1239static const char *eob = "csum";
1240static int det = 0;
1241// obsolete...
1242static void esp8266_afterreset(byte read) {
1243 ringbuffer_add_byte(&esp_ringbuffer, read);
1244 if (read == eob[det]) {
1245 det++;
1246 } else {
1247 det = 0;
1248 if (read == eob[det]) {
1249 det++;
1250 }
1251 }
1252 if (det == 4) {
1253 esp8266_set_baudrate(ESP8266_AFTER_BOOT_DEFAULT_BAUDRATE);
1254 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
1255 }
1256}
1257
1263 if (get_esp8266_usart_mode() == ESP8266_USART_IGNORE) {
1264 return;
1265 }
1266 byte read = 0xFF & val;
1267
1268 int state = wireless_get_current_state();
1269
1270 if ((com_state == 0) && (val == '{')) {
1271 com_state = 1;
1272 esp_indicate_terminal_ready(0);
1273 }
1274 if (state == WIRELESS_STATE_RESETTING) {
1275 ringbuffer_add_byte(&esp_ringbuffer, read);
1276 return;
1277 }
1278 if (get_esp8266_usart_mode() == ESP8266_USART_PACKET_ONLY) {
1279 esp8266_add_byte(read);
1280 if (esp8266_debug) {
1281 // if (!esp8266_is_in_packet()) {
1282 ringbuffer_add_byte(&esp_ringbuffer, read);
1283 //}
1284 }
1285 return;
1286 } else if (get_esp8266_usart_mode() == ESP8266_USART_SMART) {
1287 esp8266_add_byte(read);
1288 if (!esp8266_is_in_packet()) {
1289 ringbuffer_add_byte(&esp_ringbuffer, read);
1290 }
1291 return;
1292 } else if (get_esp8266_usart_mode() == ESP8266_USART_PASSTHROUGH) {
1293 ringbuffer_add_byte(&esp_ringbuffer, read);
1294 return;
1295 } else if (get_esp8266_usart_mode() == ESP8266_USART_AFTERRESET) {
1296 esp8266_afterreset(read);
1297 return;
1298 }
1299}
1300
1301static void write_serial_buffer(int USART, const uint8_t *buf, int length) {
1302 int i;
1303
1304 for (i = 0; i < length; i++) {
1305 write_serial_char(USART, buf[i]);
1306 }
1307}
1312 char buf[16];
1313
1314 if (esp8266_debug) {
1315 printf("esp8266 - sending extra instructions\r\n");
1316 }
1317 node_to_str(config_get_ram_struct()->nodeid, buf);
1318 cat_send_local_instruction(INSTRUCTION_SET_LOCAL_NODEID, (const uint8_t *)buf, strlen(buf));
1319 const char *tok = config_get_cloud_token();
1320
1321 if ((tok != NULL) && (strlen(tok) > 0)) {
1322 cat_send_local_instruction(INSTRUCTION_SET_CLOUDTOKEN, (const uint8_t *)tok, strlen(tok));
1323 }
1324}
1329 char buf[16];
1330
1331 buf[0] = 0;
1332 if (esp8266_debug) {
1333 printf("esp8266 - asking for ota\r\n");
1334 }
1335 cat_send_local_instruction(INSTRUCTION_DOWNLOAD_UPDATE, (const uint8_t *)buf, 0);
1336}
1337
1343void cat_send_local_instruction(const PACKET_TYPE type, const uint8_t *buf, const int len) {
1344 int tl;
1345 int startpos;
1346 uint8_t b[2];
1347
1348 if (cat_is_control_byte(type)) {
1349 // big error!
1350 printf("invalid packet type\r\n");
1351 return;
1352 }
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);
1356
1357 startpos = 0;
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);
1362 startpos = tl;
1363 }
1364 }
1365 if (startpos < tl) {
1366 write_serial_buffer(USART_ESP8266, &buf[startpos], tl - startpos);
1367 }
1368 b[0] = PKT_END_BYTE;
1369 b[1] = '\n';
1370 write_serial_buffer(USART_ESP8266, (const uint8_t *)&b, 2);
1371}
1372
1373// start a wifi scan, drop results
1374void start_wifi_scan() {
1375 char buf[16];
1376
1377 buf[0] = 0;
1378 cat_send_local_instruction(INSTRUCTION_START_SCAN, (const uint8_t *)buf, 0);
1379}
1380static void scanComplete() {
1381 send_command_reply(scan_com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
1382 scan_com = NULL;
1383 printf("Wifi scan finished\r\n");
1384}
1385static void scanUpdate(const uint8_t *buf) {
1386 struct command *com = scan_com;
1387
1388 if (com == NULL) {
1389 return;
1390 }
1391
1392
1393 struct command *dcom = alloc_command();
1394
1395 if (dcom == NULL) {
1396 printf("Cannot send wifi update - no free command\r\n");
1397 return;
1398 }
1399 command_init(dcom);
1400 //dcom->recipient = com->sender; // WRONG!! next hop!
1401 dcom->target = com->sender;
1402 dcom->encoding = 'a';
1403 dcom->index = com->index;
1404 dcom->sourcedev = com->sourcedev;
1405 dcom->connid = com->connid;
1406 dcom->com = com->com;
1407 dcom->flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
1408 command_add_arg(dcom, "chan=%i", buf[0]);
1409 command_add_arg(dcom, "rssi=%i", buf[1]);
1410 command_add_arg(dcom, "ssid=%s", &buf[8]);
1411 send_command(dcom);
1412 free_command(dcom);
1413 printf("Channel=%i, rssi=%i, SSID: %s\r\n", buf[0], buf[1], &buf[8]);
1414}
1415
1416// start a wifi scan, return results to command as replies
1417void esp8266_wifi_scan(struct command *com) {
1418 char buf[16];
1419
1420 buf[0] = 0;
1421 scan_com = com;
1422 cat_send_local_instruction(INSTRUCTION_START_SCAN, (const uint8_t *)buf, 0);
1423}
1424
1425
1426const char *esp_get_last_pw() {
1427 return get_ssid_pw(0);
1428}
1429const char *esp_get_last_ssid() {
1430 return lastssid;
1431}
1432
1433// tell us if esp8266 is currently enabled.
1434int esp8266_is_enabled() {
1435 if (config_get_wifidisable()) {
1436 return 0;
1437 }
1438 // maybe consider soft-enable (e.g. calling enable/disable w/o config flag?)
1439 return 1;
1440}
1441
1443 printf("esp8266 enable\r\n");
1444 wireless_queue_event(WIRELESS_EVENT_WIFIENABLED);
1445}
1447 printf("esp8266 disable\r\n");
1448 wireless_queue_event(WIRELESS_EVENT_ONWIFIDISABLE);
1449 esp8266_off();
1450 esp8266_event_loop(); // kick through the loop once at least.
1451}
1452
1453/*******************************************************************
1454 * called from mainloop, asks the esp8266 for information about
1455 * itself
1456 */
1457static void check_esp_core() {
1458 int state = wireless_get_current_state();
1459
1460 // we allow for "not ready" states, because if we fail to connect
1461 // we still want to report the version (possibly through the 868Mhz to the cloud)
1462 if ((state != WIRELESS_STATE_CONNECTED)
1463 && (state != WIRELESS_STATE_CONNECTINGAP)
1464 && (state != WIRELESS_STATE_CONNECTINGIP)
1465 && (state != WIRELESS_STATE_CONNECTINGCLOUD)
1466 ) {
1467 return;
1468 }
1469 long now = mculib_get_seconds_since_boot();
1470
1471 // if it's fresh enough, do nothing
1472 if (core_info_age > now) {
1473 core_info_age = now;
1474 }
1475 // if the information we have is no older than this,
1476 // don't do stuff (esp_reset, does reset the counter!)
1477 if (core_after_reset && ((now - core_info_age) < 600)) {
1478 return;
1479 }
1480
1481 if (last_request_for_core > now) {
1482 last_request_for_core = now;
1483 }
1484 // ask no more frequently than every 2 seconds
1485 if ((now - last_request_for_core) < 2) {
1486 return;
1487 }
1488 last_request_for_core = now;
1489
1490 printf("esp8266: Requesting core info...\r\n");
1491 request_core_info();
1492}
1493
1494static void check_boot_firmware() {
1495 if (!espline_received_valid) {
1496 return;
1497 }
1498 const char *x = "Singingcat Firmware Version: ";
1499
1500 if (strlen(x) > strlen(espline_received)) {
1501 return;
1502 }
1503 int i;
1504
1505 for (i = 0; i < strlen(x); i++) {
1506 if (espline_received[i] != x[i]) {
1507 return;
1508 }
1509 }
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);
1512}
1513
1514static void read_esp_serial_line() {
1515 if (espline_received_valid) {
1516 espline_received_valid = 0;
1517 espline_received[0] = 0;
1518 }
1519 // return;
1520 // if (ringbuffer_find_string(USART_ESP8266, "Singingcat Firmware Version:")) {
1521 for (;;) {
1522 int nb = ringbuffer_get_byte(&esp_ringbuffer);
1523 if (nb >= 256) {
1524 break;
1525 }
1526 int l = strlen(espline_received);
1527 if (l > sizeof(espline_received) - 5) {
1528 l = 0;
1529 }
1530 if ((nb == '\r') || (nb == '\n')) {
1531 if (l > 0) {
1532 espline_received_valid = 1;
1533 break;
1534 }
1535 } else {
1536 espline_received[l++] = (byte)nb;
1537 espline_received[l] = 0;
1538 }
1539 }
1540}
1541
1542/*******************************************************************
1543* Main loop (called ~20k per second)
1544*******************************************************************/
1545static void wireless_process_event_queue();
1546static long lastloop = 0;
1547static int laststate = 0;
1548// this is called ~5k per second from mainloop
1549void esp8266_event_loop() {
1550 if (config_get_wifidisable()) {
1551 return;
1552 }
1553
1554 read_esp_serial_line();// this sets espline_received
1555
1556 if (espline_received_valid) {
1557 if (esp8266_debug) {
1558 printf("esp8266: buf: \"%s\"\r\n", &espline_received);
1559 }
1560 }
1561 mculib_serialport_transferbuffer(USART_ESP8266);
1562 /*
1563 * if (esp8266_debug & 0x4) {
1564 * check_espusart_and_send_to_terminal();
1565 * }
1566 */
1567 int state = wireless_get_current_state();
1568
1569 // in some cases we have to force next state if we're debugging
1570#ifdef DEBUG_ON_LINUX
1571 if (state == WIRELESS_STATE_RESETTING) {
1572 wireless_queue_event(WIRELESS_EVENT_RESETSUCCEEDED);
1573 }
1574#endif
1575
1576 if (state != WIRELESS_STATE_RESETTING) {
1577 do_gpio4();
1578 }
1579 //check_espusart_and_send_to_terminal();
1580
1581 long now = mculib_get_seconds_since_boot();
1582
1583 check_esp_core();
1584 // if state changed, print new state
1585 if (state != laststate) {
1586 printf("esp8266: State: %s\r\n", wireless_state_to_string(state));
1587 laststate = state;
1588 }
1589 lastloop = now;
1590
1591
1592 if (state == WIRELESS_STATE_IDLE) {
1593 wireless_queue_event(WIRELESS_EVENT_WIFIENABLED);
1594 }
1595
1596 if (state == WIRELESS_STATE_ROMCHECK) {
1597#ifdef DEBUG_ON_LINUX
1598 wireless_queue_event(WIRELESS_EVENT_ONROMCHECKED);
1599#else
1600 if (esp_read_mac()) {
1601 wireless_queue_event(WIRELESS_EVENT_ONROMFAILED);
1602 } else {
1603 wireless_queue_event(WIRELESS_EVENT_ONROMCHECKED);
1604 }
1605#endif
1606 }
1607
1608 if (state == WIRELESS_STATE_RESETTING) {
1609 check_boot_firmware(); // parse for singingcat version
1610 isupdating = 0; // after reset we are never "updating a 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;
1615 }
1616 /*
1617 * if (ringbuffer_find_string(USART_ESP8266, "[BOOTDONE]")) {
1618 * printf("esp8266: detected [BOOTDONE] message\r\n");
1619 * esp_reset_detect = 1;
1620 * }
1621 */
1622 } else if (esp_reset_detect == 1) {
1623 isupdating = 0; // after reset we are never "updating a firmware"
1624 gpio4_prev_state = mculib_pin_get(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO4);
1625 if (gpio4_prev_state == 1) {
1626 // we're resetting, we know, do not trigger again
1627 printf("esp8266: gpio high detected\r\n");
1628 wireless_queue_event(WIRELESS_EVENT_RESETSUCCEEDED);
1629 esp_reset_detect = 0;
1630 }
1631 }
1632 }
1633
1634 // connected to the cloud -> periodically call the cloud handler
1635 if (state == WIRELESS_STATE_CONNECTED) {
1637 }
1638 wireless_process_event_queue();
1639
1640 if (wifi_state_since > now) {
1641 wifi_state_since = now; // our clock goes backwards???
1642 }
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),
1650 to
1651 );
1652 wireless_timeout();
1653 }
1654 }
1655
1656 return;
1657}
1662 wireless_queue_event(WIRELESS_EVENT_CLOUDDISCONNECTED);
1663}
1664
1665/*******************************************************************
1666* wireless state machine stuff
1667*******************************************************************/
1668static int wireless_queue[10];
1672static void wireless_queue_event(int event) {
1673 int i;
1674 int max = 0;
1675
1676 if ((!esp8266_is_enabled()) && (event != WIRELESS_EVENT_WIFIENABLED)) {
1677 // if disabled, then only event allowed is to enable it
1678 return;
1679 }
1680 if (esp8266_debug) {
1681 printf("esp8266: [wireless-statemachine] Queued wireless event: %s\r\n", wireless_event_to_string(event));
1682 }
1683 for (i = 0; i < (sizeof(wireless_queue) / sizeof(wireless_queue[0])); i++) {
1684 if (wireless_queue[i] != 0) {
1685 max = i;
1686 }
1687 }
1688 if ((max + 1) >= sizeof(wireless_queue) / sizeof(wireless_queue[0])) {
1689 printf("esp8266: [wireless-statemachine] ERROR -> Out of event buffers!!\r\n");
1690 return;
1691 }
1692 wireless_queue[max + 1] = event;
1693}
1694
1695static void wireless_process_event_queue() {
1696 int i;
1697
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;
1702 }
1703 }
1704}
1705
1706// the state machine is already in new state!
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;
1713
1714 if (newstate == WIRELESS_STATE_RESETTING) {
1715 esp8266_trigger_reset_normal();
1716 }
1717 if (newstate == WIRELESS_STATE_READY) {
1718 if ((get_ap_count() == 0) || (next_reset_ap)) {
1719 next_reset_ap = 0;
1720 wireless_queue_event(WIRELESS_EVENT_GOTNOAP);
1721 } else {
1722 wireless_queue_event(WIRELESS_EVENT_GOTAP);
1723 }
1724 }
1725 if (newstate == WIRELESS_STATE_DEFAULTSOFTAP) {
1726 led_set_wifi_managed();
1727 set_ap_mode();
1728 }
1729 if (newstate == WIRELESS_STATE_TRIGGERDEFAULTSOFTAP) {
1730 led_set_wifi_managed();
1731 esp8266_reset();
1732 next_reset_ap = 1;
1733 }
1734 if (newstate == WIRELESS_STATE_CONNECTINGAP) {
1735 set_station_mode(0);
1736 }
1737 if (newstate == WIRELESS_STATE_CONNECTED) {
1738 led_indicate(LED_WIFI_CONNECTED);
1742 }
1743 if (oldstate == WIRELESS_STATE_CONNECTED) {
1744 // we left the connected stuff
1745 esp_cloud_deactivate();
1747 }
1748
1749 if (newstate == WIRELESS_STATE_NEXTAP) {
1750 // we should count up here and only go into softap
1751 // once we tried all known SSIDS
1752 // (but atm we only know one, so...)
1753 if (got_ap_pw()) {
1754 wireless_queue_event(WIRELESS_EVENT_ONNOMOREAPS);
1755 }
1756 }
1757}
1758
1759
1760/*******************************************************************
1761* end wireless state machine stuff
1762*******************************************************************/
1763/* write to serial port and USB */
1764int write_char_to_console(char b) {
1765 int i;
1766
1767 i = write_serial_char(USART_CONSOLE, b);
1768 mculib_usb_send(ESP8266_MCULIBHANDLE, 1, (uint8_t *)&b);
1769 return i;
1770}
void esp8266_enable()
enable the esp8266 (switch it on)
Definition: esp8266.c:1442
void esp8266_wififlash_bridge(void)
set esp8266 to flash mode, sync and then bridge ("startflash")
Definition: esp8266.c:675
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
int esp_read_mac()
Definition: esp8266.c:948
void decode_esp_packet_init()
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
void esp_cloud_init()
this resets the cloud state
Definition: esp8266_cloud.c:57
char * esp8266_status_string()
returns a human readable status string of the wifi connection
Definition: esp8266.c:859
void esp8266_read_byte_from_serialport(int val)
this is called directly from the usart IRQ. be quick. and do not use printf()
Definition: esp8266.c:1262
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
Definition: esp8266.c:617
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
Definition: esp8266.c:189
void esp8266_ota()
tell the esp to do an OTA
Definition: esp8266.c:1328
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 ...
Definition: esp8266_cloud.c:82
void esp8266_reset()
reset state machine and esp8266
Definition: esp8266.c:387
int esp8266_is_accespoint()
returns !=0 if we are currently an accesspoint
Definition: esp8266.c:583
int send_command_reply(struct command *com, byte flags)
send a reply to a command
Definition: queue.c:562
const char * esp_cloud_get_desired_server()
returns server we want to connect to
Definition: esp8266_cloud.c:68
void cat_send_local_instruction(const PACKET_TYPE type, const uint8_t *buf, const int len)
send a packet to the esp8266 wifi chip
Definition: esp8266.c:1343
void esp_empty_ringbuffer()
empties the ringbuffer.
Definition: esp8266.c:592
void command_init(struct command *com)
initialize a command structure with default values
void esp8266_got_packet(const byte *buf, int size)
Definition: esp8266.c:1069
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.
Definition: esp8266.c:931
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)
Definition: routing.c:111
void esp8266_disable()
disable the esp8266 (switch it off)
Definition: esp8266.c:1446
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 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.
Definition: led.c:288
void print_pkt_state_update(int subsystem, int code, uint8_t d1, uint8_t d2)
Definition: esp8266.c:1193
void esp8266_test()
Definition: esp8266.c:256
struct ipv4address * esp8266_get_current_ip()
return last ip (null if none)
Definition: esp8266.c:1229
void esp8266_add_ap(const char *ssid, const char *pw)
add an ap to the list of known ap
Definition: esp8266.c:424
void esp8266_bridge()
bridge debug serialport and esp8266 (e.g. "wifidebug")
Definition: esp8266.c:791
void esp8266_cloud_connection_failed()
called if the cloud connection failed
Definition: esp8266.c:1661
void esp8266_send_instructions()
send our nodeid and other goodies to the esp8266 chip
Definition: esp8266.c:1311
void esp8266_reset_buf()
reset buf, e.g. after packet was processed
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
int index
Definition: command.h:13
uint8_t flags
Definition: command.h:23