/**
 * @file sdcard.ino
 * @author SeanKwok (shaoxiang@m5stack.com)
 * @brief M5CoreS3 MicroSD Card Test
 * @version 0.1
 * @date 2023-12-25
 *
 *
 * @Hardwares: M5CoreS3
 * @Platform Version: Arduino M5Stack Board Manager v2.0.9
 * @Dependent Library:
 * M5GFX: https://github.com/m5stack/M5GFX
 * M5Unified: https://github.com/m5stack/M5Unified
 * M5CoreS3: https://github.com/m5stack/M5CoreS3
 */
#include <SPI.h>
#include <SD.h>
#include <M5CoreS3.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>

// 标志位,初始状态为清醒
bool isAwake = true; 
// 记录上次收到 http command的时间
unsigned long lastHttpCommandTime = 0;

const char* ssid = "lemon_2.4";
const char* password = "shengaqiao";

WebServer server(80);

const int led = 13;

//根目录的处理器
void handleRoot() {
  // 收到Http的命令时更新时间
  lastHttpCommandTime = millis();
  digitalWrite(led, 1);
  server.send(200, "text/plain", "Hello from vermelia!");
  digitalWrite(led, 0);
}

//未找到的处理器
void handleNotFound() {
  // 收到Http的命令时更新时间
  lastHttpCommandTime = millis();
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

#define SD_SPI_SCK_PIN  36
#define SD_SPI_MISO_PIN 35
#define SD_SPI_MOSI_PIN 37
#define SD_SPI_CS_PIN   4

void listDir(fs::FS &fs, const char *dirname, uint8_t levels);

M5Canvas canvas(&CoreS3.Display);
M5GFX display = CoreS3.Display;

void printf_log(const char *format, ...);
void println_log(const char *str);
void setupWifi();
void setupSD();
void setupHTTPServer();
void wakeup();

void setupWifi() {
    delay(10);
    //初始化wifi部分
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.println("");

    // Wait for connection
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

    if (MDNS.begin("vermelia")) {
      Serial.println("MDNS responder started with [vermelia]");
    }
    //初始化wifi部分

}

void setupSD() {
    //初始化屏幕
    canvas.setColorDepth(1);  // mono color
    canvas.createSprite(CoreS3.Display.width(), CoreS3.Display.height());
    canvas.setPaletteColor(1, GREEN);
    canvas.setTextSize((float)canvas.width() / 160);
    canvas.setTextScroll(true);

    //初始化SD卡
    // SD Card Initialization
    SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN);

    if (!SD.begin(SD_SPI_CS_PIN, SPI, 25000000)) {
        // Print a message if the SD card initialization
        // fails orif the SD card does not exist.
        // 如果SD卡初始化失败或者SD卡不存在,则打印消息.
        println_log("Card failed, or not present");
        while (1)
            ;
    }

    uint8_t cardType = SD.cardType();

    if (cardType == CARD_NONE) {
        println_log("No SD card attached");
        return;
    }

    println_log("SD Card Type: ");
    if (cardType == CARD_MMC) {
        println_log("MMC");
    } else if (cardType == CARD_SD) {
        println_log("SDSC");
    } else if (cardType == CARD_SDHC) {
        println_log("SDHC");
    } else {
        println_log("UNKNOWN");
    }

    uint64_t cardSize = SD.cardSize() / (1024 * 1024);
    printf_log("SD Card Size: %lluMB\n", cardSize);

    //读取根目录并列出
    listDir(SD, "/", 0);
    printf_log("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
    printf_log("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}

//初始化HTTP服务器
void setupHTTPServer() {
    //初始化服务器部分
    server.on("/", handleRoot);

    server.on("/inline", []() {
      // 收到Http的命令时更新时间
      lastHttpCommandTime = millis();
      server.send(200, "text/plain", "this works as well");
    });

    server.onNotFound(handleNotFound);

    server.begin();
    Serial.println("HTTP server started");
    //初始化服务器部分结束
}

//收到的任何的http请求都会更新lastHttpCommandTime的值
//使得!isAwake && now - lastHttpCommandTime < 60000
//成立,继而loop当中会触发唤醒例程
void wakeup(){
    //显示图片
    display.wakeup();
    isAwake = true;
}

void setup() {
    CoreS3.begin();
    //启动LED灯,定义阵脚为13,要看看对不对的
    pinMode(led, OUTPUT);
    digitalWrite(led, 0);
    //灯显示结束
    //程序开始部分
    Serial.begin(115200);
    println_log("\nHello From SD card demo program");
    display.begin();

    //初始化wifi
    setupWifi();

    //初始化服务器
    setupHTTPServer();
    //初始化SD卡
    setupSD();
    //显示图片
    display.drawPngFile(SD, "/Base.png", 0, 0);
}


void loop() {
  //web服务器的死循环部分
  server.handleClient();
  delay(20);//allow the cpu to switch to other tasks

  unsigned long now = millis();  // Obtain the host startup duration.  获取主机开机时长

  // 如果 1 分钟内没有收到 HTTP command 消息,则休眠
  if (now - lastHttpCommandTime > 60000 && isAwake ) {
      // 在此处添加休眠的相关代码
      Serial.println("Going to sleep due to no HTTP messages for 1 minutes.");
      // 在此处调用相关的关机函数或执行关机操作
      display.sleep();
      // 进入睡眠状态后设置标志位为睡眠
      isAwake = false; 
  }else if (!isAwake && now - lastHttpCommandTime < 60000) {
        wakeup();
  }

}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
    printf_log("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if (!root) {
        println_log("Failed to open directory");
        return;
    }
    if (!root.isDirectory()) {
        println_log("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file) {
        if (file.isDirectory()) {
            Serial.print("  DIR : ");
            println_log(file.name());
            if (levels) {
                listDir(fs, file.path(), levels - 1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            println_log(String(file.size()).c_str());
        }
        file = root.openNextFile();
    }
}


void printf_log(const char *format, ...) {
    char buf[256];
    va_list args;
    va_start(args, format);
    vsnprintf(buf, 256, format, args);
    va_end(args);
    Serial.print(buf);
    canvas.printf(buf);
    canvas.pushSprite(0, 0);
}

void println_log(const char *str) {
    Serial.println(str);
    canvas.println(str);
    canvas.pushSprite(0, 0);
}





import requests
from requests.adapters import HTTPAdapter
from urllib3 import Retry
import keyboard

def call_url_on_f2():
    url = "http://vermelia/inline"
    # 设置重试策略
    retry_strategy = Retry(
        total=10,  # 最大重试次数为 3 次
        backoff_factor=1,  # 重试间隔时间,以秒为单位,每次重试间隔时间为 backoff_factor * (2 ** (重试次数 - 1))
        status_forcelist=[500, 502, 503, 504]  # 只有在这些状态码时才进行重试
    )
    adapter = HTTPAdapter(max_retries=retry_strategy)
    http = requests.Session()
    http.mount("https://", adapter)
    http.mount("http://", adapter)

    try:
        response = http.get(url)
        if response.status_code == 200:
            print("Request successful.")
        else:
            print(f"Request failed with status code {response.status_code}.")
    except requests.exceptions.RequestException as e:
        print(f"An error occurred: {e}")

keyboard.add_hotkey('f2', call_url_on_f2)

keyboard.wait()