Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 212bd6b2e1 | |||
| cda7c855fe | |||
| ebf61d13d4 | |||
| a43690930b | |||
| 21fa6ef70f | |||
| 1899065ab0 |
@@ -5,6 +5,7 @@
|
|||||||
基于ESP8266的桌面气象站,能够实时显示天气信息、环境数据和时间。
|
基于ESP8266的桌面气象站,能够实时显示天气信息、环境数据和时间。
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## 功能特点
|
## 功能特点
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ POST /config/set - 设置配置 {city: "北京", standby_time: "22:00
|
|||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
**Q: 设备无法连接WiFi**
|
**Q: 设备无法连接WiFi**
|
||||||
A: 检查WiFi密码是否正确,或重启设备重新配置
|
- A: 检查WiFi密码是否正确,或重启设备重新配置
|
||||||
|
|
||||||
**Q: 天气数据不更新**
|
**Q: 天气数据不更新**
|
||||||
- A1: 检查网络连接,或尝试强制刷新天气数据
|
- A1: 检查网络连接,或尝试强制刷新天气数据
|
||||||
@@ -120,3 +121,4 @@ A: 检查WiFi密码是否正确,或重启设备重新配置
|
|||||||
- 项目主页: https://github.com/kicer/ws2
|
- 项目主页: https://github.com/kicer/ws2
|
||||||
- 项目主页: https://iot.foresh.com/git/kicer/ws2
|
- 项目主页: https://iot.foresh.com/git/kicer/ws2
|
||||||
- 问题反馈: https://github.com/kicer/ws2/issues
|
- 问题反馈: https://github.com/kicer/ws2/issues
|
||||||
|
- QQ联络群: 697580459
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
An ESP8266-based desktop weather station capable of displaying real-time weather information, environmental data, and time.
|
An ESP8266-based desktop weather station capable of displaying real-time weather information, environmental data, and time.
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ POST /config/set - Set configuration {city: "Beijing", standby_time:
|
|||||||
### Common Issues
|
### Common Issues
|
||||||
|
|
||||||
**Q: Device cannot connect to WiFi**
|
**Q: Device cannot connect to WiFi**
|
||||||
A: Check if the WiFi password is correct, or restart the device to reconfigure
|
- A: Check if the WiFi password is correct, or restart the device to reconfigure
|
||||||
|
|
||||||
**Q: Weather data doesn't update**
|
**Q: Weather data doesn't update**
|
||||||
- A1: Check network connection or try force-refreshing weather data
|
- A1: Check network connection or try force-refreshing weather data
|
||||||
@@ -120,3 +121,4 @@ This project is licensed under the MIT License
|
|||||||
- Project Homepage: https://github.com/kicer/ws2
|
- Project Homepage: https://github.com/kicer/ws2
|
||||||
- Project Homepage: https://iot.foresh.com/git/kicer/ws2
|
- Project Homepage: https://iot.foresh.com/git/kicer/ws2
|
||||||
- Issue Tracker: https://github.com/kicer/ws2/issues
|
- Issue Tracker: https://github.com/kicer/ws2/issues
|
||||||
|
- QQ Group: 697580459
|
||||||
|
|||||||
BIN
docs/web.jpg
Normal file
BIN
docs/web.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/ws2.jpg
BIN
docs/ws2.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 19 KiB |
@@ -188,6 +188,37 @@ async def eval_cmd(request):
|
|||||||
finally:
|
finally:
|
||||||
await json_response(request, json.dumps(ack))
|
await json_response(request, json.dumps(ack))
|
||||||
|
|
||||||
|
# 定时熄屏处理功能,熄屏则返回True
|
||||||
|
def standby_control():
|
||||||
|
# 获取当前时间 (格式: HH:MM)
|
||||||
|
now = time.localtime()
|
||||||
|
current_time = "{:02d}:{:02d}".format(now[3], now[4])
|
||||||
|
|
||||||
|
# 从配置中获取熄屏和唤醒时间
|
||||||
|
standby_time = config.get("standby_time")
|
||||||
|
wakeup_time = config.get("wakeup_time")
|
||||||
|
|
||||||
|
_set = config.get('brightness', 10)
|
||||||
|
|
||||||
|
# 如果设置了熄屏和唤醒时间
|
||||||
|
if standby_time and wakeup_time:
|
||||||
|
# 如果当前时间在熄屏时间之后,唤醒时间之前,则关闭屏幕
|
||||||
|
if standby_time <= wakeup_time:
|
||||||
|
if current_time >= standby_time and current_time < wakeup_time:
|
||||||
|
_set = 0
|
||||||
|
else:
|
||||||
|
if current_time >= standby_time or current_time < wakeup_time:
|
||||||
|
_set = 0
|
||||||
|
else:
|
||||||
|
_set = None
|
||||||
|
|
||||||
|
if _set is not None:
|
||||||
|
if display.brightness():
|
||||||
|
if _set == 0:
|
||||||
|
display.brightness(0)
|
||||||
|
else:
|
||||||
|
if _set > 0:
|
||||||
|
display.brightness(config.get("brightness", 10)) # 恢复亮度
|
||||||
|
|
||||||
|
|
||||||
# ntp时钟同步
|
# ntp时钟同步
|
||||||
@@ -217,7 +248,7 @@ async def fetch_weather_data(city=None):
|
|||||||
|
|
||||||
print(f"正在获取{city}天气数据...")
|
print(f"正在获取{city}天气数据...")
|
||||||
# 从配置获取API基础URL,默认使用官方API
|
# 从配置获取API基础URL,默认使用官方API
|
||||||
url = config.get("weather_api_url", "http://esp.tangofu.com/api/ws2/")
|
url = config.get("weather_api_url", "http://esp.foresh.com/api/ws2/")
|
||||||
params = {"uuid": uuid(), "city": city}
|
params = {"uuid": uuid(), "city": city}
|
||||||
|
|
||||||
# 发送GET请求
|
# 发送GET请求
|
||||||
@@ -327,7 +358,12 @@ async def ui_task():
|
|||||||
# 每隔100帧,更新一次UI显示
|
# 每隔100帧,更新一次UI显示
|
||||||
F += 1
|
F += 1
|
||||||
if F % 100 == 0:
|
if F % 100 == 0:
|
||||||
display.update_ui()
|
standby_control() # 控制开关机
|
||||||
|
# 只在亮屏时更新显示
|
||||||
|
if display.brightness():
|
||||||
|
display.update_ui()
|
||||||
|
else:
|
||||||
|
gc.collect(); print(f'LCD.idle.mem: {gc.mem_free()}')
|
||||||
|
|
||||||
# 每轮清理一次内存
|
# 每轮清理一次内存
|
||||||
gc.collect()
|
gc.collect()
|
||||||
@@ -361,6 +397,9 @@ def cb_progress(data):
|
|||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
|
# 禁用repl
|
||||||
|
if config.get('console') == "disable":
|
||||||
|
import os; os.dupterm(None, 1)
|
||||||
# 初始化液晶屏
|
# 初始化液晶屏
|
||||||
display.init_display(config.get("bl_mode") == "pwm", 7000)
|
display.init_display(config.get("bl_mode") == "pwm", 7000)
|
||||||
display.brightness(int(config.get("brightness", 10)))
|
display.brightness(int(config.get("brightness", 10)))
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class Display:
|
|||||||
self.tft.init()
|
self.tft.init()
|
||||||
self.tft.fill(0)
|
self.tft.fill(0)
|
||||||
self.show_jpg(self.bootimg, 80, 80)
|
self.show_jpg(self.bootimg, 80, 80)
|
||||||
self.message("WS2 v1.3.5 (20260202)")
|
self.message("WS2 v1.3.6 (20260203)")
|
||||||
|
|
||||||
_print_mem()
|
_print_mem()
|
||||||
return True
|
return True
|
||||||
@@ -186,7 +186,7 @@ class Display:
|
|||||||
if rh is not None and rh != self.ui_data.get('rh'):
|
if rh is not None and rh != self.ui_data.get('rh'):
|
||||||
self.ui_data['rh'] = rh
|
self.ui_data['rh'] = rh
|
||||||
self.tft.fill_rect(110,179,40,16,0)
|
self.tft.fill_rect(110,179,40,16,0)
|
||||||
self.tft.draw(self.vector_font, f' {str(rh)}%', 110,187,0xFFFF,0.5)
|
self.tft.draw(self.vector_font, f' {str(rh)}', 110,187,0xFFFF,0.5)
|
||||||
if pm is not None and pm != self.ui_data.get('pm'):
|
if pm is not None and pm != self.ui_data.get('pm'):
|
||||||
self.ui_data['pm'] = pm
|
self.ui_data['pm'] = pm
|
||||||
self.tft.fill_rect(35,213,40,16,0)
|
self.tft.fill_rect(35,213,40,16,0)
|
||||||
|
|||||||
@@ -82,12 +82,17 @@ target="_blank"
|
|||||||
download
|
download
|
||||||
>查看城市ID列表</a
|
>查看城市ID列表</a
|
||||||
>)
|
>)
|
||||||
</small></div><div class="form-group"><label class="form-label">自动熄屏时间</label
|
</small></div><div class="form-group"><label class="form-label">自动熄屏时间</label><div style="display: flex;">
|
||||||
><input
|
<input type="time" id="standby-time-input" class="form-control" placeholder="熄屏时间" style="margin-right: 10px; flex: 1;"/>
|
||||||
type="time"
|
<input type="time" id="wakeup-time-input" class="form-control" placeholder="唤醒时间" style="flex: 1;"/></div>
|
||||||
id="standby-time-input"
|
<small class="text-muted">分别设置熄屏和唤醒时间,留空则表示不自动熄屏</small></div>
|
||||||
class="form-control"
|
<div class="form-group"><label class="form-label">自定义配置</label>
|
||||||
/><small class="text-muted">留空表示不自动熄屏</small></div><button class="btn btn-success" id="save-config-btn">
|
<div id="custom-config-container" class="custom-config-list">
|
||||||
|
<div class="custom-config-row" style="display: flex; margin-bottom: 10px;">
|
||||||
|
<input type="text" placeholder="配置项" class="form-control" id="custom-config-key" style="margin-right: 10px; flex: 1;">
|
||||||
|
<input type="text" placeholder="配置值" class="form-control" id="custom-config-value" style="flex: 1;">
|
||||||
|
</div></div></div>
|
||||||
|
<button class="btn btn-success" id="save-config-btn">
|
||||||
保存配置
|
保存配置
|
||||||
</button><h3 class="mt-3">当前配置</h3><table class="table" id="current-config"><tr><th>配置项</th><th>值</th></tr></table></div><div id="advanced-tab" class="tab-content"><h3>快捷操作</h3><div class="form-group"><button class="btn btn-outline" data-cmd="get_mac">
|
</button><h3 class="mt-3">当前配置</h3><table class="table" id="current-config"><tr><th>配置项</th><th>值</th></tr></table></div><div id="advanced-tab" class="tab-content"><h3>快捷操作</h3><div class="form-group"><button class="btn btn-outline" data-cmd="get_mac">
|
||||||
MAC地址
|
MAC地址
|
||||||
@@ -121,10 +126,10 @@ WS2是一款基于ESP8266的桌面气象站,能够实时显示天气信息、
|
|||||||
温度、湿度、PM2.5、气压、AQI
|
温度、湿度、PM2.5、气压、AQI
|
||||||
</div></div></div><div class="col"><h3 class="mt-3">软件信息</h3><div class="list"><div class="list-item"><strong>固件:</strong
|
</div></div></div><div class="col"><h3 class="mt-3">软件信息</h3><div class="list"><div class="list-item"><strong>固件:</strong
|
||||||
><a
|
><a
|
||||||
href="https://iot.foresh.com/git/kicer/ws2"
|
href="https://iot.foresh.com/git/kicer/ws2/releases"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
ws2-firmware-v1.3.5-4M.bin </a
|
ws2-firmware-v1.3.6-4M.bin </a
|
||||||
><span class="badge badge-success">开源</span></div><div class="list-item"><strong>协议:</strong> HTTP REST API
|
><span class="badge badge-success">开源</span></div><div class="list-item"><strong>协议:</strong> HTTP REST API
|
||||||
</div><div class="list-item"><strong>更新频率:</strong> 每小时
|
</div><div class="list-item"><strong>更新频率:</strong> 每小时
|
||||||
</div></div></div></div><h3 class="mt-3">开放源码</h3><a
|
</div></div></div></div><h3 class="mt-3">开放源码</h3><a
|
||||||
@@ -256,6 +261,7 @@ Math.round((memoryValue / maxMemory) * 100),
|
|||||||
);// 使用micro.js的图表功能创建仪表盘
|
);// 使用micro.js的图表功能创建仪表盘
|
||||||
mw.chart.createGauge(mw.$("#memory-gauge"), percentage, 100, {
|
mw.chart.createGauge(mw.$("#memory-gauge"), percentage, 100, {
|
||||||
label: "内存使用率",
|
label: "内存使用率",
|
||||||
|
percent: true,
|
||||||
color:
|
color:
|
||||||
percentage > 80
|
percentage > 80
|
||||||
? "#e74c3c"
|
? "#e74c3c"
|
||||||
@@ -306,7 +312,10 @@ mw.val(mw.$("#city-input"), data.city);
|
|||||||
}
|
}
|
||||||
if (data.standby_time) {
|
if (data.standby_time) {
|
||||||
mw.val(mw.$("#standby-time-input"), data.standby_time);
|
mw.val(mw.$("#standby-time-input"), data.standby_time);
|
||||||
}// 更新配置表
|
}
|
||||||
|
if (data.wakeup_time) {
|
||||||
|
mw.val(mw.$("#wakeup-time-input"), data.wakeup_time);
|
||||||
|
}
|
||||||
updateConfigTable(data);
|
updateConfigTable(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showMessage("获取配置失败: " + error.message, "error");
|
showMessage("获取配置失败: " + error.message, "error");
|
||||||
@@ -343,16 +352,22 @@ mw.text(cell2, value);
|
|||||||
}// 保存配置
|
}// 保存配置
|
||||||
async function saveConfig() {
|
async function saveConfig() {
|
||||||
try {
|
try {
|
||||||
|
const userCfgKey = mw.val(mw.$("#custom-config-key"));
|
||||||
|
const userCfgVal = mw.val(mw.$("#custom-config-value"));
|
||||||
const city = mw.val(mw.$("#city-input"));
|
const city = mw.val(mw.$("#city-input"));
|
||||||
|
const wakeupTime = mw.val(mw.$("#wakeup-time-input"));
|
||||||
const standbyTime = mw.val(mw.$("#standby-time-input"));if (!city) {
|
const standbyTime = mw.val(mw.$("#standby-time-input"));if (!city) {
|
||||||
showMessage("城市名称不能为空", "error");
|
showMessage("城市名称不能为空", "error");
|
||||||
return;
|
return;
|
||||||
}const configData = {
|
}const configData = {
|
||||||
city: city,
|
city: city,
|
||||||
cityid: encodeURIComponent(city),
|
cityid: encodeURIComponent(city),
|
||||||
};// 只有当输入了熄屏时间时才添加到配置中
|
};
|
||||||
if (standbyTime !== "") {
|
if (userCfgKey !== "") {
|
||||||
|
configData[userCfgKey] = userCfgVal;
|
||||||
|
}if (standbyTime !== "" && wakeupTime !== "") {
|
||||||
configData.standby_time = standbyTime;
|
configData.standby_time = standbyTime;
|
||||||
|
configData.wakeup_time = wakeupTime;
|
||||||
}const response = await mw.ajax.post(
|
}const response = await mw.ajax.post(
|
||||||
"/config/set",
|
"/config/set",
|
||||||
configData,
|
configData,
|
||||||
|
|||||||
2
src/rom/www/js/micro.min.js
vendored
2
src/rom/www/js/micro.min.js
vendored
@@ -59,7 +59,7 @@ const MicroWeb={$:t=>document.querySelector(t),$$:t=>document.querySelectorAll(t
|
|||||||
top: ${o/2.5}px;
|
top: ${o/2.5}px;
|
||||||
font-size: ${o/7}px;
|
font-size: ${o/7}px;
|
||||||
font-weight: bold;">
|
font-weight: bold;">
|
||||||
${e}
|
${e}${i.percent?"%":""}
|
||||||
<div style="font-size: ${o/10}px; color: #666;">
|
<div style="font-size: ${o/10}px; color: #666;">
|
||||||
${i.label||""}
|
${i.label||""}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user