Chat freely about anything...

User avatar
By Bill Gray
#49629 Hello,

I've been pulling my hair out on this for a couple of days.

I've got two(2) esp8266s.

One is setup as an AP and web server. Works great.

The other is a client that is supposed to log on to the AP's wifi network then create a TCP connection to the web server, and get some data.

The client code works when I'm running in STATION_MODE but for some reason I can't get a TCP connection to work when the client is in STATIONAP_MODE. I don't know what I am doing wrong.

A couple of notes:
1) I need to run the client in STATIONAP_MODE for the larger project that I am working on
2) I'm using the SDK functions through the Arduino IDE. For the larger project I need to use various Arduino libraries, but the Arduino WiFi libraries for esp8266 are too laggy for my application, and that is why I've moved to the SDK functions.

Code: Select allextern "C" {
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "user_config.h"
#include "user_interface.h"
#include "uart.h"
#include "c_types.h"
#include "espconn.h"
#include "mem.h"
}

esp_tcp tcp;
espconn conn;
os_timer_t connectTimer;

void setup() {
  Serial.begin( 115200 );
  Serial.printf("\nIn setup()\nConnecting to WiFi\n");

  //Set station mode
  wifi_station_disconnect();
//  wifi_set_opmode( STATION_MODE );  // works just fine as a STATION
  wifi_set_opmode( STATIONAP_MODE );// does NOT work? will not tcp connect to another esp8266.

  char ssid[32] = "projectSSID";
  char password[64] = "projectPassword";

  //Set ap settings
  struct station_config stationConf;
  stationConf.bssid_set = 0;
  memcpy(&stationConf.ssid, ssid, 32);
  memcpy(&stationConf.password, password, 64);
  wifi_station_set_config(&stationConf);
  wifi_station_connect();

  os_timer_setfn( &connectTimer, connectTCP, NULL );
  os_timer_arm( &connectTimer, 1000, 0 );

  return;
}

void loop() {
}

void connectTCP( void *arg ) {
  struct ip_info ipconfig;

  os_timer_disarm( &connectTimer );

  wifi_get_ip_info(STATION_IF, &ipconfig);
  if ( wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0 ) {
    Serial.printf("\nGot local IP=%d.%d.%d.%d\n", IP2STR(&ipconfig.ip) );
    Serial.printf("Dest IP=%d.%d.%d.%d\n", IP2STR( &ipconfig.gw ) );

    conn.type = ESPCONN_TCP;
    conn.state = ESPCONN_NONE;
    conn.proto.tcp = &tcp;
    conn.proto.tcp->local_port = espconn_port();
    conn.proto.tcp->remote_port = 80;
    os_memcpy(conn.proto.tcp->local_ip, &ipconfig.ip, 4);
    os_memcpy(conn.proto.tcp->remote_ip, &ipconfig.gw, 4);

    Serial.printf("conn Print type=%d, state=%d, local_ip=%d.%d.%d.%d, local_port=%d, remote_ip=%d.%d.%d.%d remote_port=%d\n",
                  conn.type,
                  conn.state,
                  IP2STR(conn.proto.tcp->local_ip),
                  conn.proto.tcp->local_port,
                  IP2STR(conn.proto.tcp->remote_ip),
                  conn.proto.tcp->remote_port );

    espconn_regist_connectcb(&conn, stationConnectedCb);
    espconn_regist_disconcb(&conn, stationDisconCb);
    espconn_regist_reconcb(&conn, stationReconCb);
    espconn_regist_recvcb(&conn, stationRecvCb);
    espconn_regist_sentcb(&conn, stationSentCb);

    Serial.printf("espconn_connect()=%d\n", espconn_connect(&conn) );
  }
  else {
    Serial.print(".");
    os_timer_arm( &connectTimer, 1000, 0 );
  }
}

void stationConnectedCb(void *arg) {

  Serial.print("In stationConnectedCb\n");

  struct espconn *newConn = (struct espconn *)arg;

  char *data = "GET / HTTP/1.0\r\n\r\n\r\n";
  Serial.printf("Sending to server data=%s\n", data );
  sint8 d = espconn_sent(newConn, (uint8*)data, strlen(data));

  espconn_regist_recvcb(newConn, stationRecvCb);
}

void stationReconCb(void *arg, sint8 err) {
  struct espconn *failedConn = (struct espconn*)arg;
  Serial.printf("In stationReconCb err=%d\n", err);
  Serial.printf("failedConn type=%d, state=%d, local_ip=%d.%d.%d.%d, local_port=%d, remote_ip=%d.%d.%d.%d remote_port=%d\n",
                failedConn->type,
                failedConn->state,
                IP2STR(failedConn->proto.tcp->local_ip),
                failedConn->proto.tcp->local_port,
                IP2STR(failedConn->proto.tcp->remote_ip),
                failedConn->proto.tcp->remote_port );
}

void stationDisconCb(void *arg) {
  Serial.printf("In stationDisconCb\n");
  //  network_init();
}

void stationSentCb(void *arg) {
  Serial.print("In stationSentCb\n");
}

void stationRecvCb(void *arg, char *data, unsigned short len) {
  Serial.print("In stationRecvCb\n");

  struct espconn *recConn = (struct espconn *)arg;

  Serial.printf("Received Data=%s\n", data);
}


Any suggestions will be very much appreciated.

Thanks,

Bill
User avatar
By martinayotte
#49663 When a ESP is in STA+AP mode is connecting to another ESP, it is simply a routing issue and clash with the gateway address since both have a local 192.168.4.1, the client try to connect to itself instead of connecting to remote AP.

Either you change the AP subnet of the client or you stick with STA mode.
User avatar
By Bill Gray
#49670 Ahhhh!!!!

That was it. Thank you so much. It seems obvious now that I've got it working, but that little wrinkle really had me spun.

I'm still a bit unclear on how the AP network and the STA network are related to each other. Since you can't route directly between the two by default, I'd figured that they were completely separate and that therefore you could connect as a STA to network with gateway=192.168.4.1 and then setup up your own independent sub-network with whatever gateway IP you liked on the your own AP... including the default 192.168.4.1

Is there a resource that explains how the AP and STA networks are related to each other?

Thanks so much!

Bill
User avatar
By Bluesun
#49876 I'm also interested in this, as I'm having a similar problem.

I'm attempting to bind to a port on IPADDR_ANY and allow connection from both the AP side and the STATION side. It works flawlessly on the STATION side (meaning when it connects to my wireless and gets an IP address on my home subnet, I can connect to it and send/receive data without issue), but when trying to connect to the AP side (meaning the DHCP server on the ESP gives me an IP address on its subnet, which is different from the AP side's subnet) it either sort of works, doesn't respond, or doesn't work at all. I've been wracking my brain trying to figure out what I can do to resolve this.

My particular situation basically requires it to work both ways, and I'm not clear on how you specify which interface you are binding to. I'm basically trying to implement a poor man's mesh network, but I'm stuck here.

EDIT: Turns out my issue was also network definition related. I had the AP subnet misconfigured, so it was on the same subnet as the STATION subnet. Once I clearned this up, all seems to work just fine.

to be clear, here's my AP ip_info, set to 192.168.0.0/24, and my home network is 10.10.0.0/24

Code: Select allstruct ip_info ap_ip;
    IP4_ADDR(&ap_ip.ip, 192, 168, 0, 1);
    IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0);
    IP4_ADDR(&ap_ip.netmask, 255, 255, 255, 0);
    sdk_wifi_set_ip_info(1, &ap_ip);