@@ -14,11 +14,12 @@ | |||||
* [Core] Migrated the trace to a non-static approach (Breaking Change!) | * [Core] Migrated the trace to a non-static approach (Breaking Change!) | ||||
* [Core] Added a builder for application messages using a fluent API | * [Core] Added a builder for application messages using a fluent API | ||||
* [Client] Added a first version of a managed client which will manage the connection, subscription etc. automatically (Thanks to @JTrotta) | * [Client] Added a first version of a managed client which will manage the connection, subscription etc. automatically (Thanks to @JTrotta) | ||||
* [Server] Added support for WebSockets via ASP.NET Core 2.0 (Thanks to @ChristianRiedl) | |||||
* [Client] The session state response from the server is now returned in the _ConnectAsync_ method and also part of the _Connected_ event args | * [Client] The session state response from the server is now returned in the _ConnectAsync_ method and also part of the _Connected_ event args | ||||
* [Server] Added support for WebSockets via ASP.NET Core 2.0 (Thanks to @ChristianRiedl) | |||||
* [Server] Added support for a custom application message interceptor | |||||
</releaseNotes> | </releaseNotes> | ||||
<copyright>Copyright Christian Kratky 2016-2017</copyright> | <copyright>Copyright Christian Kratky 2016-2017</copyright> | ||||
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M</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</tags> | |||||
<dependencies> | <dependencies> | ||||
<group targetFramework="netstandard1.3"> | <group targetFramework="netstandard1.3"> | ||||
@@ -6,12 +6,13 @@ namespace MQTTnet.Core.Internal | |||||
{ | { | ||||
public static MqttApplicationMessage ToApplicationMessage(this MqttPublishPacket publishPacket) | public static MqttApplicationMessage ToApplicationMessage(this MqttPublishPacket publishPacket) | ||||
{ | { | ||||
return new MqttApplicationMessage( | |||||
publishPacket.Topic, | |||||
publishPacket.Payload, | |||||
publishPacket.QualityOfServiceLevel, | |||||
publishPacket.Retain | |||||
); | |||||
return new MqttApplicationMessage | |||||
{ | |||||
Topic = publishPacket.Topic, | |||||
Payload = publishPacket.Payload, | |||||
QualityOfServiceLevel = publishPacket.QualityOfServiceLevel, | |||||
Retain = publishPacket.Retain | |||||
}; | |||||
} | } | ||||
public static MqttPublishPacket ToPublishPacket(this MqttApplicationMessage applicationMessage) | public static MqttPublishPacket ToPublishPacket(this MqttApplicationMessage applicationMessage) | ||||
@@ -5,6 +5,11 @@ namespace MQTTnet.Core | |||||
{ | { | ||||
public sealed class MqttApplicationMessage | public sealed class MqttApplicationMessage | ||||
{ | { | ||||
public MqttApplicationMessage() | |||||
{ | |||||
} | |||||
[Obsolete("Use object initializer or _MqttApplicationMessageBuilder_ instead.")] | |||||
public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain) | public MqttApplicationMessage(string topic, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain) | ||||
{ | { | ||||
Topic = topic ?? throw new ArgumentNullException(nameof(topic)); | Topic = topic ?? throw new ArgumentNullException(nameof(topic)); | ||||
@@ -13,12 +18,12 @@ namespace MQTTnet.Core | |||||
Retain = retain; | Retain = retain; | ||||
} | } | ||||
public string Topic { get; } | |||||
public string Topic { get; set; } | |||||
public byte[] Payload { get; } | |||||
public byte[] Payload { get; set; } | |||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; } | |||||
public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; } | |||||
public bool Retain { get; } | |||||
public bool Retain { get; set; } | |||||
} | } | ||||
} | } |
@@ -13,7 +13,7 @@ namespace MQTTnet.Core | |||||
private string _topic; | private string _topic; | ||||
private byte[] _payload; | private byte[] _payload; | ||||
private bool _retain; | private bool _retain; | ||||
public MqttApplicationMessageBuilder WithTopic(string topic) | public MqttApplicationMessageBuilder WithTopic(string topic) | ||||
{ | { | ||||
_topic = topic; | _topic = topic; | ||||
@@ -102,7 +102,13 @@ namespace MQTTnet.Core | |||||
throw new MqttProtocolViolationException("Topic is not set."); | throw new MqttProtocolViolationException("Topic is not set."); | ||||
} | } | ||||
return new MqttApplicationMessage(_topic, _payload ?? new byte[0], _qualityOfServiceLevel, _retain); | |||||
return new MqttApplicationMessage | |||||
{ | |||||
Topic = _topic, | |||||
Payload = _payload ?? new byte[0], | |||||
QualityOfServiceLevel = _qualityOfServiceLevel, | |||||
Retain = _retain | |||||
}; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -65,7 +65,7 @@ namespace MQTTnet.Core.Serializer | |||||
case MqttUnsubscribePacket unsubscribePacket: return Serialize(unsubscribePacket, writer); | case MqttUnsubscribePacket unsubscribePacket: return Serialize(unsubscribePacket, writer); | ||||
case MqttUnsubAckPacket unsubAckPacket: return Serialize(unsubAckPacket, writer); | case MqttUnsubAckPacket unsubAckPacket: return Serialize(unsubAckPacket, writer); | ||||
default: throw new MqttProtocolViolationException("Packet type invalid."); | default: throw new MqttProtocolViolationException("Packet type invalid."); | ||||
} | |||||
} | |||||
} | } | ||||
private static MqttBasePacket Deserialize(MqttPacketHeader header, MqttPacketReader reader) | private static MqttBasePacket Deserialize(MqttPacketHeader header, MqttPacketReader reader) | ||||
@@ -233,11 +233,13 @@ namespace MQTTnet.Core.Serializer | |||||
if (willFlag) | if (willFlag) | ||||
{ | { | ||||
packet.WillMessage = new MqttApplicationMessage( | |||||
reader.ReadStringWithLengthPrefix(), | |||||
reader.ReadWithLengthPrefix(), | |||||
(MqttQualityOfServiceLevel)willQoS, | |||||
willRetain); | |||||
packet.WillMessage = new MqttApplicationMessage | |||||
{ | |||||
Topic = reader.ReadStringWithLengthPrefix(), | |||||
Payload = reader.ReadWithLengthPrefix(), | |||||
QualityOfServiceLevel = (MqttQualityOfServiceLevel)willQoS, | |||||
Retain = willRetain | |||||
}; | |||||
} | } | ||||
if (usernameFlag) | if (usernameFlag) | ||||
@@ -3,15 +3,14 @@ using System.Collections.Generic; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using MQTTnet.Core.Diagnostics; | using MQTTnet.Core.Diagnostics; | ||||
using MQTTnet.Core.Internal; | |||||
using MQTTnet.Core.Packets; | using MQTTnet.Core.Packets; | ||||
namespace MQTTnet.Core.Server | namespace MQTTnet.Core.Server | ||||
{ | { | ||||
public sealed class MqttClientRetainedMessagesManager | public sealed class MqttClientRetainedMessagesManager | ||||
{ | { | ||||
private readonly Dictionary<string, MqttApplicationMessage> _retainedMessages = new Dictionary<string, MqttApplicationMessage>(); | |||||
private readonly MqttNetTrace _trace; | private readonly MqttNetTrace _trace; | ||||
private readonly Dictionary<string, MqttPublishPacket> _retainedMessages = new Dictionary<string, MqttPublishPacket>(); | |||||
private readonly MqttServerOptions _options; | private readonly MqttServerOptions _options; | ||||
public MqttClientRetainedMessagesManager(MqttServerOptions options, MqttNetTrace trace) | public MqttClientRetainedMessagesManager(MqttServerOptions options, MqttNetTrace trace) | ||||
@@ -35,7 +34,7 @@ namespace MQTTnet.Core.Server | |||||
_retainedMessages.Clear(); | _retainedMessages.Clear(); | ||||
foreach (var retainedMessage in retainedMessages) | foreach (var retainedMessage in retainedMessages) | ||||
{ | { | ||||
_retainedMessages[retainedMessage.Topic] = retainedMessage.ToPublishPacket(); | |||||
_retainedMessages[retainedMessage.Topic] = retainedMessage; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -45,25 +44,25 @@ namespace MQTTnet.Core.Server | |||||
} | } | ||||
} | } | ||||
public async Task HandleMessageAsync(string clientId, MqttPublishPacket publishPacket) | |||||
public async Task HandleMessageAsync(string clientId, MqttApplicationMessage applicationMessage) | |||||
{ | { | ||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket)); | |||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage)); | |||||
List<MqttPublishPacket> allRetainedMessages; | |||||
List<MqttApplicationMessage> allRetainedMessages; | |||||
lock (_retainedMessages) | lock (_retainedMessages) | ||||
{ | { | ||||
if (publishPacket.Payload?.Any() == false) | |||||
if (applicationMessage.Payload?.Any() == false) | |||||
{ | { | ||||
_retainedMessages.Remove(publishPacket.Topic); | |||||
_trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' cleared retained message for topic '{1}'.", clientId, publishPacket.Topic); | |||||
_retainedMessages.Remove(applicationMessage.Topic); | |||||
_trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' cleared retained message for topic '{1}'.", clientId, applicationMessage.Topic); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
_retainedMessages[publishPacket.Topic] = publishPacket; | |||||
_trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' updated retained message for topic '{1}'.", clientId, publishPacket.Topic); | |||||
_retainedMessages[applicationMessage.Topic] = applicationMessage; | |||||
_trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' updated retained message for topic '{1}'.", clientId, applicationMessage.Topic); | |||||
} | } | ||||
allRetainedMessages = new List<MqttPublishPacket>(_retainedMessages.Values); | |||||
allRetainedMessages = new List<MqttApplicationMessage>(_retainedMessages.Values); | |||||
} | } | ||||
try | try | ||||
@@ -71,7 +70,7 @@ namespace MQTTnet.Core.Server | |||||
// ReSharper disable once UseNullPropagation | // ReSharper disable once UseNullPropagation | ||||
if (_options.Storage != null) | if (_options.Storage != null) | ||||
{ | { | ||||
await _options.Storage.SaveRetainedMessagesAsync(allRetainedMessages.Select(p => p.ToApplicationMessage()).ToList()); | |||||
await _options.Storage.SaveRetainedMessagesAsync(allRetainedMessages); | |||||
} | } | ||||
} | } | ||||
catch (Exception exception) | catch (Exception exception) | ||||
@@ -80,9 +79,9 @@ namespace MQTTnet.Core.Server | |||||
} | } | ||||
} | } | ||||
public List<MqttPublishPacket> GetMessages(MqttSubscribePacket subscribePacket) | |||||
public List<MqttApplicationMessage> GetMessages(MqttSubscribePacket subscribePacket) | |||||
{ | { | ||||
var retainedMessages = new List<MqttPublishPacket>(); | |||||
var retainedMessages = new List<MqttApplicationMessage>(); | |||||
lock (_retainedMessages) | lock (_retainedMessages) | ||||
{ | { | ||||
foreach (var retainedMessage in _retainedMessages.Values) | foreach (var retainedMessage in _retainedMessages.Values) | ||||
@@ -72,7 +72,7 @@ namespace MQTTnet.Core.Server | |||||
{ | { | ||||
if (_willMessage != null) | if (_willMessage != null) | ||||
{ | { | ||||
_mqttClientSessionsManager.DispatchPublishPacket(this, _willMessage.ToPublishPacket()); | |||||
_mqttClientSessionsManager.DispatchApplicationMessage(this, _willMessage); | |||||
} | } | ||||
_cancellationTokenSource?.Cancel(false); | _cancellationTokenSource?.Cancel(false); | ||||
@@ -175,27 +175,30 @@ namespace MQTTnet.Core.Server | |||||
var retainedMessages = _mqttClientSessionsManager.RetainedMessagesManager.GetMessages(subscribePacket); | var retainedMessages = _mqttClientSessionsManager.RetainedMessagesManager.GetMessages(subscribePacket); | ||||
foreach (var publishPacket in retainedMessages) | foreach (var publishPacket in retainedMessages) | ||||
{ | { | ||||
EnqueuePublishPacket(publishPacket); | |||||
EnqueuePublishPacket(publishPacket.ToPublishPacket()); | |||||
} | } | ||||
} | } | ||||
private async Task HandleIncomingPublishPacketAsync(IMqttCommunicationAdapter adapter, MqttPublishPacket publishPacket) | private async Task HandleIncomingPublishPacketAsync(IMqttCommunicationAdapter adapter, MqttPublishPacket publishPacket) | ||||
{ | { | ||||
if (publishPacket.Retain) | |||||
var applicationMessage = publishPacket.ToApplicationMessage(); | |||||
_options.ApplicationMessageInterceptor?.Invoke(applicationMessage); | |||||
if (applicationMessage.Retain) | |||||
{ | { | ||||
await _mqttClientSessionsManager.RetainedMessagesManager.HandleMessageAsync(ClientId, publishPacket); | |||||
await _mqttClientSessionsManager.RetainedMessagesManager.HandleMessageAsync(ClientId, applicationMessage); | |||||
} | } | ||||
switch (publishPacket.QualityOfServiceLevel) | |||||
switch (applicationMessage.QualityOfServiceLevel) | |||||
{ | { | ||||
case MqttQualityOfServiceLevel.AtMostOnce: | case MqttQualityOfServiceLevel.AtMostOnce: | ||||
{ | { | ||||
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket); | |||||
_mqttClientSessionsManager.DispatchApplicationMessage(this, applicationMessage); | |||||
return; | return; | ||||
} | } | ||||
case MqttQualityOfServiceLevel.AtLeastOnce: | case MqttQualityOfServiceLevel.AtLeastOnce: | ||||
{ | { | ||||
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket); | |||||
_mqttClientSessionsManager.DispatchApplicationMessage(this, applicationMessage); | |||||
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, | await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, | ||||
new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier }); | new MqttPubAckPacket { PacketIdentifier = publishPacket.PacketIdentifier }); | ||||
@@ -210,7 +213,7 @@ namespace MQTTnet.Core.Server | |||||
_unacknowledgedPublishPackets.Add(publishPacket.PacketIdentifier); | _unacknowledgedPublishPackets.Add(publishPacket.PacketIdentifier); | ||||
} | } | ||||
_mqttClientSessionsManager.DispatchPublishPacket(this, publishPacket); | |||||
_mqttClientSessionsManager.DispatchApplicationMessage(this, applicationMessage); | |||||
await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, | await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, | ||||
new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }); | new MqttPubRecPacket { PacketIdentifier = publishPacket.PacketIdentifier }); | ||||
@@ -117,11 +117,11 @@ namespace MQTTnet.Core.Server | |||||
} | } | ||||
} | } | ||||
public void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket) | |||||
public void DispatchApplicationMessage(MqttClientSession senderClientSession, MqttApplicationMessage applicationMessage) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientSession?.ClientId, publishPacket.ToApplicationMessage()); | |||||
var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientSession?.ClientId, applicationMessage); | |||||
ApplicationMessageReceived?.Invoke(this, eventArgs); | ApplicationMessageReceived?.Invoke(this, eventArgs); | ||||
} | } | ||||
catch (Exception exception) | catch (Exception exception) | ||||
@@ -133,7 +133,7 @@ namespace MQTTnet.Core.Server | |||||
{ | { | ||||
foreach (var clientSession in _clientSessions.Values.ToList()) | foreach (var clientSession in _clientSessions.Values.ToList()) | ||||
{ | { | ||||
clientSession.EnqueuePublishPacket(publishPacket); | |||||
clientSession.EnqueuePublishPacket(applicationMessage.ToPublishPacket()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -4,7 +4,6 @@ using System.Threading; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using MQTTnet.Core.Adapter; | using MQTTnet.Core.Adapter; | ||||
using MQTTnet.Core.Diagnostics; | using MQTTnet.Core.Diagnostics; | ||||
using MQTTnet.Core.Internal; | |||||
namespace MQTTnet.Core.Server | namespace MQTTnet.Core.Server | ||||
{ | { | ||||
@@ -42,7 +41,8 @@ namespace MQTTnet.Core.Server | |||||
{ | { | ||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage)); | if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage)); | ||||
_clientSessionsManager.DispatchPublishPacket(null, applicationMessage.ToPublishPacket()); | |||||
_options.ApplicationMessageInterceptor?.Invoke(applicationMessage); | |||||
_clientSessionsManager.DispatchApplicationMessage(null, applicationMessage); | |||||
} | } | ||||
public async Task StartAsync() | public async Task StartAsync() | ||||
@@ -16,6 +16,8 @@ namespace MQTTnet.Core.Server | |||||
public Func<MqttConnectPacket, MqttConnectReturnCode> ConnectionValidator { get; set; } | public Func<MqttConnectPacket, MqttConnectReturnCode> ConnectionValidator { get; set; } | ||||
public Action<MqttApplicationMessage> ApplicationMessageInterceptor { get; set; } | |||||
public IMqttServerStorage Storage { get; set; } | public IMqttServerStorage Storage { get; set; } | ||||
} | } | ||||
} | } |
@@ -36,6 +36,7 @@ MQTTnet is a high performance .NET library for MQTT based communication. It prov | |||||
* Extensible client credential validation | * Extensible client credential validation | ||||
* Retained messages are supported including persisting via interface methods (own implementation required) | * Retained messages are supported including persisting via interface methods (own implementation required) | ||||
* WebSockets supported (via ASP.NET Core 2.0) | * WebSockets supported (via ASP.NET Core 2.0) | ||||
* A custom message interceptor can be added which allows transforming or extending every received application message | |||||
# Supported frameworks | # Supported frameworks | ||||
* .NET Standard 1.3+ | * .NET Standard 1.3+ | ||||
@@ -53,11 +53,13 @@ namespace MQTTnet.Core.Tests | |||||
Username = "USER", | Username = "USER", | ||||
KeepAlivePeriod = 123, | KeepAlivePeriod = 123, | ||||
CleanSession = true, | CleanSession = true, | ||||
WillMessage = new MqttApplicationMessage( | |||||
"My/last/will", | |||||
Encoding.UTF8.GetBytes("Good byte."), | |||||
MqttQualityOfServiceLevel.AtLeastOnce, | |||||
true) | |||||
WillMessage = new MqttApplicationMessage | |||||
{ | |||||
Topic = "My/last/will", | |||||
Payload = Encoding.UTF8.GetBytes("Good byte."), | |||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce, | |||||
Retain = true | |||||
} | |||||
}; | }; | ||||
SerializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw=="); | SerializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw=="); | ||||
@@ -88,11 +90,13 @@ namespace MQTTnet.Core.Tests | |||||
Username = "USER", | Username = "USER", | ||||
KeepAlivePeriod = 123, | KeepAlivePeriod = 123, | ||||
CleanSession = true, | CleanSession = true, | ||||
WillMessage = new MqttApplicationMessage( | |||||
"My/last/will", | |||||
Encoding.UTF8.GetBytes("Good byte."), | |||||
MqttQualityOfServiceLevel.AtLeastOnce, | |||||
true) | |||||
WillMessage = new MqttApplicationMessage | |||||
{ | |||||
Topic = "My/last/will", | |||||
Payload = Encoding.UTF8.GetBytes("Good byte."), | |||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce, | |||||
Retain = true | |||||
} | |||||
}; | }; | ||||
DeserializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw=="); | DeserializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw=="); | ||||
@@ -151,12 +151,12 @@ namespace MQTTnet.TestApp.NetCore | |||||
private static MqttApplicationMessage CreateMessage() | private static MqttApplicationMessage CreateMessage() | ||||
{ | { | ||||
return new MqttApplicationMessage( | |||||
"A/B/C", | |||||
Encoding.UTF8.GetBytes("Hello World"), | |||||
MqttQualityOfServiceLevel.AtMostOnce, | |||||
false | |||||
); | |||||
return new MqttApplicationMessage | |||||
{ | |||||
Topic = "A/B/C", | |||||
Payload = Encoding.UTF8.GetBytes("Hello World"), | |||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce | |||||
}; | |||||
} | } | ||||
private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count) | private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count) | ||||
@@ -32,7 +32,7 @@ namespace MQTTnet.TestApp.NetCore | |||||
} | } | ||||
else if (pressedKey.KeyChar == '2') | else if (pressedKey.KeyChar == '2') | ||||
{ | { | ||||
Task.Run(RunServerAsync); | |||||
Task.Run(ServerTest.RunAsync); | |||||
} | } | ||||
else if (pressedKey.KeyChar == '3') | else if (pressedKey.KeyChar == '3') | ||||
{ | { | ||||
@@ -119,12 +119,12 @@ namespace MQTTnet.TestApp.NetCore | |||||
{ | { | ||||
Console.ReadLine(); | Console.ReadLine(); | ||||
var applicationMessage = new MqttApplicationMessage( | |||||
"A/B/C", | |||||
Encoding.UTF8.GetBytes("Hello World"), | |||||
MqttQualityOfServiceLevel.AtLeastOnce, | |||||
false | |||||
); | |||||
var applicationMessage = new MqttApplicationMessage | |||||
{ | |||||
Topic = "A/B/C", | |||||
Payload = Encoding.UTF8.GetBytes("Hello World"), | |||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce | |||||
}; | |||||
await client.PublishAsync(applicationMessage); | await client.PublishAsync(applicationMessage); | ||||
} | } | ||||
@@ -135,66 +135,6 @@ namespace MQTTnet.TestApp.NetCore | |||||
} | } | ||||
} | } | ||||
private static Task RunServerAsync() | |||||
{ | |||||
MqttNetTrace.TraceMessagePublished += (s, e) => | |||||
{ | |||||
Console.WriteLine($">> [{e.TraceMessage.Timestamp:O}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}"); | |||||
if (e.TraceMessage.Exception != null) | |||||
{ | |||||
Console.WriteLine(e.TraceMessage.Exception); | |||||
} | |||||
}; | |||||
try | |||||
{ | |||||
var options = new MqttServerOptions | |||||
{ | |||||
ConnectionValidator = p => | |||||
{ | |||||
if (p.ClientId == "SpecialClient") | |||||
{ | |||||
if (p.Username != "USER" || p.Password != "PASS") | |||||
{ | |||||
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword; | |||||
} | |||||
} | |||||
return MqttConnectReturnCode.ConnectionAccepted; | |||||
} | |||||
}; | |||||
options.Storage = new RetainedMessageHandler(); | |||||
//var certificate = new X509Certificate(@"C:\certs\test\test.cer", ""); | |||||
//options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); | |||||
//options.ConnectionBacklog = 5; | |||||
//options.DefaultEndpointOptions.IsEnabled = true; | |||||
//options.TlsEndpointOptions.IsEnabled = false; | |||||
var mqttServer = new MqttServerFactory().CreateMqttServer(options); | |||||
mqttServer.ClientDisconnected += (s, e) => | |||||
{ | |||||
Console.Write("Client disconnected event fired."); | |||||
}; | |||||
mqttServer.StartAsync(); | |||||
Console.WriteLine("Press any key to exit."); | |||||
Console.ReadLine(); | |||||
mqttServer.StopAsync(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
} | |||||
Console.ReadLine(); | |||||
return Task.FromResult(0); | |||||
} | |||||
// ReSharper disable once UnusedMember.Local | // ReSharper disable once UnusedMember.Local | ||||
private static async void WikiCode() | private static async void WikiCode() | ||||
{ | { | ||||
@@ -0,0 +1,81 @@ | |||||
using System; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using MQTTnet.Core.Diagnostics; | |||||
using MQTTnet.Core.Protocol; | |||||
using MQTTnet.Core.Server; | |||||
namespace MQTTnet.TestApp.NetCore | |||||
{ | |||||
public static class ServerTest | |||||
{ | |||||
public static Task RunAsync() | |||||
{ | |||||
MqttNetTrace.TraceMessagePublished += (s, e) => | |||||
{ | |||||
Console.WriteLine($">> [{e.TraceMessage.Timestamp:O}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}"); | |||||
if (e.TraceMessage.Exception != null) | |||||
{ | |||||
Console.WriteLine(e.TraceMessage.Exception); | |||||
} | |||||
}; | |||||
try | |||||
{ | |||||
var options = new MqttServerOptions | |||||
{ | |||||
ConnectionValidator = p => | |||||
{ | |||||
if (p.ClientId == "SpecialClient") | |||||
{ | |||||
if (p.Username != "USER" || p.Password != "PASS") | |||||
{ | |||||
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword; | |||||
} | |||||
} | |||||
return MqttConnectReturnCode.ConnectionAccepted; | |||||
} | |||||
}; | |||||
options.Storage = new RetainedMessageHandler(); | |||||
options.ApplicationMessageInterceptor = message => | |||||
{ | |||||
if (MqttTopicFilterComparer.IsMatch(message.Topic, "/myTopic/WithTimestamp/#")) | |||||
{ | |||||
// Replace the payload with the timestamp. But also extending a JSON | |||||
// based payload with the timestamp is a suitable use case. | |||||
message.Payload = Encoding.UTF8.GetBytes(DateTime.Now.ToString("O")); | |||||
} | |||||
}; | |||||
//var certificate = new X509Certificate(@"C:\certs\test\test.cer", ""); | |||||
//options.TlsEndpointOptions.Certificate = certificate.Export(X509ContentType.Cert); | |||||
//options.ConnectionBacklog = 5; | |||||
//options.DefaultEndpointOptions.IsEnabled = true; | |||||
//options.TlsEndpointOptions.IsEnabled = false; | |||||
var mqttServer = new MqttServerFactory().CreateMqttServer(options); | |||||
mqttServer.ClientDisconnected += (s, e) => | |||||
{ | |||||
Console.Write("Client disconnected event fired."); | |||||
}; | |||||
mqttServer.StartAsync(); | |||||
Console.WriteLine("Press any key to exit."); | |||||
Console.ReadLine(); | |||||
mqttServer.StopAsync(); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
} | |||||
Console.ReadLine(); | |||||
return Task.FromResult(0); | |||||
} | |||||
} | |||||
} |
@@ -119,11 +119,12 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
payload = Convert.FromBase64String(Payload.Text); | payload = Convert.FromBase64String(Payload.Text); | ||||
} | } | ||||
var message = new MqttApplicationMessage( | |||||
Topic.Text, | |||||
payload, | |||||
qos, | |||||
Retain.IsChecked == true); | |||||
var message = new MqttApplicationMessageBuilder() | |||||
.WithTopic(Topic.Text) | |||||
.WithPayload(payload) | |||||
.WithQualityOfServiceLevel(qos) | |||||
.WithRetainFlag(Retain.IsChecked == true) | |||||
.Build(); | |||||
await _mqttClient.PublishAsync(message); | await _mqttClient.PublishAsync(message); | ||||
} | } | ||||