DotNet的MQTT实施
DotNet的MQTT实施
在DotNet上实施MQTT的更高层次的软件包。Es ist sogar .NET-Standard 2.0版本:
GitHub
Hier etwas Doku:
制备
以下代码显示了如何使用MqttFactory以最简单的方式创建新的MQTT客户端。
// Create a new MQTT client. var factory = new MqttFactory(); var mqttClient = factory.CreateMqttClient();
客户选择
MQTT客户端的所有选项都捆绑在一个名为MqttClientOptions的类中。可以通过属性手动在代码中填充选项,但建议使用MqttClientOptionsBuilder。此类提供了一个流畅的API,并通过提供一些重载和帮助程序方法来轻松设置选项。以下代码显示了如何将构建器与几个随机选项一起使用。
// Create TCP based options using the builder.
var options = new MqttClientOptionsBuilder()
.WithClientId("Client1")
.WithTcpServer("broker.hivemq.com")
.WithCredentials("bud", "%spencer%")
.WithTls()
.WithCleanSession()
.Build();
TCP连接
以下代码显示了如何设置MQTT客户端的选项以利用基于TCP的连接。
// Use TCP connection.
var options = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com", 1883) // Port is optional
.Build();
安全的TCP连接
以下代码显示了如何使用TLS安全的TCP连接(属性仅设置为参考):
// Use secure TCP connection.
var options = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com")
.WithTls()
.Build();
处理特殊证书
为了处理特殊的证书错误,可以使用特殊的验证回调(.NET Framework和netstandard)。对于UWP应用,可以使用属性。
// For .NET Framwork & netstandard apps:
MqttTcpChannel.CustomCertificateValidationCallback = (x509Certificate, x509Chain, sslPolicyErrors, mqttClientTcpOptions) =>
{
if (mqttClientTcpOptions.Server == "server_with_revoked_cert")
{
return true;
}
return false;
};
// For UWP apps:
MqttTcpChannel.CustomIgnorableServerCertificateErrorsResolver = o =>
{
if (o.Server == "server_with_revoked_cert")
{
return new []{ ChainValidationResult.Revoked };
}
return new ChainValidationResult[0];
};
WebSocket连接
为了使用WebSocket通信通道,需要以下代码。
// Use WebSocket connection.
var options = new MqttClientOptionsBuilder()
.WithWebSocketServer("broker.hivemq.com:8000/mqtt")
.Build();
也可以通过调用UseTls()方法来使用安全的Web套接字连接,该方法会将协议从ws://切换到wss://。通常,需要子协议,该子协议可以直接添加到URI或专用属性中。
连接中
设置MQTT客户端选项后,可以建立连接。以下代码显示了如何与服务器连接。
// Use WebSocket connection.
var options = new MqttClientOptionsBuilder()
.WithWebSocketServer("broker.hivemq.com:8000/mqtt")
.Build();
await client.ConnectAsync(options);
重新连接
如果与服务器的连接丢失,则会触发Disconnected事件。如果由于无法访问服务器等导致对ConnectAsync的调用失败,也会触发该事件。这允许仅调用ConnectAsync方法一次,并通过使用Disconnected事件来处理重试等。如果重新连接失败,则再次触发Disconnected事件。下面的代码显示了如何设置此行为,包括短暂的延迟。
mqttClient.Disconnected += async (s, e) =>
{
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
await Task.Delay(TimeSpan.FromSeconds(5));
try
{
await mqttClient.ConnectAsync(options);
}
catch
{
Console.WriteLine("### RECONNECTING FAILED ###");
}
};
消费信息
以下代码显示了如何处理传入消息:
mqttClient.ApplicationMessageReceived += (s, e) =>
{
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
Console.WriteLine();
};
订阅主题
一旦与服务器建立连接,就可以订阅主题。以下代码显示了MQTT客户端连接后如何订阅主题。
client.Connected += async (s, e) =>
{
Console.WriteLine("### CONNECTED WITH SERVER ###");
// Subscribe to a topic
await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
Console.WriteLine("### SUBSCRIBED ###");
};
发布消息
可以直接使用属性或使用MqttApplicationMessageBuilder创建应用程序消息。此类具有一些有用的重载,可以轻松处理不同的有效负载格式。构建器的API是流畅的API。以下代码显示了如何编写应用程序消息并发布它们:
var message = new MqttApplicationMessageBuilder()
.WithTopic("MyTopic")
.WithPayload("Hello World")
.WithExactlyOnceQoS()
.WithRetainFlag()
.Build();
await client.PublishAsync(message);
不需要填写应用程序消息的所有属性。以下代码显示了如何创建非常基本的应用程序消息:
var message = new MqttApplicationMessageBuilder()
.WithTopic("/MQTTnet/is/awesome")
.Build();
RPC呼叫
MQTTnet.Extensions.Rpc扩展名(以nuget形式提供)允许发送请求并等待匹配的答复。这是通过定义一个模式来完成的,该模式使用主题将请求和响应相关联。根据客户端使用情况,可以定义超时。以下代码显示了如何发送RPC调用。
var rpcClient = new MqttRpcClient(_mqttClient); var timeout = TimeSpan.FromSeconds(5); var qos = MqttQualityOfServiceLevel.AtMostOnce; var response = await rpcClient.ExecuteAsync(timeout, "myMethod", payload, qos);
响应请求的设备(Arduino,ESP8266等)需要解析并回复主题。以下代码显示了如何在C中实现处理程序。
// If using the MQTT client PubSubClient it must be ensured that the request topic for each method is subscribed like the following.
_mqttClient.subscribe("MQTTnet.RPC/+/ping");
_mqttClient.subscribe("MQTTnet.RPC/+/do_something");
// It is not allowed to change the structure of the topic. Otherwise RPC will not work. So method names can be separated using
// an _ or . but no +, # or . If it is required to distinguish between devices own rules can be defined like the following.
_mqttClient.subscribe("MQTTnet.RPC/+/deviceA.ping");
_mqttClient.subscribe("MQTTnet.RPC/+/deviceB.ping");
_mqttClient.subscribe("MQTTnet.RPC/+/deviceC.getTemperature");
// Within the callback of the MQTT client the topic must be checked if it belongs to MQTTnet RPC. The following code shows one
// possible way of doing this.
void mqtt_Callback(char *topic, byte *payload, unsigned int payloadLength)
{
String topicString = String(topic);
if (topicString.startsWith("MQTTnet.RPC/")) {
String responseTopic = topicString + String("/response");
if (topicString.endsWith("/deviceA.ping")) {
mqtt_publish(responseTopic, "pong", false);
return;
}
}
}
// Important notes:
// ! Do not send response message with the _retain_ flag set to true.
// ! All required data for a RPC call and the result must be placed into the payload.

浙公网安备 33010602011771号