smartconfig.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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_smartconfig.h"
  26. #include "smartconfig.h"
  27. static const char *TAG = "smartconfig";
  28. /* Flag to indicate sending smartconfig ACK or not. */
  29. static bool s_sc_ack_send = false;
  30. static int sc_ack_send_get_errno(int fd)
  31. {
  32. int sock_errno = 0;
  33. u32_t optlen = sizeof(sock_errno);
  34. getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
  35. return sock_errno;
  36. }
  37. static void sc_ack_send_task(void *pvParameters)
  38. {
  39. sc_ack_t *ack = (sc_ack_t *)pvParameters;
  40. tcpip_adapter_ip_info_t local_ip;
  41. uint8_t *remote_ip = ack->ctx.ip;
  42. int remote_port = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT;
  43. struct sockaddr_in server_addr;
  44. socklen_t sin_size = sizeof(server_addr);
  45. int send_sock = 0;
  46. int optval = 1;
  47. int sendlen;
  48. int ack_len = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN;
  49. uint8_t packet_count = 1;
  50. int err;
  51. int ret;
  52. bzero(&server_addr, sizeof(struct sockaddr_in));
  53. server_addr.sin_family = AF_INET;
  54. server_addr.sin_addr.s_addr = inet_addr((const char*)remote_ip);
  55. server_addr.sin_port = htons(remote_port);
  56. esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
  57. vTaskDelay(200 / portTICK_RATE_MS);
  58. while (s_sc_ack_send) {
  59. /* Get local IP address of station */
  60. ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip);
  61. if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) {
  62. /* If ESP touch, smartconfig ACK contains local IP address. */
  63. if (ack->type == SC_ACK_TYPE_ESPTOUCH) {
  64. memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
  65. }
  66. /* Create UDP socket. */
  67. send_sock = socket(AF_INET, SOCK_DGRAM, 0);
  68. if (send_sock < 0) {
  69. ESP_LOGE(TAG, "Creat udp socket failed");
  70. free(ack);
  71. vTaskDelete(NULL);
  72. }
  73. setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));
  74. while (s_sc_ack_send) {
  75. /* Send smartconfig ACK every 100ms. */
  76. vTaskDelay(100 / portTICK_RATE_MS);
  77. sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size);
  78. if (sendlen > 0) {
  79. /* Totally send 30 smartconfig ACKs. Then smartconfig is successful. */
  80. if (packet_count++ >= SC_ACK_MAX_COUNT) {
  81. if (ack->link_flag) {
  82. *ack->link_flag = 1;
  83. }
  84. if (ack->cb) {
  85. ack->cb(SC_STATUS_LINK_OVER, remote_ip);
  86. }
  87. close(send_sock);
  88. free(ack);
  89. vTaskDelete(NULL);
  90. }
  91. }
  92. else {
  93. err = sc_ack_send_get_errno(send_sock);
  94. if (err == ENOMEM || err == EAGAIN) {
  95. ESP_LOGD(TAG, "send failed, errno %d", err);
  96. continue;
  97. }
  98. ESP_LOGE(TAG, "send failed, errno %d", err);
  99. close(send_sock);
  100. free(ack);
  101. vTaskDelete(NULL);
  102. }
  103. }
  104. }
  105. else {
  106. vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
  107. }
  108. }
  109. free(ack);
  110. vTaskDelete(NULL);
  111. }
  112. void sc_ack_send(sc_ack_t *param)
  113. {
  114. sc_ack_t *ack = NULL;
  115. if (param == NULL) {
  116. ESP_LOGE(TAG, "Smart config ack parameter error");
  117. return;
  118. }
  119. ack = malloc(sizeof(sc_ack_t));
  120. if (ack == NULL) {
  121. ESP_LOGE(TAG, "Smart config ack parameter malloc fail");
  122. return;
  123. }
  124. memcpy(ack, param, sizeof(sc_ack_t));
  125. s_sc_ack_send = true;
  126. xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL);
  127. }
  128. void sc_ack_send_stop(void)
  129. {
  130. s_sc_ack_send = false;
  131. }