You can chat about native SDK questions and issues here.
User avatar
By Affix
#62639 Hey guys,

I've been playing around with a NodeMCU and the NonOS SDK. I have decided to release an example (including a nodeMCU pin mapping header).

The code is based around the TCP Example from Espressif, but much better commented.

In your user_config.h define SSID and PASSWORD

This example accepts a few commands but is easily extendable.

Code: Select allaffix@iMac ~$ telnet 192.168.0.22                                                                                                                                                           
Trying 192.168.0.22...
Connected to 192.168.0.22.
Escape character is '^]'.
Welcome to the simple Command TCP Server Example
>> sdkver
SDK Version : 2.0.0(5a875ba)
>> on
Switching LED On
>> off
Switching LED off
>> hello
Command not recognized
>> exit
Goodbye!
Connection closed by foreign host.


So heres the code!

mcu_map.h (nodeMCU pin mapping (LoLin))
Code: Select all#ifndef __MCU_MAP_H__
#define __MCU_MAP_H__
#define D3 0
#define D10 1
#define D4 2
#define D9 3
#define D2 4
#define D1 5
#define SD2 9
#define SD3 10
#define D6 12
#define D7 13
#define D5 14
#define D8 15
#define D0 16
#endif


user_main.c
Code: Select all#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "stdio.h"
#include "gpio.h"
#include "os_type.h"
#include "espconn.h"
#include "mcu_map.h"
#include "user_config.h"

LOCAL struct espconn esp_conn;
LOCAL esp_tcp esptcp;


// Define the local port
#define SERVER_LOCAL_PORT   23

/******************************************************************************
 * FunctionName : data_recv
 * Description  : receive data callback.
 * Parameters   : arg -- Additional argument to pass to the callback function
 * Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
data_recv(void *arg, char *data, unsigned short length)
{
   char *resp;
   struct espconn *conn = arg;
   os_printf("tcp recv : %s \r\n", data);

   // Handle Received Commands
   if(strstr(data, "on"))
   {
      resp = "Switching LED On\r\n>> ";
      GPIO_OUTPUT_SET(D1, 1); // Set LED on
   }
   else if(strstr(data, "off"))
   {
      resp = "Switching LED off\r\n>> ";
      GPIO_OUTPUT_SET(D1, 0); // Set LED off
   }
   else if(strstr(data, "exit"))
   {
      resp = "Goodbye!\r\n";
      espconn_sent(conn, resp, strlen(resp));
      espconn_disconnect(conn); // Disconnect from the client
   }
   else if(strstr(data, "sdkver"))
   {
      resp = "SDK Version : ";
      char *ver = (char *)system_get_sdk_version();
      resp = strcat(resp, ver);
      char *nl = "\r\n>> ";
      resp = strcat(resp, nl);
   }
   else
   {
      // Invalid Command
      resp = "Command not recognized\r\n>> ";
   }
   espconn_sent(conn, resp, strlen(resp)); // Send response
}

/******************************************************************************
 * FunctionName : connection_accept
 * Description  : Accept a TCP Connection
 * Parameters   : arg -- Additional argument to pass to the callback function
 * Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
connection_accept(void *arg)
{
    struct espconn *conn = arg;
    espconn_regist_recvcb(conn, data_recv); // Register callback for data recv
    char *prompt = "Welcome to the simple Command TCP Server Example\r\n>> ";
    espconn_sent(conn, prompt, strlen(prompt)); // Send a welcome message
}


/******************************************************************************
 * FunctionName : user_tcpserver_init
 * Description  : initialize a TCP server
 * Parameters   : port -- server port
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_tcpserver_init(uint32 port)
{
    esp_conn.type = ESPCONN_TCP; // Set TCP
    esp_conn.state = ESPCONN_NONE; // Set the current state to none
    esp_conn.proto.tcp = &esptcp; // Set Protocol
    esp_conn.proto.tcp->local_port = port; // Set Port

    espconn_regist_connectcb(&esp_conn, connection_accept); // Register a callback for accepted connections

    sint8 ret = espconn_accept(&esp_conn); // Accept a connection

    os_printf("espconn_accept [%d] !!! \r\n", ret);

}


LOCAL os_timer_t main_timer; // Timer to check IP

/******************************************************************************
 * FunctionName : user_esp_platform_check_ip
 * Description  : check whether get ip address
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_esp_platform_check_ip(void)
{
    struct ip_info ipconfig;

    os_timer_disarm(&main_timer); // Disable the Timer

    wifi_get_ip_info(STATION_IF, &ipconfig); // Get IP info and assign to the struct

    // Check we have an IP
    if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0) {
      user_tcpserver_init(SERVER_LOCAL_PORT); // Initialize the TCP Server
      GPIO_OUTPUT_SET(D2, 1); // Set IP Status Status LED HIGH

    } else {
       // Check we have access to the AP
        if ((wifi_station_get_connect_status() == STATION_WRONG_PASSWORD ||
                wifi_station_get_connect_status() == STATION_NO_AP_FOUND ||
                wifi_station_get_connect_status() == STATION_CONNECT_FAIL)) {

         os_printf("Failed to connect to AP!!! \r\n");
        } else {
           // Re-Arm the timers
            os_timer_setfn(&main_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);
            os_timer_arm(&main_timer, 100, 0);
        }
    }
}

/******************************************************************************
 * FunctionName : user_set_station_config
 * Description  : Configure ESP for WiFi Connection
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_set_station_config(void)
{
   char ssid[32] = SSID; // Defined in user_config.h
   char password[64] = PASSWORD; // Defined in user_config.h

   struct station_config stationConf;

   os_memcpy(&stationConf.ssid, ssid, 32); // Set SSID
   os_memcpy(&stationConf.password, password, 64); // Set Password
   wifi_station_set_config(&stationConf); // Set config

   // Set timer to check if we have an IP
   os_timer_disarm(&main_timer);
   os_timer_setfn(&main_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);
   os_timer_arm(&main_timer, 100, 0);
}

/******************************************************************************
 * FunctionName : user_init
 * Description  : Application Entry Point
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void user_init(void)
{
   os_printf("Command Accepting TCP Server Example\n");

   gpio_init();                  // Initialize GPIO
   GPIO_OUTPUT_SET(D4, 0);          // Set on board LED
   wifi_set_opmode(STATION_MODE);   // Set STATION Mode (0x01)
   user_set_station_config();      // Set Configuration

}
User avatar
By MartinC
#73475 Just FYI here's an alternate way of doing it without using timers (note the use of a WiFi Event handler to detect when we've been given an IP address):

Code: Select all//
//  tcpServer.c
// 
//
//  Created by MC on 25/01/2018.
//

#include <ets_sys.h>
#include <osapi.h>
#include <os_type.h>
#include <user_interface.h>
#include <espconn.h>

#include "../user_rf_cal_sector_set.c"

#define FLASH ICACHE_FLASH_ATTR     // put functions in IROM instead of IRAM

#define TCP_LOCAL_PORT 25867
#define WIFI_SSID "my_ssid"
#define WIFI_PASSWORD "my_password"


// function declarations
//
void initDoneCB(void);
void wifiEventCB(System_Event_t *);
void createTcpSocket(void);
void tcpConnectCB(void *);
void tcpRecvData(void *, char *, unsigned short);


// function definitions
//
void FLASH user_rf_pre_init(void) {
}


void FLASH user_init(void) {
    system_init_done_cb(&initDoneCB);
    wifi_set_event_handler_cb(&wifiEventCB);
}


void FLASH initDoneCB(void) {
    struct station_config stationConfig;
   
    wifi_set_opmode_current(STATION_MODE);
    strncpy((char *)stationConfig.ssid, WIFI_SSID, 32);
    strncpy((char *)stationConfig.password, WIFI_PASSWORD, 64);
    wifi_station_set_config_current(&stationConfig);
    wifi_station_connect();
}


void FLASH wifiEventCB(System_Event_t *pEvent) {
    switch(pEvent->event) {
        case EVENT_STAMODE_GOT_IP:
            os_printf("got IP address: %d.%d.%d.%d\n", IP2STR(&pEvent->event_info.got_ip.ip));
            createTcpSocket();
            break;
        case EVENT_STAMODE_CONNECTED:
            os_printf("connected to AP\n");
            break;
        default:
            break;
    }
}


void FLASH createTcpSocket(void) {
    static struct espconn conn1;
    static esp_tcp tcp1;
   
    // configure TCP protocol settings
    //
    tcp1.local_port = TCP_LOCAL_PORT;

    // create socket
    //
    conn1.type = ESPCONN_TCP;
    conn1.state = ESPCONN_NONE;
    conn1.proto.tcp = &tcp1;        // bind socket to protocol
   
    // register callback for TCP connection events
    //
    espconn_regist_connectcb(&conn1, &tcpConnectCB);
   
    // listen on tcp socket
    //
    espconn_accept(&conn1);
   
    os_printf("Listening on socket proto TCP, port %d\n", TCP_LOCAL_PORT);
}


void FLASH tcpConnectCB(void *pArg) {
    struct espconn *pConn = (struct espconn *)pArg;
   
    os_printf("connection from %d.%d.%d.%d port %d\n",
              IP2STR(pConn->proto.tcp->remote_ip),
              pConn->proto.tcp->remote_port);
   
    // register callback for data received on this connection
    //
    espconn_regist_recvcb(pConn, &tcpRecvData);
}


void FLASH tcpRecvData(void *pArg, char *pData, unsigned short len) {
    struct espconn *pConn = (struct espconn *)pArg;
   
    os_printf("received %d bytes from %d.%d.%d.%d port %d: \"%s\"\n",
              len,
              IP2STR(pConn->proto.tcp->remote_ip),
              pConn->proto.tcp->remote_port,
              pData);
}


credit to @kolban for introducing me to this technique.