Browse Source

Merge branch 'master' into feature/low_level_client

release/3.x.x
Christian Kratky 4 years ago
parent
commit
db906eca24
7 changed files with 139 additions and 15 deletions
  1. +3
    -0
      Build/MQTTnet.nuspec
  2. +48
    -0
      Source/MQTTnet/Extensions/MqttClientOptionsBuilderExtension.cs
  3. +32
    -0
      Source/MQTTnet/Extensions/UserPropertyExtension.cs
  4. +0
    -15
      Source/MQTTnet/Formatter/V3/MqttV310DataConverter.cs
  5. +1
    -0
      Source/MQTTnet/MQTTnet.csproj
  6. +33
    -0
      Tests/MQTTnet.Core.Tests/MqttApplicationMessage_Tests.cs
  7. +22
    -0
      Tests/MQTTnet.Core.Tests/MqttClientOptionsBuilder_Tests.cs

+ 3
- 0
Build/MQTTnet.nuspec View File

@@ -22,6 +22,9 @@
* [Server] Added interceptor for unsubscriptions.
* [MQTTnet.Server] Added interceptor for unsubscriptions.
* [MQTTnet.AspNetCore] improved compatibility with AspNetCore 3.1
* [Core] Added MqttApplicationMessage.GetUserProperty() convenience method (thanks to @PMExtra).
* [Client] Support WithConnectionUri to configure client (thanks to @PMExtra).
* [Server] Removed exceptions when user properties are set with MQTT protocol version 3.1
* [LowLevelMqttClient] Added low level MQTT client in order to provide more flexibility when using the MQTT protocol. This client requires detailed knowledge about the MQTT protocol.
</releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright>


+ 48
- 0
Source/MQTTnet/Extensions/MqttClientOptionsBuilderExtension.cs View File

@@ -0,0 +1,48 @@
using System;
using System.Linq;
using MQTTnet.Client.Options;

namespace MQTTnet.Extensions
{
public static class MqttClientOptionsBuilderExtension
{
public static MqttClientOptionsBuilder WithConnectionUri(this MqttClientOptionsBuilder builder, Uri uri)
{
var port = uri.IsDefaultPort ? null : (int?) uri.Port;
switch (uri.Scheme.ToLower())
{
case "tcp":
case "mqtt":
builder.WithTcpServer(uri.Host, port);
break;

case "mqtts":
builder.WithTcpServer(uri.Host, port).WithTls();
break;

case "ws":
case "wss":
builder.WithWebSocketServer(uri.ToString());
break;

default:
throw new ArgumentException("Unexpected scheme in uri.");
}
if (!string.IsNullOrEmpty(uri.UserInfo))
{
var userInfo = uri.UserInfo.Split(':');
var username = userInfo[0];
var password = userInfo.Length > 1 ? userInfo[1] : "";
builder.WithCredentials(username, password);
}

return builder;
}

public static MqttClientOptionsBuilder WithConnectionUri(this MqttClientOptionsBuilder builder, string uri)
{
return WithConnectionUri(builder, new Uri(uri, UriKind.Absolute));
}
}
}

+ 32
- 0
Source/MQTTnet/Extensions/UserPropertyExtension.cs View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
using System.Linq;

namespace MQTTnet.Extensions
{
public static class UserPropertyExtension
{
public static string GetUserProperty(this MqttApplicationMessage message, string propertyName, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
{
if (message == null) throw new ArgumentNullException(nameof(message));
if (propertyName == null) throw new ArgumentNullException(nameof(propertyName));

return message.UserProperties?.SingleOrDefault(up => up.Name.Equals(propertyName, comparisonType))?.Value;
}

public static T GetUserProperty<T>(this MqttApplicationMessage message, string propertyName, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
{
var value = GetUserProperty(message, propertyName, comparisonType);

var typeDescriptor = TypeDescriptor.GetConverter(typeof(T));
try
{
return (T) typeDescriptor.ConvertFromString(value);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Cannot convert value({value ?? "null"}) of UserProperty({propertyName}) to {typeof(T).FullName}.", ex);
}
}
}
}

+ 0
- 15
Source/MQTTnet/Formatter/V3/MqttV310DataConverter.cs View File

@@ -20,11 +20,6 @@ namespace MQTTnet.Formatter.V3
{
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));

if (applicationMessage.UserProperties?.Any() == true)
{
throw new MqttProtocolViolationException("User properties are not supported in MQTT version 3.");
}

return new MqttPublishPacket
{
Topic = applicationMessage.Topic,
@@ -171,11 +166,6 @@ namespace MQTTnet.Formatter.V3
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (options.UserProperties?.Any() == true)
{
throw new MqttProtocolViolationException("User properties are not supported in MQTT version 3.");
}

var subscribePacket = new MqttSubscribePacket();
subscribePacket.TopicFilters.AddRange(options.TopicFilters);
@@ -186,11 +176,6 @@ namespace MQTTnet.Formatter.V3
{
if (options == null) throw new ArgumentNullException(nameof(options));

if (options.UserProperties?.Any() == true)
{
throw new MqttProtocolViolationException("User properties are not supported in MQTT version 3.");
}

var unsubscribePacket = new MqttUnsubscribePacket();
unsubscribePacket.TopicFilters.AddRange(options.TopicFilters);



+ 1
- 0
Source/MQTTnet/MQTTnet.csproj View File

@@ -42,6 +42,7 @@
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
<PackageReference Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
<PackageReference Include="System.Net.Security" Version="4.3.2" />
<PackageReference Include="System.Net.WebSockets" Version="4.3.0" />
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />


+ 33
- 0
Tests/MQTTnet.Core.Tests/MqttApplicationMessage_Tests.cs View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Extensions;
using MQTTnet.Packets;

namespace MQTTnet.Tests
{
[TestClass]
public class MqttApplicationMessage_Tests
{
[TestMethod]
public void GetUserProperty_Test()
{
var message = new MqttApplicationMessage
{
UserProperties = new List<MqttUserProperty>
{
new MqttUserProperty("foo", "bar"),
new MqttUserProperty("value", "1011"),
new MqttUserProperty("CASE", "insensitive")
}
};

Assert.AreEqual("bar", message.GetUserProperty("foo"));
Assert.AreEqual(1011, message.GetUserProperty<int>("value"));
Assert.AreEqual("insensitive", message.GetUserProperty("case"));
Assert.AreEqual(null, message.GetUserProperty("nonExists"));
Assert.AreEqual(null, message.GetUserProperty<int?>("nonExists"));
Assert.ThrowsException<InvalidOperationException>(() => message.GetUserProperty<int>("nonExists"));
}
}
}

+ 22
- 0
Tests/MQTTnet.Core.Tests/MqttClientOptionsBuilder_Tests.cs View File

@@ -0,0 +1,22 @@
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Client.Options;
using MQTTnet.Extensions;

namespace MQTTnet.Tests
{
[TestClass]
public class MqttClientOptionsBuilder_Tests
{
[TestMethod]
public void WithConnectionUri_Credential_Test()
{
var options = new MqttClientOptionsBuilder()
.WithConnectionUri("mqtt://user:password@127.0.0.1")
.Build();
Assert.AreEqual("user", options.Credentials.Username);
Assert.IsTrue(Encoding.UTF8.GetBytes("password").SequenceEqual(options.Credentials.Password));
}
}
}

Loading…
Cancel
Save