esp-open-rtosを使ってみる

Telnet Server

examples/access_pointに、すごく簡単なTelnetサーバーのサンプルが含まれています。
lwIPのSequential-style API(Netconn API)が使われています。
そのままでは全ての応答を受けとれなかったので、netconn_delete()の前に少し時間待ちのためのvTaskDelay()を追加し てビルドしました。
        netconn_write(client, buf, strlen(buf), NETCONN_COPY);
        vTaskDelay(100);
        netconn_delete(client);

このサンプルは起動すると、SoftAPモードで動きます。
Telnet ServerとSoftAPモードは全く関係ないので、おそらくIPアドレスを固定にしたかったんだと思います。
APの接続情報は以下のように定義されています。
#define AP_SSID "esp-open-rtos AP"
#define AP_PSK "esp-open-rtos"

また、IPアドレスは以下のように定義されています。
    IP4_ADDR(&ap_ip.ip, 172, 16, 0, 1);
    IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0);
    IP4_ADDR(&ap_ip.netmask, 255, 255, 0, 0);

そこで、Linuxマシンを使って、このAPに接続し、telnetを使って172.16.0.1に接続してみました。
$ sudo nmcli d wifi connect "esp-open-rtos AP" password esp-open-rtos
Device 'wlp3s0' successfully activated with 'fbcada6c-0222-4db6-90f1-83f201cc315a'.

$ telnet 172.16.0.1
Trying 172.16.0.1...
Connected to 172.16.0.1.
Escape character is '^]'.
Uptime 37 seconds
Free heap 45020 bytes
Your address is 172.16.0.3

Connection closed by foreign host.

処理の一番最後でnetconn_delete()しているので、WindowsのTeraTermでは、接続しても一瞬動きますが、すぐに Disconnectされてしまい、
応答を見ることができません。



そこで、WindowsのTeraTermでも使えるTelnetサーバーを作ってみました。
接続するとプロンプトが表示されるのでexitで終了します。


コードはこちらで紹介しているSocket Serverを少し変えただけです。
Stationモードで動きますので、IPアドレスはDHCPから払い出されたものを使います。
/* The example of esp-free-rtos
 *
 * This sample code is in the public domain.
 */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "espressif/esp_common.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "ssid_config.h"
#include "esp8266.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

#define TELNET_PORT 23 // telnet port

SemaphoreHandle_t xSemaphore;

void showNetworkInfo() {
  uint8_t hwaddr[6];
  if (sdk_wifi_get_macaddr(STATION_IF, hwaddr)) {
    printf("[%s] MAC address="MACSTR"\n",pcTaskGetName(0),MAC2STR(hwaddr));
  }
  struct ip_info info;
  if (sdk_wifi_get_ip_info(STATION_IF, &info)) {
    printf("[%s] IP address="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.ip));
    printf("[%s] Netmask="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.netmask));
    printf("[%s] Gateway="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.gw));
  }
}

// Telnet Server Task
void task2(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);

  /* wait for Semaphore */
  xSemaphoreTake(xSemaphore, portMAX_DELAY);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Take\n",pcTaskGetName(0),nowTick);

  /* set up address to connect to */
  struct sockaddr_in srcAddr;
  struct sockaddr_in dstAddr;
  memset(&srcAddr, 0, sizeof(srcAddr));
  srcAddr.sin_family = AF_INET;
  srcAddr.sin_port = htons(TELNET_PORT);
  srcAddr.sin_addr.s_addr = INADDR_ANY;

  /* create the socket */
  int srcSocket;
  int dstSocket;
  socklen_t dstAddrSize;
  int ret;
  int numrcv;

  srcSocket = lwip_socket(AF_INET, SOCK_STREAM, 0);
  LWIP_ASSERT("srcSocket >= 0", srcSocket >= 0);

  /* bind socket */
  ret = lwip_bind(srcSocket, (struct sockaddr *)&srcAddr, sizeof(srcAddr));
  /* should succeed */
  LWIP_ASSERT("ret == 0", ret == 0);

  /* listen socket */
  ret = lwip_listen(srcSocket, 5);
  /* should succeed */
  LWIP_ASSERT("ret == 0", ret == 0);

  char buf[1024];
  while(1) {
    // 接続の受付け
    printf("[%s:%d] 接続を待っています クライアントプログラムを動かして下さい\n",pcTaskGetName(0),nowTick);
    dstAddrSize = sizeof(dstAddr);
    dstSocket = lwip_accept(srcSocket, (struct sockaddr *)&dstAddr, &dstAddrSize);
    printf("[%s:%d] dstSocket=%d\n",pcTaskGetName(0),nowTick,dstSocket);
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] %s から接続を受けました\n",pcTaskGetName(0),nowTick,inet_ntoa(dstAddr.sin_addr));

    snprintf(buf, sizeof(buf), "Uptime %d seconds\r\n", xTaskGetTickCount() * portTICK_PERIOD_MS / 1000);
    ret = lwip_write(dstSocket, buf, strlen(buf));
    snprintf(buf, sizeof(buf), "Free heap %d bytes\r\n", (int) xPortGetFreeHeapSize());
    ret = lwip_write(dstSocket, buf, strlen(buf));
    snprintf(buf, sizeof(buf), "Your address is %s\r\n\r\n", inet_ntoa(dstAddr.sin_addr));
    ret = lwip_write(dstSocket, buf, strlen(buf));

    while(1) { // クライアントがSocketをクローズしてからこちらもクローズする
      /* write prompt */
      strcpy(buf,"\r\n>");
      ret = lwip_write(dstSocket, buf, strlen(buf));

      /* read something */
      memset(buf,0,sizeof(buf));
      numrcv = lwip_read(dstSocket, buf, 1024);
      nowTick = xTaskGetTickCount();
      printf("[%s:%d] numrcv=%d\n",pcTaskGetName(0),nowTick,numrcv);
      if(numrcv ==0 || numrcv ==-1 ){ // client close socket
        lwip_close(dstSocket); break;
      }
      printf("Recv=[%s]",buf);
      if(strncmp(buf,"exit",4) == 0){
        lwip_close(dstSocket); break;
      }
    } // end while
  } // end for


  /* close (never come here) */
  ret = lwip_close(srcSocket);
  LWIP_ASSERT("ret == 0", ret == 0);
  vTaskDelete( NULL );

}

// WiFi Task
void task1(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);

  /* Wait until we have joined AP and are assigned an IP */
  int wifiStatus;
  while (1) {
    wifiStatus = sdk_wifi_station_get_connect_status();
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] wifiStatus=%d\n",pcTaskGetName(0),nowTick,wifiStatus);
    //if (sdk_wifi_station_get_connect_status() == STATION_GOT_IP) break;
    if (wifiStatus == STATION_GOT_IP) break;
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Connected to AP\n",pcTaskGetName(0),nowTick);
  showNetworkInfo();

  /* Now start task2 */
  xSemaphoreGive(xSemaphore);
  vTaskDelete( NULL );
}


void user_init(void)
{
  uart_set_baud(0, 115200);
  printf("SDK version:%s\n", sdk_system_get_sdk_version());
  printf("pcTaskGetName=%s\n",pcTaskGetName(0));

  struct sdk_station_config config = {
      .ssid = WIFI_SSID,
      .password = WIFI_PASS,
  };

  // Required to call wifi_set_opmode before station_set_config.
  sdk_wifi_set_opmode(STATION_MODE);
  sdk_wifi_station_set_config(&config);

  /* Create Semaphore */
  xSemaphore = xSemaphoreCreateBinary();
  /* Check everything was created. */
  configASSERT( xSemaphore );

  xTaskCreate(task1, "WiFi", 256, NULL, 2, NULL);
  xTaskCreate(task2, "Server", 512, NULL, 2, NULL);
}

続く....