M5シリーズ全機種でWifiをSTAかAP接続しWebDAVを実装してSDカードをPCのネットワークドライブに割り付ける話

#1. はじめに

お仕事でSDカード(TFカード)を扱う案件があり
ちょっとWEBを検索するともちろん lang-ship さんのところにたどり着く

https://lang-ship.com/blog/work/m5lite-sd/

1個のソースで全機種対応とか素晴らしすぎるので
ちょっとお借りして色々実装してみた

* FTPや普通のServerも試したのですがやはりWebDav最強です
* 最終的にはBLEで作りたいのですが　それはその時のお話をまた(謎

#2. 扱えるマイクロSDカードの種類

手元に多量にあった(支給された)SDカードシールドは至って普通のもの
但し書きには 32GByte までOK FORMAT は FAT or FAT32 との事
手元には 1Gbyte/2Gbyte/8Gbyte/16Gbyte/32Gbyte/128Gbyte のマイクロSDがあり
色々やってみた結果 128Gbyteまでは FAT32フォーマットで読み書き出来る事が分かりました
コマンドラインで FAT32 でフォーマット出来るのですが　今回は

https://www.iodata.jp/lib/software/i/1498.htm

を使って簡単にフォーマットしてみます

#3. WebDavのライブラリ

https://github.com/ardyesp/ESPWebDAV

まんまのライブラリがありましたので
これを使わさせて頂きます
また　デバイス取得ライブラリは lang-ship さんの

https://github.com/tanakamasayuki/ESP32LitePack

こちらを使わせて頂きます

#4. ソースコード
以下の4本のコードを同じフォルダに入れて作業を行って下さい

``` SDCardServer.ino
#include <M5Lite.h>

#include "Device.h"
#include "Ap.h"
#include "Server.h"

void setup() {
  M5Lite.begin();
  setupDevice();
  setupServer(!M5Lite.BtnA.isPressed());
}

void loop()
{
  loopServer();
  M5Lite.Ex.delay(1);
}
```
``` Ap.h
#include <WiFi.h>

#define APSSID      "WebSDav"
#define APPSK       "#WebSDav#"
#define STASSID     "********" // ご自分のルータSSID
#define STAPSK      "********" // ご自分のルータPassword
#define HOSTNAME    "WebSDav"

void setupSTA() {
  WiFi.persistent(true);
  WiFi.setHostname(HOSTNAME);
  WiFi.mode(WIFI_STA);
  Serial.begin(115200);
  WiFi.begin(STASSID, STAPSK);
  Serial.println("Connecting to " STASSID " ...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to "); Serial.println(STASSID);
  Serial.print("IP address: "); Serial.println(WiFi.localIP());
  Serial.print("RSSI: "); Serial.println(WiFi.RSSI());
}

void setupAP() {
  IPAddress ip(192, 168, 4,  1);
  IPAddress subnet(255, 255, 255, 0);
  WiFi.softAPConfig(ip, ip, subnet);
  WiFi.softAP(APSSID, APPSK);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("Connected to "); Serial.println(APSSID);
  Serial.print("IP address: "); Serial.println(myIP);
}

``` 
``` Device.h
SPIClass SPI_EXT;

void setupDevice() {
  if (M5.Ex.board == lgfx::board_M5Stack) {
    // AutoStart
  } else if (M5.Ex.board == lgfx::board_M5StackCore2) {
    // AutoStart
  } else if (M5.Ex.board == lgfx::board_M5StickC) {
    // SD   M5StickC
    // 3V3  3V3
    // GND  GND
    // CLK  GPIO0
    // MISO GPIO36
    // MOSI GPIO26
    // CS   GND
    SPI_EXT.begin(0, 36, 26, -1);
    SD.begin(-1, SPI_EXT);
  } else if (M5.Ex.board == lgfx::board_M5StickCPlus) {
    // SD   M5StickC
    // 3V3  3V3
    // GND  GND
    // CLK  GPIO0
    // MISO GPIO36
    // MOSI GPIO26
    // CS   GND
    SPI_EXT.begin(0, 36, 26, -1);
    SD.begin(-1, SPI_EXT);
  } else if (M5.Ex.board == lgfx::board_unknown) {
    // SD   ATOM(Lite, Matrix) Doesn't work with Echo!
    // 3V3  3V3
    // GND  GND
    // CLK  GPIO23
    // MISO GPIO33
    // MOSI GPIO19
    // CS   GND
    SPI_EXT.begin(23, 33, 19, -1);
    SD.begin(-1, SPI_EXT);
  }
}

```
``` Server.h
#include <WiFi.h>
#include <ESPmDNS.h>
#include <ESPWebDAV.h>

#define SERVER_STA  0
#define SERVER_AP   1

FS& gfs = SD;

// WiFiServerSecure tcp(443);
WiFiServer tcp(80);

ESPWebDAV dav;

void setupServer(uint16_t kind) {
  if (kind) setupSTA();
  else      setupAP();
  MDNS.begin(HOSTNAME);
  tcp.begin();
  dav.begin(&tcp, &gfs);
  dav.setTransferStatusCallback([](const char* name, int percent, bool receive) {
    Serial.printf("%s: '%s': %d%%\n", receive ? "recv" : "send", name, percent);
  });
  Serial.print(HOSTNAME);
  Serial.println(" Server Started");
}

void loopServer()
{
  dav.handleClient();
}

```

#5. ネットワークドライブとして認識させる(STAモード)

まずは何もしないでM5を立ち上げるとDHCPにネットワークIPが割り振られます
今回は 192.168.1.11 に割り振られました
これを.... mDNS がいい感じで　"WebSDav.local" とし名前を付けてくれます

エクスプローラで 何もない場所に
![NetWorkScrn.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/23b7415d-4f77-0139-0cdf-20ac974d6785.jpeg)

`file`://WebSDav\DavWWWRoot としてやるとあら不思議 SDカードの中身が見えます
![NetWorkScrn2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/48d3e230-adf3-e72b-de73-e8ef28ed707d.jpeg)

そのままリンクをショートカットしデスクトップへ
![NetWorkScrn3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/ffbd5e9a-4eeb-49aa-7e0c-d723b4c5f133.jpeg)

そのショートカットを右クリックでネットワークフォルダとして `S:` に割付
![NetWorkScrn5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/0817ff69-b5f3-d37d-d5a4-d96379644ccc.jpeg)

をを S: ドライブが出来ました
![NetWorkScrn6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/1f861db1-0129-a151-d3ea-b668c2e2405a.jpeg)

コマンドプロンプトでも S: ドライブが見えてます
![NetWorkScrn7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/384440f4-1ee6-5fc5-ab2d-90490f1e23a5.jpeg)

デスクトップに Sample.txt を作って中身に `Hoge?` と書込み
![NetWorkScrn8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/2670b747-1f22-96cf-f688-464edb853dbd.jpeg)

その　Sample.txt をドラッグして S: ドライブにドロップすると
![NetWorkScrn9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/8dbb19b3-504f-ee84-9506-5490f8d8baed.jpeg)

これもいい感じでファイルを書込む事が出来ます
![NetWorkScrn10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/73e46009-5721-c4e0-8533-b6ecb4cdb874.jpeg)

#6. iPhone からのアクセス

WevDav のクライアントとして今回は ES File Explorer を使いました
![ip01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/c3f302e5-f9df-5e3f-76be-f5eb2ea5838d.png)

サービスから一番下のWebDavを選択し
![ip02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/f4e1d172-fa8b-0b6a-fbb6-10bd1d6bd20a.png)

URL に `http://WebSDav.local/`

![ip04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/90e9ad2d-42bc-2f20-a30f-0903aba18fbe.png)


![ip05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/da0940c4-8ae5-7dee-cbdf-8c4945786228.png)

先ほどPC上でドラッグドロップした Sample.txt が見えます
![ip06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/77f935c0-8b8d-9a08-027a-f6460d3f165b.png)

もちろん中身も見ることが出来ます
![ip07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2063214/ce16f9a1-07dc-89e7-5a3d-f78caba31df1.png)

#6. ポータブルドライブとして認識させる(APモード)
M5のボタンを押しながらRESET掛けると
APモードで起動されます

``` 
  #define APSSID      "WebSDav"
  #define APPSK       "#WebSDav#"
  IPAddress ip(192, 168, 4,  1);
  setupServer(!M5Lite.BtnA.isPressed());
```
アクセスポイントとして上記が設定されていますので
お出かけ先でSDカードを読み書きしなければ成らない場合でも安心です...

#7. アクセスの速度は?
遅い..遅すぎる..
なんとか高速化できないか対応中です

#8. さいごに
いつも素敵なヒントを下さる lang-ship さんに感謝です
よろしくお願い申し上げます