@@ -12,7 +12,7 @@ | |||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> | <requireLicenseAcceptance>true</requireLicenseAcceptance> | ||||
<description>This is a support library to integrate MQTTnet into AspNetCore.</description> | <description>This is a support library to integrate MQTTnet into AspNetCore.</description> | ||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | <releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | |||||
<copyright>Copyright Christian Kratky 2016-2021</copyright> | |||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | ||||
<dependencies> | <dependencies> | ||||
<group targetFramework="netstandard2.0"> | <group targetFramework="netstandard2.0"> | ||||
@@ -12,7 +12,7 @@ | |||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> | <requireLicenseAcceptance>true</requireLicenseAcceptance> | ||||
<description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description> | <description>This is an extension library which provides a managed MQTT client with additional features using MQTTnet.</description> | ||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | <releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | |||||
<copyright>Copyright Christian Kratky 2016-2021</copyright> | |||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | ||||
<dependencies> | <dependencies> | ||||
<dependency id="MQTTnet" version="$nugetVersion" /> | <dependency id="MQTTnet" version="$nugetVersion" /> | ||||
@@ -12,7 +12,7 @@ | |||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> | <requireLicenseAcceptance>true</requireLicenseAcceptance> | ||||
<description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description> | <description>This is an extension library which allows executing synchronous device calls including a response using MQTTnet.</description> | ||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | <releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | |||||
<copyright>Copyright Christian Kratky 2016-2021</copyright> | |||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | ||||
<dependencies> | <dependencies> | ||||
<dependency id="MQTTnet" version="$nugetVersion" /> | <dependency id="MQTTnet" version="$nugetVersion" /> | ||||
@@ -12,7 +12,7 @@ | |||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> | <requireLicenseAcceptance>true</requireLicenseAcceptance> | ||||
<description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description> | <description>This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.</description> | ||||
<releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | <releaseNotes>For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).</releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | |||||
<copyright>Copyright Christian Kratky 2016-2021</copyright> | |||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | ||||
<dependencies> | <dependencies> | ||||
<dependency id="MQTTnet" version="$nugetVersion" /> | <dependency id="MQTTnet" version="$nugetVersion" /> | ||||
@@ -12,7 +12,8 @@ | |||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> | <requireLicenseAcceptance>true</requireLicenseAcceptance> | ||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description> | <description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker) and supports v3.1.0, v3.1.1 and v5.0.0 of the MQTT protocol.</description> | ||||
<releaseNotes> | <releaseNotes> | ||||
* [ManagedClient] Extended ReconnectAsync (thanks to @nvsnkv, #1202). | |||||
* [ManagedClient] Extended ReconnectAsync (thanks to @nvsnkv, #1202). | |||||
* [ManagedClient] Improved Amazon AWS support (thanks to @scottbrogden-iheartmedia, #1209). | |||||
* [Server] Fixed a memory/performance leak when using QoS Level 1. | * [Server] Fixed a memory/performance leak when using QoS Level 1. | ||||
* [Server] Exposed connection timestamp in client status. | * [Server] Exposed connection timestamp in client status. | ||||
* [Server] Refactored connection management code. | * [Server] Refactored connection management code. | ||||
@@ -21,7 +22,7 @@ | |||||
* [MQTTnet, MQTTnet.Extensions.ManagedClient] Fixed bug that allowed invalid subscriptions (Thanks to @marcelwinh). | * [MQTTnet, MQTTnet.Extensions.ManagedClient] Fixed bug that allowed invalid subscriptions (Thanks to @marcelwinh). | ||||
Git commit: $gitCommit | Git commit: $gitCommit | ||||
</releaseNotes> | </releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2020</copyright> | |||||
<copyright>Copyright Christian Kratky 2016-2021</copyright> | |||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> | ||||
<dependencies> | <dependencies> | ||||
<group targetFramework="net452" /> | <group targetFramework="net452" /> | ||||
@@ -18,6 +18,10 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; } | MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; } | ||||
int? MaxSubcribeUnsubscribeMessagesAtOnce { get; } | |||||
/// <summary> | |||||
/// Defines the maximum amount of topic filters which will be sent in a SUBSCRIBE/UNSUBSCRIBE packet. | |||||
/// Amazon AWS limits this number to 8. The default is int.MaxValue. | |||||
/// </summary> | |||||
int MaxTopicFiltersInSubscribeUnsubscribePackets { get; } | |||||
} | } | ||||
} | } |
@@ -28,6 +28,7 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
/// at reconnect and are solely owned by <see cref="MaintainConnectionAsync"/>. | /// at reconnect and are solely owned by <see cref="MaintainConnectionAsync"/>. | ||||
/// </summary> | /// </summary> | ||||
readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>(); | readonly Dictionary<string, MqttQualityOfServiceLevel> _reconnectSubscriptions = new Dictionary<string, MqttQualityOfServiceLevel>(); | ||||
readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>(); | readonly Dictionary<string, MqttQualityOfServiceLevel> _subscriptions = new Dictionary<string, MqttQualityOfServiceLevel>(); | ||||
readonly HashSet<string> _unsubscriptions = new HashSet<string>(); | readonly HashSet<string> _unsubscriptions = new HashSet<string>(); | ||||
readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0); | readonly SemaphoreSlim _subscriptionsQueuedSignal = new SemaphoreSlim(0); | ||||
@@ -205,7 +206,6 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
await applicationMessageSkippedHandler.HandleApplicationMessageSkippedAsync(applicationMessageSkippedEventArgs).ConfigureAwait(false); | await applicationMessageSkippedHandler.HandleApplicationMessageSkippedAsync(applicationMessageSkippedEventArgs).ConfigureAwait(false); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -248,6 +248,7 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
_unsubscriptions.Add(topic); | _unsubscriptions.Add(topic); | ||||
} | } | ||||
} | } | ||||
_subscriptionsQueuedSignal.Release(); | _subscriptionsQueuedSignal.Release(); | ||||
return Task.FromResult(0); | return Task.FromResult(0); | ||||
@@ -481,8 +482,14 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
lock (_subscriptions) | lock (_subscriptions) | ||||
{ | { | ||||
subscriptions = _subscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }).ToList(); | |||||
subscriptions = _subscriptions.Select(i => new MqttTopicFilter | |||||
{ | |||||
Topic = i.Key, | |||||
QualityOfServiceLevel = i.Value | |||||
}).ToList(); | |||||
_subscriptions.Clear(); | _subscriptions.Clear(); | ||||
unsubscriptions = new HashSet<string>(_unsubscriptions); | unsubscriptions = new HashSet<string>(_unsubscriptions); | ||||
_unsubscriptions.Clear(); | _unsubscriptions.Clear(); | ||||
} | } | ||||
@@ -492,7 +499,7 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
continue; | continue; | ||||
} | } | ||||
_logger.Verbose("Publishing {0} subscriptions and {1} unsubscriptions)", subscriptions.Count, unsubscriptions.Count); | |||||
_logger.Verbose("Publishing {0} added and {1} removed subscriptions", subscriptions.Count, unsubscriptions.Count); | |||||
foreach (var unsubscription in unsubscriptions) | foreach (var unsubscription in unsubscriptions) | ||||
{ | { | ||||
@@ -504,48 +511,48 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
_reconnectSubscriptions[subscription.Topic] = subscription.QualityOfServiceLevel; | _reconnectSubscriptions[subscription.Topic] = subscription.QualityOfServiceLevel; | ||||
} | } | ||||
List<MqttTopicFilter> subs = new List<MqttTopicFilter>(); | |||||
foreach (var sub in subscriptions) | |||||
var addedTopicFilters = new List<MqttTopicFilter>(); | |||||
foreach (var subscription in subscriptions) | |||||
{ | { | ||||
subs.Add(sub); | |||||
//aws only allows 8 in a single message | |||||
if (subs.Count == Options.MaxSubcribeUnsubscribeMessagesAtOnce) | |||||
addedTopicFilters.Add(subscription); | |||||
if (addedTopicFilters.Count == Options.MaxTopicFiltersInSubscribeUnsubscribePackets) | |||||
{ | { | ||||
await SendSubscribeUnsubscribe(subs, null).ConfigureAwait(false); | |||||
subs.Clear(); | |||||
await SendSubscribeUnsubscribe(addedTopicFilters, null).ConfigureAwait(false); | |||||
addedTopicFilters.Clear(); | |||||
} | } | ||||
} | } | ||||
await SendSubscribeUnsubscribe(subs, null); | |||||
await SendSubscribeUnsubscribe(addedTopicFilters, null).ConfigureAwait(false); | |||||
List<string> unSubs = new List<string>(); | |||||
var removedTopicFilters = new List<string>(); | |||||
foreach (var unSub in unsubscriptions) | foreach (var unSub in unsubscriptions) | ||||
{ | { | ||||
unSubs.Add(unSub); | |||||
//aws only allows 8 in a single message | |||||
if (unSubs.Count == Options.MaxSubcribeUnsubscribeMessagesAtOnce) | |||||
removedTopicFilters.Add(unSub); | |||||
if (removedTopicFilters.Count == Options.MaxTopicFiltersInSubscribeUnsubscribePackets) | |||||
{ | { | ||||
await SendSubscribeUnsubscribe(null, unSubs).ConfigureAwait(false); | |||||
unSubs.Clear(); | |||||
await SendSubscribeUnsubscribe(null, removedTopicFilters).ConfigureAwait(false); | |||||
removedTopicFilters.Clear(); | |||||
} | } | ||||
} | } | ||||
await SendSubscribeUnsubscribe(null, unSubs); | |||||
await SendSubscribeUnsubscribe(null, removedTopicFilters).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
async Task SendSubscribeUnsubscribe(List<MqttTopicFilter> subscriptions, List<string> unsubscriptions) | |||||
async Task SendSubscribeUnsubscribe(List<MqttTopicFilter> addedSubscriptions, List<string> removedSubscriptions) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
if (unsubscriptions != null && unsubscriptions.Any()) | |||||
if (removedSubscriptions != null && removedSubscriptions.Any()) | |||||
{ | { | ||||
await InternalClient.UnsubscribeAsync(unsubscriptions.ToArray()).ConfigureAwait(false); | |||||
await InternalClient.UnsubscribeAsync(removedSubscriptions.ToArray()).ConfigureAwait(false); | |||||
} | } | ||||
if (subscriptions != null && subscriptions.Any()) | |||||
if (addedSubscriptions != null && addedSubscriptions.Any()) | |||||
{ | { | ||||
await InternalClient.SubscribeAsync(subscriptions.ToArray()).ConfigureAwait(false); | |||||
await InternalClient.SubscribeAsync(addedSubscriptions.ToArray()).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
catch (Exception exception) | catch (Exception exception) | ||||
@@ -562,20 +569,26 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
{ | { | ||||
if (_reconnectSubscriptions.Any()) | if (_reconnectSubscriptions.Any()) | ||||
{ | { | ||||
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter { Topic = i.Key, QualityOfServiceLevel = i.Value }); | |||||
List<MqttTopicFilter> subs = new List<MqttTopicFilter>(); | |||||
var subscriptions = _reconnectSubscriptions.Select(i => new MqttTopicFilter | |||||
{ | |||||
Topic = i.Key, | |||||
QualityOfServiceLevel = i.Value | |||||
}); | |||||
var topicFilters = new List<MqttTopicFilter>(); | |||||
foreach (var sub in subscriptions) | foreach (var sub in subscriptions) | ||||
{ | { | ||||
subs.Add(sub); | |||||
//aws only allows 8 in a single message | |||||
if (subs.Count == Options.MaxSubcribeUnsubscribeMessagesAtOnce) | |||||
topicFilters.Add(sub); | |||||
if (topicFilters.Count == Options.MaxTopicFiltersInSubscribeUnsubscribePackets) | |||||
{ | { | ||||
await SendSubscribeUnsubscribe(subs, null).ConfigureAwait(false); | |||||
subs.Clear(); | |||||
await SendSubscribeUnsubscribe(topicFilters, null).ConfigureAwait(false); | |||||
topicFilters.Clear(); | |||||
} | } | ||||
} | } | ||||
await SendSubscribeUnsubscribe(subs, null).ConfigureAwait(false); | |||||
await SendSubscribeUnsubscribe(topicFilters, null).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
catch (Exception exception) | catch (Exception exception) | ||||
@@ -665,4 +678,4 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime; | return remainingTime < TimeSpan.Zero ? TimeSpan.Zero : remainingTime; | ||||
} | } | ||||
} | } | ||||
} | |||||
} |
@@ -4,7 +4,7 @@ using MQTTnet.Server; | |||||
namespace MQTTnet.Extensions.ManagedClient | namespace MQTTnet.Extensions.ManagedClient | ||||
{ | { | ||||
public class ManagedMqttClientOptions : IManagedMqttClientOptions | |||||
public sealed class ManagedMqttClientOptions : IManagedMqttClientOptions | |||||
{ | { | ||||
public IMqttClientOptions ClientOptions { get; set; } | public IMqttClientOptions ClientOptions { get; set; } | ||||
@@ -18,6 +18,6 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
public MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; set; } = MqttPendingMessagesOverflowStrategy.DropNewMessage; | public MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; set; } = MqttPendingMessagesOverflowStrategy.DropNewMessage; | ||||
public int? MaxSubcribeUnsubscribeMessagesAtOnce { get; set; } = null; | |||||
public int MaxTopicFiltersInSubscribeUnsubscribePackets { get; set; } = int.MaxValue; | |||||
} | } | ||||
} | } |
@@ -69,9 +69,9 @@ namespace MQTTnet.Extensions.ManagedClient | |||||
return this; | return this; | ||||
} | } | ||||
public ManagedMqttClientOptionsBuilder WithMaxSubcribeUnsubscribeMessagesAtOnce(int? value) | |||||
public ManagedMqttClientOptionsBuilder WithMaxTopicFiltersInSubscribeUnsubscribePackets(int value) | |||||
{ | { | ||||
_options.MaxSubcribeUnsubscribeMessagesAtOnce = value; | |||||
_options.MaxTopicFiltersInSubscribeUnsubscribePackets = value; | |||||
return this; | return this; | ||||
} | } | ||||