// FactoryTestをWebからダウンロードして書き込む
// 参考:https://lang-ship.com/blog/work/m5stickc-web-update-ota/
#include <M5StickCPlus.h>
#include <WiFi.h>
#include <Update.h>
const char *ssid = "ics-ap"; // 802.11b/g (2.4GHz)only. 5GHz is not supported.
const char *password = "jikkenics";
WiFiClient client;
void execOTA(String host, int port, String bin);
void lcdprintln(String mes, uint16_t color, int y)
{
if (y == 0)
M5.Lcd.fillScreen(color);
if (y < 999)
M5.Lcd.setCursor(0, y, 4);
M5.Lcd.setTextColor(BLACK, color);
M5.Lcd.println(mes);
}
void setup()
{
M5.begin();
M5.Lcd.setRotation(3);
lcdprintln(" -- WebOTA --\n\n wifi connecting...", ORANGE, 0);
WiFi.begin(ssid, password); // 接続開始
while (WiFi.status() != WL_CONNECTED)
{ // 接続中...
M5.Beep.tone(2000);
delay(200);
M5.Beep.mute();
delay(1000);
M5.Lcd.print(".");
}
// 接続完了!!
M5.Beep.tone(4000);
lcdprintln(" Wifi Connected!\n ", GREEN, 0);
String gotip = WiFi.localIP().toString(); // m5デバイスのIPアドレス
M5.Lcd.println(gotip);
delay(1500);
M5.Beep.mute();
String host = "cit.istlab.info";
int port = 80;
String bin = "/f/M5StickCPlus_FactoryTest2022.ino.bin";
execOTA(host, port, bin);
}
void loop()
{
}
// Utility to extract header value from headers
String getHeaderValue(String header, String headerName)
{
return header.substring(strlen(headerName.c_str()));
}
// OTA Logic
void execOTA(String host, int port, String bin)
{
// Connection Succeed
Serial.println("");
Serial.println("Connected to Wi-Fi");
long contentLength = 0;
bool isValidContentType = false;
lcdprintln(" Downloading...", YELLOW, 0);
if (client.connect(host.c_str(), port))
{
Serial.println("Fetching Bin: " + String(bin));
client.print(String("GET ") + bin + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Cache-Control: no-cache\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 5000)
{
Serial.println("Client Timeout !");
client.stop();
return;
}
}
while (client.available())
{
String line = client.readStringUntil('\n');
line.trim();
if (!line.length())
{
break;
}
if (line.startsWith("HTTP/1.1"))
{
if (line.indexOf("200") < 0)
{
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
break;
}
}
if (line.startsWith("Content-Length: "))
{
contentLength = atol((getHeaderValue(line, "Content-Length: ")).c_str());
Serial.println("Got " + String(contentLength) + " bytes from server");
}
if (line.startsWith("Content-Type: "))
{
String contentType = getHeaderValue(line, "Content-Type: ");
Serial.println("Got " + contentType + " payload.");
if (contentType == "application/octet-stream")
{
isValidContentType = true;
}
}
}
}
else
{
Serial.println("Connection to " + String(host) + " failed. Please check your setup");
}
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
if (contentLength && isValidContentType)
{
bool canBegin = Update.begin(contentLength);
if (canBegin)
{
lcdprintln(" Downloaded.\n Upgrading...(wait 2-3 min.)", GREENYELLOW, 999);
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
size_t written = Update.writeStream(client);
if (written == contentLength)
{
Serial.println("Written : " + String(written) + " successfully");
}
else
{
Serial.println("Written only : " + String(written) + "/" + String(contentLength) + ". Retry?");
}
if (Update.end())
{
M5.Beep.tone(4000);
lcdprintln("\n\n OTA Done. \n shutdown now", GREENYELLOW, 0);
delay(2000);
M5.Beep.mute();
Serial.println("OTA done!");
if (Update.isFinished())
{
Serial.println("Update successfully completed. Rebooting.");
// ESP.restart();
M5.Axp.Write1Byte(0x32, M5.Axp.Read8bit(0x32) | 0x80); // 電源OFF
}
else
{
Serial.println("Update not finished? Something went wrong!");
}
}
else
{
Serial.println("Error Occurred. Error #: " + String(Update.getError()));
}
}
else
{
Serial.println("Not enough space to begin OTA");
client.flush();
}
}
else
{
Serial.println("There was no content in the response");
client.flush();
}
}