from machine import UART, Pin, Timer
import time
import network
from umqtt.simple import MQTTClient
# 串口配置
UART_PORT = 1
UART_BAUDRATE = 115200
UART_TX_PIN = 1
UART_RX_PIN = 3
# LED 引脚
LED_PIN = 15
# 网络配置
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASSWORD = ""
# 巴法云 MQTT 配置
MQTT_BROKER = "bemfa.com"
MQTT_PORT = 9501
MQTT_CLIENT_ID = "f72ebbb051666a315cbae015845649f1"
MQTT_LIGHT_TOPIC = "light002"
MQTT_STATUS_TOPIC = "status"
ONLINE_STATUS = "on"
# 全局变量
light_status = False
mqtt_client = None
timer = None
uart = None
led = None
wifi_connected = False
connection_attempts = 0 # 连接尝试计数
max_connection_attempts = 3 # 最大连接尝试次数
def connect_wifi():
"""连接 WiFi 网络"""
global wifi_connected
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("正在连接 WiFi...")
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
max_wait = 15 # 增加等待时间
while max_wait > 0:
if wlan.isconnected():
break
max_wait -= 1
time.sleep(1)
if wlan.isconnected():
print(f"WiFi 连接成功,网络配置: {wlan.ifconfig()}")
wifi_connected = True
return True
else:
print("WiFi 连接失败")
wifi_connected = False
return False
else:
print(f"已连接 WiFi,网络配置: {wlan.ifconfig()}")
wifi_connected = True
return True
def setup_hardware():
"""初始化硬件组件:串口、LED"""
global uart, led
# 初始化串口
uart = UART(UART_PORT, baudrate=UART_BAUDRATE, tx=Pin(UART_TX_PIN), rx=Pin(UART_RX_PIN))
# 初始化 LED
led = Pin(LED_PIN, Pin.OUT)
return uart, led
def connect_mqtt():
"""连接巴法云 MQTT 服务器"""
global mqtt_client, connection_attempts
# 限制连接尝试频率
connection_attempts += 1
if connection_attempts > max_connection_attempts:
print("连接尝试次数过多,等待30秒后重试...")
time.sleep(30)
connection_attempts = 0
try:
# 确保之前的客户端已关闭
if mqtt_client:
try:
mqtt_client.disconnect()
except:
pass
mqtt_client = None
# 创建新的MQTT客户端连接
mqtt_client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, MQTT_PORT, keepalive=60)
mqtt_client.set_callback(mqtt_message_callback)
mqtt_client.connect()
print("已连接到巴法云 MQTT 服务器")
# 订阅控制主题
mqtt_client.subscribe(MQTT_LIGHT_TOPIC)
print(f"已订阅主题: {MQTT_LIGHT_TOPIC}")
# 立即发布一次在线状态
publish_online_status(None)
connection_attempts = 0 # 重置连接尝试计数
return True
except Exception as e:
print(f"连接 MQTT 服务器失败: {e}")
mqtt_client = None
return False
def publish_light_status(status):
"""发布灯状态到巴法云指定 MQTT 主题"""
global mqtt_client
if mqtt_client:
try:
mqtt_client.publish(MQTT_LIGHT_TOPIC, status)
print(f"已发布灯状态到 {MQTT_LIGHT_TOPIC}: {status}")
except Exception as e:
print(f"发布灯状态失败: {e}")
def publish_online_status(timer):
"""定期发布在线状态到巴法云平台"""
global mqtt_client
if mqtt_client:
try:
status_topic = f"{MQTT_CLIENT_ID}/{MQTT_STATUS_TOPIC}"
mqtt_client.publish(status_topic, ONLINE_STATUS, retain=True)
print(f"已发布在线状态到 {status_topic}")
except Exception as e:
print(f"发布在线状态失败: {e}")
def mqtt_message_callback(topic, msg):
"""处理接收到的 MQTT 消息"""
global light_status, led, uart
topic_str = topic.decode('utf-8')
msg_str = msg.decode('utf-8')
print(f"收到消息: 主题={topic_str}, 内容={msg_str}")
# 检查是否是我们订阅的主题
if topic_str == MQTT_LIGHT_TOPIC:
if msg_str == 'ON':
led.value(1)
light_status = True
uart.write(b"\rMQTT: LED is ON.\n")
print("LED 已打开")
elif msg_str == 'OFF':
led.value(0)
light_status = False
uart.write(b"\rMQTT: LED is OFF.\n")
print("LED 已关闭")
def check_mqtt_connection():
"""检查 MQTT 连接状态,如果断开则重新连接"""
global mqtt_client, wifi_connected
# 首先确保WiFi已连接
if not wifi_connected:
wifi_connected = connect_wifi()
if not wifi_connected:
return False
# 检查MQTT连接状态
if mqtt_client:
try:
# 使用ping检查连接是否活跃
mqtt_client.ping()
return True
except:
print("MQTT ping失败,连接已断开")
mqtt_client = None
# 连接断开,尝试重新连接
print("MQTT 连接已断开,尝试重新连接...")
return connect_mqtt()
def main():
"""主程序逻辑:串口控制 LED、MQTT 上传状态"""
global light_status, mqtt_client, timer
# 连接 WiFi
wifi_connected = connect_wifi()
if not wifi_connected:
print("WiFi 连接失败,程序退出")
return
# 初始化硬件
uart, led = setup_hardware()
# 连接 MQTT 服务器
if not connect_mqtt():
print("MQTT 连接失败,程序退出")
return
# 设置定时器定期发送在线状态,增加间隔时间减少网络负担
timer = Timer(0)
timer.init(period=120000, mode=Timer.PERIODIC, callback=publish_online_status)
# 运行前提示信息
uart.write(b"\rPlease enter 1 or 0,1 is open led,0 is close led:\n")
while True:
# 检查 MQTT 连接
if not check_mqtt_connection():
time.sleep(10) # 连接失败后增加等待时间
continue
# 处理 MQTT 消息
try:
mqtt_client.check_msg()
except Exception as e:
print(f"处理 MQTT 消息时出错: {e}")
mqtt_client = None
time.sleep(5) # 出错后短暂等待
# 处理串口数据
if uart.any():
data = uart.read()
print("Received:", data)
if data == b'1':
led.value(1)
light_status = True
uart.write(b"\rinput 1, LED is ON.\n")
publish_light_status("ON")
elif data == b'0':
led.value(0)
light_status = False
uart.write(b"\rinput 0, LED is OFF.\n")
publish_light_status("OFF")
else:
uart.write(b"\rInvalid input! Please enter 1 or 0.\n")
time.sleep(0.1) # 适当延时,减少 CPU 使用率
if __name__ == "__main__":
main()