简介
使用MicroPython编写ESP32控制代码,将ESP32调试板上的小蓝灯(2号引脚)自动注册到Homeassistant
代码
# coding: utf-8
# 2023.03.12 by Yone
import time
import network
import json
from umqtt.simple import MQTTClient
from machine import Pin
class WiFi:
def __init__(self, ssid, password) -> None:
self._ssid = ssid
self._password = password
self._wlan = network.WLAN(network.STA_IF)
def connect(self):
self._wlan.active(True)
if not self._wlan.isconnected():
print("[+] 连接网络...")
self._wlan.connect(self._ssid, self._password)
i = 1
while not self._wlan.isconnected():
print("[-] 正在链接...{}".format(i))
i += 1
time.sleep(1)
print("[!] 网络配置: ", self._wlan.ifconfig())
class Device:
def __init__(self, name: str, sensors: list) -> None:
self.name = name
# 绑定 { 传感器名称: 传感器对象 }
self.sensors = { sensor.name: sensor for sensor in sensors }
class Sensor:
def __init__(self, pin_id, name, type) -> None:
self.name = name
self.type = type
self.pin_id = pin_id
self._sensor = Pin(self.pin_id, Pin.OUT)
# 绑定 { 传感器状态: 传感器控制函数 }
self.controller = {
"ON": self.open,
"OFF": self.close
}
# self.close()
self.controller["OFF"]()
def open(self):
self.status = "ON"
self._sensor.value(1)
print("[*] {sensor_name}状态:ON".format(sensor_name=self.name))
def close(self):
self.status = "OFF"
self._sensor.value(0)
print("[*] {sensor_name}状态:OFF".format(sensor_name=self.name))
class HARegistrar:
def __init__(self, mqtt_client, device_name, sensor) -> None:
self._mqtt_client = mqtt_client
self._device_name = device_name
self._sensor = sensor
def get_register_topic(self):
return "homeassistant/switch/HA/{uid}/config".format(uid=self.get_uid())
def get_register_content(self):
return {
# 设备和传感器名字,ID
"unique_id": self.get_uid(),
# 传感器类型
"name": self._sensor.type,
# 传感器图标
"icon": "mdi:lightbulb",
# 设备和传感器名字,状态主题
"state_topic": self.get_status_topic(),
# 设备和传感器名字,设备信息主题
"json_attributes_topic": "{mqtt_topic_prefix}/attributes".format(mqtt_topic_prefix=self.get_iot_mqtt_topic_prefix()),
# 设备和传感器名字,HA控制命令主题
"command_topic": self.get_command_topic(),
# 设备信息
"device": {
"identifiers": self._device_name,
"manufacturer": "Yone",
"model": "HA",
"name": self._device_name,
"sw_version": "1.0"
}
}
def get_status_topic(self):
return "{mqtt_topic_prefix}/state".format(mqtt_topic_prefix=self.get_iot_mqtt_topic_prefix())
def get_command_topic(self):
return "{mqtt_topic_prefix}/set".format(mqtt_topic_prefix=self.get_iot_mqtt_topic_prefix())
def get_uid(self):
return "HA-{device_name}-{sensor_name}".format(device_name=self._device_name, sensor_name=self._sensor.name)
def get_iot_mqtt_topic_prefix(self):
return "HA-{device_name}/{sensor_name}".format(device_name=self._device_name, sensor_name=self._sensor.name)
def register(self):
print("[-] 注册{sensor_name}".format(sensor_name=self._sensor.name))
# 注册传感器
self._mqtt_client.publish(
self.get_register_topic(),
json.dumps(self.get_register_content())
)
# 发送传感器状态
self._mqtt_client.publish(
self.get_status_topic(),
self._sensor.status
)
# 订阅传感器控制主题
self._mqtt_client.subscribe(
self.get_command_topic()
)
class Manager:
def __init__(self, wifi, mqtt_client, device) -> None:
self._wifi = wifi
self._mqtt_client = mqtt_client
self._device = device
self._controller = dict()
def register_device(self):
for sensor_name in self._device.sensors:
# 创建新注册器
registrar = HARegistrar(self._mqtt_client, self._device.name, self._device.sensors[sensor_name])
# 注册设备
registrar.register()
# 绑定 { 命令主题: 传感器 }
self._controller[registrar.get_command_topic()] = self._device.sensors[sensor_name]
def _msg_callback(self, command_topic, msg):
# 通过命令主题获取传感器
sensor = self._controller[command_topic.decode()]
# 通过状态获取控制函数,并运行
sensor.controller[msg.decode()]()
# 创建新注册器
registrar = HARegistrar(self._mqtt_client, self._device.name, sensor)
# 通过注册器获取状态主题,并更新设备状态
self._mqtt_client.publish(registrar.get_status_topic(), msg.decode())
def run(self):
# 连接Wi-Fi
self._wifi.connect()
# 设置MQTT服务器消息回调
self._mqtt_client.set_callback(self._msg_callback)
# 连接MQTT服务器
self._mqtt_client.connect()
time.sleep(0.5)
# 循环注册设备
self.register_device()
# 每秒检测一下MQTT服务器发来的消息
while True:
self._mqtt_client.check_msg()
time.sleep(1)
def main():
device_name = "ESP32_01"
manager = Manager(
WiFi("ssid", "password"),
MQTTClient(device_name, "mqtt_server_ip", 1883, "admin", "password"),
# 设备对象
Device(
# 设备名称
device_name,
# 传感器列表
[
Sensor(2, "blue_led", "LED")
]
)
)
manager.run()
if __name__ == "__main__":
main()
其他
有空再改进一下传感器类Sensor,让不同类型(灯,温度测量,电机,编码器)的传感器成为独立的类,都继承Sensor类