轻松集成:使用 .NET 在 Home Assistant 中添加自定义设备,实现电脑远程关机

本文介绍如何使用.NET为Home Assistant添加自定义设备,而无需进行额外的配置。通过使用Home Assistant的自动发现功能,我们可以让Home Assistant自动识别和添加新设备,从而简化设备管理流程。通过本文,你将学习如何编写一个简单的.NET程序,将其接入Home Assistant,并实现自定义设备的自动发现和远程关机。

1. 背景

通过前面的文章《搭建EMQX MQTT服务器并接入Home Assistant和.NET程序》,我们已经了解了如何部署EMQX MQTT服务器并接入Home Assistant。在这个基础上,我们可以通过MQTT协议实现设备之间的通信,包括设备的发现、状态更新等功能。Home Assistant提供了自动发现功能,可以自动识别和添加新设备,无需手动配置。这为我们添加自定义设备提供了便利。

在本文中,我们将介绍如何使用.NET为Home Assistant添加自定义设备,实现电脑远程关机的功能。我们将编写一个简单的.NET程序,将其接入Home Assistant,并实现自定义设备的自动发现和远程关机功能。通过这个例子,你将学习如何使用.NET和Home Assistant实现设备集成,为智能家居系统增加新的功能。

2. MQTT 发现消息格式

MQTT 发现消息需要遵循特定的格式:

复制代码
<discovery_prefix>/<component>/[<node_id>/]<object_id>/config
  • <discovery_prefix>:发现前缀,默认为 homeassistant,可以在 Home Assistant 配置中更改。
  • <component>:支持的 MQTT 集成组件之一,例如 binary_sensor
  • <node_id> (可选):提供主题的节点 ID,不被 Home Assistant 使用,但可以用于结构化 MQTT 主题。
  • <object_id>:设备的 ID,用于区分不同的设备。

对于一个开关设备,我们可以使用以下格式:

复制代码
homeassistant/button/pc/<pc_mac>/config

这里的 <pc_mac> 是电脑的 MAC 地址,这里通过这种简单的方式区分不同的设备。通过这个格式,我们可以实现设备的自动发现和配置。对于 button 组件,我们需要提供一些配置信息,例如设备的名称、唯一标识、状态主题、命令主题等。这些信息将帮助 Home Assistant 识别和管理设备,我们可以通过官网的设备介绍文档查看更多信息。

对于 MAC 地址的获取,我们可以通过下面的代码,例如:

cs 复制代码
/// <summary>
/// 获取第一个可用的网卡的MAC地址
/// </summary>
/// <returns></returns>
static string? GetMacAddress()
{
    return NetworkInterface.GetAllNetworkInterfaces()
        .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
        .Select(nic => nic.GetPhysicalAddress().ToString())
        .FirstOrDefault();
}

3. 发布设备配置信息

在.NET程序中,我们在程序启动时需要发布该设备的配置信息,让Home Assistant能够识别和添加该设备。在前面的一篇文章中,我们已经了解了如何使用MQTTnet库来实现MQTT客户端,这里我们可以使用MQTTnet库来发布设备配置信息。

cs 复制代码
var topic = $"{iot_discovery_prefix}/{mac}";

// 发布发现消息
var discoveryMessage = new
{
    name = "我的电脑",
    command_topic = $"{topic}/commands",
    unique_id = $"pc_{mac}",
    availability = new
    {
        topic = $"{topic}/availability",
    }
};
var payload = Encoding.UTF8.GetBytes(System.Text.Json.JsonSerializer.Serialize(discoveryMessage));
Console.WriteLine($"Discovery message: {Encoding.UTF8.GetString(payload)}");

var message = new MqttApplicationMessageBuilder()
    .WithTopic($"{topic}/config")
    .WithPayload(payload)
    .Build();

这里我们使用了一个简单的JSON格式来表示设备的配置信息,包括设备的名称、命令主题、唯一标识、可用性主题等。这些信息将帮助Home Assistant识别和管理设备。我们将这个JSON消息发布到<discovery_prefix>/<component>/[<node_id>/]<object_id>/config主题,让Home Assistant能够识别和添加该设备。

4. 调整设备可用性

上一节的配置消息发布后,我们的设备将被Home Assistant自动识别和添加,无需手动配置。这为我们添加自定义设备提供了便利,同时也提高了设备的可管理性和易用性。但是需要注意的一点是,设备添加成功后是不可用的状态,需要我们调整设备的可用性,让Home Assistant能够正常使用该设备。

关于设备的可用性,我们需要在设备启动时发布可用性消息,表示设备已经启动并可用。这样Home Assistant才能正常使用该设备。我们可以在设备启动时发布一个可用性消息,例如:

cs 复制代码
// 发布在线消息
await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
    .WithTopic($"{topic}/availability")
    .WithPayload("online")
    .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
    .WithRetainFlag()
    .Build());

这里我们发布了一个online的消息,表示设备已经启动并可用。这样Home Assistant就能够正常使用该设备了。

当然,可用性的调整也需要考虑到设备的异常情况,例如设备的断线、关机等情况。在这种情况下,我们需要发布一个offline的消息,表示设备不可用。在设备开始连接配置时,我们可以配置一个遗嘱消息,当设备异常断线时,MQTT服务器会自动发布这个遗嘱消息,表示设备不可用。这样Home Assistant就能够及时发现设备的异常情况,提高设备的可靠性和稳定性。

cs 复制代码
var options = new MqttClientOptionsBuilder()
            .WithClientId(mac)
            .WithTcpServer("MQTT服务地址", 1883)
            .WithCredentials("你的客户端登录用户名", "你的密码")
            // 遗嘱消息
            .WithWillTopic($"{topic}/availability")
            .WithWillPayload("offline")
            .WithWillQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
            .WithCleanSession()
            .Build();

5. 实现远程关机功能

在设备添加和可用性调整后,我们的设备已经可以被Home Assistant正常使用了。接下来我们可以实现设备的功能,当监听到Home Assistant的命令时执行相应的操作,例如远程关机。这实现这一功能之前我们还需要再启动的时候订阅命令主题,例如:

cs 复制代码
// 订阅命令主题
await mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic($"{topic}/commands").Build());

这里我们订阅了命令主题,当Home Assistant发送命令时我们就能够接收到。接收到命令后我们可以执行相应的操作,例如远程关机:

cs 复制代码
private static Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
{
    var topic = arg.ApplicationMessage.Topic;
    var payload = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment);
    
    Console.WriteLine($"Message received on topic: {topic}.");
    Console.WriteLine($"Payload: {payload}");

    if (topic.EndsWith("commands"))
    {
        // 按钮按下
        if (payload == "PRESS")
        {
            Console.WriteLine("Shutting down...");
            // System.Diagnostics.Process.Start("shutdown", "/s /t 0");
            System.Diagnostics.Process.Start("shutdown", "/s");
            Environment.Exit(0);
            // 可以取消关机 shutdown /a
        }
    }

    return Task.CompletedTask;
}

当然这里的指令我没有使用立马关机,而是使用了弹窗的方式提醒即将关机,这样可以避免误操作。如果正在使用而出现了误操作,在调试时,我们可以使用命令行 shutdown -a 来取消关机。

6. 最后

通过这个例子,我们学习了如何使用.NET为Home Assistant添加自定义设备,实现电脑远程关机的功能。以上只是一个简单的使用案例,如果你需要具体的实现并使用这个工具,则还需要考虑更多的细节,例如信息的配置,开机启动等。通过这个例子,你可以学习如何使用.NET和Home Assistant实现设备集成,为智能家居系统增加新的功能。

相关推荐
rockey6278 小时前
AScript异步执行与await关键字
c#·.net·script·eval·expression·异步执行·动态脚本
叫我少年10 小时前
ASP.NET Core 最小 API 快速参考
.net·api
Oflycomm11 小时前
模组开发不迷路:Wi-Fi 7、蓝牙6.0、5G RedCap、PLC双模怎么选?这份选型指南建议收藏
物联网·5g·iot·6g·蓝牙模组·wifi模组·世界电信和信息社会日大会
步步为营DotNet19 小时前
深入.NET 11:C# 14 在边缘计算数据处理的优化与实践
c#·.net·边缘计算
云飞云共享云桌面19 小时前
SolidWorks 服务器通过云飞云共享云桌面10人研发共享方案
运维·服务器·3d·设计模式·电脑
AxureMost20 小时前
免费开源无广告,电脑护眼首选轻量软件
电脑
Kurisu57520 小时前
FilzaCracked_4.0.0_TS.ipa2026最新官方正版免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)手机版通用
ios·智能手机·电脑·巨魔
ACP广源盛139246256732 天前
IX8024 对标 ASM2824 @ACP#搭配昆仑芯 P800 构建 AI 服务器 PCIe4.0 高速互联架构
网络·人工智能·嵌入式硬件·电脑
步步为营DotNet2 天前
洞悉.NET 11:Blazor 与 Microsoft.Extensions.AI 的融合创新实践
人工智能·microsoft·.net
回忆2012初秋2 天前
.NET 8.0 实战:基于 MQTTnet 封装高可用的 MQTT 发布/订阅工具类
开发语言·mqtt·.net