Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_esp8266.c
1 #include <bc_esp8266.h>
2 #include <bc_rtc.h>
3 
4 #define _BC_ESP8266_DELAY_INITIALIZATION_AT_COMMAND 100
5 #define _BC_ESP8266_DELAY_SEND_RESPONSE 100
6 #define _BC_ESP8266_DELAY_WIFI_CONNECT 1000
7 #define _BC_ESP8266_DELAY_SOCKET_CONNECT 300
8 #define _BC_ESP8266_TIMEOUT_WIFI_CONNECT 20
9 #define _BC_ESP8266_TIMEOUT_SOCKET_CONNECT 10
10 
11 // Apply changes to the factory configuration
12 static const char *_esp8266_init_commands[] =
13 {
14  // Disable AT Commands Echoing
15  "ATE0\r\n",
16  // Set Station mode
17  "AT+CWMODE=1\r\n",
18  // Disable Multiple Connections
19  "AT+CIPMUX=0\r\n",
20  // Does not Show the Remote IP and Port with +IPD
21  "AT+CIPDINFO=0\r\n",
22  // Disable Auto-Connect
23  "AT+CWAUTOCONN=0\r\n",
24  // Enable DHCP
25  "AT+CWDHCP=1,1\r\n",
26  // Sets the Size of SSL Buffer
27  "AT+CIPSSLSIZE=4096\r\n",
28  NULL
29 };
30 
31 static void _bc_esp8266_task(void *param);
32 static bool _bc_esp8266_read_response(bc_esp8266_t *self);
33 static bool _bc_esp8266_read_socket_data(bc_esp8266_t *self);
34 static void _uart_event_handler(bc_uart_channel_t channel, bc_uart_event_t event, void *param);
35 static void _bc_esp8266_set_rtc_time(char *str);
36 
38 {
39  memset(self, 0, sizeof(*self));
40 
41  self->_uart_channel = uart_channel;
42 
43  self->_config.mode = BC_ESP8266_CONFIG_MODE_STATION;
44  self->_config.ssid[0] = '\0';
45  self->_config.password[0] = '\0';
46  self->_config.sntp_enabled = 0;
47 
48  // CH_PD of ESP8266
52 
53  // RESET of ESP8266
57 
58  bc_fifo_init(&self->_tx_fifo, self->_tx_fifo_buffer, sizeof(self->_tx_fifo_buffer));
59  bc_fifo_init(&self->_rx_fifo, self->_rx_fifo_buffer, sizeof(self->_rx_fifo_buffer));
60 
62  bc_uart_set_async_fifo(self->_uart_channel, &self->_tx_fifo, &self->_rx_fifo);
63  bc_uart_async_read_start(self->_uart_channel, BC_TICK_INFINITY);
64  bc_uart_set_event_handler(self->_uart_channel, _uart_event_handler, self);
65 
66  self->_task_id = bc_scheduler_register(_bc_esp8266_task, self, BC_TICK_INFINITY);
67  self->_state = BC_ESP8266_STATE_DISCONNECTED;
68 }
69 
70 static void _uart_event_handler(bc_uart_channel_t channel, bc_uart_event_t event, void *param)
71 {
72  (void) channel;
73  bc_esp8266_t *self = (bc_esp8266_t*)param;
74 
75  if (event == BC_UART_EVENT_ASYNC_READ_DATA && self->_state == BC_ESP8266_STATE_IDLE)
76  {
77  bc_scheduler_plan_relative(self->_task_id, 100);
78  self->_state = BC_ESP8266_STATE_RECEIVE;
79  }
80 }
81 
82 void bc_esp8266_set_event_handler(bc_esp8266_t *self, void (*event_handler)(bc_esp8266_t *, bc_esp8266_event_t, void *), void *event_param)
83 {
84  self->_event_handler = event_handler;
85  self->_event_param = event_param;
86 }
87 
88 void bc_esp8266_set_station_mode(bc_esp8266_t *self, char *ssid, char *password)
89 {
90  self->_config.mode = BC_ESP8266_CONFIG_MODE_STATION;
91  strncpy(self->_config.ssid, ssid, 63);
92  strncpy(self->_config.password, password, 63);
93 }
94 
95 void bc_esp8266_set_sntp(bc_esp8266_t *self, int timezone)
96 {
97  bc_esp8266_set_sntp_with_servers(self, timezone, NULL, NULL, NULL);
98 }
99 
100 void bc_esp8266_set_sntp_with_servers(bc_esp8266_t *self, int timezone, char *sntp_server1, char *sntp_server2, char *sntp_server3)
101 {
102  self->_config.sntp_enabled = 1;
103  self->_config.sntp_timezone = timezone;
104  if (sntp_server1 != NULL)
105  {
106  strncpy(self->_config.sntp_server1, sntp_server1, 127);
107  }
108  else
109  {
110  strcpy(self->_config.sntp_server1, "0.pool.ntp.org");
111  }
112  if (sntp_server2 != NULL)
113  {
114  strncpy(self->_config.sntp_server2, sntp_server2, 127);
115  }
116  else
117  {
118  strcpy(self->_config.sntp_server2, "1.pool.ntp.org");
119  }
120  if (sntp_server3 != NULL)
121  {
122  strncpy(self->_config.sntp_server3, sntp_server3, 127);
123  }
124  else
125  {
126  strcpy(self->_config.sntp_server3, "2.pool.ntp.org");
127  }
128 }
129 
131 {
132  if (self->_state == BC_ESP8266_STATE_READY || self->_state == BC_ESP8266_STATE_IDLE)
133  {
134  return true;
135  }
136 
137  return false;
138 }
139 
141 {
142  if (self->_state != BC_ESP8266_STATE_DISCONNECTED ||
143  self->_config.ssid[0] == '\0' || self->_config.password[0] == '\0')
144  {
145  return false;
146  }
147 
148  // Enable CH_PD
150 
151  self->_state = BC_ESP8266_STATE_INITIALIZE;
152 
153  bc_scheduler_plan_now(self->_task_id);
154 
155  return true;
156 }
157 
159 {
160  // Disable CH_PD
162 
163  self->_state = BC_ESP8266_STATE_DISCONNECTED;
164 
165  return true;
166 }
167 
168 bool bc_esp8266_socket_connect(bc_esp8266_t *self, const char *type, const char *host, uint16_t port)
169 {
170  if (!bc_esp8266_is_ready(self) || host == NULL || port == 0 || strlen(host) == 0 ||
171  (strlen(host) + 15) > BC_ESP8266_TX_MAX_PACKET_SIZE)
172  {
173  return false;
174  }
175 
176  static char buffer[BC_ESP8266_TX_MAX_PACKET_SIZE];
177  sprintf(buffer, "\"%s\",\"%s\",%d", type, host, port);
178 
179  self->_message_length = strlen(buffer);
180 
181  memcpy(self->_message_buffer, buffer, self->_message_length);
182 
183  self->_state = BC_ESP8266_STATE_SOCKET_CONNECT_COMMAND;
184 
185  bc_scheduler_plan_now(self->_task_id);
186 
187  return true;
188 }
189 
190 bool bc_esp8266_tcp_connect(bc_esp8266_t *self, const char *host, uint16_t port)
191 {
192  return bc_esp8266_socket_connect(self, "TCP", host, port);
193 }
194 
195 bool bc_esp8266_udp_connect(bc_esp8266_t *self, const char *host, uint16_t port)
196 {
197  return bc_esp8266_socket_connect(self, "UDP", host, port);
198 }
199 
200 bool bc_esp8266_ssl_connect(bc_esp8266_t *self, const char *host, uint16_t port)
201 {
202  return bc_esp8266_socket_connect(self, "SSL", host, port);
203 }
204 
205 bool bc_esp8266_send_data(bc_esp8266_t *self, const void *buffer, size_t length)
206 {
207  if (!bc_esp8266_is_ready(self) || length == 0 || length > BC_ESP8266_TX_MAX_PACKET_SIZE)
208  {
209  return false;
210  }
211 
212  self->_message_length = length;
213 
214  memcpy(self->_message_buffer, buffer, self->_message_length);
215 
216  self->_state = BC_ESP8266_STATE_SOCKET_SEND_COMMAND;
217 
218  bc_scheduler_plan_now(self->_task_id);
219 
220  return true;
221 }
222 
223 static void _bc_esp8266_task(void *param)
224 {
225  bc_esp8266_t *self = param;
226 
227  while (true)
228  {
229  switch (self->_state)
230  {
231  case BC_ESP8266_STATE_READY:
232  {
233  self->_state = BC_ESP8266_STATE_IDLE;
234 
235  if (self->_event_handler != NULL)
236  {
237  self->_event_handler(self, BC_ESP8266_EVENT_READY, self->_event_param);
238  }
239 
240  continue;
241  }
242  case BC_ESP8266_STATE_IDLE:
243  case BC_ESP8266_STATE_DISCONNECTED:
244  {
245  return;
246  }
247  case BC_ESP8266_STATE_RECEIVE:
248  {
249  self->_state = BC_ESP8266_STATE_IDLE;
250 
251  while (_bc_esp8266_read_response(self))
252  {
253  if (memcmp(self->_response, "+IPD", 4) == 0)
254  {
255  // Data length is between "," and ":"
256  char *comma_search = strchr(self->_response, ',');
257  if (comma_search == NULL)
258  {
259  continue;
260  }
261  comma_search++;
262  char *colon_search = strchr(self->_response, ':');
263  if (colon_search == NULL)
264  {
265  continue;
266  }
267  if ((colon_search - comma_search) > 9)
268  {
269  continue;
270  }
271  char length_text[10];
272  memcpy(length_text, comma_search, colon_search - comma_search);
273  length_text[colon_search - comma_search] = '\0';
274  self->_message_length = atoi(length_text);
275 
276  self->_message_part_length = (strlen(self->_response) - 1) - (colon_search - self->_response);
277  colon_search++;
278  memcpy(self->_message_buffer, colon_search, self->_message_part_length);
279 
280  if (self->_message_length > sizeof(self->_message_buffer))
281  {
282  self->_message_length = sizeof(self->_message_buffer);
283  }
284 
285  self->_state = BC_ESP8266_STATE_SOCKET_RECEIVE;
286 
288  return;
289  }
290  }
291 
292  return;
293  }
294  case BC_ESP8266_STATE_ERROR:
295  {
296  if (self->_event_handler != NULL)
297  {
298  self->_event_handler(self, BC_ESP8266_EVENT_ERROR, self->_event_param);
299  }
300 
301  self->_state = BC_ESP8266_STATE_INITIALIZE;
302 
303  continue;
304  }
305  case BC_ESP8266_STATE_INITIALIZE:
306  {
307  self->_init_command_index = 0;
308  self->_state = BC_ESP8266_STATE_INITIALIZE_COMMAND_SEND;
309 
310  continue;
311  }
312  case BC_ESP8266_STATE_INITIALIZE_COMMAND_SEND:
313  {
314  self->_state = BC_ESP8266_STATE_ERROR;
315 
316  // Purge RX FIFO
317  char rx_character;
318  while (bc_uart_async_read(self->_uart_channel, &rx_character, 1) != 0)
319  {
320  }
321 
322  strcpy(self->_command, _esp8266_init_commands[self->_init_command_index]);
323  size_t length = strlen(self->_command);
324 
325  if (bc_uart_async_write(self->_uart_channel, self->_command, length) != length)
326  {
327  continue;
328  }
329 
330  self->_state = BC_ESP8266_STATE_INITIALIZE_COMMAND_RESPONSE;
331  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_INITIALIZATION_AT_COMMAND);
332 
333  return;
334  }
335  case BC_ESP8266_STATE_INITIALIZE_COMMAND_RESPONSE:
336  {
337  self->_state = BC_ESP8266_STATE_ERROR;
338 
339  if (!_bc_esp8266_read_response(self))
340  {
341  continue;
342  }
343 
344  // repeated command, continue reading response
345  if (memcmp(self->_response, "AT", 2) == 0 && !_bc_esp8266_read_response(self))
346  {
347  continue;
348  }
349 
350  if (memcmp(self->_response, "OK", 2) != 0)
351  {
352  continue;
353  }
354 
355  self->_init_command_index++;
356 
357  if (_esp8266_init_commands[self->_init_command_index] == NULL)
358  {
359  self->_state = BC_ESP8266_STATE_WIFI_CONNECT_COMMAND;
360  }
361  else
362  {
363  self->_state = BC_ESP8266_STATE_INITIALIZE_COMMAND_SEND;
364  }
365 
366  continue;
367  }
368  case BC_ESP8266_STATE_WIFI_CONNECT_COMMAND:
369  case BC_ESP8266_STATE_SNTP_CONFIG_COMMAND:
370  case BC_ESP8266_STATE_SNTP_TIME_COMMAND:
371  case BC_ESP8266_STATE_SOCKET_CONNECT_COMMAND:
372  case BC_ESP8266_STATE_SOCKET_SEND_COMMAND:
373  {
374  bc_esp8266_state_t response_state;
375 
376  if (self->_state == BC_ESP8266_STATE_WIFI_CONNECT_COMMAND)
377  {
378  sprintf(self->_command, "AT+CWJAP_CUR=\"%s\",\"%s\"\r\n", self->_config.ssid, self->_config.password);
379  response_state = BC_ESP8266_STATE_WIFI_CONNECT_RESPONSE;
380  }
381  else if (self->_state == BC_ESP8266_STATE_SNTP_CONFIG_COMMAND)
382  {
383  sprintf(self->_command, "AT+CIPSNTPCFG=%u,%d,\"%s\",\"%s\",\"%s\"\r\n",
384  self->_config.sntp_enabled,
385  self->_config.sntp_timezone,
386  self->_config.sntp_server1,
387  self->_config.sntp_server2,
388  self->_config.sntp_server3);
389  response_state = BC_ESP8266_STATE_SNTP_CONFIG_RESPONSE;
390  }
391  else if (self->_state == BC_ESP8266_STATE_SNTP_TIME_COMMAND)
392  {
393  strcpy(self->_command, "AT+CIPSNTPTIME?\r\n");
394  response_state = BC_ESP8266_STATE_SNTP_TIME_RESPONSE;
395  }
396  else if (self->_state == BC_ESP8266_STATE_SOCKET_CONNECT_COMMAND)
397  {
398  strcpy(self->_command, "AT+CIPSTART=");
399  response_state = BC_ESP8266_STATE_SOCKET_CONNECT_RESPONSE;
400  }
401  else
402  {
403  sprintf(self->_command, "AT+CIPSEND=%d\r\n", self->_message_length);
404  response_state = BC_ESP8266_STATE_SOCKET_SEND_DATA;
405  }
406 
407  self->_state = BC_ESP8266_STATE_ERROR;
408 
409  uint8_t command_length = strlen(self->_command);
410  size_t length = command_length;
411 
412  if (response_state == BC_ESP8266_STATE_SOCKET_CONNECT_RESPONSE)
413  {
414  for (size_t i = 0; i < self->_message_length; i++)
415  {
416  // put binary data directly to the "string" buffer
417  self->_command[command_length + i] = self->_message_buffer[i];
418  }
419  self->_command[command_length + self->_message_length] = '\r';
420  self->_command[command_length + self->_message_length + 1] = '\n';
421 
422  length = command_length + self->_message_length + 2;
423  }
424 
425  if (bc_uart_async_write(self->_uart_channel, self->_command, length) != length)
426  {
427  continue;
428  }
429 
430  self->_state = response_state;
431  self->_timeout_cnt = 0;
432 
433  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_SEND_RESPONSE);
434 
435  return;
436  }
437  case BC_ESP8266_STATE_SOCKET_SEND_DATA:
438  {
439  self->_state = BC_ESP8266_STATE_ERROR;
440 
441  if (bc_uart_async_write(self->_uart_channel, self->_message_buffer, self->_message_length) != self->_message_length)
442  {
443  continue;
444  }
445 
446  self->_state = BC_ESP8266_STATE_SOCKET_SEND_RESPONSE;
447 
448  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_SEND_RESPONSE);
449 
450  return;
451  }
452  case BC_ESP8266_STATE_WIFI_CONNECT_RESPONSE:
453  {
454  /*
455  Success response:
456  WIFI DISCONNECT
457  WIFI CONNECTED
458  WIFI GOT IP
459 
460  OK
461  */
462 
463  self->_timeout_cnt++;
464  if (self->_timeout_cnt > _BC_ESP8266_TIMEOUT_WIFI_CONNECT)
465  {
466  self->_state = BC_ESP8266_STATE_WIFI_CONNECT_ERROR;
467  continue;
468  }
469 
470  if (!_bc_esp8266_read_response(self))
471  {
472  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_WIFI_CONNECT);
473  return;
474  }
475 
476  if (strcmp(self->_response, "OK\r") == 0)
477  {
478  if (self->_config.sntp_enabled)
479  {
480  self->_state = BC_ESP8266_STATE_SNTP_CONFIG_COMMAND;
481  }
482  else
483  {
484  self->_state = BC_ESP8266_STATE_READY;
485  if (self->_event_handler != NULL)
486  {
487  self->_event_handler(self, BC_ESP8266_EVENT_WIFI_CONNECT_SUCCESS, self->_event_param);
488  }
489  }
490  }
491  else if (strcmp(self->_response, "FAIL\r") == 0)
492  {
493  self->_state = BC_ESP8266_STATE_WIFI_CONNECT_ERROR;
494  }
495  else
496  {
497  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_WIFI_CONNECT);
498  return;
499  }
500 
501  continue;
502  }
503  case BC_ESP8266_STATE_WIFI_CONNECT_ERROR:
504  {
505  self->_state = BC_ESP8266_STATE_DISCONNECTED;
506 
507  if (self->_event_handler != NULL)
508  {
509  self->_event_handler(self, BC_ESP8266_EVENT_WIFI_CONNECT_ERROR, self->_event_param);
510  }
511 
512  continue;
513  }
514  case BC_ESP8266_STATE_SNTP_CONFIG_RESPONSE:
515  {
516  self->_state = BC_ESP8266_STATE_ERROR;
517 
518  if (!_bc_esp8266_read_response(self))
519  {
520  continue;
521  }
522 
523  if (memcmp(self->_response, "OK", 2) != 0)
524  {
525  continue;
526  }
527 
528  self->_state = BC_ESP8266_STATE_SNTP_TIME_COMMAND;
529 
530  continue;
531  }
532  case BC_ESP8266_STATE_SNTP_TIME_RESPONSE:
533  {
534  /*
535  Success response:
536  +CIPSNTPTIME:Sun Jul 21 12:02:06 2019
537  OK
538  */
539 
540  self->_timeout_cnt++;
541  if (self->_timeout_cnt > _BC_ESP8266_TIMEOUT_WIFI_CONNECT)
542  {
543  self->_state = BC_ESP8266_STATE_WIFI_CONNECT_ERROR;
544  continue;
545  }
546 
547  if (!_bc_esp8266_read_response(self))
548  {
549  continue;
550  }
551 
552  if (strcmp(self->_response, "OK\r") == 0)
553  {
554  self->_state = BC_ESP8266_STATE_READY;
555  if (self->_event_handler != NULL)
556  {
557  self->_event_handler(self, BC_ESP8266_EVENT_WIFI_CONNECT_SUCCESS, self->_event_param);
558  }
559  }
560  else if (memcmp(self->_response, "+CIPSNTPTIME:", 13) == 0)
561  {
562  _bc_esp8266_set_rtc_time(self->_response + 13);
563  }
564 
565  continue;
566  }
567  case BC_ESP8266_STATE_SOCKET_CONNECT_RESPONSE:
568  {
569  /*
570  Success response:
571  CONNECT
572 
573  OK
574  */
575 
576  self->_timeout_cnt++;
577  if (self->_timeout_cnt > _BC_ESP8266_TIMEOUT_SOCKET_CONNECT)
578  {
579  self->_state = BC_ESP8266_STATE_SOCKET_CONNECT_ERROR;
580  continue;
581  }
582 
583  if (!_bc_esp8266_read_response(self))
584  {
585  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_SOCKET_CONNECT);
586  return;
587  }
588 
589  if (strcmp(self->_response, "OK\r") == 0)
590  {
591  self->_state = BC_ESP8266_STATE_READY;
592  if (self->_event_handler != NULL)
593  {
594  self->_event_handler(self, BC_ESP8266_EVENT_SOCKET_CONNECT_SUCCESS, self->_event_param);
595  }
596  }
597  else if (strcmp(self->_response, "ERROR\r") == 0)
598  {
599  self->_state = BC_ESP8266_STATE_SOCKET_CONNECT_ERROR;
600  }
601  else
602  {
603  bc_scheduler_plan_current_from_now(_BC_ESP8266_DELAY_SOCKET_CONNECT);
604  return;
605  }
606 
607  continue;
608  }
609  case BC_ESP8266_STATE_SOCKET_CONNECT_ERROR:
610  {
611  self->_state = BC_ESP8266_STATE_READY;
612 
613  if (self->_event_handler != NULL)
614  {
615  self->_event_handler(self, BC_ESP8266_EVENT_SOCKET_CONNECT_ERROR, self->_event_param);
616  }
617 
618  continue;
619  }
620  case BC_ESP8266_STATE_SOCKET_SEND_RESPONSE:
621  {
622  self->_state = BC_ESP8266_STATE_SOCKET_SEND_ERROR;
623 
624  if (!_bc_esp8266_read_response(self))
625  {
626  continue;
627  }
628 
629  if (strcmp(self->_response, "OK\r") != 0)
630  {
631  continue;
632  }
633 
634  self->_state = BC_ESP8266_STATE_RECEIVE;
635 
636  if (self->_event_handler != NULL)
637  {
638  self->_event_handler(self, BC_ESP8266_EVENT_SOCKET_SEND_SUCCESS, self->_event_param);
639  }
640 
641  continue;
642  }
643  case BC_ESP8266_STATE_SOCKET_SEND_ERROR:
644  {
645  self->_state = BC_ESP8266_STATE_READY;
646 
647  if (self->_event_handler != NULL)
648  {
649  self->_event_handler(self, BC_ESP8266_EVENT_SOCKET_SEND_ERROR, self->_event_param);
650  }
651 
652  continue;
653  }
654  case BC_ESP8266_STATE_SOCKET_RECEIVE:
655  {
656  if (!_bc_esp8266_read_socket_data(self))
657  {
658  continue;
659  }
660 
661  self->_state = BC_ESP8266_STATE_READY;
662 
663  if (self->_event_handler != NULL)
664  {
665  self->_event_handler(self, BC_ESP8266_EVENT_DATA_RECEIVED, self->_event_param);
666  }
667 
668  continue;
669  }
670  default:
671  {
672  break;
673  }
674  }
675  }
676 }
677 
679 {
680  return self->_message_length;
681 }
682 
683 uint32_t bc_esp8266_get_received_message_data(bc_esp8266_t *self, uint8_t *buffer, uint32_t buffer_size)
684 {
685  if (self->_message_length > buffer_size)
686  {
687  return 0;
688  }
689 
690  memcpy(buffer, self->_message_buffer, self->_message_length);
691 
692  return self->_message_length;
693 }
694 
695 static bool _bc_esp8266_read_response(bc_esp8266_t *self)
696 {
697  size_t length = 0;
698 
699  while (true)
700  {
701  char rx_character;
702 
703  if (bc_uart_async_read(self->_uart_channel, &rx_character, 1) == 0)
704  {
705  return false;
706  }
707 
708  if (rx_character == '\n')
709  {
710  continue;
711  }
712 
713  self->_response[length++] = rx_character;
714 
715  if (rx_character == '\r')
716  {
717  if (length == 1)
718  {
719  length = 0;
720 
721  continue;
722  }
723 
724  self->_response[length] = '\0';
725 
726  break;
727  }
728 
729  if (length == sizeof(self->_response) - 1)
730  {
731  return false;
732  }
733  }
734 
735  return true;
736 }
737 
738 static bool _bc_esp8266_read_socket_data(bc_esp8266_t *self)
739 {
740  while (true)
741  {
742  char rx_character;
743 
744  if (bc_uart_async_read(self->_uart_channel, &rx_character, 1) == 0)
745  {
746  return false;
747  }
748 
749  self->_message_buffer[self->_message_part_length++] = rx_character;
750 
751  if (self->_message_part_length == self->_message_length)
752  {
753  break;
754  }
755  }
756 
757  return true;
758 }
759 
760 static void _bc_esp8266_set_rtc_time(char *str)
761 {
762  bc_rtc_t rtc;
763  char token[5];
764  uint8_t j = 0;
765  uint8_t state = 0;
766  size_t length = strlen(str);
767  for (size_t i = 0; i <= length; i++)
768  {
769  char c = str[i];
770  if (c == ' ' || c == ':' || c == '\0' || j == 4)
771  {
772  token[j] = '\0';
773 
774  // Month
775  if (state == 1)
776  {
777  if (strcmp(token, "Jan") == 0)
778  {
779  rtc.month = 1;
780  }
781  else if (strcmp(token, "Feb") == 0)
782  {
783  rtc.month = 2;
784  }
785  else if (strcmp(token, "Mar") == 0)
786  {
787  rtc.month = 3;
788  }
789  else if (strcmp(token, "Apr") == 0)
790  {
791  rtc.month = 4;
792  }
793  else if (strcmp(token, "May") == 0)
794  {
795  rtc.month = 5;
796  }
797  else if (strcmp(token, "Jun") == 0)
798  {
799  rtc.month = 6;
800  }
801  else if (strcmp(token, "Jul") == 0)
802  {
803  rtc.month = 7;
804  }
805  else if (strcmp(token, "Aug") == 0)
806  {
807  rtc.month = 8;
808  }
809  else if (strcmp(token, "Sep") == 0)
810  {
811  rtc.month = 9;
812  }
813  else if (strcmp(token, "Oct") == 0)
814  {
815  rtc.month = 10;
816  }
817  else if (strcmp(token, "Nov") == 0)
818  {
819  rtc.month = 11;
820  }
821  else if (strcmp(token, "Dec") == 0)
822  {
823  rtc.month = 12;
824  }
825  }
826  // Day
827  else if (state == 2)
828  {
829  rtc.date = atoi(token);
830  }
831  // Hours
832  else if (state == 3)
833  {
834  rtc.hours = atoi(token);
835  }
836  // Minutes
837  else if (state == 4)
838  {
839  rtc.minutes = atoi(token);
840  }
841  // Seconds
842  else if (state == 5)
843  {
844  rtc.seconds = atoi(token);
845  }
846  // Year
847  else if (state == 6)
848  {
849  if (strcmp(token, "1970") == 0)
850  {
851  return;
852  }
853  rtc.year = atoi(token);
854  }
855 
856  j = 0;
857  state++;
858  }
859  else
860  {
861  token[j++] = c;
862  }
863  }
864  bc_rtc_set_date_time(&rtc);
865 }
void bc_esp8266_set_station_mode(bc_esp8266_t *self, char *ssid, char *password)
Set station mode.
Definition: bc_esp8266.c:88
Ready event.
Definition: bc_esp8266.h:26
bc_uart_channel_t
UART channels.
Definition: bc_uart.h:13
uint8_t seconds
Seconds parameter, from 00 to 59.
Definition: bc_rtc.h:17
uint8_t hours
Hours parameter, 24Hour mode, 00 to 23.
Definition: bc_rtc.h:20
bool bc_esp8266_disconnect(bc_esp8266_t *self)
Disable ESP8266 and disconnect.
Definition: bc_esp8266.c:158
bc_esp8266_event_t
Callback events.
Definition: bc_esp8266.h:23
Error event.
Definition: bc_esp8266.h:29
uint32_t bc_esp8266_get_received_message_length(bc_esp8266_t *self)
Get length of the received message.
Definition: bc_esp8266.c:678
bool bc_uart_async_read_start(bc_uart_channel_t channel, bc_tick_t timeout)
Start async reading.
Definition: bc_uart.c:475
uint32_t bc_esp8266_get_received_message_data(bc_esp8266_t *self, uint8_t *buffer, uint32_t buffer_size)
Get received message data.
Definition: bc_esp8266.c:683
Event is reading done.
Definition: bc_uart.h:133
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_esp8266_set_event_handler(bc_esp8266_t *self, void(*event_handler)(bc_esp8266_t *, bc_esp8266_event_t, void *), void *event_param)
Set callback function.
Definition: bc_esp8266.c:82
8N1: 8 data bits, none parity bit, 1 stop bit
Definition: bc_uart.h:70
void bc_scheduler_plan_now(bc_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
Definition: bc_scheduler.c:119
bool bc_esp8266_udp_connect(bc_esp8266_t *self, const char *host, uint16_t port)
Establish UDP Connection.
Definition: bc_esp8266.c:195
void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
bool bc_esp8266_ssl_connect(bc_esp8266_t *self, const char *host, uint16_t port)
Establish SSL Connection.
Definition: bc_esp8266.c:200
void bc_gpio_set_mode(bc_gpio_channel_t channel, bc_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: bc_gpio.c:340
bool bc_esp8266_send_data(bc_esp8266_t *self, const void *buffer, size_t length)
Send data.
Definition: bc_esp8266.c:205
void bc_uart_init(bc_uart_channel_t channel, bc_uart_baudrate_t baudrate, bc_uart_setting_t setting)
Initialize UART channel.
Definition: bc_uart.c:53
bc_uart_event_t
Callback events.
Definition: bc_uart.h:127
GPIO channel P8.
Definition: bc_gpio.h:39
void bc_esp8266_set_sntp(bc_esp8266_t *self, int timezone)
Enable SNTP and set time zone.
Definition: bc_esp8266.c:95
void bc_fifo_init(bc_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
Definition: bc_fifo.c:4
GPIO channel P6.
Definition: bc_gpio.h:33
bool bc_esp8266_connect(bc_esp8266_t *self)
Enable ESP8266 and connect to WiFi.
Definition: bc_esp8266.c:140
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
uint8_t minutes
Minutes parameter, from 00 to 59.
Definition: bc_rtc.h:19
uint8_t month
Month in a year, 1 to 12.
Definition: bc_rtc.h:23
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
size_t bc_uart_async_write(bc_uart_channel_t channel, const void *buffer, size_t length)
Add data to be transmited in async mode.
Definition: bc_uart.c:428
void bc_uart_set_async_fifo(bc_uart_channel_t channel, bc_fifo_t *write_fifo, bc_fifo_t *read_fifo)
Set buffers for async transfers.
Definition: bc_uart.c:422
void bc_uart_set_event_handler(bc_uart_channel_t channel, void(*event_handler)(bc_uart_channel_t, bc_uart_event_t, void *), void *event_param)
Set callback function.
Definition: bc_uart.c:416
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
size_t bc_uart_async_read(bc_uart_channel_t channel, void *buffer, size_t length)
Get data that has been received in async mode.
Definition: bc_uart.c:571
void bc_esp8266_init(bc_esp8266_t *self, bc_uart_channel_t uart_channel)
Initialize ESP8266.
Definition: bc_esp8266.c:37
bool bc_esp8266_tcp_connect(bc_esp8266_t *self, const char *host, uint16_t port)
Establish TCP Connection.
Definition: bc_esp8266.c:190
UART baudrat 115200 bps.
Definition: bc_uart.h:43
uint8_t date
Date in a month, 1 to 31.
Definition: bc_rtc.h:22
bool bc_rtc_set_date_time(bc_rtc_t *rtc)
Set gate and time to RTC.
Definition: bc_rtc.c:77
void bc_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
Definition: bc_scheduler.c:139
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
uint16_t year
Year parameter, 2000 to 2099.
Definition: bc_rtc.h:24
RTC date and time structure.
Definition: bc_rtc.h:15
GPIO channel operates as output.
Definition: bc_gpio.h:102
void bc_esp8266_set_sntp_with_servers(bc_esp8266_t *self, int timezone, char *sntp_server1, char *sntp_server2, char *sntp_server3)
Enable SNTP and set configuration.
Definition: bc_esp8266.c:100
bool bc_esp8266_is_ready(bc_esp8266_t *self)
Check if modem is ready for commands.
Definition: bc_esp8266.c:130