smartconfig_ack.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /*
  15. * After station connects to AP and gets IP address by smartconfig,
  16. * it will use UDP to send 'ACK' to cellphone.
  17. */
  18. #include <string.h>
  19. #include "freertos/FreeRTOS.h"
  20. #include "freertos/task.h"
  21. #include "lwip/sockets.h"
  22. #include "tcpip_adapter.h"
  23. #include "esp_log.h"
  24. #include "esp_wifi.h"
  25. #include "esp_event.h"
  26. #include "esp_smartconfig.h"
  27. #include "smartconfig_ack.h"
  28. #define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */
  29. #define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */
  30. #define SC_ACK_TOUCH_SERVER_PORT 18266 /*!< ESP touch UDP port of server on cellphone */
  31. #define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */
  32. #define SC_ACK_TOUCH_LEN 11 /*!< Length of ESP touch ACK context */
  33. #define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */
  34. #define SC_ACK_MAX_COUNT 30 /*!< Maximum count of sending smartconfig ACK */
  35. /**
  36. * @brief Smartconfig parameters passed to sc_ack_send call.
  37. */
  38. typedef struct sc_ack {
  39. smartconfig_type_t type; /*!< Smartconfig type(ESPTouch or AirKiss) */
  40. struct {
  41. uint8_t token; /*!< Smartconfig token from the cellphone */
  42. uint8_t mac[6]; /*!< MAC address of station */
  43. uint8_t ip[4]; /*!< IP address of cellphone */
  44. } ctx;
  45. } sc_ack_t;
  46. static const char *TAG = "smartconfig";
  47. /* Flag to indicate sending smartconfig ACK or not. */
  48. static bool s_sc_ack_send = false;
  49. static int sc_ack_send_get_errno(int fd)
  50. {
  51. int sock_errno = 0;
  52. u32_t optlen = sizeof(sock_errno);
  53. getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
  54. return sock_errno;
  55. }
  56. static void sc_ack_send_task(void *pvParameters)
  57. {
  58. sc_ack_t *ack = (sc_ack_t *)pvParameters;
  59. tcpip_adapter_ip_info_t local_ip;
  60. uint8_t remote_ip[4];
  61. if (ack->type == SC_TYPE_ESPTOUCH) {
  62. memcpy(remote_ip, ack->ctx.ip, sizeof(remote_ip));
  63. } else {
  64. memset(remote_ip, 255, 4);
  65. }
  66. int remote_port = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT;
  67. struct sockaddr_in server_addr;
  68. socklen_t sin_size = sizeof(server_addr);
  69. int send_sock = -1;
  70. int optval = 1;
  71. int sendlen;
  72. int ack_len = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN;
  73. uint8_t packet_count = 1;
  74. int err;
  75. int ret;
  76. bzero(&server_addr, sizeof(struct sockaddr_in));
  77. server_addr.sin_family = AF_INET;
  78. memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(remote_ip));
  79. server_addr.sin_port = htons(remote_port);
  80. esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
  81. vTaskDelay(200 / portTICK_RATE_MS);
  82. while (s_sc_ack_send) {
  83. /* Get local IP address of station */
  84. ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip);
  85. if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) {
  86. /* If ESP touch, smartconfig ACK contains local IP address. */
  87. if (ack->type == SC_TYPE_ESPTOUCH) {
  88. memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
  89. }
  90. /* Create UDP socket. */
  91. send_sock = socket(AF_INET, SOCK_DGRAM, 0);
  92. if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) {
  93. ESP_LOGE(TAG, "Creat udp socket failed");
  94. goto _end;
  95. }
  96. setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));
  97. while (s_sc_ack_send) {
  98. /* Send smartconfig ACK every 100ms. */
  99. vTaskDelay(100 / portTICK_RATE_MS);
  100. sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size);
  101. if (sendlen <= 0) {
  102. err = sc_ack_send_get_errno(send_sock);
  103. ESP_LOGD(TAG, "send failed, errno %d", err);
  104. vTaskDelay(100 / portTICK_RATE_MS);
  105. }
  106. /* Send 30 smartconfig ACKs. Then smartconfig is successful. */
  107. if (packet_count++ >= SC_ACK_MAX_COUNT) {
  108. esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY);
  109. goto _end;
  110. }
  111. }
  112. }
  113. else {
  114. vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
  115. }
  116. }
  117. _end:
  118. if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) {
  119. close(send_sock);
  120. }
  121. free(ack);
  122. vTaskDelete(NULL);
  123. }
  124. esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t *cellphone_ip)
  125. {
  126. sc_ack_t *ack = NULL;
  127. if (cellphone_ip == NULL) {
  128. ESP_LOGE(TAG, "Cellphone IP address is NULL");
  129. return ESP_ERR_INVALID_ARG;
  130. }
  131. ack = malloc(sizeof(sc_ack_t));
  132. if (ack == NULL) {
  133. ESP_LOGE(TAG, "ACK parameter malloc fail");
  134. return ESP_ERR_NO_MEM;
  135. }
  136. ack->type = type;
  137. ack->ctx.token = token;
  138. memcpy(ack->ctx.ip, cellphone_ip, 4);
  139. s_sc_ack_send = true;
  140. if (xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL) != pdPASS) {
  141. ESP_LOGE(TAG, "Create sending smartconfig ACK task fail");
  142. free(ack);
  143. return ESP_ERR_NO_MEM;
  144. }
  145. return ESP_OK;
  146. }
  147. void sc_send_ack_stop(void)
  148. {
  149. s_sc_ack_send = false;
  150. }