esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.01k stars 13.33k forks source link

WiFiclient fails to connect #1849

Closed SteverR closed 8 years ago

SteverR commented 8 years ago

Hi all:

I am new to posting (among many things) and apologize if I violate protocol in any way.

I would appreciate assistance with WiFiclient.cpp. In a nutshell, it fails to connect.

I am compiling on a Windows 7 using Visual Micro within Visual Studio 2015 with the board 

set as WeMos D1 Mini. My ultimate goal is to log a temperature sensor using EasyIOT.

I will first report serial port output and comment on the difficulty this reveals and then 

provide copies of the two code segments that are implicated.

BEGIN serial port output

Opening port
Port open
.X.X.X.X.X.X.X
WiFi connected. and assigned ip of 192.168.1.140
in WFC A.. tcp_connect() done. remote ip = 192.168.1.104 local ip = 192.168.1.140 but _client fails
in WFC B after esp_yield()  remote ip = 32.87.70.67 local ip = 10.32.105.110 but _client fails
connection failed

in WFC A.. tcp_connect() done. remote ip = 192.168.1.104 local ip = 192.168.1.140 but _client fails
in WFC B after esp_yield()  remote ip = 32.87.70.67 local ip = 10.32.105.110 but _client fails
connection failed

END serial port output

COMMENT: The serial port output indicates success at signing on to the access point and obtaining an IP. In WFC (short for WiFiclient::connect), all seems to go well through the call to tcp_connect() or at least the ip s are intact and correct at that point. However _client does not pass muster. After the call to esp_yield(), the ip s are not intact and _client still fails. Hence the return to the calling program triggers 'connection failed'.

Any help or suggestions would be much appreciated.

Code segments follow. I will start with the relevant portions of WiFiclient.cpp followed by the calling code.

//BEGIN Selection from WiFiClient.cpp /* WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible with Arduino WiFi shield library

Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. */ // BEGIN snip A. material omitted is unchanged from downloaded code. // END snip A

//BEGIN Code of WIFiClient::connect() with modifications to elicit feedback, labeled as SR_debug

#define SR_debug 
#if defined(SR_debug)

    String ip_as_string;   //SR additions
    String message;
    String message_header = "\n in WFC ";

#endif
int WiFiClient::connect(IPAddress ip, uint16_t port)
{

    ip_addr_t addr;
    addr.addr = ip;

    if (_client)    
     stop();

    // if the default interface is down, tcp_connect exits early without
    // ever calling tcp_err
    // http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html
    netif* interface = ip_route(&addr);

    if (!interface) {
        DEBUGV("no route to host\r\n");
        return 0;
    }

    tcp_pcb* pcb = tcp_new();
    if (!pcb)
        return 0;

    if (_localPort > 0) {
        pcb->local_port = _localPort++;
    }

    tcp_arg(pcb, this);
    tcp_err(pcb, &WiFiClient::_s_err);
  tcp_connect(pcb, &addr, port, reinterpret_cast<tcp_connected_fn>(&WiFiClient::_s_connected));

    #if defined(SR_debug) 
  message = message_header + "A.. tcp_connect() done. ";        Serial.print(message);
  Serial.print("remote ip = ");
  Serial.print(inet_ntoa(pcb->remote_ip.addr));
  Serial.print(" local ip = ");
  Serial.print(inet_ntoa(pcb->local_ip.addr));
  if (_client) { Serial.print(" and _client is good"); }
  else { Serial.print(" but _client fails"); };
    #endif

    esp_yield();  

        #if defined(SR_debug) 
    message = message_header + "B after esp_yield()  ";     Serial.print(message);
    Serial.print("remote ip = ");
    Serial.print(inet_ntoa(pcb->remote_ip.addr));
    Serial.print(" local ip = ");
    Serial.print(inet_ntoa(pcb->local_ip.addr));
    if (_client) { Serial.print(" and _client is good"); }
    else { Serial.print(" but _client fails"); };
    #endif

    if (_client)
        return 1;

    //  if tcp_error was called, pcb has already been destroyed.
    // tcp_abort(pcb);
    return 0;
}
//END Code of WIFiClient::connect() with modifications to elicit feedback, labeled as SR_debug

//BEGIN highest level calling program (edited for brevity)
#include <ESP8266WiFi.h>
#include <Base64.h>
#include "lwip/inet.h"
template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }

const char* ssid = "dd-wrt";
const char* password = "*******";

// EasyIoT server definitions
#define EIOT_USERNAME    "admin"
#define EIOT_PASSWORD    "test"
#define EIOT_IP_ADDRESS  "192.168.1.104"
#define EIOT_PORT        80
#define EIOT_NODE        "N14S0"

#define USER_PWD_LEN 40
char unameenc[USER_PWD_LEN];
float oldTemp;
IPAddress loc_addr;
char* ch_ip = new char[20];

WiFiClient client;

void setup() {
    Serial.begin(9600);
    delay(10);

    WiFi.begin(ssid, password);

    Serial.print("Brief version - Connecting to My Router");

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".X");
    }
    Serial.println("");
    Serial.print(" WiFi connected. ");

    loc_addr = WiFi.localIP();  //retrieve IP assignment 
    sprintf(ch_ip, "%i.%i.%i.%i", loc_addr[0], loc_addr[1], loc_addr[2], loc_addr[3]);//and format readable version
            //OK, hardly elegant but it works. Suggestions for improvement are welcome.
    Serial << "and assigned ip of " << ch_ip;

    // snip A. Lines that would inform EIOT after connection achieved
    Unchanged from downloaded example and almost surely not relevant.
    //end snip A.
}

void loop() {

    float t = 88.888; //dummy replacement for reading temperature from sensor
    sendTeperature(t);
    delay(1000 * 60 * 10);  //millis * 60seconds * 10mins
                            //delay(1000*20);  //millis * 60seconds * 10mins
}

void sendTeperature(float temp)
{
    WiFiClient client;

    while (!client.connect(EIOT_IP_ADDRESS, EIOT_PORT)) {
        Serial.println("\nconnection failed");
        //wifiConnect(); 
    }

    //snip B. code to post temperature to easy_iot once connection is established.
    Unchanged from downloaded example and almost surely not relevant.
    //end snip B
}

//END highest level calling program (edited for brevity)
igrr commented 8 years ago

Could you please enable debug output in the IDE (Debug Level: Core and Debug Port: Serial), and paste here the serial output. This will contain error code returned by LwIP, if the connection failed due to an error. Otherwise, if error callback wasn't called, it means the connection has timed out, which may happen for many reasons (e.g. a firewall on your 192.168.1.104 host?)

SteverR commented 8 years ago

Thanks for the help. Good catch. Switching the firewall off allowed the connect to complete.

northallice commented 8 years ago

i wish i understand all of that :'( well, i am trying to make my wemos d1 r2 become an access point and also connected to the other network around. i hope you interesting for helping me.