Giter Club home page Giter Club logo

hivemq-mqtt-client-dotnet's Introduction

The Spectacular (BETA) C# MQTT Client for .NET

NuGet Version GitHub release (latest by date) GitHub Workflow Status Nuget GitHub

Static Badge Static Badge Static Badge

  • Easy-to-Install: Available as a Nuget package.
  • Compliant: Fully compliant with the MQTT 5.0 specification.
  • Works with Any MQTT 5.0 Broker: Built by HiveMQ but not only for HiveMQ.
  • Opensource: No blackbox code. Only trusted, tested and reviewed opensource code.
  • Easy to Use: Smart defaults, excellent interfaces and intelligent automation makes implementing a breeze.
  • Fast: Optimized & benchmarked. See the benchmark results here.
  • Actively Maintained: Built by the MQTT professionals that built HiveMQ (and do this for a living).
  • Extensively Documented: What good is it without excellent documentation?
  • Supported: Contact us anytime in this repository, in the community forum or through support.
  • Extensive Event System: Hook into all parts of the client down to the packet level with built in events.
  • Global and Per-Subscription Message Handling: Use multiple targeted handlers for more targeted and specialized message processing.
  • Full Last Will & Testament Support: Reliable message delivery and notification of client disconnections.
  • Observable: Configure up to TRACE level logging for package internals.
  • Secure Client Identification: Full support for X.509 client certificates and TLS connections.
  • Globally Compatible: Built to be a fully compliant MQTT 5.0 client compatible with all reputable MQTT brokers.

Do you have a success story with this client? Let us know. We'd love to feature your story in a blog post or video and you'll get some sweet HiveMQ swag (and publicity) along the way.

What is this?

MQTT is an open standard protocol for publishing and consuming messages from IoT devices all the way up to mainframes. It's binary, massively performant and easy to use.

This client library is used to publish and consume messages over MQTT. So you can get a the temperature from a remote sensor, send a control message to a factory robot, tunnel WhatsApp messages to a Twitter account or anything else you can imagine.

This is the client library that speaks with an MQTT broker that delivers messages to their final destination.

Need a broker? Sign up for a free broker at HiveMQ Cloud and be up and running in a couple minutes. Connect up to 100 devices - no credit card required.

MQTT Resources

Need an MQTT Broker?

This client communicates with an MQTT broker to publish and consume messages. It's built to be compatible with all major MQTT brokers but if you need a broker now run the HiveMQ Community Edition:

docker run --name hivemq-ce -d -p 1883:1883 hivemq/hivemq-ce

This will run the HiveMQ Community Edition broker on localhost port 1883.

If you need advanced features, checkout our premium editions or alternatively HiveMQ Cloud which is free to connect up to 100 devices (no credit card required).

Install

This package is available on NuGet.org and can be installed with:

dotnet add package HiveMQtt

See the HiveMQtt NuGet page for more installation options.

Example

The following illustrates the client pattern to connect, subscribe and publish messages.

using HiveMQtt.Client;
using HiveMQtt.MQTT5.Types;

// Setup Client options and instantiate
var options = new HiveMQClientOptionsBuilder().
                    WithBroker("candy.x39.eu.hivemq.cloud").
                    WithPort(8883).
                    WithUseTls(true).
                    Build();
var client = new HiveMQClient(options);

// Setup an application message handlers BEFORE subscribing to a topic
client.OnMessageReceived += (sender, args) =>
{
    Console.WriteLine("Message Received: {}", args.PublishMessage.PayloadAsString);
};

// Connect to the MQTT broker
var connectResult = await client.ConnectAsync().ConfigureAwait(false);

// Configure the subscriptions we want and subscribe
var builder = new SubscribeOptionsBuilder();
builder.WithSubscription("topic1", QualityOfService.AtLeastOnceDelivery)
       .WithSubscription("topic2", QualityOfService.ExactlyOnceDelivery);
var subscribeOptions = builder.Build();
var subscribeResult = await client.SubscribeAsync(subscribeOptions);

// Publish a message
var publishResult = await client.PublishAsync("topic1/example", "Hello Payload");

For a Quickstart, more examples and walkthroughs, see the documentation.

Other MQTT Clients

For a list of all known MQTT clients, see MQTT.org.

πŸ›‘ License

License

This project is licensed under the terms of the Apache Software License 2.0 license. See LICENSE for more details.

πŸ“ƒ Citation

@misc{hivemq-mqtt-client-dotnet,
  author = {HiveMQ GmbH},
  title = {The HiveMQ C# MQTT client for .NET},
  year = {2024},
  publisher = {GitHub},
  journal = {GitHub repository},
  howpublished = {\url{https://github.com/hivemq/hivemq-mqtt-client-dotnet}}
}

hivemq-mqtt-client-dotnet's People

Contributors

catcherwong avatar dependabot[bot] avatar pglombardo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hivemq-mqtt-client-dotnet's Issues

Review, improve and standardize MemoryStream processing

πŸ› Bug Report

var stream = new MemoryStream(100)

#20 (comment)

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. ...

Code sample

Environment

Where are you running/using this client?

What version of this client are you using?

Operating System?

Hardware or Device?

Screenshots

πŸ“ˆ Expected behavior

πŸ“Ž Additional context

Documentation: How to Debug & Debugging Best Practices

πŸš€ Feature Request

To investigate issues should be as easy as possible. Let's provide guidance on how to most efficiently debug development issues.

πŸ”ˆ Motivation

πŸ›° Alternatives

πŸ“Ž Additional context

How do you connect with self made credentials to the broker?

Checklist

❓ Question

I'm trying to connect to a broker in the cloud, specifically the azure event grid. I was able to connect using MQTTX as a test client, but needed to use specific certifications and keys in order to connect. I'm not authorized to connect using basic settings, how would I pass these credentials on to become authorized, particularly in .net

Payload format indicator contains always "UNSPECIFIED" value after publishing

Hello guys :)

Here some reports regarding bugs found so far when publishing messages using c# client library.

πŸ› Bug Report

A published message with PayloadFormatIndicator = UTF8Encoded is always sent with Unspecified. When a Validate() method is called, it is always being set to Unspecified when contains both values. This is wrong, it should only throw an exception if it contains a different value, Unspecified if it is nullalble or keep the current value.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. Define a client of type HiveMQClient with a specific options for your configuration.
  2. Create a event handler for client.OnPublishSent event and assign to it. The event handler should print a value from OnPublishSentEventArgs.PublishPacket.Message.PayloadFormatIndicator.
  3. Create an instance of MQTT5PublishMessage and set a value as PayloadFormatIndicator = MQTT5PayloadFormatIndicator.UTF8Encoded.
  4. Finally publish the message defined in step 3 as await client.PublishAync(message).ConfigureAwait(false)

Code Example

The code in discussion can be found here

Environment

The client is ran in Windows 10 OS with dotnet 6 sdk and HiveMQTT v0.5.0 C# nuget package.

πŸ“ˆ Expected behavior

The value of the PayloadFormatIndicator should be the one it is set before publishing.

Add CLA requirement to Github repository

πŸ› Bug Report

HiveMQ requires a contributors license agreement for contributions. This needs to be added to the repository.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. ...

Code sample

Environment

Where are you running/using this client?

What version of this client are you using?

Operating System?

Hardware or Device?

Screenshots

πŸ“ˆ Expected behavior

πŸ“Ž Additional context

Sparkplug B 3.0 support

πŸš€ Feature Request

Support for Sparkplug B 3.0 (Sparkplug Aware)

πŸ”ˆ Motivation

Mainly the interoperability between applications. Currently, we use Ignition with Sparkplug B for MQTT communication to bridge our OT and IT systems. HiveMQ already integrates with Sparkplug B, and we'd greatly appreciate it if your client could align with this integration. As HiveMQ license holders, integrating your client into our ecosystem would help streamline our operations. Furthermore, it would become an integral part of 'HiveMQ' rather than relying on a third-party library that has not seen updates for a year.

πŸ›° Alternatives

Manual implementation or third party libraries (which in my opinion don't really exist for .NET, or at least, not fully supported or out of date).

Establish strategy for CLS compliance

πŸš€ Feature Request

Because of the nature of the MQTT protocol, we make use of specific byte length and signed/unsigned variables that turn out to be non CLS compliant.

CLS compliance includes rules like:

Unsigned types should not be part of the public interface of the class.

The library uses UInt8, ushort and other similar types throughout. We likely have to do a full review to be CLS compliant.

πŸ“Ž Additional context

DNS Resolution with Multiple Addresses

πŸ› Bug Report

If the DNS lookup return an unexpected number of records, the client currently bombs out.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. ...

Code sample

Environment

Where are you running/using this client?

What version of this client are you using?

Operating System?

Hardware or Device?

Screenshots

πŸ“ˆ Expected behavior

πŸ“Ž Additional context

Per-Subscription Callbacks are not working with single-level wildcard "+"

πŸ› Bug Report

If using a single-level wildcard in a per-Subscription callback the callback is never fired.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. Create a simple .net console application
  2. Paste the below code into the Program.cs file
  3. Execute the console application
  4. Per subscription callback is never executed when a message is received
  5. If you use a topic without a wildcard it works fine

Code sample

using System.Text;
using System.Text.Json;
using HiveMQtt.Client;
using HiveMQtt.Client.Options;
using HiveMQtt.MQTT5.Types;

var options = new HiveMQClientOptions
{
    Host = "127.0.0.1",
    Port = 1883,
    CleanStart = true,  // <--- Set to false to receive messages queued on the broker
    ClientId = "ConnectReceiveAndPublish",
};

var client = new HiveMQClient(options);

// Connect to the broker
var connectResult = await client.ConnectAsync().ConfigureAwait(false);
if (connectResult.ReasonCode != HiveMQtt.MQTT5.ReasonCodes.ConnAckReasonCode.Success)
{
    throw new Exception($"Failed to connect: {connectResult.ReasonString}");
}

// Subscribe to a topic
var topic = "hivemqtt/sendmessageonloop/+/test";

var builder = new SubscribeOptionsBuilder();
var subscribeOptions = builder.WithSubscription(
        new TopicFilter(topic, QualityOfService.AtLeastOnceDelivery),
        (sender, e) =>
        {
            //Console.WriteLine($"Message received on topic {e.PublishMessage.Topic}: {e.PublishMessage.PayloadAsString}");
            var jsonString = e.PublishMessage.PayloadAsString;
            var jsonDocument = JsonDocument.Parse(jsonString);

            // Traverse the JSON document using the JsonElement API
            var root = jsonDocument.RootElement;
            var message_number = root.GetProperty("MessageNumber").GetInt32();

            Console.WriteLine($"Message Received; topic={e.PublishMessage.Topic}, message number={message_number}");
        })
    .Build();

var subscribeResult = await client.SubscribeAsync(subscribeOptions).ConfigureAwait(false);
Console.WriteLine($"Subscribed to {topic}: {subscribeResult.Subscriptions[0].SubscribeReasonCode}");

Console.WriteLine("Waiting for 10 seconds to receive messages queued on the topic...");
await Task.Delay(10000).ConfigureAwait(false);

Console.WriteLine(string.Empty);
Console.WriteLine("Now publishing a QoS2 message every 15 seconds. Press Q to quit.");

// Publish Loop - press q to exit
var message_number = 0;
while (true)
{
    message_number++;
    var payload = JsonSerializer.Serialize(new
    {
        Content = "ConnectReceiveAndPublish",
        MessageNumber = message_number,
    });

    var message = new MQTT5PublishMessage
    {
        Topic = $"hivemqtt/sendmessageonloop/{message_number}/test",
        Payload = Encoding.ASCII.GetBytes(payload),
        QoS = QualityOfService.ExactlyOnceDelivery,
    };

    var resultPublish = await client.PublishAsync(message).ConfigureAwait(false);
    Console.WriteLine($"Published QoS2 message {message_number} to topic {topic}: {resultPublish.QoS2ReasonCode}");

    for (var x = 0; x < 5; x++)
    {
        await Task.Delay(3750).ConfigureAwait(false);

        if (Console.KeyAvailable)
        {
            if (Console.ReadKey().Key == ConsoleKey.Q)
            {
                Console.WriteLine("Disconnecting gracefully...");
                await client.DisconnectAsync().ConfigureAwait(false);
                return;
            }
        }
    }
}

Environment

Where are you running/using this client?
.net 8 console application

What version of this client are you using?
0.10.2

Operating System?
Linux (Fedora)

Hardware or Device?
Dell Notebook (Intel processor)

πŸ“ˆ Expected behavior

The callback is fired and the data is written to the console (see code example)

Add Guidance, Options and Documentation on TLS Configuration

πŸš€ Feature Request

We should provide a way to reveal the TLS version in use and potentially select a version to use. This depends on .NET as best practice suggests to allow the .NET VM decide. Some clarification is needed here.

This option should be well documented too.

πŸ”ˆ Motivation

Configurability and ease of use against all brokers.

πŸ›° Alternatives

N/A

πŸ“Ž Additional context

Add Before/After Socket Connect/Disconnect Events

πŸš€ Feature Request

Requested from the support team. We should also provide these events in the client and document the distinction between these and After/Before Connect/Disconnect which are the MQTT protocol packet level events.

πŸ”ˆ Motivation

Extends the event system in the client.

πŸ›° Alternatives

None

πŸ“Ž Additional context

Client gets disconnected from broker - best way to reconnect

Checklist

Hello!

Friendly reminder, discussions is missing.

  • I've searched the project's issues.

❓ Question

My hivemq client gets disconnected after approximately 50mins. what is best way to reconnect.

 var options = new HiveMQClientOptions()
            {
                Host = broker.hivemq.com,
                Port = 1883,
                UseTLS = true,
                UserName = "admin",
                Password = "adminPassword",
                CleanStart = false,

                KeepAlive = 43200,
                SessionExpiryInterval = 2000,
            };

What do you recommend,

  1. Try to modify HiveMQClientOptions above to extend session, set SessionExpiryInterval to 0 and add some reconnect method?
  2. add some reconnect option (not sure if it available)?
Java (https://www.hivemq.com/article/hivemq-mqtt-client-features/reconnect-handling/)
 .automaticReconnectWithDefaultConfig()
  1. manually disconnect and then connect after some period of time?
... 
_hiveMQTTClient.BeforeDisconnect += _hiveMQTTClient_BeforeDisconnect; 
private void _hiveMQTTClient_BeforeDisconnect(object sender, HiveMQtt.Client.Events.BeforeDisconnectEventArgs e)

    {
        Console.WriteLine("Attempting to reconnect...");

        try
        {
            await client.ConnectAsync();

            if (client.IsConnected)
            {
                Console.WriteLine("Reconnected to the broker");
                // You can re-subscribe to topics or perform any other necessary actions here
            }
        }
        catch (MqttClientStateException ex)
        {
            Console.WriteLine($"Reconnect attempt failed: {ex.Message}");
        }
    }

FR: Manual Message Acknowledgement

Describe the feature

For received QoS 1 + 2 publishes, it would be ideal if there was an option to manually acknowledge the messages.

E.g. don't send the PubAck or PubRec until the consumer signals to do so

FR: Standard and Extensible Logging

Describe the feature

The NuGet package needs standard logging using best practices so that:

  1. The NuGet package is smart & silent by default
  2. Logging can be redirected to application logger
  3. Logging verbosity can be configured

Validate Maximum Packet Size on Received Packets

πŸ› Bug Report

Per the specification on Maximum Packet Size:

If a Client receives a packet whose size exceeds this limit, this is a Protocol Error, the Client uses DISCONNECT with Reason Code 0x95 (Packet too large), as described in section 4.13.

This client should validate received packet size.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. ...

Code sample

Environment

Where are you running/using this client?

What version of this client are you using?

Operating System?

Hardware or Device?

Screenshots

πŸ“ˆ Expected behavior

πŸ“Ž Additional context

Certain (long?) MQTT packets are malformed

Attempting to publish (or perhaps receive) MQTT packets with certain combinations of topic and payload produces malformed MQTT packets. I can’t nail down exactly what conditions make it happen, but it seems to depend at least on the lengths of those strings. The test case below triggers the bug:

var clientOptions = new HiveMQClientOptions
{
    // <redacted>
};
using var client = new HiveMQClient(clientOptions);
client.OnMessageReceived += (_, args) =>
{
    Console.WriteLine("Received {0} ({1} byte payload)", 
        args.PublishMessage.Topic, 
        args.PublishMessage.Payload?.Length ?? 0);
};

await client.ConnectAsync();
await client.SubscribeAsync("#");

var testMessage = new MQTT5PublishMessage
{
    Topic = "example12345678901234567891234567890123456",
    QoS = QualityOfService.AtLeastOnceDelivery,
    Payload = new byte[76],
};
await client.PublishAsync(testMessage);
await Task.Delay(1000);

which results in OnMessageReceived printing garbage for the β€œtopic” string with a 0-byte payload.

I can make this happen every time if the topic string is exactly 42 bytes and the payload is at least 76; I assume other conditions can also trigger it, but I haven’t discovered them.

Per-Subscription Callbacks

πŸš€ Feature Request

The feature I am requesting is essentially the callback feature in the HiveMQ Java Client. See example and Javadoc.

πŸ”ˆ Motivation

I am currently evaluating migrating some .NET Core apps from the M2MQTT library to this one after having successfully migrating a number of Java applications from the Paho Java library to the HiveMQ Java library. You are all probably aware of my motivations for using this library (MQTT5 support, async APIs, etc.)

The motivations for adding this feature are primarily:

  • Feature parity with the HiveMQ Java library (this makes it easy for users/orgs leveraging both libraries)
  • Separation of concerns in client code
    • Ex. I might have two classes that subscribe to different MQTT topics for entirely different reasons. Methods/callbacks in these classes should not need to filter out irrelevant messages.

πŸ›° Alternatives

My current alternative is to implement this logic in my client application. I create a wrapper around the IHiveMQClient library that manages subscriptions internally and calls the relevant callbacks as needed.

πŸ“Ž Additional context

Please let me know if any additional content is needed or if this feature already exists and I somehow missed it.

SSL/TLS Support

πŸš€ Feature Request

This client still lacks TLS support. To be added soon.

πŸ”ˆ Motivation

πŸ›° Alternatives

πŸ“Ž Additional context

Use integration tests with containers, to avoid having the need to setup a broker before running the tests

πŸš€ Feature Request

Can we use the Java test containers or have a script that runs the the CE version of HiveMQ to run the integration tests.

Also separate the integration tests from unit tests.

πŸ”ˆ Motivation

Try to maintain the good practices of other HiveMQ projects

πŸ›° Alternatives

Have a docker compose to help run faster the unit and integration tests locally

πŸ“Ž Additional context

https://www.hivemq.com/blog/hivemq-is-now-available-in-testcontainers/

UseTLS == false on TLS connection results in a cryptic error

πŸ› Bug Report

This error should be much clearer by providing a path forward for users.

image001

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

Connect to a TLS port with UseTLS=false

Code sample

Environment

Where are you running/using this client?

What version of this client are you using?

Operating System?

Hardware or Device?

Screenshots

πŸ“ˆ Expected behavior

πŸ“Ž Additional context

Example: Connecting to HiveMQ Cloud with TLS

πŸš€ Feature Request

This should be documented to make it a simple process for those new to this client.

πŸ”ˆ Motivation

πŸ›° Alternatives

πŸ“Ž Additional context

After adding multiple PublishAsync commands "The operation has timed out" appears and client disconnects

πŸ› Bug Report

I realized after adding multiple PublishAsync commands one after another, your client is somehow disconnected and can't
receive further messages or Publish new ones

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. In your example, just add multiple client.PublishAsync commands one after another and you will see in output
  2. tried to follow this video and I get the same error, and this guy also uses free cluster version, did you make changes to cluster?

Code sample

/*
 * Copyright 2023-present HiveMQ and the HiveMQ Community
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using HiveMQtt.Client;
using HiveMQtt.Client.Options;
using HiveMQtt.MQTT5.ReasonCodes;
using HiveMQtt.MQTT5.Types;

// Built from the Microsoft CLI Template.
// See https://aka.ms/new-console-template for more information

// Example Options to connect to HiveMQ cloud
//
// See here for more information to get your own free instance:
// https://www.hivemq.com/mqtt-cloud-broker/
//
// These values could instead be set with:
//    Environment.GetEnvironmentVariable("HIVEMQTTCLI_HOST")
//  if you set your environment variables externally.
//
var options = new HiveMQClientOptions
{
    Host = "randomstring.s2.eu.hivemq.cloud",
    Port = 8883,
    UseTLS = true,
    UserName = "user",
    Password = "password",
};

// Example Options to connect to HiveMQ Public Broker (insecure public testing broker)
//
// These values could instead be set with:
//    Environment.GetEnvironmentVariable("HIVEMQTTCLI_HOST")
//  if you set your environment variables externally.
//
/*
var options = new HiveMQClientOptions
{
    Host = "broker.hivemq.com",
    Port = 8883,
    UseTLS = true,
};
*/

// Example HiveMQClientOptions to connect to a local MQTT broker without authentication
/*
var options = new HiveMQClientOptions
{
    Host = "127.0.0.1",
    Port = 1883,
};
*/

var client = new HiveMQClient(options);

if (options.UseTLS)
{
    Console.WriteLine($"Connecting to {options.Host} on port {options.Port} using TLS...");
}
else
{
    Console.WriteLine($"Connecting to {options.Host} on port {options.Port} without TLS...");
}

// Connect
HiveMQtt.Client.Results.ConnectResult connectResult;
try
{
    connectResult = await client.ConnectAsync().ConfigureAwait(false);
    if (connectResult.ReasonCode == ConnAckReasonCode.Success)
    {
        Console.WriteLine($"Connect successful: {connectResult}");
    }
    else
    {
        // FIXME: Add ToString
        Console.WriteLine($"Connect failed: {connectResult}");
        Environment.Exit(-1);
    }
}
catch (System.Net.Sockets.SocketException e)
{
    Console.WriteLine($"Error connecting to the MQTT Broker with the following socket error: {e.Message}");
    Environment.Exit(-1);
}
catch (Exception e)
{
    Console.WriteLine($"Error connecting to the MQTT Broker with the following message: {e.Message}");
    Environment.Exit(-1);
}

client.OnMessageReceived += (sender, args) =>
{
    string received_message = args.PublishMessage.PayloadAsString;
    Console.WriteLine(received_message);
};

await client.SubscribeAsync("tests/MostBasicPublishWithQoS2Async").ConfigureAwait(false);

Console.WriteLine("Publishing a QoS level 2 message...");

var msg = new string(/*lang=json,strict*/
"{\"interference\": \"1029384\"}");
var result = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);
//var r1 = await client.ConnectAsync().ConfigureAwait(false);
var result1 = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);
//var r2 = await client.ConnectAsync().ConfigureAwait(false);
var result2 = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);

Console.WriteLine(result);

Console.WriteLine("Disconnecting from broker...");

await client.DisconnectAsync().ConfigureAwait(false);

Console log

Connecting to 11f15bd0c12d4e74934d357066842197.s2.eu.hivemq.cloud on port 8883 using TLS...
Connect successful: ConnectResult[Code: Success]: SessionPresent: False, SessionExpiryInterval: 300, MaximumQoS: 2, RetainAvailable: True, TopicAliasMaximum: 5, BrokerReceiveMaximum: 10
Publishing a QoS level 2 message...
{"interference": "1029384"}
{"interference": "1029384"}
<THIRD PUBLISH FAILS>

Output

--> PublishPacket
OnPublishSentEventLauncher
--> PubRelPacket
OnPubRelSentEventLauncher
<-- Publish
OnMessageReceivedEventLauncher
<-- PubRec
OnPubRecReceivedEventLauncher
OnPublishQoS2CompleteEventLauncher
<-- Disconnect
OnDisconnectReceivedEventLauncher
TrafficInflowProcessor IsCompleted: end of the stream
6: TrafficInflowProcessor Exiting...Connected
--> PublishPacket
OnPublishSentEventLauncher
--> PubRelPacket
OnPubRelSentEventLauncher
Exception thrown: 'System.TimeoutException' in System.Private.CoreLib.dll
An exception of type 'System.TimeoutException' occurred in System.Private.CoreLib.dll but was not handled in user code
The operation has timed out.

Environment

  • HiveMQ 0.1.10
  • HiveMQ Cluster Free version 10gb data, up to 100 devices
  • Microsoft Visual Studio Professional 2022 (64-bit) - Current Version 17.3.3
  • Windows 10, Version 10.0.190044
  • HP Zbook 15 G5

πŸ“ˆ Expected behavior

As in video, I don't expect to be disconnected after publishing few messages.

Workaround

I tried to add ``ConnectAsyncafter everyPublishAsync``` (uncomment lines 118, 120) and in the web client I'm able to see all 3 messages but I get only one in Visual Studio CMD

image

Connecting to 11f15bd0c12d4e74934d357066842197.s2.eu.hivemq.cloud on port 8883 using TLS...
Connect successful: ConnectResult[Code: Success]: SessionPresent: False, SessionExpiryInterval: 300, MaximumQoS: 2, RetainAvailable: True, TopicAliasMaximum: 5, BrokerReceiveMaximum: 10
Publishing a QoS level 2 message...
{"interference": "1029384"}
HiveMQtt.Client.Results.PublishResult
Disconnecting from broker...

C:\Users\u26t71\Desktop\HiveMQtt-CLI\bin\Debug\net6.0\HiveMQtt-CLI.exe (process 22668) exited with code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .

πŸ“Ž Additional context

When I start debug mode, also I see connection timed out on same code that was working described in Workaround section.
I tried to disconnect and connect after publish and it is working but then I'm unable to see other messages that are published in visual studio, in web client it is fine,

var msg = new string(/*lang=json,strict*/
"{\"interference\": \"1029384\"}");
var result = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);
await client.DisconnectAsync().ConfigureAwait(false);
var r1 = await client.ConnectAsync().ConfigureAwait(false);
var result1 = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);
await client.DisconnectAsync().ConfigureAwait(false);
var r2 = await client.ConnectAsync().ConfigureAwait(false);
var result2 = await client.PublishAsync("tests/MostBasicPublishWithQoS2Async", msg, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);

AfterDisconnect is not fired in provided example

πŸ› Bug Report

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. Download reconnect example and add broker.hivemq.com option. Example is below.
options.Host = "broker.hivemq.com";
options.Port = 1883;
  1. When I press q after message Disconnecting gracefully... event AfterDisconnect is not fired.
Subscribing to hivemqtt/waiting/game...
We are connected to the broker and will be waiting indefinitely for messages or a disconnect.
--> Publish messages to hivemqtt/waiting/game and they will be printed.
--> Shutdown/disconnect the broker and see the AfterDisconnect code execute.
Publishing a test message...
--> Message Received: {"Command":"Hello"}
Press q exit...
q

Disconnecting gracefully...

Code sample

using HiveMQtt.Client;
using HiveMQtt.Client.Options;
using System.Text.Json;

var topic = "hivemqtt/waiting/game";

var options = new HiveMQClientOptions();
options.Host = "broker.hivemq.com";
options.Port = 1883;

var client = new HiveMQClient(options);

// Add handlers
// Message handler
client.OnMessageReceived += (sender, args) =>
{
    // Handle Message in args.PublishMessage
    Console.WriteLine($"--> Message Received: {args.PublishMessage.PayloadAsString}");
};

// This handler is called when the client is disconnected
client.AfterDisconnect += async (sender, args) =>
{
    var client = (HiveMQClient)sender;

    Console.WriteLine($"AfterDisconnect Handler called with args.CleanDisconnect={args.CleanDisconnect}.");

    // We've been disconnected
    if (args.CleanDisconnect)
    {
        Console.WriteLine("--> AfterDisconnectEventArgs indicate a clean disconnect.");
        Console.WriteLine("--> A clean disconnect was requested by either the client or the broker.");
    }
    else
    {
        Console.WriteLine("--> AfterDisconnectEventArgs indicate an unexpected disconnect.");
        Console.WriteLine("--> This could be due to a network outage, broker outage, or other issue.");
        Console.WriteLine("--> In this case we will attempt to reconnect periodically.");

        // We could have been disconnected for any number of reasons: network outage, broker outage, etc.
        // Here we loop with a backing off delay until we reconnect

        // Start with a small delay and double it on each retry up to a maximum value
        var delay = 5000;
        var reconnectAttempts = 0;

        while (true)
        {
            await Task.Delay(delay).ConfigureAwait(false);
            reconnectAttempts++;

            if (reconnectAttempts > 3)
            {
                Console.WriteLine("--> Maximum reconnect attempts exceeded.  Exiting.");
                break;
            }

            try
            {
                Console.WriteLine($"--> Attempting to reconnect to broker.  This is attempt #{reconnectAttempts}.");
                var connectResult = await client.ConnectAsync().ConfigureAwait(false);

                if (connectResult.ReasonCode != HiveMQtt.MQTT5.ReasonCodes.ConnAckReasonCode.Success)
                {
                    Console.WriteLine($"--> Failed to connect: {connectResult.ReasonString}");

                    // Double the delay with each failed retry to a maximum
                    delay = Math.Min(delay * 2, 30000);
                    Console.WriteLine($"--> Will delay for {delay / 1000} seconds until next try.");
                }
                else
                {
                    Console.WriteLine("--> Reconnected successfully.");
                    break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"--> Failed to connect: {ex.Message}");

                // Double the delay with each failed retry to a maximum
                delay = Math.Min(delay * 2, 10000);
                Console.WriteLine($"--> Will delay for {delay / 1000} seconds until next try.");
            }
        }
    } // if (args.CleanDisconnect)

    Console.WriteLine("--> Exiting AfterDisconnect handler.");
};

// Attempt to connect to the broker
try
{
    var connectResult = await client.ConnectAsync().ConfigureAwait(false);
    if (connectResult.ReasonCode != HiveMQtt.MQTT5.ReasonCodes.ConnAckReasonCode.Success)
    {
        throw new Exception($"Failed to connect to broker: {connectResult.ReasonString}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Failed to connect to broker: {ex.Message}");
    return;
}

// Subscribe to a topic
Console.WriteLine($"Subscribing to {topic}...");
await client.SubscribeAsync(topic).ConfigureAwait(false);

Console.WriteLine($"We are connected to the broker and will be waiting indefinitely for messages or a disconnect.");
Console.WriteLine($"--> Publish messages to {topic} and they will be printed.");
Console.WriteLine($"--> Shutdown/disconnect the broker and see the AfterDisconnect code execute.");

await Task.Delay(1000).ConfigureAwait(false);

// Publish a message
Console.WriteLine("Publishing a test message...");
var resultPublish = await client.PublishAsync(
    topic,
    JsonSerializer.Serialize(new
    {
        Command = "Hello",
    })
).ConfigureAwait(false);


while (true)
{
    await Task.Delay(2000).ConfigureAwait(false);
    Console.WriteLine("Press q exit...");
    if (Console.ReadKey().Key == ConsoleKey.Q)
    {
        Console.WriteLine("\n");
        break;
    }
}

Console.WriteLine("Disconnecting gracefully...");
await client.DisconnectAsync().ConfigureAwait(false);

Environment

Where are you running/using this client?

Locally, visual studio 2022

What version of this client are you using?

Latest, that is provided with example, 0.4.0.

Operating System?
Win10.

πŸ“ˆ Expected behavior

AfterDisconnect should be fired and messages should be displayed.

AfterDisconnect Handler called with args.CleanDisconnect
...

πŸ“Ž Additional context

I tried with BeforeDisconnect and lambda is fired but for wrong purpose.
I hope you are able to reproduce it.
I guess that you didn't notice this because you used local broker for testing options.Host = "127.0.0.1";.

Questions

  1. How long do you think this will take to fix?
  2. Is there a possible workaround, using BeforeDisconnect, OnDisconnectetReceived if it will take a few weeks to fix this.

Timeout exception after publishing on QOS 2

I connect the the server with a ClientId and "Clean Start" = False.
The idea is to "queue" messages while the cliente is disconnected
Then subscribe to a topic with QOS2 and I can send and receive with no problem up to here.

I disconnect and with the "online client" publish som message to the topic.

When I connect back with the cliente I get the messages that were sent while the client was disconnected.

Put if I try to publish i get a "Timeout exception" (always).
Bellow is part of the client code and the exception is received 5 seconds after we use m_hiveClient.PublishAsync (bellow)

	public void Publish(string topic, string data)
	{
		lock (m_locker)
		{
			if (string.IsNullOrEmpty(topic) || string.IsNullOrEmpty(data))
			{
				throw new Exception("ParΓ‘metros no vΓ‘lidos");
			}
			if (!m_hiveClient.IsConnected())
			{
				throw new Exception("Cliente no conectado");
			}

			Log.MsgSnd.Trace($"Client({m_config.clientId}:{m_id}) - Topic({topic}) Data({data})");
			PublishResult result = m_hiveClient.PublishAsync(topic, data, QualityOfService.ExactlyOnceDelivery).Result;
			if (Log.Debug.IsTraceEnabled)
			{
				Log.Debug.Trace($"Client({m_config.clientId}:{m_id}) - PublishResult: {JsonConvert.SerializeObject(result, Formatting.Indented)}");
			}
		}
	}

Here's the error after i Publish a message "hola?" to the topic "angelo"

2023-10-12 09:20:41.2650 (1) GenexusMqtt.Lib.Hive.MqttClient.Publish@232 - Client(client1:569eb2ee-acac-4069-b79a-b15f7ed7eb89) - Topic(angelo) Data(hola?)
2023-10-12 09:20:46.2708 (1) GenexusMqtt.Lib.Hive.MqttHandler.Publish@115 - Client(569eb2ee-acac-4069-b79a-b15f7ed7eb89) Topic(angelo) Data(hola?)- Error al publicar el mensaje
System.AggregateException: One or more errors occurred. (The operation has timed out.)
---> System.TimeoutException: The operation has timed out.
at HiveMQtt.Client.HiveMQClient.PublishAsync(MQTT5PublishMessage message)
at HiveMQtt.Client.HiveMQClient.PublishAsync(String topic, String payload, QualityOfService qos)
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1.get_Result()
at GenexusMqtt.Lib.Hive.MqttClient.Publish(String topic, String data) in C:\Users\Administrator\Documents\mqtt-hive_4\GenexusMqtt.Lib\Hive\MqttClient.cs:line 233
at GenexusMqtt.Lib.Hive.MqttHandler.Publish(Guid id, String topic, String data) in C:\Users\Administrator\Documents\mqtt-hive_4\GenexusMqtt.Lib\Hive\MqttHandler.cs:line 115
2023-10-12 09:20:46.2708 (1) Test.App.MainWindow.PublishClient@187 - Error al publicar el mensaje del cliente 1

Configurable Ping Interval

πŸš€ Feature Request

On small devices that go into power save mode there is a need to keep the TCP connection alive to avoid TLS renegotiation which can be expensive in terms of power and network transmission. There is also the issue of mid-network devices (firewall, switch, relay) that may terminate connections under different circumstances because of a lack of connection activity.

We want to make this client as configurable as possible. As such the Ping interval should be configurable. Documentation should also clearly explain the relationship between TCP, TLS, Ping and Session Expiry.

πŸ“Ž Additional context

Observations

I tried using your client and these are the issues I found:

  1. When building your project using Visual Studio 2022 there were 308 warnings (never a good thing to see)
  2. I didn't realise that HiveMQClient Connect returns a status for connection success, I would expect an exception normally. Not realising that I wasn't connected I tried to subscribe to a topic and instead of getting an exception to say I wasn't connected I got a timeout instead.
  3. Once I did get the client connected I could publish a topic but not receive even though I subscribed and could see the message in the online client.

HiveMQTT subscriber dies, never recovers, after receiving large burst of messages

πŸ› Bug Report

I'm working on an MQTT PoC that needs to be able to process 30,000 3k-7kb packets per second per node (large scale network) with QoS=0. Tried doing this with MQTTNet and ran into issues with it dotnet/MQTTnet#1962 - so I thought I would give HiveMQ a try.

Here is what I was able to produce with the same sample I used for MQTTnet:

[INFO][04/10/2024 22:04:14.925Z][Thread 0004][akka://MyActorSystem/user/supervisor] RabbitMQ supervisor started - MQTT reader and writer running
[INFO][04/10/2024 22:04:20.385Z][Thread 0029][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [0] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:04:20.401Z][Thread 0029][akka://MyActorSystem/user/supervisor/mqtt-reader] Subscription running
[INFO][04/10/2024 22:04:20.402Z][Thread 0029][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [0] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:24.950Z][Thread 0011][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [0] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:25.136Z][Thread 0019][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [0] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:04:29.949Z][Thread 0012][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [8164] messages from MQTT [1633.1718078937852 msg/s]
[INFO][04/10/2024 22:04:30.135Z][Thread 0022][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [9093] messages to Rabbit [1819.0071665641635 msg/s]
[INFO][04/10/2024 22:04:35.227Z][Thread 0077][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [4050.8370577319124 msg/s]
[INFO][04/10/2024 22:04:36.252Z][Thread 0012][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [25324] messages to Rabbit [2653.277448258188 msg/s]
[INFO][04/10/2024 22:04:39.946Z][Thread 0029][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:40.132Z][Thread 0044][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [1087.8009516041482 msg/s]
[INFO][04/10/2024 22:04:44.948Z][Thread 0078][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:45.135Z][Thread 0029][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:04:49.953Z][Thread 0015][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:50.138Z][Thread 0078][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:04:54.958Z][Thread 0015][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:04:55.127Z][Thread 0078][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:04:59.944Z][Thread 0078][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:05:00.130Z][Thread 0078][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:05:04.951Z][Thread 0015][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:05:05.137Z][Thread 0044][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:05:09.958Z][Thread 0044][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]
[INFO][04/10/2024 22:05:10.129Z][Thread 0044][akka://MyActorSystem/user/supervisor/rabbit-writer] Wrote [29544] messages to Rabbit [0 msg/s]
[INFO][04/10/2024 22:05:14.947Z][Thread 0078][akka://MyActorSystem/user/supervisor/mqtt-reader] Read [29544] messages from MQTT [0 msg/s]

Received about ~30k messages and then the client dies - no disconnect message or anything is received. The OnMessage event stops firing and according to EMQX, the client is still alive but it's no longer ACKing any of the published messages.

πŸ”¬ How To Reproduce

Steps to reproduce the behavior:

  1. ...

Code sample

Fairly simply client setup - we're just writing any of the messages we receive to a ChannelWriter<MQTT5PublishMessage> - those messages will get picked up by Akka.NET's Streaming library which will pipe the messages to RabbitMQ. Akka.Streams hasn't had any trouble keeping up.

private async Task ConfigureMqttClientAsync()
    {
        var mqttClientOptions = new HiveMQClientOptionsBuilder()
            .WithClientId(_appSetting.MQTT_ClientId)
            .WithBroker(_appSetting.MQTT_Host)
            .WithPort(_appSetting.MQTT_Port)
            .WithUserName(_appSetting.MQTT_User)
            .WithPassword(_appSetting.MQTT_Password)
            .WithCleanStart(false)
            .WithMaximumPacketSize(7 * 1024)
            //.WithUseTls(true)
            .Build();

        _mqttClient = new HiveMQClient(mqttClientOptions);

      var qosSetting = _appSetting.MQTT_QoS switch
        {
            0 => QualityOfService.AtMostOnceDelivery,
            1 => QualityOfService.AtLeastOnceDelivery,
            2 => QualityOfService.ExactlyOnceDelivery,
            _ => QualityOfService
                .AtMostOnceDelivery // Handle invalid QoS setting (assuming default to QoS 0 in this example)
        };

        var topicFilter = new TopicFilter(_appSetting.MQTT_Topic, qosSetting);

        var mqttSubscribeOptions = new SubscribeOptionsBuilder()
            .WithSubscription(topicFilter).Build();

        _mqttClient.OnMessageReceived += ManagedMqttClient_ApplicationMessageReceived2Async;
        _mqttClient.OnDisconnectReceived += ManagedMqttClient_DisconnectedAsync;
        _mqttClient.OnPublishReceived +=  (sender, args) =>
        {
            _self.Tell(ClientRecv.Instance);
        };
        
        var connectResult = await _mqttClient.ConnectAsync();
        await _mqttClient.SubscribeAsync(mqttSubscribeOptions);
        _log.Info("Subscription running");
    }

private void ManagedMqttClient_DisconnectedAsync(object? sender, OnDisconnectReceivedEventArgs e)
    {
        _log.Warning("MQTT client disconnected for reason: {0}", e.DisconnectPacket.DisconnectReasonCode);
        _mqttClient.Dispose(); // dispose the client
        _mqttClient.OnMessageReceived -= ManagedMqttClient_ApplicationMessageReceived2Async;
        _mqttClient.OnDisconnectReceived -= ManagedMqttClient_DisconnectedAsync;
        _self.Tell(ConfigureMqttClient.Instance);
    }

    private void ManagedMqttClient_ApplicationMessageReceived2Async(object? sender, OnMessageReceivedEventArgs e)
    {
        try
        {
            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            _channelWriter.WriteAsync(e.PublishMessage, cts.Token);
            _self.Tell(Processed.Instance);
        }
        catch (Exception ex)
        {
            _log.Error(ex, "Error acknowledging message {0}", e.PublishMessage.CorrelationData);
        }
    }

Environment

Windows, .NET 8, using an EMQX 5.5.1 broker running on Ubuntu WSL2

Screenshots

What I can see in the EMQX broker logs is that HiveMQTT fails to keep up not long after the load starts - notice the lack of PUBACK responses here:

2024-04-10T16:45:59.156931-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6712, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.156974-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6713, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.156993-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6714, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157038-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6715, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157064-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6716, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157083-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6717, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157101-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6718, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157120-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6719, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157136-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6720, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157156-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6721, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157176-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6722, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157195-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6723, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157212-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6724, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157253-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6725, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin
2024-04-10T16:45:59.157329-05:00 [MQTT] [email protected]:54600 msg: mqtt_packet_sent, packet: PUBLISH(Q1, R0, D0, Topic=dev/topic_1, PacketId=6726, Payload={"idRequest":"77444ea7-207f-4f4b-b2fe-4cff777e4efe","time":1660643404,"statusCode":"OK","errorMessag... The 1019 bytes of this log are truncated), username: admin

PUBACK events, eventually, do get fired back at the server but only after the message is no longer retained in the fixed-size buffer.

What I can't figure out is - _why doesn't my OnMessageReceived handler get fired when this is happening?

πŸ“ˆ Expected behavior

I'd expect the MQTT client to keep up with the events being thrown at it - the project should really add some event processing benchmarks; that's a much more important measure than event publishing throughput IMHO.

MQTT publish packets β‰₯ 128 bytes are malformed

πŸ› Bug Report

MQTT publish packets whose lengths are β‰₯ 128 bytes are malformed by PublishPacket.cs:271 since the code assumes the varint only requires one byte. This may be related to #71 but is not the same thing, since that test case doesn't involve a packet this large.

πŸ”¬ How To Reproduce

Attempt to send a packet with a sufficiently large payload.

Code sample

var clientOptions = new HiveMQClientOptions
{
    // <redacted>
};
using var client = new HiveMQClient(clientOptions);
await client.ConnectAsync();

var testMessage = new MQTT5PublishMessage
{
    Topic = "example",
    QoS = QualityOfService.AtLeastOnceDelivery,
    Payload = new byte[256],
};
await client.PublishAsync(testMessage);

Environment

v0.1.10, Windows, .NET 6.0

πŸ“Ž Additional context

Discovered while single-stepping in the debugger while troubleshooting #71.

Add Azure Functions MQTT Trigger Support

πŸš€ Feature Request

Azure Functions has trigger bindings for many protocols but not MQTT.

A recent customer pointed out that they are using this 3rd party library but it's limited to .NET 6.

In my search so far, I haven't found an alternative.

We should create and maintain an opensource MQTT binding for Azure.

πŸ”ˆ Motivation

There is currently no way to trigger an Azure function from an MQTT message for .NET 7 or 8.

πŸ›° Alternatives

.NET 6 Only and hasn't been updated in quite some time: https://github.com/Hotzilla/CaseOnline.Azure.WebJobs.Extensions.Mqtt.net6

πŸ“Ž Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.