diff --git a/src/rom/app.py b/src/rom/app.py index ef2f86f..e06feab 100644 --- a/src/rom/app.py +++ b/src/rom/app.py @@ -167,7 +167,7 @@ async def animation_task(): try: # 动画参数 frame_count = 20 - frame_delay = 10 # 帧延迟(毫秒) + frame_delay = 100 # 帧延迟(毫秒) await uasyncio.sleep_ms(2 * 1000) print(f"开始JPG动画,帧延迟: {frame_delay}ms") @@ -188,7 +188,7 @@ async def animation_task(): # 每轮清理一次内存 gc.collect() - frame += 1 + frame += 2 except Exception as e: print(f"动画帧错误: {e}") @@ -211,11 +211,12 @@ def cb_progress(data): def start(): # 初始化液晶屏 - display.init_display(config.get("bl_mode") != "gpio") + #display.init_display(config.get("bl_mode") != "gpio") + display.init_display(False, buffer_size=5000) display.brightness(int(config.get("brightness", 10))) display.show_jpg("/rom/images/T1.jpg", 80, 80) gc.collect() - display.message("WiFi connect ...") + cb_progress("WiFi connect ...") if not wifi_manager.connect(cb_progress): gc.collect() @@ -227,6 +228,7 @@ def start(): machine.reset() gc.collect() + display.load_ui() # init web server from rom.nanoweb import Nanoweb @@ -289,7 +291,7 @@ def start(): lcd_status = { "ready": display.is_ready(), "brightness": display.brightness(), - "ui_type": config.get("ui_type", "default"), + "ui_type": display.ui_type, } await request.write(json.dumps(lcd_status)) @@ -383,7 +385,7 @@ def start(): loop.create_task(animation_task()) gc.collect() - display.message(f"success: {gc.mem_free()}...") + print(f"success: {gc.mem_free()}...") # run! loop.run_forever() diff --git a/src/rom/display.py b/src/rom/display.py index a931fd3..0ef9c8a 100644 --- a/src/rom/display.py +++ b/src/rom/display.py @@ -30,11 +30,16 @@ class Display: self._brightness = 80 # 默认亮度80% self._initialized = True self._pos_y0 = 10 - self.en_font = '/rom/fonts/en-8x16.rfont' - self.cn_font = '/rom/fonts/cn-22x24.bfont' - self.vector_font = '/rom/fonts/en-32x32.hfont' + self.en_font = '/rom/fonts/en0.rfont' + self.vector_font = '/rom/fonts/en.hfont' + self.cn_font = '/rom/fonts/cn.bfont' + self.time_font = '/rom/fonts/time.bfont' # 前景色、背景色、提示框背景色 self._COLORS = (0xFE19, 0x0000, 0x7800) + self.ui_type = 'default' + # ui数据 + self.ui_data = {} + self.ticks = 0 # 据此切换多行显示 def init_display(self, bl_pwm=True, buffer_size=2048): """初始化液晶屏,默认2048够用且不易有内存碎片""" @@ -137,6 +142,99 @@ class Display: ] self.window("配置设备网络连接", tips, "portal ip: 192.168.4.1") + # 更新ui数据 + def update_ui(self, city=None, weather=None, advice=None, aqi=None, lunar=None, envdat=None): + self.ticks += 1 + if self.ui_type == 'default': + # 中文的城市名称 + if city is not None and city != self.ui_data.get('city'): + self.ui_data['city'] = city + if self.tft.write(self.cn_font, city, 15,10) == 0: + # 城市可能未包括,则显示?? + self.tft.write(self.cn_font, '??', 15,10) + # 天气符号: 0-7 (晴、云、雨、雷、雪、雾、风、未知) + if weather is not None and weather != self.ui_data.get('weather'): + self.tft.jpg(f"/rom/images/{weather}.jpg",165,10,st7789.SLOW) + self.ui_data['weather'] = weather + # 建议信息可能有很多条,需要轮换展示 + if advice is not None and advice != self.ui_data.get('advice'): + self.ui_data['advice'] = advice + # AQI等级分成0-5级,分别对应优、良、中、差、污、恶 + if aqi is not None and aqi != self.ui_data.get('aqi'): + _t = (('优',0x07E0),('良',0xFFE0),('中',0xFD20),('差',0xF800),('污',0x8010),('恶',0x7800)) + _l,_c = _t[aqi] + self.tft.fill_rect(105, 8, 40, 25, _c) + self.tft.write(self.cn_font, _l, 114,10, 0,_c) + self.ui_data['aqi'] = aqi + # 农历日期,需要和当前日期轮换展示 + if lunar is not None and lunar != self.ui_data.get('lunar'): + self.ui_data['lunar'] = lunar + # 环境数据 + if envdat is not None: + t,rh = envdat.get('t'),envdat.get('rh') + pm,ap = envdat.get('pm'),envdat.get('ap') + # 填充后再更新文本 + if t is not None and t != self.ui_data.get('t'): + self.ui_data['t'] = t + self.tft.fill_rect(35,179,40,16,0) + self.tft.draw(self.vector_font, str(t), 35,187,0xFFFF,0.5) + if rh is not None and rh != self.ui_data.get('rh'): + self.ui_data['rh'] = rh + self.tft.fill_rect(110,179,40,16,0) + self.tft.draw(self.vector_font, str(rh), 110,187,0xFFFF,0.5) + if pm is not None and pm != self.ui_data.get('pm'): + self.ui_data['pm'] = pm + self.tft.fill_rect(35,213,40,16,0) + self.tft.draw(self.vector_font, str(pm), 35,221,0xFFFF,0.5) + if ap is not None and ap != self.ui_data.get('ap'): + self.ui_data['ap'] = ap + self.tft.fill_rect(110,213,40,16,0) + self.tft.draw(self.vector_font, str(ap), 110,221,0xFFFF,0.5) + # 处理日期 + from machine import RTC + y,m,d,_w,H,M,*_ = RTC().datetime() + w = ('一','二','三','四','五','六','天')[_w] + if m!=self.ui_data.get('month') or d!=self.ui_data.get('day'): + self.ui_data['month'] = m + self.ui_data['day'] = d + self.ui_data['weekday'] = w + # just stop lunar, wait refresh + self.ui_data['lunar'] = None + # 切换日期显示 + lunar = self.ui_data.get('lunar') + if lunar is not None and self.ticks & 0x01: + w = self.tft.write(self.cn_font, f'{lunar} 星期{w}', 15,135) + else: + w = self.tft.write(self.cn_font, f'{m:2d}月{d:2d}日 星期{w}', 15,135) + print(f'todo: fill date.tail: {w}') + # 处理时间显示 + if H != self.ui_data.get('hour'): + self.ui_data['hour'] = H + self.tft.write(self.time_font,f'{H:02d}:',25,80,0xF080) + if M != self.ui_data.get('minute'): + self.ui_data['minute'] = M + self.tft.write(self.time_font,f'{M:02d}',135,80,0xFF80) + # 处理建议显示 + advice = self.ui_data.get('advice') + if isinstance(advice, list) and advice: + i = self.ticks % len(advice) + c = advice[i] + w = self.tft.write(self.cn_font, advice[i], 15,45) + print(f'todo: fill advice.tail: {w}') + + # 初始化ui固定元素 + def load_ui(self): + if self.ui_type == 'default': + # 默认黑色背景 + self.tft.fill(0) + # 固定的环境数据图标 + self.tft.jpg("/rom/images/t.jpg",11,177,st7789.SLOW) + self.tft.jpg("/rom/images/rh.jpg",85,177,st7789.SLOW) + self.tft.jpg("/rom/images/pm.jpg",11,209,st7789.SLOW) + self.tft.jpg("/rom/images/ap.jpg",85,208,st7789.SLOW) + + # 更新其他默认数据 + self.update_ui() # 全局液晶屏实例 display = Display() diff --git a/utils/convert_assets.sh b/utils/convert_assets.sh index 839e77c..4b067d6 100755 --- a/utils/convert_assets.sh +++ b/utils/convert_assets.sh @@ -1,15 +1,49 @@ #!/bin/bash # -*- coding: utf-8 -*- -CN_TEXT='配置设备网络连接热点自动进入页面0123456789 abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ!%*+,-./()[]\"<>=?℃' +CN_TEXT='北京月日星期一二三四五六末优良中差污恶能见度配置设备网络连接热点自动进入页面0123456789 abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ!%*+,-./()[]\"<>=?℃' +TIME_TEXT='0123456789: .-' SRC_DIR=./assets DST_DIR=../src/rom/fonts -OTF_FONT=$SRC_DIR/NotoSansSC-Regular.otf +README=$DST_DIR/README.md -python3 pyfont_to_bin.py $SRC_DIR/romand.py $DST_DIR/en-32x32.hfont -python3 pyfont_to_bin.py $SRC_DIR/vga1_8x16.py $DST_DIR/en-8x16.rfont -python3 pyfont_to_bin.py $SRC_DIR/vga1_16x32.py $DST_DIR/en-16x32.rfont +# 中文黑体源字体 +CN_OTF_FONT=$SRC_DIR/STHeiti.ttc +# 英文时间源字体 +TIME_OTF_FONT=$SRC_DIR/BloodWaxItalic.otf -python3 font2bitmap.py -s "$CN_TEXT" $OTF_FONT 22 > $SRC_DIR/cn-22x24.py -python3 pyfont_to_bin.py $SRC_DIR/cn-22x24.py $DST_DIR/cn-22x24.bfont +echo "# 字体文件说明" > $README +echo "" >>$README + +echo "1. en0.rfont/en1.rfont 英文字体" >> $README +echo "> 顺序排列,相等大小、可快速定位" >> $README +echo "" >>$README +python3 pyfont_to_bin.py $SRC_DIR/vga1_8x16.py $DST_DIR/en0.rfont +python3 pyfont_to_bin.py $SRC_DIR/vga1_16x32.py $DST_DIR/en1.rfont + +echo "2. en.hfont 矢量英文字体" >> $README +echo "> 顺序排列,带索引表,只画线无背景色,可自由缩放,显示速度快" >> $README +echo "" >>$README +python3 pyfont_to_bin.py $SRC_DIR/romand.py $DST_DIR/en.hfont + +echo "3. cn.bfont 中文字体" >> $README +echo "> 有字符MAP表(当前顺序查找、需实现二叉树查找)" >> $README +echo "" >>$README +python3 font2bitmap.py -s "$CN_TEXT" $CN_OTF_FONT 22 > $SRC_DIR/cn.py +python3 pyfont_to_bin.py $SRC_DIR/cn.py $DST_DIR/cn.bfont + +echo "4. time.bfont 时间字体" >> $README +echo "> 有字符MAP表(当前顺序查找、需实现二叉树查找)" >> $README +echo "" >>$README +python3 font2bitmap.py -s "$TIME_TEXT" $TIME_OTF_FONT 48 > $SRC_DIR/time.py +python3 pyfont_to_bin.py $SRC_DIR/time.py $DST_DIR/time.bfont + + +# 开始转换图片文件 +SRC_DIR=./assets +DST_DIR=../src/rom/images + +# 透明色转换成黑色背景,质量95% +python3 png_to_jpg.py -d $SRC_DIR/ --color black --quality 100 +cp -v $SRC_DIR/*.jpg $DST_DIR/ diff --git a/utils/icons.html b/utils/icons.html new file mode 100644 index 0000000..1f15f2d --- /dev/null +++ b/utils/icons.html @@ -0,0 +1,253 @@ + + +
+ + +