【CanMV K230 AI视觉】 气象时钟
- 功能描述:
- 说明
- HMDI资源
- 3.5寸屏幕
- 使用方法
为了方便小伙伴们理解,请查看视频
B站连接
功能描述:
- 天气信息获取:通过连接到互联网,实时获取天气数据,包括温度、湿度、天气状况、风向
- 实时时间显示:气象时钟能够显示当前的时间。
- 可视化天气:包括城市, 温度,相对湿度,实时风向,空气质量
说明
HMDI资源
HDMI屏幕的小伙伴下载链接:K230 气象时钟文件,包含图片,字体,代码
我在此基础上做了一个HDMI的气象时钟。(为了让小伙伴多给上面的大佬点赞,我这边的资源是VIP资源。)小伙伴可以去大佬那里点赞领取代码文件。3.5屏幕的小伙伴直接使用。HDMI的,可以使用我下面的代码。(资源里都带)
3.5寸屏幕
由大佬Dai0707分享,下载链接原作者博客.https://forum.01studio.cc/t/topic/70/2
文件 | 说明 |
---|---|
ui | 图片 |
urllib | 代码 |
main.py | 3.5寸屏代码 |
main咸鱼浆.py | HDMI代码 |
Source… | 字体 |
'''
实验名称:天气时钟
实验平台:01Studio CanMV K230
镜像版本:V1.0
日期:2024-8-27验证发布
教程:wiki.01studio.cc
作者:半只半解
版本:v1.0
修改:咸鱼浆
HDMI显示,更改UI坐标等等
'''
import os, time, gc, sys, network, json, re
from clock.urllib import urequest ,ntptime
from media.display import *
from media.media import *
from machine import Pin
# 初始化 Wi-Fi 指示灯
WIFI_LED_PIN = 52
LED = Pin(WIFI_LED_PIN, Pin.OUT)
bg=image.Image(f"/sdcard/clock/ui/1.jpeg").to_rgb565()
# 选择显示方式
#Display.init(Display.ST7701) # 使用 LCD 屏幕显示
Display.init(Display.LT9611) #通过HDMI显示图像
# 初始化媒体管理器
MediaManager.init()
# 创建图像对象用于绘制
canvas = image.Image(1920, 1080, image.RGB565)
canvas.clear() # 清空图像
# WiFi账号密码
SSID ='123456'
CODE ='123456'
time.sleep(5) #等待WiFi模块初始化
def WIFI_Connect(max_retries=5):
"""
连接到指定的 Wi-Fi 网络,并在屏幕上显示连接状态。
"""
# 初始化 Wi-Fi 接口
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
start_time = time.time() # 记录时间做超时判断
retries = max_retries # 重试次数
if not wlan.isconnected():
print('连接到网络...')
canvas.clear() # 清除屏幕并显示 "正在连接到 WiFi..." 的信息
canvas.draw_string_advanced(600, 500, 80, "正在连接到 WiFi...", color=(255, 255, 255))
Display.show_image(canvas)
wlan.connect(SSID, CODE) # WiFi连接
while not wlan.isconnected(): # 添加重试逻辑
LED.value(1)
time.sleep_ms(300)
LED.value(0)
time.sleep_ms(300)
if time.time() - start_time > 15: # 超时判断,15秒没连接成功判定为超时
print('WIFI 连接超时 !')
wlan.active(False)
return False
if wlan.isconnected():
LED.value(1) # LED点亮
canvas.clear()# 清除上次残留
# 显示连接成功的信息
canvas.draw_string_advanced(600, 200, 80, "WiFi 连接成功", color=(255, 255, 255))
canvas.draw_string_advanced(600, 400, 80, "WiFi IP: " + wlan.ifconfig()[0], color=(255, 255, 255))
canvas.draw_string_advanced(600, 600, 80, "咸鱼浆", color=(255, 137, 54))
Display.show_image(canvas)
print('网络信息:', wlan.ifconfig()) # 打印网络信息
# 立即获取天气信息和同步时间
weather_get()
sync_ntp()
return True
else:
canvas.clear() # 清除上次残留
canvas.draw_string_advanced(600, 500, 80, "连接失败!", color=(255, 255, 255))
Display.show_image(canvas)
for _ in range(3): # LED 闪烁三次提示连接失败
LED.value(1)
time.sleep_ms(300)
LED.value(0)
time.sleep_ms(300)
print('连接失败!!!', wlan.ifconfig()) # 打印错误信信息并把LED重置为熄灭状态
# LED 重置为熄灭状态
LED.value(0)
return False
""""
同步NTP服务器时间
"""
def sync_ntp():
ntp_servers = ['202.120.2.101', 'ntp.ntsc.ac.cn'] # 第二个NTP服务器作为备选
for server in ntp_servers:
ntptime.host = server
try:
ntptime.settime()
print(f"成功从 {server} 同步时间")
break
except Exception as e:
print(f"从 {server} 同步ntp时间错误: {repr(e)}")
continue
else:
print("所有NTP服务器均无法同步时间,请检查网络连接或NTP服务器地址。")
""""
处理日期和时间
"""
def zero_str(str_num):
num = int(str_num)
return "0" + str(num) if num > 0 and num < 10 else str(num)
"""
天气爬取
"""
# 定义一个长度为5的字符列表
weather = ['']*5
is_first_run = True # 添加一个标志来标记是否为首次运行
def weather_get(max_retries=5):
print("尝试获取天气数据...")
global weather
retries = max_retries
# 保存当前的天气信息
previous_weather = weather.copy()
while retries > 0:
try:
myURL = urequest.urlopen("http://www.weather.com.cn/weather1d/101070101.shtml")
text = myURL.read(40000).decode('utf-8') # 获取前38000个数据以节省内存
#text = myURL.read(40000) # 获取前38000个数据以节省内存 V1.1版本用这个
# 在网页内容中找出 var observe24h_data 相关内容
match = re.search('var observe24h_data = ' + '(.*?)' + ';', text)
if match:
text2 = json.loads(match.group(1))
# 获取城市、温度、湿度、风向、风力级数
weather[0] = text2['od']['od1'] # 城市
weather[1] = text2['od']['od2'][0]['od22'] # 温度
weather[2] = text2['od']['od2'][0]['od27'] # 相对湿度
weather[3] = text2['od']['od2'][0]['od24'] # 实时风向
weather[4] = text2['od']['od2'][0]['od28'] # 空气质量
return # 成功获取数据后退出函数
except Exception as e:
print(f"Error fetching weather data: {e}")
retries -= 1 # 减少重试次数
if retries > 0:
print(f"尝试重新获取天气数据,剩余{retries}次...")
time.sleep(5) # 等待一段时间再重试
# 如果获取失败,恢复之前的天气信息
weather = previous_weather.copy()
print("获取天气数据失败!")
""""
开始连接wifi
"""
try:
wifi_connected = WIFI_Connect()
except Exception as e:
print(f"连接WIFI失败: {e}")
wifi_connected = False
# 如果连接失败,显示连接失败的信息
if not wifi_connected:
print('WiFi连接失败.')
canvas.clear() # 清屏,黑色
canvas.draw_string_advanced(600, 500, 80, "连接失败,复位重新连接!", color=(255, 255, 255))
Display.show_image(canvas) # 显示
while True:
pass # 阻塞在此,不再继续执行
else:
# 创建一个包含所有图片路径的列表
#kof_paths = [f"/sdcard/clock/ui/kof/{i}.png" for i in range(1, 18)] # 从1到17
#star_paths = [f"/sdcard/clock/ui/star/{i}.png" for i in range(1, 25)] # 从1到24
#logo_paths = [f"/sdcard/clock/ui/logo/{i}.png" for i in range(1, 31)] # 从1到31
# 预处理所有图像并转换为RGB565格式
#star_rgb565 = [image.Image(path).to_rgb565() for path in star_paths]
#kof_rgb565 = [image.Image(path).to_rgb565() for path in kof_paths]
#logo_rgb565 = [image.Image(path).to_rgb565() for path in logo_paths]
# 用于显示图片
#star_index = 0
#kof_index = 0
#logo_index = 0
# 获取空气质量字符串
aqi_str = weather[4]
# 初始绘制,首次绘制.
if is_first_run:
# 清除上次残留
canvas.draw_rectangle(0, 0, 1920, 1080, color = (0, 0, 0), thickness = 2, fill = True)
canvas.draw_image(bg, 0, 0, alpha=256, scale=1.0)
canvas.draw_string_advanced(140, 20, 120, f" {weather[0]} ", color = (255, 165, 0))
# 绘制温度湿度信息
canvas.draw_string_advanced(150, 190, 120, f"温度: {weather[1]}℃", color=(255,160,122))
canvas.draw_string_advanced(900, 190, 120, f"湿度: {weather[2]}%", color=(32,178,170))
# 清楚上次残留,并绘制风向信息
canvas.draw_rectangle(140, 900, 840, 140, color = (199, 212, 195), thickness = 2, fill = True)
canvas.draw_string_advanced(140, 900, 120, f"实时风向: {weather[3]}", color=(255, 255, 0))
# 空气质量
try:
aqi = int(aqi_str)
except ValueError:
aqi = 0 # 设置默认值
if 0 <= aqi < 50: # 优
canvas.draw_rectangle(900, 30, 120, 100, color=(0, 255, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 优!", color=(0, 0, 0))
elif 50 <= aqi < 100: # 良
canvas.draw_rectangle(900, 30, 120, 100, color=(249, 218, 101), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 良", color=(0, 0, 0))
elif 100 <= aqi < 150: # 轻度
canvas.draw_rectangle(900, 30, 120, 100, color=(255, 165, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 轻度", color=(0, 0, 0))
elif 150 <= aqi < 200: # 中度
canvas.draw_rectangle(900, 30, 120, 100, color=(212, 106, 106), thickness=2, fill=True)
canvas.draw_string_advanced(900, 20, 80, f" 中度", color=(0, 0, 0))
elif 200 <= aqi < 300: # 重度
canvas.draw_rectangle(900, 30, 120, 100, color=(220, 20, 60), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 重度", color=(0, 0, 0))
elif 300 <= aqi < 500: # 严重
canvas.draw_rectangle(900, 30, 120, 100, color=(139, 0, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 严重", color=(0, 0, 0))
is_first_run = False # 设置标志为False,下次循环不绘制这些信息
# 主循环
last_weather_update = time.time() # 记录最后一次更新天气的时间
try:
while True:
os.exitpoint() #检测IDE中断
current_time = time.time() # 当前时间
localtime_now = time.localtime() # 每次循环开始时定义 localtime_now
if current_time - last_weather_update > 1000: # 每隔1000秒更新一次天气信息
last_weather_update = current_time
weather_get() # 获取天气
sync_ntp() # 同步时间
aqi_str = weather[4] # 更新空气质量字符串
# 在同步时间之后获取本地时间并格式化
time_str = '%s-%s-%s %s:%s:%s' % (
localtime_now[0], # 年
zero_str(localtime_now[1]), # 月
zero_str(localtime_now[2]), # 日
zero_str(localtime_now[3]), # 小时
zero_str(localtime_now[4]), # 分钟
zero_str(localtime_now[5]) # 秒
)
print("当前日期和时间:",time_str)
# 清除上次残留, # 日期:年月日
canvas.draw_rectangle(140, 400, 950, 200, color = (214, 202, 56), thickness = 2, fill = True)
canvas.draw_string_advanced(120, 390, 180, f" {localtime_now[0]}-{zero_str(localtime_now[1])}-{zero_str(localtime_now[2])}", color=(144,238,144))
# 清除上次残留, # 城市信息
canvas.draw_rectangle(150, 20, 140, 140, color = (0, 0, 0), thickness = 2, fill = True)
canvas.draw_string_advanced(140, 20, 120, f" {weather[0]} ", color = (255, 165, 0))
# 绘制温度湿度信息
canvas.draw_string_advanced(150, 190, 120, f"温度: {weather[1]}℃", color=(255,160,122))
canvas.draw_string_advanced(900, 190, 120, f"湿度: {weather[2]}%", color=(32,178,170))
# 清楚上次残留,并绘制风向信息
canvas.draw_rectangle(140, 900, 840, 140, color = (199, 212, 195), thickness = 2, fill = True)
canvas.draw_string_advanced(140, 900, 120, f"实时风向: {weather[3]}", color=(255, 255, 0))
# 空气质量
try:
aqi = int(aqi_str)
except ValueError:
aqi = 0 # 设置默认值
if 0 <= aqi < 50: # 优
canvas.draw_rectangle(900, 30, 120, 100, color=(0, 255, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 优!", color=(0, 0, 0))
elif 50 <= aqi < 100: # 良
canvas.draw_rectangle(900, 30, 120, 100, color=(249, 218, 101), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 良", color=(0, 0, 0))
elif 100 <= aqi < 150: # 轻度
canvas.draw_rectangle(900, 30, 120, 100, color=(255, 165, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 轻度", color=(0, 0, 0))
elif 150 <= aqi < 200: # 中度
canvas.draw_rectangle(900, 30, 120, 100, color=(212, 106, 106), thickness=2, fill=True)
canvas.draw_string_advanced(900, 20, 80, f" 中度", color=(0, 0, 0))
elif 200 <= aqi < 300: # 重度
canvas.draw_rectangle(900, 30, 120, 100, color=(220, 20, 60), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 重度", color=(0, 0, 0))
elif 300 <= aqi < 500: # 严重
canvas.draw_rectangle(900, 30, 120, 100, color=(139, 0, 0), thickness=2, fill=True)
canvas.draw_string_advanced(900, 30, 80, f" 严重", color=(0, 0, 0))
###########
#主循环绘制#
###########
# 清除上次残留, # 日期:年月日
canvas.draw_rectangle(140, 400, 950, 200, color = (214, 202, 56), thickness = 2, fill = True)
canvas.draw_string_advanced(120, 390, 180, f" {localtime_now[0]}-{zero_str(localtime_now[1])}-{zero_str(localtime_now[2])}", color=(144,238,144))
# 清除上次残留,# 时间 :小时分钟秒
canvas.draw_rectangle(140, 620, 700, 170, color = (102, 218, 119), thickness = 2, fill = True)
canvas.draw_string_advanced(120, 610, 150, f" {zero_str(localtime_now[3])}:{zero_str(localtime_now[4])}:{zero_str(localtime_now[5])}", color=(199, 237, 204))
# 图片绘制
#
# canvas.draw_image(star_rgb565[star_index], 480, 0, alpha=256, scale=1.0)
# canvas.draw_image(kof_rgb565[kof_index], 700,700, alpha=256, scale=1.0)
Display.show_image(canvas) # 显示图片
time.sleep_ms(20) # 消除图片过快鬼畜
# 查询内存,可有可无K230随便造这些小功能
DRAM = gc.mem_free()
if DRAM < 1000000: # 内存不足
gc.collect() # 回收内存
# 更新索引,使用模运算实现循环
# star_index = (star_index + 1) % len(star_rgb565)
# kof_index = (kof_index + 1) % len(kof_rgb565)
# logo_index = (logo_index + 1) % len(logo_rgb565)
# bg = (bg) % len(bg_rgb565)
except KeyboardInterrupt:
print("用户停止程序")
except Exception as e:
print(f"发生异常: {e}")
finally:
# 释放显示资源
Display.deinit()
MediaManager.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
使用方法
大致使用方法:
1,首先连接WIFI
输入WIFI账号密码
2,默认获取的是深圳市的气象数据
修改城市的方法也很简单,找到这段代码
把HTTP复制 在浏览器上粘贴
改一下自己想看的地方,然后吧链接替换就行