Two wemos d1 mini in network; one is not reachable

Hello!

I'm building a water pump automation project.

For this I used two Wemos D1 minis.
One of them is the server - it hosts a wi-fi network, and a web-server. It expects the sensor to connect and register itself, then the server will start polling the sensor.

The other one is the sensor. It also hosts a web-server to reply the server's polling. Upon connecting to a predefined wi-fi network, it registers self at gateway /register endpoint.

What happens:
Both ESPs work separately quite well.
I can connect to server using my laptop or phone, and it replies correctly at / and /register endpoints.

If I setup the sensor to connect to my regular wi-fi network, then it's reachable, and it replies correctly at / and /sensor endpoints.

The problem happens when sensor connects to server's network. Then it's not reachable at its endpoints, "Connection refused".

What may be the cause for that?

Thank you.

Sensor code

Server code

Then it's not reachable at its endpoints, "Connection refused".

Where does it say that ?String sensor_host = "http://192.168.4.2";That is an assumption.
but the truth is told here

currentHost = "http://" + WiFi.localIP().toString();
  // Print the IP address
  Serial.print("Use this URL: ");
  Serial.println(currentHost);

Of course i suspect you never get to find out.
Have you tried using wifi.config() ? (silly question i don't see it) to change the gateway to 192.168.4.0 #define APPSK "1234567890"is that your actual password ? if so it's ok. (many times people create invalid passwords)
I am just doing some guess work here since i see nothing really obvious, the AP works, tbh i have never actually connected 2 ESP's to each other.

"What may be the cause for that?"

Well, it seems you have possibly set up one board as a station/server on a router network, and another board as an AP access point. I haven't looked at the code as you did not post it using code tags, but if you are using somthing like "softAP", then it may not provide direct access/bridging and communication between the two boards.

Thanks for replying.

Deva_Rishi:
Of course i suspect you never get to find out.

I got to find it out, because the sensor is supposed to send its host (IP) in the register request.

Have you tried using wifi.config() ? (silly question i don't see it) to change the gateway to 192.168.4.0

I tried, it didn't help.

#define APPSK "1234567890"

is that your actual password ? if so it's ok. (many times people create invalid passwords)

I use a different one, but it's valid - in serial monitor I can see the sensor or my laptop for that cause connecting.

What's more intriguing - when I connect to server's network with laptop or phone, its endpoints work fine and I never get the Connection refused.

zoomkat:
Well, it seems you have possibly set up one board as a station/server on a router network, and another board as an AP access point.

Sorry, I didn't get this.
One ESP creates a network, the other one is connecting to it.

I haven't looked at the code as you did not post it using code tags

I didn't post it in code tag, since there is quite a lot of it, and github has some good code viewing capabilities.

but if you are using somthing like "softAP", then it may not provide direct access/bridging and communication between the two boards.

Why not?
It works when I connect with a laptop to it.

Also I tried the minimal GET sketch, also returns code -1, Connection refused.

But when I do a similar GET request from my computer it's fine.

/**
 * BasicHTTPClient.ino
 *
 *  Created on: 24.05.2015
 *
 */

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#define USE_SERIAL Serial

#define APSSID "ESP-Pump-Server"
#define APPSK "****"

ESP8266WiFiMulti WiFiMulti;

void setup() {

    USE_SERIAL.begin(115200);
    USE_SERIAL.setDebugOutput(true);

    USE_SERIAL.println();
    USE_SERIAL.println();
    USE_SERIAL.println();

    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
    }

    WiFiMulti.addAP(APSSID, APPSK);

}

void loop() {
    // wait for WiFi connection
    if((WiFiMulti.run() == WL_CONNECTED)) {

        HTTPClient http;
        http.setTimeout(2000);

        USE_SERIAL.print("[HTTP] begin...\n");
        // configure traged server and url
        //http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
        //http.begin("http://192.168.1.12/test.html"); //HTTP
        http.begin(WiFi.gatewayI ().toString(), 80, "/");

        USE_SERIAL.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int httpCode = http.GET();

        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();
                USE_SERIAL.println(payload);
            }
        } else {
            USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();
    }

    delay(10000);
}

"But when I do a similar GET request from my computer it's fine."

What is the URL used by the computer when it connects successfully? The "Connection refused" sounds like maybe a router refusing a connection to the router's network.

zoomkat:
"But when I do a similar GET request from my computer it's fine."

What is the URL used by the computer when it connects successfully? The "Connection refused" sounds like maybe a router refusing a connection to the router's network.

URL is http://192.168.4.1 - the default ESP8266 gateway IP.

"URL is http://192.168.4.1 - the default ESP8266 gateway IP."

Then that is what you probably need to use in your client code instead of 192.168.1.12 to connect to that access point. I haven't seen a way to bridge from the AP side (192.168.4.1) to the station/server side (192.168.1.12) of an ESP connected in a router network.

I haven't seen a way to bridge from the AP side (192.168.4.1) to the station/server side (192.168.1.12) of an ESP connected in a router network.

I don't think he is trying to do that, but maybe didn't update the sketch he posted between switching. Anyway, just humor me, can you put both of them in station mode and get the client to connect to the server ? Then of course you will need the IP address that the router (which is an AP) has assigned to the Station. Maybe that is not the right approach, I am still not quite clear on the 'connection refused' part of your response, does it simply refuse the credentials you provide, or does it refuse to respond to your request ?
Since i haven't actually done it (but i have actually supported someone that had already succeeded at connecting an ESP as a STA to an ESP as an AP, but he or she had gotten stuck further down the line) i have to just refer you to a tutorial

Just out of curiosity, if all you are doing is to poll a sensor, why not simply use MQTT for sensor data transfer?

"I don't think he is trying to do that"

The OP has only posted what appears to be client code. Without the server code, one can only guess or try to reverse engineer what he/she is actually doing vs. statements of what they want to do.

The OP has only posted what appears to be client code. Without the server code, one can only guess or try to reverse engineer what he/she is actually doing vs. statements of what they want to do.

The OP posted both sensor(client0 code and server code (as links to github rather than the preferred within </> code-tags) but they are both there.

Also I tried the minimal GET sketch, also returns code -1, Connection refused.

So it seems that you can connect but your request is denied, have you tried adding a handleNotFound() callback ?

Deva_Rishi:
The OP posted both sensor(client0 code and server code (as links to github rather than the preferred within </> code-tags) but they are both there.[/code]

Correct.

Still here is a copy-paste from github:

/* Create a WiFi access point and provide a web server on it. */

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>

#include "server_config.h"

#ifndef APSSID
#define BLYNK_AUTH_CODE "aaaa"
#define APSSID "ESP-Pump-Server"
#define APPSK "1234567890"
#define SENSOR_ID "12345"
#endif

const int VERSION = 1;
// hw
const int RELAY_PIN = D4;

// software
HTTPClient http;
String sensor_host = "http://192.168.4.2";

// thresholds in cm; sensor value
const int SENSOR_FULL_THRESHOLD = 20;
const int SENSOR_LOW_THRESHOLD = 160;
int last_measurement = -1;

// default check is once per 15 minutes
const int SENSOR_POLL_DELAY = 900000;
// while pump is active check every second
const int ACTIVE_SENSOR_POLL_DELAY = 1000;

/* Set these to your desired credentials. */
const char *ssid = APSSID;
const char *password = APPSK;

int SERVER_STATE = 0;
const int STATE_IDLE = 0;
const int STATE_ERROR = 1;
const int STATE_SENSOR_CONNECTED = 2;
const int STATE_SENSOR_OK = 3;
const int STATE_RELAY_CLOSED = 4;

int get_state() {
  return SERVER_STATE;
}

ESP8266WebServer server(80);

void state_on_registered() {
  Serial.println("state_on_registered");
  SERVER_STATE = STATE_SENSOR_CONNECTED;
}
void state_on_sensor_full() {
  Serial.println("state_on_sensor_full");
  SERVER_STATE = STATE_SENSOR_OK;
}

void state_on_relay_close() {
  Serial.println("state_on_relay_close");
  SERVER_STATE = STATE_RELAY_CLOSED;
}

void state_on_error() {
  Serial.println("state_on_error");
  SERVER_STATE = STATE_ERROR;
}

void handleRoot() {
  server.send(200, "text/html", "ESP-Pump-Server");
}

void handleRegister() {
  if (server.method() != HTTP_POST) {
    server.send(405, "text/plain", "Method Not Allowed");
    Serial.println("handleRegister wrong method");
  } else {
    String message = "";

    if (server.arg("sensor_code") == SENSOR_ID) {
      Serial.println("sensor_registered true");
      if (server.hasArg("sensor_host")) {
        sensor_host = server.arg("sensor_host");
        state_on_registered();
        Serial.println("Sensor registered @ " + sensor_host);
      }
    }
    // debug
    Serial.println("handleRegister args:");
    Serial.println(server.arg("sensor_code"));
    Serial.println(SENSOR_ID);
    Serial.println(server.arg("sensor_host"));
    Serial.println(message);

    if (get_state() == STATE_SENSOR_CONNECTED) {
      server.send(200, "text/html", "Registered");
    } else {
      server.send(401, "text/html", "Wrong arguments");
    }
  }
}

void readSensorData() {
  String URL = sensor_host + "/sensor";
  http.begin(URL);
  
  Serial.println("readSensorData @ " + URL);
 
  int httpCode = http.GET();
  if (httpCode > 0) {
    String payload = http.getString();
    Serial.println("readSensorData GET: " + payload);
    check_measurement(payload.toInt());
  } else {
    state_on_error();
  }
 
  http.end();
  // #TODO replace with proper non-blocking delay
  delay(ACTIVE_SENSOR_POLL_DELAY);
}

void check_measurement(int tmp_last_measurement) {
  if (tmp_last_measurement >= 0) {
    last_measurement = tmp_last_measurement;
    // normal operation
    if (get_state() == STATE_RELAY_CLOSED) {
      // relay closed, waiting till the tank reaches FULL
      if (last_measurement <= SENSOR_FULL_THRESHOLD) {
        state_on_sensor_full();
      }
    } else {
      // relay open, just watching the tank
      if (last_measurement >= SENSOR_LOW_THRESHOLD) {
        state_on_relay_close();
      }
    }
    
  } else {
    state_on_error();
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(RELAY_PIN, OUTPUT);
  
  Serial.println();
  Serial.print("Configuring access point...");

  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.on("/", handleRoot);
  server.on("/register", handleRegister);
  server.begin();
  Serial.println("HTTP server started");

  WiFi.hostname("relay-server");
}

void loop() {
  server.handleClient();
  
/*
 * State Loop
 * 
 * If registered
   * If relay open then poll sensor with timer REGULAR
   * If SENSOR_LOW then close relay
     * If SENSOR_OK then open relay
     * poll sensor with timer ACTIVE
 * 
 */

  readSensorData();
  if (get_state() >= STATE_SENSOR_CONNECTED) {    
//    readSensorData();
  }

  digitalWrite(RELAY_PIN, get_state() == STATE_RELAY_CLOSED);

}

So it seems that you can connect but your request is denied, have you tried adding a handleNotFound() callback ?

I tried, but to no effect.
This is not a 404 error.

SteveMann:
Just out of curiosity, if all you are doing is to poll a sensor, why not simply use MQTT for sensor data transfer?

I didn't know about it, and I'm familiar with REST.

Deva_Rishi:
I don't think he is trying to do that, but maybe didn't update the sketch he posted between switching. Anyway, just humor me, can you put both of them in station mode and get the client to connect to the server?

Tried to do it yesterday, but nothing woked at all, even the things that used to be stable before.

Starting to assume that there is a hardware issue with one of my boards.

have you tried running the tutorial i provided the link for in #8 (as a 'back to basics' option)

"The OP posted both sensor(client0 code and server code (as links to github rather than the preferred within </> code-tags) but they are both there."

Fetch boy, fetch!

zoomkat:
Fetch boy, fetch!

Excuse me ?

Deva_Rishi:
have you tried running the tutorial i provided the link for in #8 (as a 'back to basics' option)

Not yet - for some reason one of my boards resets itself (watchdog timer), while trying to connect to wifi.
Trying to dig that one out.

Also - do I need to change Erase Mode?
It's currently in "Only Sketch".

ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 3456, room 16 
tail 0
chksum 0x84
csum 0x84
va5432625
~ld

SDK:2.2.2-dev(38a443e)/Core:2.7.1=20701000/lwIP:STABLE-2_1_2_RELEASE/glue:1.2-30-g92add50/BearSSL:5c771be

with the code

/**
   BasicHTTPClient.ino

    Created on: 24.05.2015

*/

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClient.h>

ESP8266WiFiMulti WiFiMulti;

void setup() {

  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "PASSWORD");

}

void loop() {
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;

    HTTPClient http;

    Serial.print("[HTTP] begin...\n");
    if (http.begin(client, "http://jigsaw.w3.org/HTTP/connection.html")) {  // HTTP


      Serial.print("[HTTP] GET...\n");
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }

      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }

  delay(10000);
}

beshur:
Not yet - for some reason one of my boards resets itself (watchdog timer), while trying to connect to wifi.
Trying to dig that one out.

delay(10000);

Absolutely guarantees a WDT timeout on the ESP.

Also - do I need to change Erase Mode?
It's currently in "Only Sketch".

It might be a good idea to erase the wifi settings as well, cause 4 is a wdt, and i am not sure how the wifimulti works exactly, but clearly it is taking more time than it should, and since connecting is happening in the background, it may be that it is trying to connect to a network in your list with incorrect credentials. If the problem persists i would drop the WiFimulti for the moment and go for the specific network connection that you want.

SteveMann:

delay(10000);

Absolutely guarantees a WDT timeout on the ESP.

Reduced the delay to 3000, dropped wifi multi, and I was getting a new error:

Fatal exception 3(LoadStoreErrorCause)

I did some more searching, and found this thread that suggests erasing flash.

I changed the Erase Flash in Aduino to "All Flash Contents" and it helped.

Now two arduinos can connect to the same wi-fi (regular router), and "server" can request "sensor" its data.

Moving on to fixing original issue later.