### Refactor MQTTnet Server Startup Options Source: https://github.com/dotnet/mqttnet/wiki/Upgrading-guide This snippet details the changes required for starting an MQTTnet server. The `MqttServerOptionsBuilder` is now passed directly to `CreateMqttServer` along with the logger, and `StartAsync` is called without arguments. This reflects a restructuring of server initialization and configuration. ```csharp var options = new MqttServerOptionsBuilder(); var mqttFactory = new MqttFactory(); var server = mqttFactory.CreateMqttServer(_serverLogger); await server.StartAsync(options.WithDefaultEndpointPort(port).Build()); // to var options = new MqttServerOptionsBuilder(); var mqttFactory = new MqttFactory(); var server = mqttFactory.CreateMqttServer(options.WithDefaultEndpointPort(port).Build(), _serverLogger); await server.StartAsync(); ``` -------------------------------- ### Run Minimal MQTT Server Source: https://context7.com/dotnet/mqttnet/llms.txt Creates and starts a basic MQTT server (broker) that accepts connections on the default port (1883). This is the simplest way to get an MQTT server running. ```csharp using MQTTnet.Server; var mqttServerFactory = new MqttServerFactory(); // Configure server options // The default endpoint port is 1883 (unencrypted) var mqttServerOptions = new MqttServerOptionsBuilder() .WithDefaultEndpoint() .Build(); using var mqttServer = mqttServerFactory.CreateMqttServer(mqttServerOptions); await mqttServer.StartAsync(); Console.WriteLine("MQTT Server started on port 1883."); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); // Stop and dispose the MQTT server await mqttServer.StopAsync(); ``` -------------------------------- ### Create Basic MQTT Server with TCP Endpoint Source: https://github.com/dotnet/mqttnet/wiki/Server Demonstrates the simplest way to create and start an MQTT server with a TCP endpoint listening on the default port 1883. It includes starting the server and stopping it gracefully. ```csharp var mqttServer = new MqttFactory().CreateMqttServer(); await mqttServer.StartAsync(new MqttServerOptions()); Console.WriteLine("Press any key to exit."); Console.ReadLine(); await mqttServer.StopAsync(); ``` -------------------------------- ### Configure MQTT Server Options with Builder Source: https://github.com/dotnet/mqttnet/wiki/Server Shows how to configure MQTT server options using the MqttServerOptionsBuilder, which is the recommended approach. This example sets the connection backlog and a custom default endpoint port. ```csharp var optionsBuilder = new MqttServerOptionsBuilder() .WithConnectionBacklog(100) .WithDefaultEndpointPort(1884); var mqttServer = new MqttFactory().CreateMqttServer(); await mqttServer.StartAsync(optionsBuilder.Build()); ``` -------------------------------- ### Configure Certificate Based Authentication Source: https://github.com/dotnet/mqttnet/wiki/Client Provides an example of setting up MQTT client options for certificate-based authentication. This involves providing a list of X509 certificates for the connection. ```csharp // Certificate based authentication List certs = new List { new X509Certificate2("myCert.pfx") }; var options = new MqttClientOptionBuilder() .WithTcpServer(broker, port) .WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = true, Certificates = certs }) .Build(); ``` -------------------------------- ### Install MQTTnet Packages Source: https://context7.com/dotnet/mqttnet/llms.txt Installs the necessary MQTTnet packages via NuGet Package Manager for client, server, or ASP.NET Core integration. ```bash Install-Package MQTTnet Install-Package MQTTnet.Server Install-Package MQTTnet.AspNetCore ``` -------------------------------- ### Implement MQTT RPC Response Handler in C/C++ Source: https://github.com/dotnet/mqttnet/wiki/Client Provides an example of how to implement an MQTT RPC response handler, likely for embedded devices. It includes subscribing to specific RPC topics, checking if a topic belongs to MQTTnet RPC, and publishing a response to a designated response topic. ```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. ``` -------------------------------- ### Example MQTT Controller with Attribute Routing Source: https://github.com/dotnet/mqttnet/wiki/Server Demonstrates an MQTT controller that inherits from `MqttBaseController` and uses `MqttRoute` attributes to define message routing. It showcases dependency injection, typed route constraints, accessing the MQTT context and message payload, and returning responses like `Ok()` or `BadMessage()`. ```csharp [MqttController] [MqttRoute("[controller]")] public class MqttWeatherForecastController : MqttBaseController { private readonly ILogger _logger; // Controllers have full support for dependency injection public MqttWeatherForecastController(ILogger logger) { _logger = logger; } // Supports template routing with typed constraints [MqttRoute("{zipCode:int}/temperature")] public Task WeatherReport(int zipCode) { // We have access to the MqttContext if (zipCode != 90210) { MqttContext.CloseConnection = true; } // We have access to the raw message. There is no model binding (yet) so we get our message like // this instead of using a [FromBody] attribute. var temperature = BitConverter.ToDouble(Message.Payload); _logger.LogInformation($"It's {temperature} degrees in Hollywood"); // Example validation if (temperature <= 0 || temperature >= 130) { // Prevents the message from being published on the topic to any subscribers return BadMessage(); } // Publish the message to all subscribers on this topic return Ok(); } } ``` -------------------------------- ### Publish MQTT Messages using C# Source: https://context7.com/dotnet/mqttnet/llms.txt Illustrates how to publish application messages to an MQTT topic. This example covers basic message publishing, allowing configuration of QoS levels and the retain flag for message persistence. It requires the MQTTnet library. ```csharp using MQTTnet; var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); // Build and publish an application message var applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("19.5") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); await mqttClient.DisconnectAsync(); Console.WriteLine("MQTT application message is published."); ``` -------------------------------- ### Start MQTT Server with Encrypted TLS/SSL Endpoint Source: https://github.com/dotnet/mqttnet/wiki/Server Demonstrates how to configure the MQTT server to use an encrypted connection with TLS/SSL. It requires a certificate with a private key and sets the endpoint port and SSL protocol. ```csharp using System.Reflection; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; ... var currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var certificate = new X509Certificate2(Path.Combine(currentPath, "certificate.pfx"),"yourPassword", X509KeyStorageFlags.Exportable); var optionsBuilder = new MqttServerOptionsBuilder() .WithoutDefaultEndpoint() // This call disables the default unencrypted endpoint on port 1883 .WithEncryptedEndpoint() .WithEncryptedEndpointPort(config.Port) .WithEncryptionCertificate(certificate.Export(X509ContentType.Pfx)) .WithEncryptionSslProtocol(SslProtocols.Tls12) ``` -------------------------------- ### Configure TCP Connection Options Source: https://github.com/dotnet/mqttnet/wiki/Client Illustrates how to set MQTT client options specifically for a TCP-based connection. It includes an example of specifying the broker address and an optional port number. ```csharp // Use TCP connection. var options = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com", 1883) // Port is optional .Build(); ``` -------------------------------- ### MQTT Server with Logging in C# Source: https://context7.com/dotnet/mqttnet/llms.txt This snippet shows how to create an MQTT server in C# and enable logging using a custom `ConsoleLogger`. It demonstrates setting up the server, starting it, and handling graceful shutdown. The custom logger implements `IMqttNetLogger` to output log messages with different colors based on their severity. ```csharp using System.Globalization; using MQTTnet.Diagnostics.Logger; using MQTTnet.Server; // Create a custom logger var logger = new ConsoleLogger(); var mqttServerFactory = new MqttServerFactory(logger); var mqttServerOptions = new MqttServerOptionsBuilder() .WithDefaultEndpoint() .Build(); using var mqttServer = mqttServerFactory.CreateMqttServer(mqttServerOptions); await mqttServer.StartAsync(); Console.WriteLine("MQTT Server with logging started."); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); await mqttServer.StopAsync(); // Custom logger implementation public class ConsoleLogger : IMqttNetLogger { private readonly object _consoleLock = new(); public bool IsEnabled => true; public void Publish(MqttNetLogLevel logLevel, string source, string message, object[]? parameters, Exception? exception) { var color = logLevel switch { MqttNetLogLevel.Verbose => ConsoleColor.Gray, MqttNetLogLevel.Info => ConsoleColor.Green, MqttNetLogLevel.Warning => ConsoleColor.Yellow, MqttNetLogLevel.Error => ConsoleColor.Red, _ => ConsoleColor.White }; if (parameters?.Length > 0) { message = string.Format(CultureInfo.InvariantCulture, message, parameters); } lock (_consoleLock) { Console.ForegroundColor = color; Console.WriteLine($"[{logLevel}] [{source}] {message}"); if (exception != null) { Console.WriteLine(exception); } Console.ResetColor(); } } } ``` -------------------------------- ### Publish Messages from MQTTnet Server (C#) Source: https://context7.com/dotnet/mqttnet/llms.txt This C# example shows how to publish messages directly from an MQTTnet server without needing a connected client. It utilizes the `InjectApplicationMessage` method to send messages to specific topics, useful for server-initiated notifications or data pushes. ```csharp using MQTTnet; using MQTTnet.Server; var mqttServerFactory = new MqttServerFactory(); var mqttServerOptions = new MqttServerOptionsBuilder() .WithDefaultEndpoint() .Build(); using var mqttServer = mqttServerFactory.CreateMqttServer(mqttServerOptions); await mqttServer.StartAsync(); Console.WriteLine("MQTT Server started."); // Create a message to publish from the server var message = new MqttApplicationMessageBuilder() .WithTopic("server/announcements") .WithPayload("Server started successfully!") .Build(); // Inject the message into the broker await mqttServer.InjectApplicationMessage( new InjectedMqttApplicationMessage(message) { SenderClientId = "Server" }); Console.WriteLine("Message published from server."); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); await mqttServer.StopAsync(); ``` -------------------------------- ### Configure MQTT Server in ASP.NET Core 3.1+ Source: https://github.com/dotnet/mqttnet/wiki/Server Configures an MQTT server for ASP.NET Core 3.1+ using the latest abstractions. This setup primarily supports WebSocket connections and maps the MQTT endpoint using `MapMqtt`. TLS middleware for connections is not yet available. ```csharp // In class _Program_ of the ASP.NET Core 3.1+ project. private static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseKestrel(o => { o.ListenAnyIP(1883, l => l.UseMqtt()); // MQTT pipeline o.ListenAnyIP(5000); // Default HTTP pipeline }) .UseStartup() .Build(); // In class _Startup_ of the ASP.NET Core 3.1+ project. public void ConfigureServices(IServiceCollection services) { services .AddHostedMqttServer(mqttServer => mqttServer.WithoutDefaultEndpoint()) .AddMqttConnectionHandler() .AddConnections(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseEndpoints(endpoints => { endpoints.MapMqtt("/mqtt"); }); app.UseMqttServer(server => { // Todo: Do something with the server }); } ``` -------------------------------- ### Configure ASP.NET 5.0 Startup for MQTT Source: https://github.com/dotnet/mqttnet/wiki/Server Sets up MQTT services and endpoints in the Startup class of an ASP.NET 5.0 application. It registers the MQTT server, connection handler, and connections, and maps the MQTT endpoint for WebSocket connections. ```csharp using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using MQTTnet.AspNetCore; using MQTTnet.AspNetCore.Extensions; public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddHostedMqttServer(mqttServer => mqttServer.WithoutDefaultEndpoint()) .AddMqttConnectionHandler() .AddConnections(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapConnectionHandler( "/mqtt", httpConnectionDispatcherOptions => httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector = protocolList => protocolList.FirstOrDefault() ?? string.Empty); }); app.UseMqttServer(server => { // Todo: Do something with the server }); } } ``` -------------------------------- ### Register and Configure MQTT Services in ASP.NET Startup Source: https://github.com/dotnet/mqttnet/wiki/Server Registers the `MqttService` as a singleton and configures the hosted MQTT server with dependency injection in the `ConfigureServices` method of an ASP.NET application's Startup class. It also adds the MQTT connection handler and WebSocket adapter. ```csharp services.AddSingleton(); services.AddHostedMqttServerWithServices(options => { var s = options.ServiceProvider.GetRequiredService(); s.ConfigureMqttServerOptions(options); }); services.AddMqttConnectionHandler(); services.AddMqttWebSocketServerAdapter(); ``` -------------------------------- ### Create MQTT Client with MqttFactory Source: https://github.com/dotnet/mqttnet/wiki/Client Demonstrates the most basic way to create a new MQTT client instance using the MqttFactory. This is the initial step before configuring client options and establishing a connection. ```csharp // Create a new MQTT client. var factory = new MqttFactory(); var mqttClient = factory.CreateMqttClient(); ``` -------------------------------- ### Update ApplicationMessageReceivedHandler to InterceptingPublishAsync in MQTTnet Source: https://github.com/dotnet/mqttnet/wiki/Upgrading-guide This example shows how to update the `ApplicationMessageReceivedHandler` to use the `InterceptingPublishAsync` event. This change aligns with MQTTnet's shift towards using asynchronous interception events for handling incoming application messages. ```csharp server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => { ... }); // to server.InterceptingPublishAsync += async e => { ... }; ``` -------------------------------- ### Establish MQTT Connection (C#) Source: https://github.com/dotnet/mqttnet/wiki/Client Connects an MQTT client to a server using the previously configured options. Supports cancellation via `CancellationToken`. This method should be called after setting up client options. ```csharp // Use WebSocket connection. var options = new MqttClientOptionsBuilder() .WithWebSocketServer("broker.hivemq.com:8000/mqtt") .Build(); await mqttClient.ConnectAsync(options, CancellationToken.None); // Since 3.0.5 with CancellationToken ``` -------------------------------- ### Validate CA Certificate for TLS/SSL Connection Source: https://github.com/dotnet/mqttnet/wiki/Server Provides code to validate the Certificate Authority (CA) certificate for a TLS/SSL connection without installing it on the machine. It customizes the RemoteCertificateValidationCallback to check against a provided CA certificate. ```csharp var caFile = new FileInfo("root.crt"); var ca = new X509Certificate2(caFile.FullName); options.TlsEndpointOptions.RemoteCertificateValidationCallback += (sender, cer, chain, sslPolicyErrors) => { try { if (sslPolicyErrors == SslPolicyErrors.None) { return true; } if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) { chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; chain.ChainPolicy.ExtraStore.Add(ca); chain.Build((X509Certificate2)cer); return chain.ChainElements.Cast().Any(a => a.Certificate.Thumbprint == ca.Thumbprint); } } catch { } return false; }; ``` -------------------------------- ### Configure MQTT Server Instance and Handlers Source: https://github.com/dotnet/mqttnet/wiki/Server Stores a reference to the MQTT server instance and sets up its client connected and disconnected handlers. This method is used in conjunction with `ConfigureMqttServerOptions` to integrate the MQTT server with an ASP.NET MVC controller. ```csharp public void ConfigureMqttServer(IMqttServer mqtt) { this.mqtt = mqtt; mqtt.ClientConnectedHandler = this; mqtt.ClientDisconnectedHandler = this; } ``` -------------------------------- ### Handle Connection Timeout with MQTTnet Source: https://context7.com/dotnet/mqttnet/llms.txt Shows how to gracefully handle MQTT connection timeouts by using a CancellationToken with a specified duration. This example attempts to connect to a non-existent server to trigger the timeout and demonstrates catching the OperationCanceledException. ```csharp using MQTTnet; var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("127.0.0.1") // Non-existent server for demo .Build(); try { using var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(3)); await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token); } catch (OperationCanceledException) { Console.WriteLine("Connection timeout - server not responding."); } catch (Exception ex) { Console.WriteLine($"Connection failed: {ex.Message}"); } ``` -------------------------------- ### Saving Retained Messages with JSON Storage (C#) Source: https://github.com/dotnet/mqttnet/wiki/Server Implements an IMqttServerStorage interface to save and load retained MQTT messages using JSON serialization. This example uses Newtonsoft.Json and stores messages in a local file. It requires the Newtonsoft.Json NuGet package. ```csharp // Setting the options options.Storage = new RetainedMessageHandler(); // The implementation of the storage: // This code uses the JSON library "Newtonsoft.Json". public class RetainedMessageHandler : IMqttServerStorage { private const string Filename = "C:\\MQTT\\RetainedMessages.json"; public Task SaveRetainedMessagesAsync(IList messages) { File.WriteAllText(Filename, JsonConvert.SerializeObject(messages)); return Task.FromResult(0); } public Task> LoadRetainedMessagesAsync() { IList retainedMessages; if (File.Exists(Filename)) { var json = File.ReadAllText(Filename); retainedMessages = JsonConvert.DeserializeObject>(json); } else { retainedMessages = new List(); } return Task.FromResult(retainedMessages); } } ``` -------------------------------- ### Configure Services for MQTT Attribute Routing in ASP.NET Core Source: https://github.com/dotnet/mqttnet/wiki/Server Configures the necessary services for MQTTnet's attribute routing in an ASP.NET Core application. It identifies and builds routes, enables the MQTT server, and sets up the connection handler. This is typically done in the `Startup.cs` file. ```csharp public void ConfigureServices(IServiceCollection services) { // Identify and build routes for the current assembly services.AddMqttControllers(); services .AddHostedMqttServer(mqttServer => mqttServer.WithoutDefaultEndpoint()) .AddHostedMqttServerWithServices(mqttServer => { // Optionally set server options here mqttServer.WithoutDefaultEndpoint(); // Enable Attribute routing mqttServer.WithAttributeRouting(); }) .AddMqttConnectionHandler() .AddConnections(); } ``` -------------------------------- ### Use MQTT Endpoint and Server in ASP.NET Configure Source: https://github.com/dotnet/mqttnet/wiki/Server Configures the application pipeline in the `Configure` method of an ASP.NET application's Startup class to use the MQTT endpoint and the MQTT server instance. It retrieves the `MqttService` from the application's service provider to configure the server. ```csharp app.UseMqttEndpoint(); app.UseMqttServer(server => app.ApplicationServices.GetRequiredService().ConfigureMqttServer(server)); ``` -------------------------------- ### Troubleshoot MQTT Connection with OpenSSL Source: https://github.com/dotnet/mqttnet/wiki/Client This command demonstrates how to test a TLS connection to an MQTT broker using OpenSSL. It's useful for verifying network connectivity and certificate validation before diving into client-side code issues. Ensure you replace placeholders with your actual certificate, key, and endpoint details. ```bash openssl s_client -CAfile awsca.pem -cert xxx.pem.crt -key xxx.pem.key -connect yyy.iot.region.amazonaws.com:8883 ``` -------------------------------- ### Build MQTT Topic Filter and Message with Topic Templates in C# Source: https://github.com/dotnet/mqttnet/blob/master/Source/MQTTnet.Extensions.TopicTemplate/README.md Demonstrates how to create an MQTT topic filter and an MQTT application message using the MqttTopicTemplate class. It shows how parameters in the template are handled differently when building a filter (replaced with wildcard) versus building a message (replaced with specific values). ```csharp var template = new MqttTopicTemplate("App/v1/{sender}/message"); var filter = new MqttTopicFilterBuilder() .WithTopicTemplate(template) // (1) .WithAtLeastOnceQoS() .WithNoLocal() .Build(); // filter.Topic == "App/v1/+/message" var myTopic = template .WithParameter("sender", "me, myself & i"); // (2) var message = new MqttApplicationMessageBuilder() .WithTopicTemplate( // (3) myTopic) .WithPayload("Hello!") .Build(); // message.Topic == "App/v1/me, myself & i/message" Assert.IsTrue(message.MatchesTopicTemplate(template)); // (4) ``` -------------------------------- ### Persist MQTT Retained Messages to File (C#) Source: https://context7.com/dotnet/mqttnet/llms.txt This example shows how to implement persistence for retained MQTT messages by storing them in a JSON file. It hooks into the server's events for loading messages on startup and saving them when they change or are cleared. The `RetainedMessageModel` class handles the serialization and deserialization of messages. Dependencies include System.Text.Json, MQTTnet, and MQTTnet.Server. ```csharp using System.Text.Json; using MQTTnet; using MQTTnet.Packets; using MQTTnet.Protocol; using MQTTnet.Server; var storePath = Path.Combine(Path.GetTempPath(), "RetainedMessages.json"); var mqttServerFactory = new MqttServerFactory(); var mqttServerOptions = new MqttServerOptionsBuilder() .WithDefaultEndpoint() .Build(); using var server = mqttServerFactory.CreateMqttServer(mqttServerOptions); // Load retained messages on startup server.LoadingRetainedMessageAsync += async eventArgs => { try { if (File.Exists(storePath)) { var json = await File.ReadAllTextAsync(storePath); var messages = JsonSerializer.Deserialize>(json); eventArgs.LoadedRetainedMessages = messages? .Select(m => m.ToApplicationMessage()) .ToList() ?? new List(); Console.WriteLine($"Loaded {eventArgs.LoadedRetainedMessages.Count} retained messages."); } } catch (Exception ex) { Console.WriteLine($"Error loading retained messages: {ex.Message}"); } }; // Save retained messages when they change server.RetainedMessageChangedAsync += async eventArgs => { try { var models = eventArgs.StoredRetainedMessages .Select(RetainedMessageModel.Create) .ToList(); var json = JsonSerializer.Serialize(models, new JsonSerializerOptions { WriteIndented = true }); await File.WriteAllTextAsync(storePath, json); Console.WriteLine("Retained messages saved."); } catch (Exception ex) { Console.WriteLine($"Error saving retained messages: {ex.Message}"); } }; // Clear retained messages file when cleared via API server.RetainedMessagesClearedAsync += _ => { if (File.Exists(storePath)) { File.Delete(storePath); Console.WriteLine("Retained messages cleared."); } return Task.CompletedTask; }; await server.StartAsync(); Console.WriteLine("MQTT Server with retained message persistence started."); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); await server.StopAsync(); // Model class for serialization public class RetainedMessageModel { public string? Topic { get; set; } public byte[]? Payload { get; set; } public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; } public static RetainedMessageModel Create(MqttApplicationMessage msg) => new() { Topic = msg.Topic, Payload = msg.PayloadSegment.ToArray(), QualityOfServiceLevel = msg.QualityOfServiceLevel }; public MqttApplicationMessage ToApplicationMessage() => new() { Topic = Topic, PayloadSegment = new ArraySegment(Payload ?? Array.Empty()), QualityOfServiceLevel = QualityOfServiceLevel, Retain = true }; } ``` -------------------------------- ### Configure MQTT Client Options with Builder Source: https://github.com/dotnet/mqttnet/wiki/Client Shows how to configure MQTT client options using the MqttClientOptionsBuilder, which provides a fluent API for setting various parameters like client ID, TCP server, credentials, TLS, and clean session. This is the recommended approach for configuring client options. ```csharp // Create TCP based options using the builder. var options = new MqttClientOptionsBuilder() .WithClientId("Client1") .WithTcpServer("broker.hivemq.com") .WithCredentials("bud", "%spencer%") .WithTls() .WithCleanSession() .Build(); ``` -------------------------------- ### Publish MQTT Messages with Builder in C# Source: https://github.com/dotnet/mqttnet/wiki/Client Illustrates how to create and publish MQTT application messages using the MqttApplicationMessageBuilder. This builder supports fluent API for setting topic, payload, QoS, and retain flag. A basic message can be published with just a topic. ```csharp var message = new MqttApplicationMessageBuilder() .WithTopic("MyTopic") .WithPayload("Hello World") .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await mqttClient.PublishAsync(message, CancellationToken.None); // Since 3.0.5 with CancellationToken ``` ```csharp var message = new MqttApplicationMessageBuilder() .WithTopic("/MQTTnet/is/awesome") .Build(); ``` -------------------------------- ### Create and Connect MQTT Client Source: https://context7.com/dotnet/mqttnet/llms.txt Demonstrates creating an MQTT client instance using MqttClientFactory and connecting to a broker using the builder pattern for configuration. It establishes a basic TCP connection and disconnects cleanly. ```csharp using MQTTnet; // Create a new MQTT client using the factory var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); // Configure connection options using the builder var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); // Connect to the broker var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); Console.WriteLine("The MQTT client is connected."); Console.WriteLine($"Result: {response.ResultCode}"); // Disconnect cleanly when done await mqttClient.DisconnectAsync(); ``` -------------------------------- ### ASP.NET Core MVC MQTT Service Integration Source: https://github.com/dotnet/mqttnet/wiki/Tips-and-Tricks This C# code illustrates how to integrate MQTT functionality into an ASP.NET Core MVC controller using dependency injection. It outlines the steps for configuring the MqttService, setting up server options, and registering necessary services and middleware in the Startup class. ```csharp public void ConfigureMqttServerOptions(AspNetMqttServerOptionsBuilder options) { options.WithConnectionValidator(this); options.WithApplicationMessageInterceptor(this); } public void ConfigureMqttServer(IMqttServer mqtt) { this.mqtt = mqtt; mqtt.ClientConnectedHandler = this; mqtt.ClientDisconnectedHandler = this; } ``` ```csharp services.AddSingleton(); services.AddHostedMqttServerWithServices(options => { var s = options.ServiceProvider.GetRequiredService(); s.ConfigureMqttServerOptions(options); }); services.AddMqttConnectionHandler(); services.AddMqttWebSocketServerAdapter(); ``` ```csharp app.UseMqttEndpoint(); app.UseMqttServer(server => app.ApplicationServices.GetRequiredService WebHost.CreateDefaultBuilder(args) .UseKestrel(o => { o.ListenAnyIP(1883, l => l.UseMqtt()); // MQTT pipeline o.ListenAnyIP(5000); // Default HTTP pipeline }) .UseStartup() .Build(); // In class _Startup_ of the ASP.NET Core 2.1 or 2.2 project. public void ConfigureServices(IServiceCollection services) { //this adds a hosted mqtt server to the services services.AddHostedMqttServer(builder => builder.WithDefaultEndpointPort(1883)); //this adds tcp server support based on Microsoft.AspNetCore.Connections.Abstractions services.AddMqttConnectionHandler(); //this adds websocket support services.AddMqttWebSocketServerAdapter(); } ``` -------------------------------- ### Handle Incoming MQTT Messages in C# Source: https://github.com/dotnet/mqttnet/wiki/Client Demonstrates how to use the UseApplicationMessageReceivedHandler to process incoming MQTT messages. It logs the topic, payload, QoS, and retain flag. Publishing a message within this handler requires Task.Run for QoS > 0 to maintain message ordering. ```csharp mqttClient.UseApplicationMessageReceivedHandler(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(); Task.Run(() => mqttClient.PublishAsync("hello/world")); }); ``` -------------------------------- ### Perform RPC Call with MQTTnet.Extensions.Rpc in C# Source: https://github.com/dotnet/mqttnet/wiki/Client Demonstrates how to send a Remote Procedure Call (RPC) using the MQTTnet.Extensions.Rpc library. It shows how to configure a timeout and QoS level, and execute a method with a payload, waiting for a response. ```csharp var rpcClient = new MqttRpcClient(_mqttClient); var timeout = TimeSpan.FromSeconds(5); var qos = MqttQualityOfServiceLevel.AtMostOnce; var response = await rpcClient.ExecuteAsync(timeout, "myMethod", payload, qos); ``` -------------------------------- ### Configure MQTT Server in ASP.NET Core 2.0 Source: https://github.com/dotnet/mqttnet/wiki/Server Configures a hosted MQTT server with TCP and WebSocket support in ASP.NET Core 2.0. Requires the MQTTnet.AspNetCore library. Adds a hosted MQTT server and adapters for TCP and WebSocket to the service collection, and maps the WebSocket endpoint. ```csharp // In class _Startup_ of the ASP.NET Core 2.0 project. public void ConfigureServices(IServiceCollection services) { // This adds a hosted mqtt server to the services services.AddHostedMqttServer(builder => builder.WithDefaultEndpointPort(1883)); // This adds TCP server support based on System.Net.Socket services.AddMqttTcpServerAdapter(); // This adds websocket support services.AddMqttWebSocketServerAdapter(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // This maps the websocket to an MQTT endpoint app.UseMqttEndpoint(); // Other stuff } ``` -------------------------------- ### Subscribe to MQTT Topic After Connection in C# Source: https://github.com/dotnet/mqttnet/wiki/Client Shows how to subscribe to a specific MQTT topic once a connection to the server is established. This is achieved using the UseConnectedHandler and MqttTopicFilterBuilder. ```csharp mqttClient.UseConnectedHandler(async e => { Console.WriteLine("### CONNECTED WITH SERVER ###"); // Subscribe to a topic await mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("my/topic").Build()); Console.WriteLine("### SUBSCRIBED ###"); }); ``` -------------------------------- ### Subscribe to MQTT Topics in C# Source: https://context7.com/dotnet/mqttnet/llms.txt Demonstrates how to subscribe to a single MQTT topic using MQTTnet. It sets up a client, connects to a broker, and configures a message handler to process incoming messages. The client then subscribes to a specified topic. ```csharp using MQTTnet; using System.Text; var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); // Setup message handling BEFORE connecting so queued messages are handled mqttClient.ApplicationMessageReceivedAsync += e => { Console.WriteLine("Received application message."); Console.WriteLine($" Topic: {e.ApplicationMessage.Topic}"); Console.WriteLine($" Payload: {Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment)}"); Console.WriteLine($" QoS: {e.ApplicationMessage.QualityOfServiceLevel}"); Console.WriteLine($" Retain: {e.ApplicationMessage.Retain}"); return Task.CompletedTask; }; await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); // Subscribe to a topic var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder() .WithTopicFilter("mqttnet/samples/topic/2") .Build(); await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None); Console.WriteLine("MQTT client subscribed to topic."); // Keep running to receive messages Console.WriteLine("Press enter to exit."); Console.ReadLine(); ``` -------------------------------- ### Connect via WebSocket (C#) Source: https://github.com/dotnet/mqttnet/wiki/Client Configures an MQTT client to use a WebSocket communication channel. The URI specifies the server address and port. Secure WebSocket connections (wss://) can be established by calling `UseTls()`. ```csharp // Use WebSocket connection. var options = new MqttClientOptionsBuilder() .WithWebSocketServer("broker.hivemq.com:8000/mqtt") .Build(); ``` -------------------------------- ### MQTT v5 Enhanced Authentication with MQTTnet Source: https://context7.com/dotnet/mqttnet/llms.txt Demonstrates setting up MQTT server and client with enhanced authentication mechanisms like Kerberos using MQTT v5. It covers server-side validation and client-side handling of authentication challenges and data exchange. Requires MQTTnet library. ```csharp using System.Text; using MQTTnet; using MQTTnet.Formatter; using MQTTnet.Protocol; using MQTTnet.Server; using MQTTnet.Server.EnhancedAuthentication; // Server setup with enhanced authentication var mqttServerFactory = new MqttServerFactory(); var serverOptions = new MqttServerOptionsBuilder() .WithDefaultEndpoint() .Build(); using var server = mqttServerFactory.CreateMqttServer(serverOptions); server.ValidatingConnectionAsync += async args => { if (args.AuthenticationMethod == "CUSTOM-AUTH") { // Exchange authentication data with client var result = await args.ExchangeEnhancedAuthenticationAsync( new ExchangeEnhancedAuthenticationOptions(), args.CancellationToken); Console.WriteLine($"Received auth data: {Encoding.UTF8.GetString(result.AuthenticationData)}"); // Send challenge back to client var authOptions = mqttServerFactory.CreateExchangeExtendedAuthenticationOptionsBuilder() .WithAuthenticationData("server-challenge") .Build(); result = await args.ExchangeEnhancedAuthenticationAsync(authOptions, args.CancellationToken); // Verify response and complete authentication args.ResponseAuthenticationData = Encoding.UTF8.GetBytes("auth-complete"); args.ReasonCode = MqttConnectReasonCode.Success; } else { args.ReasonCode = MqttConnectReasonCode.BadAuthenticationMethod; } }; await server.StartAsync(); // Client setup with enhanced authentication handler var mqttClientFactory = new MqttClientFactory(); var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer("localhost") .WithProtocolVersion(MqttProtocolVersion.V500) .WithEnhancedAuthenticationHandler(new CustomAuthHandler()) .WithEnhancedAuthentication("CUSTOM-AUTH") .Build(); using var client = mqttClientFactory.CreateMqttClient(); var connectResult = await client.ConnectAsync(clientOptions); Console.WriteLine($"Connected with enhanced auth: {connectResult.ResultCode}"); // Custom authentication handler public class CustomAuthHandler : IMqttEnhancedAuthenticationHandler { public async Task HandleEnhancedAuthenticationAsync(MqttEnhancedAuthenticationEventArgs eventArgs) { // Send initial auth data await eventArgs.SendAsync(new SendMqttEnhancedAuthenticationDataOptions { Data = Encoding.UTF8.GetBytes("client-credentials") }); // Receive server challenge var response = await eventArgs.ReceiveAsync(CancellationToken.None); Console.WriteLine($"Server challenge: {Encoding.UTF8.GetString(response.AuthenticationData)}"); // Send response to challenge await eventArgs.SendAsync(new SendMqttEnhancedAuthenticationDataOptions { Data = Encoding.UTF8.GetBytes("challenge-response") }, CancellationToken.None); } } ``` -------------------------------- ### Intercepting Subscriptions (C#) Source: https://github.com/dotnet/mqttnet/wiki/Server Sets up a subscription interceptor to control which topics MQTT clients can subscribe to. This is useful for securing topics and restricting access based on client ID. It shows how to deny subscriptions and optionally close the client connection. ```csharp // Protect several topics from being subscribed from every client. var optionsBuilder = new MqttServerOptionsBuilder() .WithSubscriptionInterceptor(context => { if (context.TopicFilter.Topic.StartsWith("admin/foo/bar") && context.ClientId != "theAdmin") { context.AcceptSubscription = false; } if (context.TopicFilter.Topic.StartsWith("the/secret/stuff") && context.ClientId != "Imperator") { context.AcceptSubscription = false; context.CloseConnection = true; } }) .Build(); ``` -------------------------------- ### Validate Incoming MQTT Client Connections Source: https://github.com/dotnet/mqttnet/wiki/Server Illustrates how to set up a connection validator for the MQTT server to authenticate incoming client connections. It checks client ID length, username, and password, returning appropriate reason codes. ```csharp var optionsBuilder = new MqttServerOptionsBuilder() .WithConnectionValidator(c => { if (c.ClientId.Length < 10) { c.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; return; } if (c.Username != "mySecretUser") { c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; return; } if (c.Password != "mySecretPassword") { c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; return; } c.ReasonCode = MqttConnectReasonCode.Success; }); ``` -------------------------------- ### Configure MQTTnet Client with TLS Certificates in C# Source: https://github.com/dotnet/mqttnet/wiki/Client This snippet demonstrates how to configure an MQTTnet client to use TLS with client certificates. It involves creating an X509Certificate2 object from a PFX file and then passing it to the MqttClientOptionsBuilderTlsParameters. It's crucial to ensure the certificate path and password are correct. ```csharp List certs = new List { new X509Certificate2("ClientCertPath", "ClientCertPass", X509KeyStorageFlags.Exportable) }; var clientOptions = new MqttClientOptionsBuilder() .WithTcpServer(endpoint, port) .WithKeepAlivePeriod(new TimeSpan(0, 0, 0, 300)) .WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = true, #pragma warning disable CS0618 // Type or member is obsolete CertificateValidationCallback = (X509Certificate x, X509Chain y, System.Net.Security.SslPolicyErrors z, IMqttClientOptions o) => #pragma warning restore CS0618 // Type or member is obsolete { return true; }, AllowUntrustedCertificates = false, IgnoreCertificateChainErrors = false, IgnoreCertificateRevocationErrors = false, Certificates = certs }) .WithProtocolVersion(MqttProtocolVersion.V311) .Build(); ``` -------------------------------- ### Connect with TLS Client Certificate Authentication (C#) Source: https://github.com/dotnet/mqttnet/wiki/Client Establishes a TLS connection to an MQTT server using client certificate authentication. Requires CA certificate and PFX client certificate with its password. The PFX file can be generated using OpenSSL. ```csharp var caCert = X509Certificate.CreateFromCertFile(@"CA-cert.crt"); var clientCert = new X509Certificate2(@"client-certificate.pfx", "ExportPasswordUsedWhenCreatingPfxFile"); var options = new ManagedMqttClientOptionsBuilder() .WithClientOptions(new MqttClientOptionsBuilder() .WithClientId(Guid.NewGuid().ToString()) .WithTcpServer(host, port) .WithTls(new MqttClientOptionsBuilderTlsParameters() { UseTls = true, SslProtocol = System.Security.Authentication.SslProtocols.Tls12, Certificates = new List() { clientCert, caCert } }) .Build()) .Build(); ``` ```bash openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in clientCertificate.cer ``` -------------------------------- ### Publish MQTT Messages with QoS and Retain using C# Source: https://context7.com/dotnet/mqttnet/llms.txt Demonstrates publishing MQTT messages with specific Quality of Service (QoS) levels and the retain flag. This allows control over message delivery guarantees and persistence on the broker. Requires the MQTTnet library and MQTT v3.1.1 or higher. ```csharp using MQTTnet; using MQTTnet.Protocol; var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); // Publish with QoS 2 (Exactly Once) and Retain flag var message = new MqttApplicationMessageBuilder() .WithTopic("home/sensors/temperature") .WithPayload("{\"value\": 22.5, \"unit\": \"celsius\"}") .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce) .WithRetainFlag() .Build(); var result = await mqttClient.PublishAsync(message, CancellationToken.None); Console.WriteLine($"Publish result: {result.ReasonCode}"); // Publish with QoS 1 (At Least Once) var qos1Message = new MqttApplicationMessageBuilder() .WithTopic("home/sensors/humidity") .WithPayload("65") .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .Build(); await mqttClient.PublishAsync(qos1Message, CancellationToken.None); ```