]> granicus.if.org Git - esp-idf/commitdiff
Refractor smartconfig
authorXiaXiaotian <xiaxiaotian@espressif.com>
Wed, 13 Sep 2017 08:42:45 +0000 (16:42 +0800)
committerXiaXiaotian <xiaxiaotian@espressif.com>
Wed, 13 Sep 2017 08:55:30 +0000 (16:55 +0800)
    Move code of receiving smartconfig packets and getting password to
    wifi lib. Open source code of sending smartconfig ACK to cellphone
    in IDF.

components/esp32/smartconfig.c [new file with mode: 0644]
components/esp32/smartconfig.h [new file with mode: 0644]

diff --git a/components/esp32/smartconfig.c b/components/esp32/smartconfig.c
new file mode 100644 (file)
index 0000000..a0636d0
--- /dev/null
@@ -0,0 +1,154 @@
+// Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+ * After station connects to AP and gets IP address by smartconfig,
+ * it will use UDP to send 'ACK' to cellphone.
+ */
+
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "lwip/sockets.h"
+#include "tcpip_adapter.h"
+#include "esp_log.h"
+#include "esp_wifi.h"
+#include "esp_smartconfig.h"
+#include "smartconfig.h"
+
+static const char *TAG = "smartconfig";
+
+/* Flag to indicate sending smartconfig ACK or not. */
+static bool s_sc_ack_send = false;
+
+static int sc_ack_send_get_errno(int fd)
+{
+    int sock_errno = 0;
+    u32_t optlen = sizeof(sock_errno);
+
+    getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
+
+    return sock_errno;
+}
+
+static void sc_ack_send_task(void *pvParameters)
+{
+    sc_ack_t *ack = (sc_ack_t *)pvParameters;
+    tcpip_adapter_ip_info_t local_ip;
+    uint8_t *remote_ip = ack->ctx.ip;
+    int remote_port = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT;
+    struct sockaddr_in server_addr;
+    socklen_t sin_size = sizeof(server_addr);
+    int send_sock = 0;
+    int optval = 1;
+    int sendlen;
+    int ack_len = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN;
+    uint8_t packet_count = 1;
+    int err;
+    int ret;
+
+    bzero(&server_addr, sizeof(struct sockaddr_in));
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_addr.s_addr = inet_addr((const char*)remote_ip);
+    server_addr.sin_port = htons(remote_port);
+
+    esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
+
+    vTaskDelay(200 / portTICK_RATE_MS);
+
+    while (s_sc_ack_send) {
+        /* Get local IP address of station */
+        ret = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &local_ip);
+        if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) {
+            /* If ESP touch, smartconfig ACK contains local IP address. */
+            if (ack->type == SC_ACK_TYPE_ESPTOUCH) {
+                memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
+            }
+
+            /* Create UDP socket. */
+            send_sock = socket(AF_INET, SOCK_DGRAM, 0);
+            if (send_sock < 0) {
+                ESP_LOGE(TAG,  "Creat udp socket failed");
+                free(ack);
+                vTaskDelete(NULL);
+            }
+
+            setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));
+
+            while (s_sc_ack_send) {
+                /* Send smartconfig ACK every 100ms. */
+                vTaskDelay(100 / portTICK_RATE_MS);
+
+                sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size);
+                if (sendlen > 0) {
+                    /* Totally send 30 smartconfig ACKs. Then smartconfig is successful. */
+                    if (packet_count++ >= SC_ACK_MAX_COUNT) {
+                        if (ack->link_flag) {
+                            *ack->link_flag = 1;
+                        }
+                        if (ack->cb) {
+                            ack->cb(SC_STATUS_LINK_OVER, remote_ip);
+                        }
+                        close(send_sock);
+                        free(ack);
+                        vTaskDelete(NULL);
+                    }
+                }
+                else {
+                    err = sc_ack_send_get_errno(send_sock);
+                    if (err == ENOMEM || err == EAGAIN) {
+                        ESP_LOGD(TAG, "send failed, errno %d", err);
+                        continue;
+                    }
+                    ESP_LOGE(TAG, "send failed, errno %d", err);
+                    close(send_sock);
+                    free(ack);
+                    vTaskDelete(NULL);
+                }
+            }
+        }
+        else {
+            vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
+        }
+    }
+
+    free(ack);
+    vTaskDelete(NULL);
+}
+
+void sc_ack_send(sc_ack_t *param)
+{
+    sc_ack_t *ack = NULL;
+
+    if (param == NULL) {
+        ESP_LOGE(TAG, "Smart config ack parameter error");
+        return;
+    }
+
+    ack = malloc(sizeof(sc_ack_t));
+    if (ack == NULL) {
+        ESP_LOGE(TAG, "Smart config ack parameter malloc fail");
+        return;
+    }
+    memcpy(ack, param, sizeof(sc_ack_t));
+
+    s_sc_ack_send = true;
+
+    xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL);
+}
+
+void sc_ack_send_stop(void)
+{
+    s_sc_ack_send = false;
+}
diff --git a/components/esp32/smartconfig.h b/components/esp32/smartconfig.h
new file mode 100644 (file)
index 0000000..1723a77
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SMARTCONFIG_H
+#define SMARTCONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SC_ACK_TASK_PRIORITY             2          /*!< Priority of sending smartconfig ACK task */
+#define SC_ACK_TASK_STACK_SIZE           2048       /*!< Stack size of sending smartconfig ACK task */
+
+#define SC_ACK_TOUCH_SERVER_PORT         18266      /*!< ESP touch UDP port of server on cellphone */
+#define SC_ACK_AIRKISS_SERVER_PORT       10000      /*!< Airkiss UDP port of server on cellphone */
+
+#define SC_ACK_TOUCH_LEN                 11         /*!< Length of ESP touch ACK context */
+#define SC_ACK_AIRKISS_LEN               7          /*!< Length of Airkiss ACK context */
+
+#define SC_ACK_MAX_COUNT                 30         /*!< Maximum count of sending smartconfig ACK */
+
+/**
+ * @brief Smartconfig ACK type.
+ */
+typedef enum {
+    SC_ACK_TYPE_ESPTOUCH = 0,                       /*!< ESP touch ACK type */
+    SC_ACK_TYPE_AIRKISS,                            /*!< Airkiss ACK type */
+} sc_ack_type_t;
+
+/**
+ * @brief Smartconfig parameters passed to sc_ack_send call.
+ */
+typedef struct sc_ack {
+    sc_ack_type_t type;           /*!< Smartconfig ACK type */
+    uint8_t *link_flag;           /*!< Smartconfig link flag */
+    sc_callback_t cb;             /*!< Smartconfig callback function */
+    struct {
+        uint8_t token;            /*!< Smartconfig token to be sent */
+        uint8_t mac[6];           /*!< MAC address of station */
+        uint8_t ip[4];            /*!< IP address of cellphone */
+    } ctx;
+} sc_ack_t;
+
+/**
+  * @brief  Send smartconfig ACK to cellphone.
+  *
+  * @attention The API is only used in libsmartconfig.a.
+  *
+  * @param  param: smartconfig parameters;
+  */
+void sc_ack_send(sc_ack_t *param);
+
+/**
+  * @brief  Stop sending smartconfig ACK to cellphone.
+  *
+  * @attention The API is only used in libsmartconfig.a.
+  */
+void sc_ack_send_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif