わいずふぁくとりいがプログラムの話題をウィキします。

ファイルウォッチプロトコル


(ESP32のWiFi機能で別のファイルシステムの状態を監視する-3)

 別のファイルシステムへ状況を見に行く何らかのインターフェースはファイルウォッチプロトコルと名づけ、ポート番号49999に実装した。
 どのようなインターフェースでも実現しやすいように、単純なコマンドレスポンス型としている。

 もっとも今回実装したのは疑似的にファイルリストを返すものだけで、「#fw:list」というコマンドを打てば、ファイル名とサイズがコンマ区切りで返される。
 ファイルサイズは問い合わせが来るたびに111バイトずつ増えていくように装っている。
 非常にたくさんのファイルリストを返す場合どうするか、タイムスタンプなどの情報も返すか?など、考えないといけないことも残っている。

 以下は引き続きESP32の実装である。
 パソコン側の実装はつぎの記事に載せる。

FWServer.h
#ifndef FW_SERVER_H
#define FW_SERVER_H

class FWServer
{
  private:
    WiFiServer m_server;
    WiFiClient m_client;

    bool ReceiveResponse(void);
    bool ParseResponseToken(void);
  
  public:
    FWServer(int port);
    void setup(void);
    void loop(void);

    bool List(void);
    bool Send(char* msg);

    class Response
    {
      public:
        static const int TOKEN_MAX = 32;
        static const int BUFFER_MAX = 128;
        char* Token[TOKEN_MAX];
        int NofToken;
        char Buffer[BUFFER_MAX];
      private:
        friend FWServer;
        char* m_p;
        int m_counter;
    }
    m_response;
};

#endif//FW_SERVER_H

FWServer
#include "FWServer.h"

FWServer::FWServer(int port)
: m_server(port)
{
}

void FWServer::setup(void)
{
  m_server.begin();
}

bool FWServer::List(void)
{
  if(!m_client)
  {
    Serial.println("FW: no client");                       
    return false;
  }
  if(!m_client.connected())
  {
    Serial.println("FW: no connected");                       
  }
  m_client.print("#fw:list\r");
  return ReceiveResponse();
}

bool FWServer::ParseResponseToken(void)
{
  char* p = &m_response.Buffer[0];
  char** token_p = &m_response.Token[0];
  m_response.NofToken = 0;
  bool out = true;
  for(int i=0; i<m_response.m_counter; ++i, ++p)
  {
    if(out)
    {
      if(*p==' ' || *p == '\t')
      {
        continue;        
      }
      else
      {
        *token_p++ = p;
        out = false;
      }
    }
    if(*p == '\r')
    {
      *p = '\0';
      ++m_response.NofToken;
      return true;
    }
    if(*p == ',')
    {
      *p = '\0';
      out = true;
      if(m_response.NofToken>=Response::TOKEN_MAX)
      {
        return false;
      }
      ++m_response.NofToken;
    }
  }
  return true;
}

bool FWServer::ReceiveResponse(void)
{
    if(!m_client)
    {
      Serial.println("FW: no client");                       
      return false;
    }
    m_response.m_p = &m_response.Buffer[0];
    m_response.m_counter = 0;
    while (m_client.connected())            // loop while the client's connected
    {
      if (m_client.available())             // if there's bytes to read from the client,
      {
        char c = m_client.read();           // read a byte, then
        if (c=='\r')
        {
          if(m_response.m_counter<Response::BUFFER_MAX-2)
          {
            *m_response.m_p++ = c;
            ++m_response.m_counter;
          }
          if(m_response.m_counter<Response::BUFFER_MAX-1)
          {
            *m_response.m_p++ = '\0';
            ++m_response.m_counter;
          }
          ParseResponseToken();
          break;
        }
        else
        {
          if(m_response.m_counter<Response::BUFFER_MAX-1)
          {
            *m_response.m_p++ = c;
            ++m_response.m_counter;
          }
        }
      }
    }
}

void FWServer::loop(void)
{
  if (!m_client)
  {
    m_client = m_server.available();      // listen for incoming clients
    if (m_client)                         // if you get a client,
    {              
      Serial.println("FW: New Client.");  // print a message out the serial port
    }
  }
}

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

管理人/副管理人のみ編集できます