C# 接入参考

最近更新时间:2023-08-11 18:24:51

我的收藏
C# 是一种现代通用的、面向对象的编程语言,由微软在 .NET 框架中开发并推出。它结合了 C++ 的强大功能和 Java 的易用性,使得开发者能够构建各种类型的应用程序,包括 Windows 客户端应用、Web 应用、数据库应用、移动应用和游戏等。
腾讯云物联网开发平台支持使用 C# 接入。本文介绍如何在 C# 项目中,使用 MQTTnet Client 库,实现与腾讯云物联网开发平台的连接、topic 订阅、上下行消息交互等功能。
说明:
1. 本示例基于 donet 6.0。
2. 第三方类库使用版本如下:
MQTTnet:v3.0.11
MQTTnet.Extensions.ManagedClient:v3.0.11
Newtonsoft.Json:v12.0.3
NLog:v5.2.3

操作场景

一款智能灯接入到物联网开发平台,通过物联网开发平台可以远程控制灯的亮度、颜色、开关,并实时获取智能灯上报到开发平台的数据。

准备工作

1. 申请 腾讯云物联网开发平台 服务。
2. 一台 Windows 电脑并且安装了 VS2017 及以上版本。

操作步骤

创建项目

1. 登录 物联网开发平台控制台,选择平台默认开通的公共实例或用户购买的企业实例
2. 单击实例后,默认进入项目列表页面,单击新建项目
项目名称:必填,输入“智能灯演示”或其他名称。
项目描述:按照实际需求填写项目描述。



3. 项目基本信息填写完成后,单击保存,即可完成新建项目。
4. 项目新建成功后,即可新建产品。

新建产品

1. 单击项目名称,进入产品列表页面,单击新建产品
2. 在新建产品页面,填写产品基本信息。
产品名称:必填,输入“智能灯”或其他产品名称。
产品品类:选择标准品类 “智能生活” > “电工照明” > “灯”。
设备类型:选择“设备”。
认证方式:选择“密钥认证”。
通信方式:按需选择。
其他都为默认选项。



3. 产品信息填写完成后,单击保存,即可完成新建产品。
4. 产品新建成功后,您可在产品列表页查看到“智能灯”。

定义产品物模型

选择“灯”类型后,系统会自动生成标准功能。




创建设备

在设备调试页面中,单击新建设备,设备名为 dev001。


有关物模型的协议介绍请参阅 物模型协议

C# MQTT 客户端使用

通过以上步骤,您已经成功拿到腾讯云物联网开发平台的设备三元组信息,接下来可以根据这个示例来使用 C# 接入。

输入三元组信息

单击创建的设备名称,获取设备三元组信息。
// 云端生成的三元组信息
static string PRODUCT_ID = "YOUR_PRODUCT_ID"; // 产品id
static string DEVICE_NAME = "YOUR_DEVICE_NAME"; // 设备名称
static string DEVICE_SECRET = "IOT_PSK"; // 设备密钥

生成 MQTT client 连接参数

通过刚才填入的三元组信息,生成 MQTT 的 clientIduserNamepassword
// 生成MQTT连接参数
byte[] decodeBytes = Convert.FromBase64String(DEVICE_SECRET);
string clientId = PRODUCT_ID + DEVICE_NAME;
string usrNmae = clientId + ";21010406;" + GetNextConnId() +";"+ 0x7fffffff.ToString();
string password = ComputeHmacSha1(usrNmae, decodeBytes) + ";hmacsha1";

创建 MQTT client 并连接云平台

IManagedMqttClient mqttClient = new MqttFactory().CreateManagedMqttClient();

var mqttOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(10))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithClientId(clientId)
.WithCredentials(usrNmae, password)
.WithTcpServer(url, 1883) // 非tls模式
.WithCleanSession()
.Build())
.Build();
如果使用 TLS 加密接入,则按照如下方式配置:
IManagedMqttClient mqttClient = new MqttFactory().CreateManagedMqttClient();

var mqttOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(10))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithClientId(clientId)
.WithCredentials(usrNmae, password)
.WithTcpServer(url, 8883) // tls 接入
.WithTls(new MqttClientOptionsBuilderTlsParameters {
UseTls = true,
IgnoreCertificateChainErrors = true,
IgnoreCertificateRevocationErrors = true,
AllowUntrustedCertificates = true,
})
.WithCleanSession()
.Build())
.Build();

监听 MQTT 连接或断连或接收事件

// 监听连接事件
mqttClient.UseConnectedHandler(e =>
{
log.Info("mqtt connect success with " + deviceId);
return Task.CompletedTask;
});

// 监听断开事件
mqttClient.UseDisconnectedHandler(e =>
{
log.Error("mqtt disconnect with " + deviceId);
return Task.CompletedTask;
});

// 监听收到的消息
mqttClient.UseApplicationMessageReceivedHandler(e =>
{
// 处理物模型数据
string topic = e.ApplicationMessage.Topic;
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
log.Debug($"down message topic: {topic} paylaod : {payload}");
if (topic.Contains("/property/"))
{
// 属性处理

}else if (topic.Contains("/event/"))
{
// 事件处理

}else if (topic.Contains("/action/"))
{
// 行为处理

}
return Task.CompletedTask;
});

连接云平台

// 连接到平台
await mqttClient.StartAsync(mqttOptions);

订阅物模型 topic

// 订阅物模型topic
var topicFilters = new[]
{
new MqttTopicFilterBuilder().WithTopic("$thing/down/property/"+deviceId).Build(),
new MqttTopicFilterBuilder().WithTopic("$thing/down/event/"+deviceId).Build(),
new MqttTopicFilterBuilder().WithTopic("$thing/down/action/"+deviceId).Build()
};
await mqttClient.SubscribeAsync(topicFilters);

上报亮度示例

int brightness = 25;
var payload_json = new JObject
{
["method"] = "report",
["clientToken"] = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(),
["params"] = new JObject
{
["brightness"] = brightness
}
};
string payload = JsonConvert.SerializeObject(payload_json).ToString();
var message = new MqttApplicationMessageBuilder()
.WithTopic("$thing/up/property/" + deviceId)
.WithPayload(payload)
.WithQualityOfServiceLevel(0)
.WithRetainFlag(false)
.Build();
await mqttClient.PublishAsync(message);
完整的示例代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using NLog;
using MQTTnet;
using MQTTnet.Client.Options;
using MQTTnet.Extensions.ManagedClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


namespace IoT.Explorer.Test
{
class DatatemplateTest
{
private static Logger log = LogManager.GetCurrentClassLogger();
// 云端生成的三元组信息
static string PRODUCT_ID = "F2F43QKKA4";
static string DEVICE_NAME = "5629fbfa12f4";
static string DEVICE_SECRET = "a91V4htL41oILv80lgCeLA==";

public static string GetNextConnId()
{
char[] connId = new char[6];
Random random = new Random();
for (int i = 0; i < 6 - 1; i++)
{
int flag = random.Next(3);
switch (flag)
{
case 0:
connId[i] = (char)(random.Next(26) + 'a');
break;
case 1:
connId[i] = (char)(random.Next(26) + 'A');
break;
case 2:
connId[i] = (char)(random.Next(10) + '0');
break;
}
}

connId[6 - 1] = '\\0';
return new string(connId);
}

public static string ComputeHmacSha1(string inputString, byte[] keyBytes)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(inputString);

using (HMACSHA1 hmac = new HMACSHA1(keyBytes))
{
byte[] hashBytes = hmac.ComputeHash(inputBytes);
string hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
return hashString;
}
}

static async Task Main(string[] args)
{
// 生成MQTT连接参数
byte[] decodeBytes = Convert.FromBase64String(DEVICE_SECRET);
string clientId = PRODUCT_ID + DEVICE_NAME;
string usrNmae = clientId + ";21010406;" + GetNextConnId() +";"+ 0x7fffffff.ToString();
string password = ComputeHmacSha1(usrNmae, decodeBytes) + ";hmacsha1";
string url = PRODUCT_ID + ".iotcloud.tencentdevices.com";
string deviceId = PRODUCT_ID + "/" + DEVICE_NAME;

try
{
IManagedMqttClient mqttClient = new MqttFactory().CreateManagedMqttClient();

var mqttOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(10))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithClientId(clientId)
.WithCredentials(usrNmae, password)
.WithTcpServer(url, 8883)
.WithTls(new MqttClientOptionsBuilderTlsParameters {
UseTls = true,
IgnoreCertificateChainErrors = true,
IgnoreCertificateRevocationErrors = true,
AllowUntrustedCertificates = true,
})
.WithCleanSession()
.Build())
.Build();

// 监听连接事件
mqttClient.UseConnectedHandler(e =>
{
log.Info("mqtt connect success with " + deviceId);
return Task.CompletedTask;
});

// 监听断开事件
mqttClient.UseDisconnectedHandler(e =>
{
log.Error("mqtt disconnect with " + deviceId);
return Task.CompletedTask;
});

// 监听收到的消息
mqttClient.UseApplicationMessageReceivedHandler(e =>
{
// 处理物模型数据
string topic = e.ApplicationMessage.Topic;
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
log.Debug($"down message topic: {topic} paylaod : {payload}");
if (topic.Contains("/property/"))
{
// 属性处理

}else if (topic.Contains("/event/"))
{
// 事件处理

}else if (topic.Contains("/action/"))
{
// 行为处理

}
return Task.CompletedTask;
});

// 连接到平台
await mqttClient.StartAsync(mqttOptions);
Thread.Sleep(2000);

// 订阅物模型topic
var topicFilters = new[]
{
new MqttTopicFilterBuilder().WithTopic("$thing/down/property/"+deviceId).Build(),
new MqttTopicFilterBuilder().WithTopic("$thing/down/event/"+deviceId).Build(),
new MqttTopicFilterBuilder().WithTopic("$thing/down/action/"+deviceId).Build()
};
await mqttClient.SubscribeAsync(topicFilters);
int brightness = 0;
while (true) {
// 周期上报亮度
var payload_json = new JObject
{
["method"] = "report",
["clientToken"] = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(),
["params"] = new JObject
{
["brightness"] = brightness
}
};
string payload = JsonConvert.SerializeObject(payload_json).ToString();
var message = new MqttApplicationMessageBuilder()
.WithTopic("$thing/up/property/" + deviceId)
.WithPayload(payload)
.WithQualityOfServiceLevel(0)
.WithRetainFlag(false)
.Build();
await mqttClient.PublishAsync(message);
log.Debug("publish message :" + payload);
brightness++;
if (!mqttClient.IsConnected)
{
break;
}
Thread.Sleep(10000);
}
// disconnect
await mqttClient.StopAsync();

}
catch (Exception ex)
{
var name = ex.GetType().FullName;
log.Error("异常:"+ex.Message);
}

}
}
}
运行日志如下:
2023-08-09 12:04:20.0860 INFO IoT.Explorer.Test.DatatemplateTest - mqtt connect success with F2F43QKKA4/5629fbfa12f4
2023-08-09 12:04:21.7918 DEBUG IoT.Explorer.Test.DatatemplateTest - publish message :{"method":"report","clientToken":"1691553861","params":{"brightness":0}}
2023-08-09 12:04:21.8791 DEBUG IoT.Explorer.Test.DatatemplateTest - down message topic: $thing/down/property/F2F43QKKA4/5629fbfa12f4 paylaod : {"method":"report_reply","clientToken":"1691553861","code":0,"status":"success"}
2023-08-09 12:04:25.6359 DEBUG IoT.Explorer.Test.DatatemplateTest - down message topic: $thing/down/property/F2F43QKKA4/5629fbfa12f4 paylaod : {"method":"control","clientToken":"v2149648760ozOCb::af400362-c384-40dd-b39c-94d82950e1ad","params":{"power_switch":1}}
2023-08-09 12:04:29.4171 DEBUG IoT.Explorer.Test.DatatemplateTest - down message topic: $thing/down/property/F2F43QKKA4/5629fbfa12f4 paylaod : {"method":"control","clientToken":"v2146761678bxCmt::295125a1-6b64-4cba-b2ca-036bbef43390","params":{"power_switch":0}}
2023-08-09 12:04:31.7989 DEBUG IoT.Explorer.Test.DatatemplateTest - publish message :{"method":"report","clientToken":"1691553871","params":{"brightness":1}}
2023-08-09 12:04:31.8919 DEBUG IoT.Explorer.Test.DatatemplateTest - down message topic: $thing/down/property/F2F43QKKA4/5629fbfa12f4 paylaod : {"method":"report_reply","clientToken":"1691553871","code":0,"status":"success"}