ESP32调试板连接MQTT自动注册小蓝灯到Homeassistant

该代码示例展示了如何用MicroPython编写程序,使ESP32通过WiFi连接到HomeAssistant,并自动注册设备上的小蓝灯(2号引脚)作为传感器。程序涉及网络连接、MQTT协议以及设备状态的上报和控制。
摘要由CSDN通过智能技术生成

文章目录

简介

使用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类

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
下面是一个简单的ESP32连接MQTT服务器的Arduino代码示例: 首先,你需要安装一个MQTT库。在Arduino IDE中,进入 "工具" -> "管理库",搜索 "PubSubClient" 并安装。 然后,你可以使用以下代码作为起点: ```c++ #include <WiFi.h> #include <PubSubClient.h> // Replace with your network credentials const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; // Replace with your MQTT broker IP address const char* mqtt_server = "your_MQTT_broker_IP"; WiFiClient espClient; PubSubClient client(espClient); void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); client.setServer(mqtt_server, 1883); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); } void reconnect() { while (!client.connected()) { Serial.println("Connecting to MQTT broker..."); if (client.connect("ESP32Client")) { Serial.println("Connected to MQTT broker"); // Subscribe to topic client.subscribe("test_topic"); } else { Serial.print("Failed to connect to MQTT broker with state "); Serial.print(client.state()); delay(2000); } } } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message received on topic: "); Serial.println(topic); Serial.print("Message content: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); // Add your custom logic here } ``` 该代码连接到WiFi网络,然后连接MQTT服务器并订阅一个主题。如果连接失败,则尝试重新连接。回调函数 `callback()` 可以在收到消息时添加自定义逻辑。 你需要将以下变量替换为你自己的值: - `ssid` 和 `password` - 你的WiFi网络名称和密码 - `mqtt_server` - 你的MQTT服务器IP地址 然后,你可以使用 `client.publish()` 函数向MQTT服务器发布消息,例如: ```c++ client.publish("test_topic", "Hello from ESP32"); ``` 这将发布一个 "Hello from ESP32" 的消息到 "test_topic" 主题。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值