espressif / ESP8266_RTOS_SDK

Latest ESP8266 SDK based on FreeRTOS, esp-idf style.
http://bbs.espressif.com
Apache License 2.0
3.34k stars 1.56k forks source link

使用微信配网。提示smartconfig: send failed, errno 0 (GIT8266O-620) #1043

Open hessonsu opened 3 years ago

hessonsu commented 3 years ago

ESP-IDF v3.4-dev-435-g89a3f254-dirty 2nd stage bootloader 操作步骤:关系安信可公众号,微信配网菜单进入配网。 偶尔:提示smartconfig: send failed, errno 0,微信端提示配网完成。

hessonsu commented 3 years ago

hi~~~,我测试发现。 在smartconfig_ack.c 的方法sc_ack_send_task中 我修改了这个方法。


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[4];
    memset(remote_ip, 0xFF, sizeof(remote_ip));
    struct sockaddr_in server_addr;
    socklen_t sin_size = sizeof(server_addr);
    int send_sock = -1;
    int optval = 1;
    int sendlen;
    int ack_len = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN;
    uint8_t packet_count = 1;
    int err;
    int ret;
    int remote_port = 0;

    if (ack->type == SC_TYPE_ESPTOUCH) {
        remote_port = SC_ACK_TOUCH_SERVER_PORT;
    } else if (ack->type == SC_TYPE_ESPTOUCH_V2) {
        uint8_t port_bit =  ack->ctx.token;
        if(port_bit > 3) {
            port_bit = 0;
        }
        remote_port = SC_ACK_TOUCH_V2_SERVER_PORT(port_bit);
    } else {
        remote_port = SC_ACK_AIRKISS_SERVER_PORT;
    }

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(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_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 < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) {
                ESP_LOGE(TAG,  "Creat udp socket failed");
                goto _end;
            }

            setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int));

            if (ack->type == SC_TYPE_AIRKISS) {
                char data = 0;
                struct sockaddr_in local_addr, from;
                socklen_t sockadd_len = sizeof(struct sockaddr);
                struct timeval timeout = {
                    SC_ACK_AIRKISS_TIMEOUT / 1000,
                    SC_ACK_AIRKISS_TIMEOUT % 1000 * 1000
                };

                bzero(&local_addr, sizeof(struct sockaddr_in));
                bzero(&from, sizeof(struct sockaddr_in));
                local_addr.sin_family = AF_INET;
                local_addr.sin_addr.s_addr = INADDR_ANY;
                local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT);

                bind(send_sock, (struct sockaddr*)&local_addr, sockadd_len);
                setsockopt(send_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

                recvfrom(send_sock, &data, 1, 0, (struct sockaddr*)&from, &sockadd_len);

                if (from.sin_addr.s_addr != INADDR_ANY) {
                    memcpy(remote_ip, &from.sin_addr, 4);
                    server_addr.sin_addr.s_addr = from.sin_addr.s_addr;
                } else {
                    goto _end;
                }
            }

            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 60 smartconfig ACKs. Then smartconfig is successful. */
                    if (packet_count++ >= SC_ACK_MAX_COUNT) {
                        esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY);
                        goto _end;
                    }
                } 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 1, errno %d", err);
                    //goto _end; **//我修改了此次,修改为continue;**
                    continue;
                }
            }
        } else {
            vTaskDelay((portTickType)(200 / portTICK_RATE_MS));
        }
    }

_end:

    if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) {
        close(send_sock);
    }

    free(ack);
    vTaskDelete(NULL);
}