0


ESP32日历(水墨屏黄历,https请求解析,自动休眠唤醒,代码开源!)

简述:小项目不到300行,包括platfromIO环境搭建,水墨屏显示,字库制作,https请求解析,定时休眠唤醒,适合刚入门esp32的同学们。

代码链接 esp32LunarDay: esp32赛博黄历,水墨屏显示,定时刷新

0.platfromIO环境搭建

参考博客:ESP32(VSCode+PlatformIO)开发环境搭建教程(2024版)_esp32 vscode-CSDN博客

0-1.选择芯片类型, 添加对应库文件

   ![](https://i-blog.csdnimg.cn/direct/721edf5718a04c7d83065b431bb1e144.png)

0-2.显示helloworld

  display.init(115200);
  display.setRotation(1);
  display.setFont(&FreeSansBold24pt7b);
  display.setCursor(60,60);
  display.setTextColor(GxEPD_BLACK);
  display.print("hello world!");
  display.firstPage();

1.水墨屏显示字符

1-1.U8g2显示中文汉字 vscode代码设置编码:UTF-8!!!

U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;//全局变量

void showData()
{
  Serial.println("Enter showData");
  display.fillScreen(GxEPD_WHITE);

  u8g2Fonts.setForegroundColor(GxEPD_RED);//设置前景色(文字颜色)
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);//设置背景色

  display.setRotation(1);//屏幕方向
  u8g2Fonts.setFont(u8g2_font_wqy12_t_chinese1);//设置 _wqy_字体
  u8g2Fonts.setCursor(160,70);
  u8g2Fonts.print("你好呀!");

}

1-2.自定义字库文件显示

    显示自己喜欢的字体参考:Adafruit_GFX u8g2库添加中文字体_u8g2 字体-CSDN博客

需要的黄历汉字太多,快速生成:python获取黄历统计字符并去重

2.https请求与解析

2-1.对应的api接口

这里我用的是免费的API,也可以替换为你自己的;

https://www.36jxs.com/api/Commonweal/almanac?sun=2026-12-30

2-2.发起请求 解析数据

esp32发起https请求,和http有一点区别,代码如下:

String connectLunar(String &str_time)
{
  String str_org_data = "";
  WiFiClientSecure client;

  client.setInsecure();
  if (!client.connect("www.36jxs.com", 443))
  {
    Serial.println("www.36jxs.com  failed");
    return String("Connect www.36jxs.com  failed");
  }

  Serial.println("Connection 36jxs success");
  //发送Get请求 
  client.print(String("GET /api/Commonweal/almanac?sun=") + str_time.c_str() + " HTTP/1.1\r\n" +
               "Host: www.36jxs.com\r\n" +
               "Connection: close\r\n" +
               "User-Agent: ESP8266\r\n" +
               "\r\n");

  while (client.connected() || client.available())
  {
    if (client.available())//读取数据并存入 str_org_data
    {
      str_org_data += client.readStringUntil('\r');
    }
  }
  Serial.println(str_org_data);
  client.stop();
  return str_org_data;
}

存储数据 std::map

原生自带的C++没有相关容器,这里我们引入需要头文件#include <ArxContainer.h>

#include <ArxContainer.h>
std::map<String, String> dataMap;

添加后可使用C++一系列容器,对上面获取解析内容进行存储。

解析Json数据:

void parseJsonString(String &strClear)
{
  int istart = strClear.indexOf("}}");
  int iend = strClear.indexOf("{\"code\"");
  String strrDate = strClear.substring(iend, istart + 2);//截取JSon字符串部分
  Serial.println("===========strDate begin=========");
  Serial.println(strrDate);
  Serial.println("===========strDate end=========");
  DynamicJsonDocument doc(2048); // 创建一个JSON文档对象,指定缓冲区大小
  DeserializationError error = deserializeJson(doc, strrDate);
  if (error)
  {
    Serial.print("Failed to parse JSON: ");
    Serial.println(error.c_str());
    return;
  }

  JsonObject data = doc["data"]; // 获取data字段的JsonObject
  // 遍历data字段中的所有子字段
  for (JsonPair kv : data)
  {
    String key = kv.key().c_str();
    String value = kv.value().as<String>();
    if (value.isEmpty())
    {
      value = "NULL";
    }
    dataMap[key] = value;
  }
  // 遍历并打印 dataMap 中的键值对
  for (auto const &pair : dataMap)
  {
    Serial.print("Key: ");
    Serial.print(pair.first);
    Serial.print(" ==== Value: ");
    Serial.println(pair.second);
  }
}

3.排版显示数据

可自行调整排版,实现效果;

因为自定义字体不能生成太大的字符(我不会 ┭┮﹏┭┮),所以数字显示使用display.print();中文部分使用U8g2.print();

显示大号日期数字:

  display.setFont(&FreeSansBold24pt7b);//设置文字字体
  display.setCursor(110, 330);//显示位置坐标 (x,y)
  display.setTextSize(6);//字体大小
  display.setTextColor(GxEPD_RED);//字体颜色

  String dateTime = dataMap["GregorianDateTime"]; //时间字符串
  if (dateTime.length() >= 2)
  {
    String lastTwoChars = dateTime.substring(dateTime.length() - 2);//获取最后两位日期进行显示
    display.print(lastTwoChars);
  }

显示黄历文字:

  u8g2Fonts.setCursor(160, 65);
  u8g2Fonts.print(String("宜 : " + dataMap["Yi"]));

  u8g2Fonts.setForegroundColor(GxEPD_GREEN);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
  u8g2Fonts.setCursor(160, 105);
  u8g2Fonts.print(String("忌 : " + dataMap["Ji"]));

  u8g2Fonts.setForegroundColor(GxEPD_ORANGE);
  u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
  u8g2Fonts.setCursor(200, 400);
  u8g2Fonts.print(String(dataMap["LMonth"]));
  u8g2Fonts.setCursor(260, 400);
  u8g2Fonts.print(String(dataMap["LDay"]));

4.设置休眠 定时更新

只获取一次接口数据,板子不需要一直运行,设置休眠并定时唤醒

4-1设置休眠

void deepSleepToMidnight()
{
  // 获取当前时间
  time_t now = time(nullptr);
  struct tm timeinfo;
  localtime_r(&now, &timeinfo);

  int currentSeconds = timeinfo.tm_hour * 3600 + timeinfo.tm_min * 60 + timeinfo.tm_sec;
  int secondsToMidnight = 86400 - currentSeconds;                // 一天86400秒 - 当前时间
  uint64_t oneDayMicros = secondsToMidnight * 1000ULL * 1000ULL; //uint64_t  (int 存不下)
  // 设置定时器唤醒时间
  esp_sleep_enable_timer_wakeup(oneDayMicros);
  // 进入深度睡眠模式
  Serial.println("Entering deep sleep..after " + String(oneDayMicros) + " wake up");
  esp_deep_sleep_start();
}

4-2打印唤醒原因

#include <esp_sleep.h>
#include <esp32/ulp.h>
esp_sleep_wakeup_cause_t wakeup_reason;//定义全局变量

void setup()
{
  // put your setup code here, to run once:

  Serial.begin(115200);
  Serial.println();
  Serial.println("setup");
  Serial.println("printlnwidth:" + String(display.width()));
  Serial.println("printlnheight:" + String(display.height()));

  // 获取睡眠唤醒原因
  wakeup_reason = esp_sleep_get_wakeup_cause();

  // 根据唤醒原因输出信息
  switch (wakeup_reason)
  {
  case ESP_SLEEP_WAKEUP_TIMER:
    Serial.println("Wake up from timer");
    break;
  case ESP_SLEEP_WAKEUP_ALL:
    Serial.println("ESP_SLEEP_WAKEUP_ALL");
    break;
  case ESP_SLEEP_WAKEUP_UNDEFINED:
    Serial.println("Wake up reason undefined");
    break;
  // 其他唤醒原因的case可以根据需要添加
  default:
    Serial.println("Wake up from other reasons");
    break;
  }
}

总结:

    完整代码已开源,需要自取哈~

    跑出来效果就是这样的啦!(屏幕磕到了┭┮﹏┭┮忽略就好~)

    ![](https://i-blog.csdnimg.cn/direct/638c132704e549e79d3eb0a1bbc4b676.jpeg)
标签: 开源

本文转载自: https://blog.csdn.net/weixin_56440631/article/details/142498266
版权归原作者 Tan Xi 所有, 如有侵权,请联系我们删除。

“ESP32日历(水墨屏黄历,https请求解析,自动休眠唤醒,代码开源!)”的评论:

还没有评论