先日の調査で、M5StickCとSDカードリーダーをつなぎ、センサで採取したデータを、SDカードに書き込むことができました(記事は こちら)。
今回は、SDカードに保存されているファイルを、Webサーバーに送信してみたいと思います。
こちら のページに、画像データをサーバーに送信する方法が書かれていたので、これを参考にさせていただきました。
まずは、Webサーバーに、以下のPHPプログラム「writefile.php」を設置し、同じ場所に「data_files」というフォルダをつくっておきます。
データを受信したら、「data_files」フォルダの下に、「<UNIX Time>.txt」という名前でファイル保存するプログラムです。
<?php
$data = file_get_contents('php://input');
$filename = "data_files/" .time() .".txt";
file_put_contents($filename, $data);
?>
M5StickCに書き込むスケッチは以下のとおりです。
#include <M5StickC.h>
#include <WiFi.h>
#include "SD.h"
#include "esp_http_client.h"
SPIClass SPI2;
File file;
const char* ssid = "XXXXXXXX";
const char* password = "XXXXXXXX";
char file_name[20] = "/test1.txt";
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
}
M5.Lcd.println(" CONNECTED");
SPI2.begin(0, 36, 26, -1); // SPI初期化
if(!SD.begin(-1, SPI2)) { // SDカード初期化
M5.Lcd.println("Card Mount Failed");
return;
}
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
file = SD.open(file_name, FILE_READ);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.print("FILE SIZE : ");
M5.Lcd.println(file.size());
char tmp_var[file.size()] = "";
while(file.available()) {
sprintf(tmp_var, "%s%c", tmp_var, char(file.read()));
}
file.close();
esp_http_client_config_t config = {0};
config.url = "http://XXXXXXXX/writefile.php";
config.method = HTTP_METHOD_POST;
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_post_field(client, (const char *)tmp_var, strlen(tmp_var));
esp_http_client_perform(client);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.println("FINISH");
esp_http_client_cleanup(client);
}
}
最初にWi-Fiネットワークに接続し、SDカードの初期化を行います。
ボタンを押すと、SDカード内の「test1.txt」ファイルを開き、その内容を指定したURLに送信します。
データ送信には「esp_http_client.h」というライブラリを使っています。
ほとんど理解できておらず、上記のサイトを参考に、見よう見まねでつくっているのですが、
- esp_http_client_init()
- → esp_http_client_set_post_field()
- → esp_http_client_perform()
- → esp_http_client_cleanup()
という手順でデータを送信することができるようです。
このスケッチを試してみたところ、小さいファイルは問題なく送信できたのですが、ファイルサイズが大きくなると送信できませんでした(5000バイト程度が上限)。
そのため、スケッチを以下のように変更しました。
#include <M5StickC.h>
#include <WiFi.h>
#include "SD.h"
#include "esp_http_client.h"
SPIClass SPI2;
File file;
const char* ssid = "XXXXXXXX";
const char* password = "XXXXXXXX";
char file_name[20] = "/test3.txt";
int var_size = 2000;
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
}
M5.Lcd.println(" CONNECTED");
SPI2.begin(0, 36, 26, -1); // SPI初期化
if(!SD.begin(-1, SPI2)) { // SDカード初期化
M5.Lcd.println("Card Mount Failed");
return;
}
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
file = SD.open(file_name, FILE_READ);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.print("FILE SIZE : ");
M5.Lcd.println(file.size());
char tmp_var[var_size+1] = "";
esp_http_client_config_t config = {0};
config.url = "http://XXXXXXXX/writefile.php";
config.method = HTTP_METHOD_POST;
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_open(client, file.size());
while(file.available()) {
sprintf(tmp_var, "%s%c", tmp_var, char(file.read()));
if(strlen(tmp_var)>=var_size) {
esp_http_client_write(client, (const char *)tmp_var, strlen(tmp_var));
sprintf(tmp_var, "");
M5.Lcd.print("*");
}
}
esp_http_client_write(client, (const char *)tmp_var, strlen(tmp_var));
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.println("FINISH");
esp_http_client_close(client);
esp_http_client_cleanup(client);
file.close();
}
}
ボタンを押すと、SDカード内の「test3.txt」ファイルを開き、その内容を送信します。
このスケッチでは、
- esp_http_client_init()
- → esp_http_client_open()
- → esp_http_client_write()
- → esp_http_client_close()
- → esp_http_client_cleanup()
という手順でデータを送信します。「esp_http_client_write()」を複数回繰り返すことで、ファイルサイズの大きなファイルも送信できます。
このスケッチを試してみたところ、250Kバイト程度のファイルを送信することができました。
なお、私がM5Stack、M5StickCの使い方を習得するのにあたっては、以下の書籍を参考にさせていただきました。
ごく基本的なところから、かなり複雑なスケッチや、ネットワーク接続など、比較的高度なものまで、つまづかずに読み進めていけるような構成になっており、大変わかりやすい本です。