上位に戻る ESP32 FTPでサーバにアップロード 初版2025/1/10

ESP32 雨検出器を作りたく始めたのですが、色々引っかかったので、記録しておこうと思います
計測したデータをグラフ表示したく、FTPでサーバにアップロードしてみました
FTPクライアントのライブラリがあるので簡単かと思いきやディレクトリの一覧取得に時々失敗する不具合に遭遇して
しまいました
ディレクトリが無い場合にディレクトリを作成する関数を作ったので記載しておきます
しかし、ESP32_FTPClient.h 詳しい説明が見当たらない・・・・・。

  1. FTPサーバについて
    もともと、FTPサーバは、フリーソフトのFileZillaを使っていて最近は外部から使わないのでルータで接続ポートを閉じていました
    ESP32から接続を試みるも、ログインは出来ますが、ファイル転送や、リスト表示はエラーになります
    ネットの情報を調べてたらFileZillaのバージョンが、今使ってるのが0.9.60beta 最新は、1.9.4 かなりバージョンが古いのでとりあえ
    バージョンアップしてみました
    アカウントなどの設定情報は引き継ぐみていですが、いきなりログインすら出来なくなりました なんじゃこれ!!
    しかも設定画面が、以前とまったく違う ムズ・・・・。
    インストールで、TLSの独自証明書を作るみたいなメッセージが出たような気がする・・・・。
    無料の認証局Let'sEncryptsのメニューが増えてるので外部公開するなら使いやすくはなってますね
    どうやら接続Protocolがデフォルトで、FTPoverTLS
    に設定されるので、平文のログインが出来なくなって
    いました
    今時平文ログインは危険すぎるか・・・。
    まあ今回は、LAN内で外部とは接続しないし
    ESP32で使うライブラリがTLSに対応していないので
    しょうがない
    TLSと、平文が出来るモードに変更しました
    サーバのファイアウォールの設定を変更しないといけないの
    で、旧設定を見て気が付きました
    20と21番ポートしか透過設定されていません
    パッシブ用のポート設定めんどかったのでしていなかったこ
    とを思い出しました
    今回は、LAN内なのでパッシブ用の専用ポートは設定せず
    に、アプリベースの許可を設定しました

    で、以上の変更でファイルのアップロードやリストの取得が動いたのでやれやれ
    ESP32から10分毎にデータを送付するようにしてテストしたところ、たまにデータが送られていない時があります
    調べていくと、フォルダを作成するときに、ディレクトリの一覧を取得していますが、この時に一覧に抜けがあるこ
    が判りました WindowsのFTPコマンドでは正常です・・・・。

    まいったねえ コマンドではエラーを検出してないしなんだろげ?
    で、別のパソコンで、WindowsのIISを有効にしてftpサーバを起動させて設定してテストしたところ
    アップロードの抜けはありません
    もう仕方ない・・・wiresharkを入れて通信をキャプチャしました ダムハブ持っていないので横取りできない サーバには
    インストしたくないのでまたまた別パソコンにインストしてテスト
    比較したところ、FileZillaの場合、最初にTLSの接続を試みてダメな場合平文の通信に移行しています
    ログインの時に平文であってもそれ以降のデータ通信でも毎回TLSの通信を試みてきます
    どうもこれが影響しているとしか思えません

    FileZillaで、平文のみの通信に出来ないか調べましたが 出来ない模様 もうしゃあない 旧バージョンに戻したところ
    正常になりました



    このFTPクライアントのライブラリを使われる場合は、ftpサーバ IISがいいかと思います
    私の場合 Webサーバが、また別のフリーソフトなのでIISのftpが使えません
    (IISは、ユーザがWindowsと連携していて、OSのアカウントを作る必要があるのと、フォルダのアクセス権などの
    設定に留意が必要ですね・・・。)

  2. FTP転送のスケッチ例
    指定のディレクトリにファイルを保存します。その際、ディレクトリが無い場合は、ディレクトリを作成ます


    #include <WiFi.h>
    #include <WiFiClient.h>
    #include <ESP32_FTPClient.h>

    #define ssid "SSIDDESU"
    #define password "passworddesu"
    char ftp_server[] = "192.xxx.xxx.xxx";
    char ftp_user[]   = "usernamae";
    char ftp_pass[]   = "passworddesu";
    //wifi接続
    int lpcnt;
    int lpcnt2;

    // you can pass a FTP timeout and debbug mode on the last 2 arguments
    ESP32_FTPClient ftp (ftp_server,ftp_user,ftp_pass, 5000, 2);//2でデバッグ 1で無し

    void setup()
    {
    //SPIFFS.format();
      Serial.begin( 115200 );

      delay(500);
      // ssidとpasswordを用いてWi-Fiに接続
      Serial.print("Connecting to ");
      Serial.println(ssid);
       while (WiFi.status() != WL_CONNECTED) {    // 接続確認
          delay(500);                            //   0.5秒毎にチェック
          lpcnt += 1 ;                           //
          if (lpcnt > 6) {                       // 6回目(3秒) で切断/再接続
            WiFi.disconnect(true,true) ;         //
            WiFi.begin(ssid, password);    //
            lpcnt = 0 ;                          //
            lpcnt2 += 1 ;                        // 再接続の回数をカウント
          }                                      //
          if (lpcnt2 > 3) {                      // 3回 接続できなければ、
            ESP.restart() ;                      // ソフトウェアリセット
          }                                      //
          Serial.print(".");                     //
      }            
     
      // IPアドレスを出力し、webserverをスタート
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());

      ftp.OpenConnection();//ftp転送開始
      mkdirs("Testdirectory"); //Testdirectoryが無ければディレクトリを作成する
      ftp.ChangeWorkDir("Testdirectory");//ディレクトリを移動
      ftp.InitFile("Type A");//アスキーモードで転送
      ftp.AppendFile("TestFileName.csv");//転送するファイルの名前
      ftp.Write("data1,data2,data3");//ファイルの中身を書き出し
      ftp.CloseFile();
      ftp.CloseConnection();
    }

    //ftp ディレクトリが無ければ作成
    void mkdirs(String dirString){
     char dirName[256];
     int flgmkdir=0;
     strcpy(dirName,dirString.c_str());//stringをcharに変換
     
     for(int iii=0; iii < 2; iii++) //フォルダが見つからないかリトライ 無くてもよい
     {
     ftp.InitFile("Type A");
     String list[128]={};
     ftp.ContentListWithListCommand("", list);
     //sizeof(list)は、byteを返すのでlistの個数ではない
     //ライブラリのサンプルを流用の為 配列サイズ128でよい
      for( uint8_t imm = 0; imm < sizeof(list); imm++)
      {
       
        if(list[imm].length() > 0)
        {
          String str=list[imm];
          Serial.print("フォルダ名:");
          Serial.println(str);
          str.trim();
          dirString.trim();
          if( str==dirString )
          {
          flgmkdir=1;
          Serial.println("見つかりました");
          break;
          }
         
       }
        else
          break;
       }
       if(flgmkdir==1){break;}
     }
       if(flgmkdir==0){
          Serial.println("見つかりませんでした作成します");
          ftp.InitFile("Type A");
          ftp.MakeDir(dirName);
          }
    }
    void loop()
    {

    }










    以上間違い等ありましたら、以下ご意見箱にお願いします

   

    ご意見箱