mirror of
https://github.com/JADE-Jerry/jcalendar.git
synced 2025-12-13 12:58:12 +08:00
Compare commits
11 Commits
v1.0.22
...
3cbdda3c60
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cbdda3c60 | ||
|
|
a8a60e8286 | ||
|
|
bf390dada2 | ||
|
|
5856a84b8d | ||
|
|
e9c0b13c37 | ||
|
|
cdbca3ee29 | ||
|
|
b301ac575b | ||
|
|
0d11f01750 | ||
|
|
25101e659a | ||
|
|
8eab03f808 | ||
|
|
7057ef3d5b |
17
README.md
17
README.md
@@ -72,7 +72,9 @@ Bilibili连接:https://www.bilibili.com/video/BV1wHDhYoE3G/<br>
|
|||||||
* 0: 周日(默认); 1: 周一;
|
* 0: 周日(默认); 1: 周一;
|
||||||
* 和风天气:
|
* 和风天气:
|
||||||
* 输入和风天气的API Key和城市id(城市对应的id请在和风天气的官网查找。)系统会每2小时刷新当前天气,如果Key置空,天气将不会被刷新。<br>
|
* 输入和风天气的API Key和城市id(城市对应的id请在和风天气的官网查找。)系统会每2小时刷新当前天气,如果Key置空,天气将不会被刷新。<br>
|
||||||
* 天气类型:0:每日天气(默认,每天凌晨刷新一次); 1: 实时天气(每两个小时刷新一次天气)<br>[城市id列表](./assets/file/China-City-List-latest.csv) <br>
|
* 天气类型:0:每日天气(默认,每天凌晨刷新一次); 1: 实时天气(每两个小时刷新一次天气)<br>
|
||||||
|
* 位置:城市id或者经纬度 例1: 101010100 例2: 116.41,39.92<br>
|
||||||
|
[城市id列表](./assets/file/China-City-List-latest.csv) <br>
|
||||||
* 倒数日:<br>输入倒数日名称和日期,名称不能超过4个中文字符,时间以yyyyMMdd的格式填入。配置正确的话,日历每天会显示倒数“距****还有**天”。如果倒数日名称为空,系统将不显示倒数日信息。
|
* 倒数日:<br>输入倒数日名称和日期,名称不能超过4个中文字符,时间以yyyyMMdd的格式填入。配置正确的话,日历每天会显示倒数“距****还有**天”。如果倒数日名称为空,系统将不显示倒数日信息。
|
||||||
* 日期Tag:<br>
|
* 日期Tag:<br>
|
||||||
1. 输入格式,yyyyMMddx,yyyy为年,每年显示设为0000,MM为月份,每月显示设为00,dd为日期,x为tag的图标(a:书签;b:金钱;c:笑脸;d:警告)。例如:00000015b,每年每月15日旁边显示$符号;00000312a,每年3月12日,显示书签符号。
|
1. 输入格式,yyyyMMddx,yyyy为年,每年显示设为0000,MM为月份,每月显示设为00,dd为日期,x为tag的图标(a:书签;b:金钱;c:笑脸;d:警告)。例如:00000015b,每年每月15日旁边显示$符号;00000312a,每年3月12日,显示书签符号。
|
||||||
@@ -108,8 +110,21 @@ A: 1. 检查USB线连接是否正常。 <br>2. app的串口下拉框里是否检
|
|||||||
A: 1. 换根质量较好的或短一些的USB线,或换个USB口插入。 <br>2. 可以将刷新的波特率降低一点,如选择速率低一点的115200。
|
A: 1. 换根质量较好的或短一些的USB线,或换个USB口插入。 <br>2. 可以将刷新的波特率降低一点,如选择速率低一点的115200。
|
||||||
7. Q: 刷新固件后,需要重新配置吗?
|
7. Q: 刷新固件后,需要重新配置吗?
|
||||||
A: 仅刷新app固件后,配置是保留的,所以,无需重新配置。如果刷新了分区表partition.bin,会将esp的nvs区刷新,这时候需要重新配置。
|
A: 仅刷新app固件后,配置是保留的,所以,无需重新配置。如果刷新了分区表partition.bin,会将esp的nvs区刷新,这时候需要重新配置。
|
||||||
|
8. Q: 填入和风天气的API Key和位置ID后,没有成功获取天气信息。
|
||||||
|
A: 2025年3月1日后注册的和风天气账户有API Host限制,请下载1.0.25以后版本,在配置时配置API Host信息。
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
### 1.0.27
|
||||||
|
* Fix: 闰月错误。(bug from nongli lib)
|
||||||
|
### 1.0.26
|
||||||
|
* Refine: 显示当前为第**周。(国际标准(ISO 8601):以周一作为每周起始日)
|
||||||
|
### 1.0.25
|
||||||
|
* Fix: 和风天气api变更,需要输入API Host(在配置页面增加配置项)
|
||||||
|
### 1.0.24
|
||||||
|
* Refine: 配置页面location约束改为64长度,允许输入经纬度设置天气位置(e.g. 116.41,39.92)
|
||||||
|
### 1.0.23
|
||||||
|
* Refine: 修改和风天气请求url。
|
||||||
|
* Fix: bug(获取holiday返回码)。
|
||||||
### 1.0.22
|
### 1.0.22
|
||||||
* 项目开源:此项目使用GNU General Public License v3.0许可证授权。详情请参阅LICENSE文件。
|
* 项目开源:此项目使用GNU General Public License v3.0许可证授权。详情请参阅LICENSE文件。
|
||||||
* Refine:农历计算功能移出。(农历功能作为独立库,以MIT协议开源)
|
* Refine:农历计算功能移出。(农历功能作为独立库,以MIT协议开源)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,7 @@
|
|||||||
// !!!preferences key限制15字符
|
// !!!preferences key限制15字符
|
||||||
#define PREF_SI_CAL_DATE "SI_CAL_DATE" // 屏幕当前显示的日期
|
#define PREF_SI_CAL_DATE "SI_CAL_DATE" // 屏幕当前显示的日期
|
||||||
#define PREF_SI_WEEK_1ST "SI_WEEK_1ST" // 每周第一天,0: 周日(默认),1:周一
|
#define PREF_SI_WEEK_1ST "SI_WEEK_1ST" // 每周第一天,0: 周日(默认),1:周一
|
||||||
|
#define PREF_QWEATHER_HOST "QWEATHER_HOST" // QWEATHER HOST
|
||||||
#define PREF_QWEATHER_KEY "QWEATHER_KEY" // QWEATHER KEY/TOKEN
|
#define PREF_QWEATHER_KEY "QWEATHER_KEY" // QWEATHER KEY/TOKEN
|
||||||
#define PREF_QWEATHER_TYPE "QWEATHER_TYPE" // 0: 每日天气,1: 实时天气
|
#define PREF_QWEATHER_TYPE "QWEATHER_TYPE" // 0: 每日天气,1: 实时天气
|
||||||
#define PREF_QWEATHER_LOC "QWEATHER_LOC" // 地理位置
|
#define PREF_QWEATHER_LOC "QWEATHER_LOC" // 地理位置
|
||||||
|
|||||||
13
src/API.hpp
13
src/API.hpp
@@ -163,10 +163,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 和风天气 - 实时天气: https://dev.qweather.com/docs/api/weather/weather-now/
|
// 和风天气 - 实时天气: https://dev.qweather.com/docs/api/weather/weather-now/
|
||||||
bool getWeatherNow(Weather& result, const char* key, const char* locid) {
|
bool getWeatherNow(Weather& result, const char* host, const char* key, const char* locid) {
|
||||||
// return getRestfulAPI("https://www.baidu.com", [&result](JsonDocument& json) {
|
// return getRestfulAPI("https://www.baidu.com", [&result](JsonDocument& json) {
|
||||||
return getRestfulAPI(
|
return getRestfulAPI(
|
||||||
"https://devapi.qweather.com/v7/weather/now?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
"https://" + String(host) + "/v7/weather/now?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
||||||
if (strcmp(json["code"], "200") != 0) {
|
if (strcmp(json["code"], "200") != 0) {
|
||||||
Serial.print(F("Get weather failed, error: "));
|
Serial.print(F("Get weather failed, error: "));
|
||||||
Serial.println(json["code"].as<const char*>());
|
Serial.println(json["code"].as<const char*>());
|
||||||
@@ -188,8 +188,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 和风天气 - 逐小时天气预报: https://dev.qweather.com/docs/api/weather/weather-hourly-forecast/
|
// 和风天气 - 逐小时天气预报: https://dev.qweather.com/docs/api/weather/weather-hourly-forecast/
|
||||||
bool getForecastHourly(HourlyForecast& result, const char* key, const char* locid) {
|
bool getForecastHourly(HourlyForecast& result, const char* host, const char* key, const char* locid) {
|
||||||
return getRestfulAPI("https://devapi.qweather.com/v7/weather/24h?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
return getRestfulAPI("https://" + String(host) + "/v7/weather/24h?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
||||||
if (strcmp(json["code"], "200") != 0) {
|
if (strcmp(json["code"], "200") != 0) {
|
||||||
Serial.print(F("Get hourly forecast failed, error: "));
|
Serial.print(F("Get hourly forecast failed, error: "));
|
||||||
Serial.println(json["code"].as<const char*>());
|
Serial.println(json["code"].as<const char*>());
|
||||||
@@ -216,8 +216,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 和风天气 - 逐天天气预报: https://dev.qweather.com/docs/api/weather/weather-daily-forecast/
|
// 和风天气 - 逐天天气预报: https://dev.qweather.com/docs/api/weather/weather-daily-forecast/
|
||||||
bool getForecastDaily(DailyForecast& result, const char* key, const char* locid) {
|
bool getForecastDaily(DailyForecast& result, const char* host, const char* key, const char* locid) {
|
||||||
return getRestfulAPI("https://devapi.qweather.com/v7/weather/3d?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
return getRestfulAPI("https://" + String(host) + "/v7/weather/3d?key=" + String(key) + "&location=" + String(locid), [&result](JsonDocument& json) {
|
||||||
if (strcmp(json["code"], "200") != 0) {
|
if (strcmp(json["code"], "200") != 0) {
|
||||||
Serial.print(F("Get daily forecast failed, error: "));
|
Serial.print(F("Get daily forecast failed, error: "));
|
||||||
Serial.println(json["code"].as<const char*>());
|
Serial.println(json["code"].as<const char*>());
|
||||||
@@ -254,6 +254,7 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 一言: https://developer.hitokoto.cn/sentence/
|
// 一言: https://developer.hitokoto.cn/sentence/
|
||||||
bool getHitokoto(Hitokoto& result) {
|
bool getHitokoto(Hitokoto& result) {
|
||||||
return getRestfulAPI("https://v1.hitokoto.cn/?max_length=15", [&result](JsonDocument& json) {
|
return getRestfulAPI("https://v1.hitokoto.cn/?max_length=15", [&result](JsonDocument& json) {
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ bool getHolidays(Holiday& result, int year, int month) {
|
|||||||
}
|
}
|
||||||
http.end();
|
http.end();
|
||||||
|
|
||||||
int status = doc["code"];
|
int status = doc["code"].as<int>();
|
||||||
if (doc["code"] != 0) {
|
if (status != 0) {
|
||||||
Serial.println("Get holidays error.");
|
Serial.println("Get holidays error.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@@ -21,11 +21,12 @@ void IRAM_ATTR checkTicks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WiFiManager wm;
|
WiFiManager wm;
|
||||||
WiFiManagerParameter para_qweather_key("qweather_key", "和风天气Token", "", 32); // 和风天气key
|
WiFiManagerParameter para_qweather_host("qweather_host", "和风天气Host", "", 64); // 和风天气key
|
||||||
|
WiFiManagerParameter para_qweather_key("qweather_key", "和风天气API Key", "", 32); // 和风天气key
|
||||||
// const char* test_html = "<br/><label for='test'>天气模式</label><br/><input type='radio' name='test' value='0' checked> 每日天气test </input><input type='radio' name='test' value='1'> 实时天气test</input>";
|
// const char* test_html = "<br/><label for='test'>天气模式</label><br/><input type='radio' name='test' value='0' checked> 每日天气test </input><input type='radio' name='test' value='1'> 实时天气test</input>";
|
||||||
// WiFiManagerParameter para_test(test_html);
|
// WiFiManagerParameter para_test(test_html);
|
||||||
WiFiManagerParameter para_qweather_type("qweather_type", "天气类型(0:每日天气,1:实时天气)", "0", 2, "pattern='\\[0-1]{1}'"); // 城市code
|
WiFiManagerParameter para_qweather_type("qweather_type", "天气类型(0:每日天气,1:实时天气)", "0", 2, "pattern='\\[0-1]{1}'"); // 城市code
|
||||||
WiFiManagerParameter para_qweather_location("qweather_loc", "位置ID", "", 9, "pattern='\\d{9}'"); // 城市code
|
WiFiManagerParameter para_qweather_location("qweather_loc", "位置ID", "", 64); // 城市code
|
||||||
WiFiManagerParameter para_cd_day_label("cd_day_label", "倒数日(4字以内)", "", 10); // 倒数日
|
WiFiManagerParameter para_cd_day_label("cd_day_label", "倒数日(4字以内)", "", 10); // 倒数日
|
||||||
WiFiManagerParameter para_cd_day_date("cd_day_date", "日期(yyyyMMdd)", "", 8, "pattern='\\d{8}'"); // 城市code
|
WiFiManagerParameter para_cd_day_date("cd_day_date", "日期(yyyyMMdd)", "", 8, "pattern='\\d{8}'"); // 城市code
|
||||||
WiFiManagerParameter para_tag_days("tag_days", "日期Tag(yyyyMMddx,详见README)", "", 30); // 日期Tag
|
WiFiManagerParameter para_tag_days("tag_days", "日期Tag(yyyyMMddx,详见README)", "", 30); // 日期Tag
|
||||||
@@ -187,6 +188,7 @@ void buttonClick(void* oneButton) {
|
|||||||
void saveParamsCallback() {
|
void saveParamsCallback() {
|
||||||
Preferences pref;
|
Preferences pref;
|
||||||
pref.begin(PREF_NAMESPACE);
|
pref.begin(PREF_NAMESPACE);
|
||||||
|
pref.putString(PREF_QWEATHER_HOST, para_qweather_host.getValue());
|
||||||
pref.putString(PREF_QWEATHER_KEY, para_qweather_key.getValue());
|
pref.putString(PREF_QWEATHER_KEY, para_qweather_key.getValue());
|
||||||
pref.putString(PREF_QWEATHER_TYPE, strcmp(para_qweather_type.getValue(), "1") == 0 ? "1" : "0");
|
pref.putString(PREF_QWEATHER_TYPE, strcmp(para_qweather_type.getValue(), "1") == 0 ? "1" : "0");
|
||||||
pref.putString(PREF_QWEATHER_LOC, para_qweather_location.getValue());
|
pref.putString(PREF_QWEATHER_LOC, para_qweather_location.getValue());
|
||||||
@@ -222,6 +224,7 @@ void buttonDoubleClick(void* oneButton) {
|
|||||||
// 根据配置信息设置默认值
|
// 根据配置信息设置默认值
|
||||||
Preferences pref;
|
Preferences pref;
|
||||||
pref.begin(PREF_NAMESPACE);
|
pref.begin(PREF_NAMESPACE);
|
||||||
|
String qHost = pref.getString(PREF_QWEATHER_HOST);
|
||||||
String qToken = pref.getString(PREF_QWEATHER_KEY);
|
String qToken = pref.getString(PREF_QWEATHER_KEY);
|
||||||
String qType = pref.getString(PREF_QWEATHER_TYPE, "0");
|
String qType = pref.getString(PREF_QWEATHER_TYPE, "0");
|
||||||
String qLoc = pref.getString(PREF_QWEATHER_LOC);
|
String qLoc = pref.getString(PREF_QWEATHER_LOC);
|
||||||
@@ -231,8 +234,9 @@ void buttonDoubleClick(void* oneButton) {
|
|||||||
String week1st = pref.getString(PREF_SI_WEEK_1ST, "0");
|
String week1st = pref.getString(PREF_SI_WEEK_1ST, "0");
|
||||||
pref.end();
|
pref.end();
|
||||||
|
|
||||||
|
para_qweather_host.setValue(qHost.c_str(), 64);
|
||||||
para_qweather_key.setValue(qToken.c_str(), 32);
|
para_qweather_key.setValue(qToken.c_str(), 32);
|
||||||
para_qweather_location.setValue(qLoc.c_str(), 9);
|
para_qweather_location.setValue(qLoc.c_str(), 64);
|
||||||
para_qweather_type.setValue(qType.c_str(), 1);
|
para_qweather_type.setValue(qType.c_str(), 1);
|
||||||
para_cd_day_label.setValue(cddLabel.c_str(), 16);
|
para_cd_day_label.setValue(cddLabel.c_str(), 16);
|
||||||
para_cd_day_date.setValue(cddDate.c_str(), 8);
|
para_cd_day_date.setValue(cddDate.c_str(), 8);
|
||||||
@@ -241,6 +245,7 @@ void buttonDoubleClick(void* oneButton) {
|
|||||||
|
|
||||||
wm.setTitle("J-Calendar");
|
wm.setTitle("J-Calendar");
|
||||||
wm.addParameter(¶_si_week_1st);
|
wm.addParameter(¶_si_week_1st);
|
||||||
|
wm.addParameter(¶_qweather_host);
|
||||||
wm.addParameter(¶_qweather_key);
|
wm.addParameter(¶_qweather_key);
|
||||||
wm.addParameter(¶_qweather_type);
|
wm.addParameter(¶_qweather_type);
|
||||||
wm.addParameter(¶_qweather_location);
|
wm.addParameter(¶_qweather_location);
|
||||||
|
|||||||
@@ -196,14 +196,15 @@ void draw_cal_year(bool partial) {
|
|||||||
calLayout.lunarYearX = u8g2Fonts.getCursorX() + 15;
|
calLayout.lunarYearX = u8g2Fonts.getCursorX() + 15;
|
||||||
calLayout.lunarDayX = u8g2Fonts.getCursorX() + 15;
|
calLayout.lunarDayX = u8g2Fonts.getCursorX() + 15;
|
||||||
|
|
||||||
// 星期几
|
// 第几周
|
||||||
u8g2Fonts.setFont(FONT_TEXT);
|
u8g2Fonts.setFont(FONT_TEXT);
|
||||||
u8g2Fonts.setFontMode(1);
|
u8g2Fonts.setFontMode(1);
|
||||||
u8g2Fonts.setFontDirection(0);
|
u8g2Fonts.setFontDirection(0);
|
||||||
u8g2Fonts.setForegroundColor(todayColor);
|
u8g2Fonts.setForegroundColor(todayColor);
|
||||||
u8g2Fonts.setCursor(calLayout.weekX, calLayout.weekY);
|
u8g2Fonts.setCursor(calLayout.weekX, calLayout.weekY);
|
||||||
u8g2Fonts.print("星期" + week_str[tmInfo.tm_wday]);
|
char week_num[8];
|
||||||
|
strftime(week_num, sizeof(week_num), "%V", &tmInfo); // 国际标准(ISO 8601):以周一作为每周起始日
|
||||||
|
u8g2Fonts.printf("第%s周", week_num);
|
||||||
calLayout.cdDayX = u8g2Fonts.getCursorX(); // update cd day X;
|
calLayout.cdDayX = u8g2Fonts.getCursorX(); // update cd day X;
|
||||||
|
|
||||||
// 今日农历年份,e.g. 乙巳年 蛇
|
// 今日农历年份,e.g. 乙巳年 蛇
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
TaskHandle_t WEATHER_HANDLER;
|
TaskHandle_t WEATHER_HANDLER;
|
||||||
|
|
||||||
|
String _qweather_host;
|
||||||
String _qweather_key;
|
String _qweather_key;
|
||||||
String _qweather_loc;
|
String _qweather_loc;
|
||||||
|
|
||||||
@@ -45,9 +46,9 @@ void task_weather(void* param) {
|
|||||||
// 实时天气
|
// 实时天气
|
||||||
bool success;
|
bool success;
|
||||||
if (_weather_type == 0) {
|
if (_weather_type == 0) {
|
||||||
success = api.getForecastDaily(_daily_forecast, _qweather_key.c_str(), _qweather_loc.c_str());
|
success = api.getForecastDaily(_daily_forecast, _qweather_host.c_str(), _qweather_key.c_str(), _qweather_loc.c_str());
|
||||||
} else {
|
} else {
|
||||||
success = api.getWeatherNow(_weather_now, _qweather_key.c_str(), _qweather_loc.c_str());
|
success = api.getWeatherNow(_weather_now, _qweather_host.c_str(), _qweather_key.c_str(), _qweather_loc.c_str());
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
_weather_status = 1;
|
_weather_status = 1;
|
||||||
@@ -74,6 +75,7 @@ void weather_exec(int status) {
|
|||||||
// Preference 获取配置信息。
|
// Preference 获取配置信息。
|
||||||
Preferences pref;
|
Preferences pref;
|
||||||
pref.begin(PREF_NAMESPACE);
|
pref.begin(PREF_NAMESPACE);
|
||||||
|
_qweather_host = pref.getString(PREF_QWEATHER_HOST, "api.qweather.com");
|
||||||
_qweather_key = pref.getString(PREF_QWEATHER_KEY, "");
|
_qweather_key = pref.getString(PREF_QWEATHER_KEY, "");
|
||||||
_qweather_loc = pref.getString(PREF_QWEATHER_LOC, "");
|
_qweather_loc = pref.getString(PREF_QWEATHER_LOC, "");
|
||||||
pref.end();
|
pref.end();
|
||||||
|
|||||||
Reference in New Issue
Block a user