Copyright © https://mongoose-os.com

Mongoose OS Forum

frame

Wifi Smartconfig with ESP8266

Hello,

I've read in the forum several times that you don't plan to support Wifi Smartconfig (ESP-Touch / Airkiss). Could you please tell me the reason?

Also I've tried to use Smartconfig API directly:

#include "smartconfig.h"
#include "user_interface.h"
...
wifi_set_opmode_current(STATION_MODE);
smartconfig_start(sc_cb);
...

Unfortunately the build process failed because of linkage error:

/home/martin/m/mos/build/objs/main.c.o:(.text.mgos_app_init+0x28): undefined reference to `smartconfig_start'

I've tried to use libsmartconfig.a from the docker image (tried both from ESP8266 with and without RTOS) and referenced it by binary_libs but then I got different linkage errors.

Could you please give me an advice how to build ii?

Thanks in advance

Best regards

Comments

  • If I link with libsmartconfig.a then I get linkage errors:

    /home/user/project/libs/libsmartconfig.a(sc_sniffer.o):(.text.smartconfig_stop+0x34): undefined reference to `espconn_delete'
    /home/user/project/libs/libsmartconfig.a(sc_sniffer.o):(.text.smartconfig_stop+0xd3): undefined reference to `espconn_delete'
    /home/user/project/libs/libsmartconfig.a(sc_airkiss.o):(.text.KISS_Send_udp+0x8): undefined reference to `espconn_sent'
    /home/user/project/libs/libsmartconfig.a(sc_airkiss.o):(.text.KISS_Send_udp+0x78): undefined reference to `espconn_sent'
    /home/user/project/libs/libsmartconfig.a(sc_airkiss.o):(.text.KISS_Udp_send_cb+0x4): undefined reference to `espconn_delete'
    /home/user/project/libs/libsmartconfig.a(sc_airkiss.o):(.text.KISS_Udp_send_cb+0x41): undefined reference to `espconn_delete'
    

    ...

    So I've added liblwip.a but that produced linking conflicts:

    /home/user/project/libs/liblwip.a(dhcp.o): In function `dhcp_set_struct':
    (.irom0.text+0xf24): multiple definition of `dhcp_set_struct'
    /home/user/project/build/objs/lwip/liblwip_cs.a(dhcp.o):/opt/Espressif/cs_lwip/./src/core/dhcp.c:637: first defined here
    /home/user/project/libs/liblwip.a(dhcp.o): In function `dhcp_cleanup':
    (.irom0.text+0xf50): multiple definition of `dhcp_cleanup'
    /home/user/project/build/objs/lwip/liblwip_cs.a(dhcp.o):/opt/Espressif/cs_lwip/./src/core/dhcp.c:1397: first defined here
    /home/user/project/libs/liblwip.a(dhcp.o): In function `dhcp_inform':
    (.irom0.text+0xf94): multiple definition of `dhcp_inform'
    

    ...

    Is it because of mongoose-os is using its own lwip implementation? Do you think it would be possible to implement espconn_* functions in app's code to make it work?

  • Or do you think it would be good idea just to remove conflictiong objects from ESP's liblwip.a?

  • I've managed to make ESP Touch work. If somebody is interested he/she can send me a message.

  • HOWTO

    Get libsmartconfig.a from mgos/esp8266-build docker image and put it to lib.

    In mos.yml add:

    binary_libs:
      - libs/libsmartconfig.a
    

    Then use this code:

    #include "mgos.h"
    
    #include "c_types.h"
    #include "ets_sys.h"
    #include "osapi.h"
    #include "os_type.h"
    #include "user_config.h"
    #include "user_interface.h"
    
    #include "sc.h"
    
    char *ssid;
    char *password;
    
    static void reboot_timer_cb(void *arg) {
      mgos_system_restart();
      (void) arg;
    }
    
    void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) {
      switch (status) {
        case SC_STATUS_WAIT:
          LOG(LL_DEBUG, ("SC_STATUS_WAIT"));
          break;
        case SC_STATUS_FIND_CHANNEL:
          LOG(LL_DEBUG, ("SC_STATUS_FIND_CHANNEL"));
          break;
        case SC_STATUS_GETTING_SSID_PSWD:
          LOG(LL_DEBUG, ("SC_STATUS_GETTING_SSID_PSWD"));
          sc_type *type = pdata;
          if (*type == SC_TYPE_ESPTOUCH) {
            LOG(LL_DEBUG, ("SC_TYPE:SC_TYPE_ESPTOUCH"));
          } else {
            LOG(LL_DEBUG, ("SC_TYPE:SC_TYPE_AIRKISS"));
          }
          break;
        case SC_STATUS_LINK:
          LOG(LL_DEBUG, ("SC_STATUS_LINK"));
          struct station_config *sta_conf = pdata;
          ssid = (char *) sta_conf->ssid;
          password = (char *) sta_conf->password;
          LOG(LL_DEBUG, ("SSID: %s | PASS: %s\n", ssid, password));
    
          wifi_station_set_config(sta_conf);
          wifi_station_disconnect();
          wifi_station_connect();
          break;
        case SC_STATUS_LINK_OVER:
          LOG(LL_DEBUG, ("SC_STATUS_LINK_OVER"));
          if (pdata != NULL) {
            uint8 *phone_ip = (uint8 *) pdata;
            LOG(LL_DEBUG, ("Phone IP: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]));
    
            mgos_sys_config_set_wifi_sta_enable(true);
            mgos_sys_config_set_wifi_sta_ssid(ssid);
            mgos_sys_config_set_wifi_sta_pass(password);
    
            char *err = NULL;
            save_cfg(&mgos_sys_config, &err); /* Writes conf9.json */
            LOG(LL_INFO, ("Saving configuration: %s", err ? err : "no error"));
            free(err);
    
            mgos_set_timer(1000, 0, reboot_timer_cb, NULL);
          }
          smartconfig_stop();
          break;
      }
    }
    
    /** callback prototype to inform about events for a espconn */
    typedef void (*espconn_recv_callback)(void *arg, char *pdata, unsigned short len);
    typedef void (*espconn_callback)(void *arg, char *pdata, unsigned short len);
    typedef void (*espconn_connect_callback)(void *arg);
    typedef void (*espconn_reconnect_callback)(void *arg, sint8 err);
    typedef void (*espconn_sent_callback)(void *arg);
    typedef void *espconn_handle;
    
    typedef struct _esp_tcp {
      int remote_port;
      int local_port;
      uint8 local_ip[4];
      uint8 remote_ip[4];
      espconn_connect_callback connect_callback;
      espconn_reconnect_callback reconnect_callback;
      espconn_connect_callback disconnect_callback;
      espconn_connect_callback write_finish_fn;
    } esp_tcp;
    
    typedef struct _esp_udp {
      int remote_port;
      int local_port;
      uint8 local_ip[4];
      uint8 remote_ip[4];
    } esp_udp;
    
    /** Protocol family and type of the espconn */
    enum espconn_type {
      ESPCONN_INVALID = 0,
      /* ESPCONN_TCP Group */
      ESPCONN_TCP = 0x10,
      /* ESPCONN_UDP Group */
      ESPCONN_UDP = 0x20,
    };
    
    /** Current state of the espconn. Non-TCP espconn are always in state ESPCONN_NONE! */
    enum espconn_state {
      ESPCONN_NONE,
      ESPCONN_WAIT,
      ESPCONN_LISTEN,
      ESPCONN_CONNECT,
      ESPCONN_WRITE,
      ESPCONN_READ,
      ESPCONN_CLOSE
    };
    
    enum espconn_option {
      ESPCONN_START = 0x00,
      ESPCONN_REUSEADDR = 0x01,
      ESPCONN_NODELAY = 0x02,
      ESPCONN_COPY = 0x04,
      ESPCONN_KEEPALIVE = 0x08,
      ESPCONN_MANUALRECV = 0x10,
      ESPCONN_END
    };
    
    enum espconn_level {
      ESPCONN_KEEPIDLE,
      ESPCONN_KEEPINTVL,
      ESPCONN_KEEPCNT
    };
    
    /** A espconn descriptor */
    struct espconn {
      /** type of the espconn (TCP, UDP) */
      enum espconn_type type;
      /** current state of the espconn */
      enum espconn_state state;
      union {
        esp_tcp *tcp;
        esp_udp *udp;
      } proto;
      /** A callback function that is informed about events for this espconn */
      espconn_recv_callback recv_callback;
      espconn_sent_callback sent_callback;
      uint8 link_cnt;
      void *reverse; // reversed for customer use
    };
    
    struct mg_connection *estc;
    
    espconn_sent_callback sent_cb;
    espconn_recv_callback recv_cb;
    
    static void udp_connection_handler(struct mg_connection *nc, int ev, void *ev_data, void *ud) {
      switch (ev) {
        case MG_EV_RECV:
          recv_cb(NULL, nc->recv_mbuf.buf, nc->recv_mbuf.len);
          nc->recv_mbuf.len = 0;
          break;
        default:
          break;
      }
    
      (void) ev_data;
      (void) ud;
    }
    
    sint8 espconn_create(struct espconn *espconn) {
        LOG(LL_DEBUG, ("espconn_create"));
    
        esp_udp *u = espconn->proto.udp;
        char addr[30];
        snprintf(addr, sizeof(addr), "udp://%d.%d.%d.%d:%d", u->remote_ip[0], u->remote_ip[1], u->remote_ip[2], u->remote_ip[3], u->remote_port);
        estc = mg_connect(mgos_get_mgr(), addr, udp_connection_handler, NULL);
    
        return 0;
    }
    
    sint8 espconn_delete(struct espconn *espconn) {
      (void) espconn;
      LOG(LL_DEBUG, ("espconn_delete"));
      return 0;
    }
    
    sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) {
      (void) espconn;
      (void) psent;
      (void) length;
      LOG(LL_DEBUG, ("espconn_send"));
      return 0;
    }
    
    // Get an available port.
    uint32 espconn_port(void) {
      LOG(LL_DEBUG, ("espconn_port"));
      return 22564; // TODO ?
    }
    
    sint8 espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb1) {
      (void) espconn;
      LOG(LL_DEBUG, ("espconn_regist_sentcb"));
      sent_cb = sent_cb1;
      return 0;
    }
    
    sint8 espconn_regist_recvcb(struct espconn *espconn, espconn_recv_callback recv_cb1) {
      (void) espconn;
      LOG(LL_DEBUG, ("espconn_regist_recvcb"));
      recv_cb = recv_cb1;
      return 0;
    }
    
    sint8 espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length) {
      // we got UDP
      // LOG(LL_INFO, ("GGG type: %d, state: %d, len: %d, %.*s", espconn->type, espconn->state, length, length, psent));
      esp_udp *u = espconn->proto.udp;
      LOG(LL_DEBUG, ("espconn_sent %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",
        u->local_ip[0], u->local_ip[1], u->local_ip[2], u->local_ip[3], u->local_port,
        u->remote_ip[0], u->remote_ip[1], u->remote_ip[2], u->remote_ip[3], u->remote_port));
    
      mg_send(estc, psent, length);
      sent_cb(espconn);
    
      return 0;
    }
    
    void start_smartconfig() {
      wifi_set_opmode(1);
      smartconfig_start(smartconfig_done);
    }
    
    enum mgos_app_init_result mgos_app_init(void) {
        // ...
        mgos_set_timer(5000, 0, start_smartconfig, NULL);
    }
    
  • Hi. Can you give detailed instructions on how to use smartconfig esp on mongoose?

  • Just use instructions from HOWTO and on your android phone use ESP8266 SmartConfig app.

  • edited February 21

    Thank you very much. However, I still do not understand how to do in the HOWTO section you guided. Can you guide me in detail?

  • thank you very much. I have done smartconfig already. But ESP has not yet returned the IP for the application.

  • Maybe you could provide some logs.

Sign In or Register to comment.