Close Connection Message MQTTNet C# - c#

I am using the MQTTNet library for the MQTT connection in my application. I am using Mosquitto Broker as a MQTT broker. My app is in .Net core 3.1.
I am having requirement to send the MQTT message to device when the app is connected, normal disconnected and unexpected disconnected.
For the connected scenario, I am using the UseConnectedHandler extension method of the IMQTTClient.
mqttClient.UseConnectedHandler((MqttClientConnectedEventArgs e) =>
{
// Console.WriteLine("MqttClient - Connected");
// Publish the Connect Message
});
For the unexpected disconnect scenario I am using the WithWillMessage feature.
var mqttOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithWillMessage(_options.LastWillMessage)
.WithCleanSession()
.WithClientId(_options.DevcommMqttClientId)
.WithProtocolVersion(MqttProtocolVersion.V500)
.WithCommunicationTimeout(TimeSpan.FromSeconds(30))
.WithCredentials(_options.DevcommMqttUsername ?? string.Empty, _options.DevcommMqttPassword ?? string.Empty)
.WithTcpServer(_options.DevcommMqttHost, _options.DevcommMqttPort)
.WithTls(o =>
{
o.UseTls = _options.DevcommUseTls;
o.AllowUntrustedCertificates = _options.DevcommTlsAllowUntrustedCertificates;
o.IgnoreCertificateChainErrors = _options.DevcommTlsIgnoreCertificateChainErrors;
o.IgnoreCertificateRevocationErrors = _options.DevcommTlsIgnoreCertificateRevocationErrors;
o.SslProtocol = ParseSslProtocols(_options.DevcommTlsProtocols);
o.Certificates = _options.DevcommTlsClientCertificates.AsEnumerable();
o.CertificateValidationHandler = CertificateValidationHandler;
})
.Build())
.Build();
I am now stuck at graceful disconnect scenario. The UseDisconnectedHandler extension method is being called after the disconnect and not before disconnect.
Mosquitto broker is providing the feature of close message, which is similar of before disconnect event.
Is there anyway that using MQTTNet I can send the before disconnect message?

Related

MQTTnet disconnects from Azure IoT Hub on message publish

I am trying to subscribe MQTT messages in Azure IoT Hub. I am able to publish message using MQTTNet library but when I create subscriber to receive message from IoT hub then connection gets disconnected once message is published to the IoT hub.
I have tried to publish message from separate application and VS code extension, in both cases subscriber gets disconnected on message published.
I am using following code for subscriber
Console.WriteLine("Starting Subscriber.....");
//create subscriber client
var mqttFactory = new MqttFactory();
var mqttClient = mqttFactory.CreateMqttClient();
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithClientId("<Device-Id>")
.WithTcpServer("<IoTHub>.azure-devices.net", 8883)
.WithCredentials("<IoTHub>.azure-devices.net/<Device-Id>/api-version=2018-06-30", "SharedAccessSignature")
.WithTls(new MqttClientOptionsBuilderTlsParameters() { UseTls = true })
.WithCleanSession()
.Build();
mqttClient.ConnectedAsync += async (MqttClientConnectedEventArgs arg) =>
{
Console.WriteLine("Connected");
};
mqttClient.DisconnectedAsync += async (MqttClientDisconnectedEventArgs arg) =>
{
Console.WriteLine("Disconnected");
};
mqttClient.ApplicationMessageReceivedAsync += async (MqttApplicationMessageReceivedEventArgs arg) =>
{
Console.WriteLine("Message received");
};
var result = mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None).GetAwaiter().GetResult();
var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic("devices/<Device-Id>/messages/events/");
})
.Build();
var r = mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None).GetAwaiter().GetResult();
Console.WriteLine("MQTT client subscribed to topic.");
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
When I run this code and publish message then I get following output
Instead of receiver event, mqtt disconnect event fires. I am using 4.1.4.563 version of MQTTnet library. Any help would be gratefully appreciated, thanks!
You are subscribing to a custom topic. See here similar question.
Device can subscribe to devices/{device_id}/messages/devicebound/#

How to connect mqtt with websocket in c#?

I tried use MQTTnet to connect mqtt.
But seems not worked, it would show the error message:
Unable to connect the remote server, the request was aborted: Could not create SSL/TLS secure channel.
I also found error message on windows event:
A fatal alert was received from the remote endpoint. The TLS protocol defined fatal alert code is 40.
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Options;
public override void Run()
{
var option = new MqttClientOptionsBuilder()
.WithWebSocketServer("wss://mymqttserver:443")
.WithClientId(Guid.NewGuid().ToString())
.WithTls(new MqttClientOptionsBuilderTlsParameters()
{
AllowUntrustedCertificates = true,
UseTls = true,
SslProtocol = SslProtocols.Tls12,
CertificateValidationCallback = delegate { return true; },
})
.WithCleanSession()
.Build();
var mqtt = new MqttFactory().CreateMqttClient() as MqttClient;
mqtt.ConnectAsync(option).Wait();
string convertMsg = JsonConvert.SerializeObject("Mqtt Connect Successfully!!");
var appMsg = new MqttApplicationMessage();
appMsg.Payload = Encoding.UTF8.GetBytes(convertMsg);
appMsg.Topic = "myTopic";
appMsg.QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce;
appMsg.Retain = false;
mqttClient.PublishAsync(appMsg).Wait();
}
I also tried connect my mqtt server with third party application.
It can connect successfully, so my mqtt server should be okay.
But I don't know why I can't use c# to connect.
In the line
.WithWebSocketServer("wss://mymqttserver:443")
You must remove the "wss://" because that is already being specified using the method ".WithWebSocketServer". So, you would have
.WithWebSocketServer("mymqttserver:443")
Just use the server and the port.

Not able to connect with broker using MQTTNet library .net core

I need an help, I can't connect with the broker.
I'm using MQTTNet library into my api project .net core
this is my code:
// GET: api/<SendCommandController>
[HttpGet]
public void Get()
{
var options = new MqttClientOptionsBuilder()
.WithTcpServer("broker.hivemq.com", 1883)
.Build();
var factory = new MqttFactory();
var mqttClient = factory.CreateMqttClient();
mqttClient.ConnectAsync(options, CancellationToken.None);
var message = new MqttApplicationMessageBuilder()
.WithTopic("Test/Mqtt")
.WithPayload("Hello World")
.WithExactlyOnceQoS()
.WithRetainFlag()
.Build();
mqttClient.PublishAsync(message, CancellationToken.None);
}
so I follow the tutorial but can't connect to broker hivemq and I can't connect to my personal broker.
So, I tested hivemq broker with mqtt.fx and works.
Only in the code the return is connected = false.
Any ideas? the error is "the client is not connected"
C# is not a language I've done much with, but I assume you are missing an await before mqttClient.ConnectAsync(options, CancellationToken.None); so the rest of the code waits for the connection to complete before trying to send the message

Which C# library use to consume QPID queues

I tried to connect a Apache QPID broker with a RabbitMQ.Client (5.1.0) C#, but I got problem connection.
I am not sure that the RabbitMQ client is compatible with QPID.
The version of the protocol AMQP is 0.9
I installed a QPID server on my computer and it looks to be be functional, including the UI.
When I ran the program, the Exception I got is :
Exception message :{"None of the specified endpoints were reachable"}
The InnerException is :
"No compatible authentication mechanism found - server offered [CRAM-MD5 SCRAM-SHA-1 SCRAM-SHA-256]"
Here is the code executed:
using RabbitMQ.Client;
class Program
{
public static void Main(string[] args)
{
var factory = new ConnectionFactory()
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
};
factory.Protocol = Protocols.AMQP_0_9_1;
try
{
// Cannot connect to QPID here
var connection = factory.CreateConnection();ยจ
}
catch (Exception ex)
{
// catch exception
}
}
}
1/ Does the RabbitMQ library compatible with Apache QPID broker ?
2/ If yes...from where does this authentication come from ?

Websockets connection failing only with Chrome accessing ASP Core Server using subprotocol

I have a MQTT client / broker implementation, client is browser websockets based, server is ASPNetCore 1.1 with Kestrel & Websockets (0.1.0).
As part of the MQTT spec, I am initiating a websockets connection using "MQTT" as the subprotocol, which the Server looks for when establishing the websockets connection.
JavaScript connection established using the following:
var wsMQTT = new WebSocket(g.protocol + "//" + g.serverName + ":" + net.WSPORT, "MQTT");
wsMQTT.binaryType = "arraybuffer";
Here is the Chrome error (basically timeout as nothing coming back from the server):
Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received.
Here is the ASPNetCore middleware for handling the websocket connection:
public async Task Invoke(HttpContext context)
{
if (context.WebSockets.IsWebSocketRequest)
{
CancellationToken ct = context.RequestAborted;
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
MQTT.Broker MQTTClient = new MQTT.Broker(_host, webSocket, context.Connection.RemoteIpAddress.ToString(), context.Connection.RemotePort.ToString(), _MQTTUser, _MQTTPass);
MQTTClient.TimeoutEvent += CloseWSSess; // When MQTT stack sees ping/resp timeout, shut down WS
if (context.WebSockets.WebSocketRequestedProtocols.Count == 1 &&
context.WebSockets.WebSocketRequestedProtocols[0].Substring(0, 4) == "MQTT")
{
_host.WriteLog(LOGTYPES.INFORMATION, "Received new MQTT WebSocket connection from " + context.Connection.RemoteIpAddress);
// receive loop
while (!ct.IsCancellationRequested && webSocket.State == WebSocketState.Open)
{
var response = await ReceiveBin(MQTTClient, ct);
}
}
else
{
CloseWSSess(MQTTClient, "Invalid WebSockets subprotocol requested from client [" + context.Connection.RemoteIpAddress.ToString() + "]. Session aborted.");
}
}
else
{
await _next.Invoke(context); // Not a web socket request
}
}
Here is the error stack from ASP Core (which isn't getting trapped inside the websockets library):
Connection id "0HL5GB806MGNU": An unhandled exception was thrown by the application.
System.IO.IOException: Unexpected end of stream at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.<EnsureDataAvailableOrReadAsync>d__38.MoveNext()
Works fine with IE, Edge and Firefox, and doesn't crash ASP Core if I remove the subprotocol from the client connection. So I suspect Chrome is establishing the connection a little differently to the other browsers which isn't being handled properly by ASP Core Websockets.
Any ideas how to solve this?
Fix is to specify the subprotocol in AcceptWebSocketAsync (ie. AcceptWebSocketAsync("MQTT").

Categories