esp8266 client mode (connect to remote host) simple example

esp8266run

Today I’ve been looking at getting the esp8266 working as a Wifi client and seeing if I could fetch some data. This builds on my previous notes on flashing the esp8266. There’s some great info here which the code below is based on, with modifications to fetch a page from a remote host.

Setting the SSID and password for the host network is pretty easy, and I based the code below on the “basic_example”, supplied with the SDK. Once configured the board will get an IP over DHCP, and configure it’s resolver. It will also respond to ping requesting, which can be a useful debugging tool.

In order to try things out, I wrote a simple program which fetches the google homepage a prints it out over the serial port. The complete tarball can be downloaded here. And when run it will print out the following:

IP: 192.168.0.8looklokkDST: 173.194.126.178conncendsentrecvHTTP/1.0 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.jp/?gfe_rd=cr&ei=BBmkVMK6NKGT8QfRqIDwAw
Content-Length: 261
Date: Wed, 31 Dec 2014 15:40:52 GMT
Server: GFE/2.0
Alternate-Protocol: 80:quic,p=0.02
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
                                                                              <T>
                                                                                >
                                                                                d
                                                                                .
</BODY></HTML>
dcon

You’ll need to change user_config.h to contain your networks SSID and password e.g.:

#define SSID "NETWORKNAME"
#define SSID_PASSWORD "NETWORKPASSWORD"

user_main.c is also reproduced below for reference. You also need the uart code from the SDK and uart.c needs to be compiled in. There were a few gotcha when writing this, the first is that the serial port seems to be configured for a rather odd 77Kbps. So it makes sense to reconfigure the serial port to a more sensible value straight away (I used 9600). It’s also not yet clear to me where the os_printf output goes. I used uart0_tx_buffer for all my debug output.

Another issue I had is that the esp8266 seems to be quite finicky about how it’s various pins are set at boot. I couldn’t get the board to come up with my FTDI serial cable attached. I had to first boot the device from a bench supply (using the “run” board in my previous notes). And then connect the serial cable after it started booting. Luckily there’s just enough time before it completes it’s wifi connection to do this so I can see the debug output (only just though, it boots and gets connected to wifi very quickly).

Anyway for reference, here’s the code. If you want to try it out checkout the tarball linked above.

#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"
//#include "user_network.h"
//#include "user_display.h"

#define user_procTaskPrio        0
#define user_procTaskQueueLen    1
os_event_t    user_procTaskQueue[user_procTaskQueueLen];
static void loop(os_event_t *events);

//Main code function
static void ICACHE_FLASH_ATTR
loop(os_event_t *events)
{
    os_printf("Hello\n\r");
    os_delay_us(10000);
    system_os_post(user_procTaskPrio, 0, 0 );
}

static void ICACHE_FLASH_ATTR networkConnectedCb(void *arg);
static void ICACHE_FLASH_ATTR networkDisconCb(void *arg);
static void ICACHE_FLASH_ATTR networkReconCb(void *arg, sint8 err);
static void ICACHE_FLASH_ATTR networkRecvCb(void *arg, char *data, unsigned short len);
static void ICACHE_FLASH_ATTR networkSentCb(void *arg);
void ICACHE_FLASH_ATTR network_init();

LOCAL os_timer_t network_timer;

static void ICACHE_FLASH_ATTR networkServerFoundCb(const char *name, ip_addr_t *ip, void *arg) {
  static esp_tcp tcp;
  struct espconn *conn=(struct espconn *)arg;
  if (ip==NULL) {
    os_printf("Nslookup failed :/ Trying again...\n");
    uart0_tx_buffer("lfai",4);
    network_init();
  }

  uart0_tx_buffer("lokk",4);
  char page_buffer[20];
  os_sprintf(page_buffer,"DST: %d.%d.%d.%d",
  *((uint8 *)&ip->addr), *((uint8 *)&ip->addr + 1),
  *((uint8 *)&ip->addr + 2), *((uint8 *)&ip->addr + 3));
  uart0_tx_buffer(page_buffer,strlen(page_buffer));

  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->remote_ip, &ip->addr, 4);
  espconn_regist_connectcb(conn, networkConnectedCb);
  espconn_regist_disconcb(conn, networkDisconCb);
  espconn_regist_reconcb(conn, networkReconCb);
  espconn_regist_recvcb(conn, networkRecvCb);
  espconn_regist_sentcb(conn, networkSentCb);
  espconn_connect(conn);
}

static void ICACHE_FLASH_ATTR networkSentCb(void *arg) {
  uart0_tx_buffer("sent",4);
}

static void ICACHE_FLASH_ATTR networkRecvCb(void *arg, char *data, unsigned short len) {

  uart0_tx_buffer("recv",4);
  
  struct espconn *conn=(struct espconn *)arg;
  int x;
  uart0_tx_buffer(data,len);
  //for (x=0; x<len; x++) networkParseChar(conn, data[x]);
}

static void ICACHE_FLASH_ATTR networkConnectedCb(void *arg) {

  uart0_tx_buffer("conn",4);
  struct espconn *conn=(struct espconn *)arg;

  char *data = "GET / HTTP/1.0\r\n\r\n\r\n";
  sint8 d = espconn_sent(conn,data,strlen(data));

  espconn_regist_recvcb(conn, networkRecvCb);
  uart0_tx_buffer("cend",4);
}

static void ICACHE_FLASH_ATTR networkReconCb(void *arg, sint8 err) {
  uart0_tx_buffer("rcon",4);
//  os_printf("Reconnect\n\r");
//  network_init();
}

static void ICACHE_FLASH_ATTR networkDisconCb(void *arg) {
  uart0_tx_buffer("dcon",4);
//  os_printf("Disconnect\n\r");
//  network_init();
}


void ICACHE_FLASH_ATTR network_start() {
  static struct espconn conn;
  static ip_addr_t ip;
  os_printf("Looking up server...\n");
    uart0_tx_buffer("look",4);
  espconn_gethostbyname(&conn, "www.google.com", &ip, networkServerFoundCb);
}

void ICACHE_FLASH_ATTR network_check_ip(void) {
  struct ip_info ipconfig;
  os_timer_disarm(&network_timer);
  wifi_get_ip_info(STATION_IF, &ipconfig);
  if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0) {
    char page_buffer[20];
    os_sprintf(page_buffer,"IP: %d.%d.%d.%d",IP2STR(&ipconfig.ip));
    uart0_tx_buffer(page_buffer,strlen(page_buffer));
    network_start();
  } else {
    os_printf("No ip found\n\r");
    os_timer_setfn(&network_timer, (os_timer_func_t *)network_check_ip, NULL);
    os_timer_arm(&network_timer, 1000, 0);
  }
}

void ICACHE_FLASH_ATTR network_init() {
  os_timer_disarm(&network_timer);
  os_timer_setfn(&network_timer, (os_timer_func_t *)network_check_ip, NULL);
  os_timer_arm(&network_timer, 1000, 0);
}

//Init function 
void ICACHE_FLASH_ATTR user_init() {

    uart_init(BIT_RATE_9600,BIT_RATE_9600);
    char ssid[32] = SSID;
    char password[64] = SSID_PASSWORD;
    struct station_config stationConf;

    //Set station mode
    wifi_set_opmode( 0x1 );

    //Set ap settings
    os_memcpy(&stationConf.ssid, ssid, 32);
    os_memcpy(&stationConf.password, password, 64);
    wifi_station_set_config(&stationConf);

    uart0_tx_buffer("init",4);

    //Start os task
    system_os_task(loop, user_procTaskPrio,user_procTaskQueue, user_procTaskQueueLen);

    system_os_post(user_procTaskPrio, 0, 0 );

    network_init();
}

Comments are closed.