@@ -0,0 +1,42 @@ | |||||
<?xml version="1.0"?> | |||||
<package > | |||||
<metadata> | |||||
<id>MQTTnet.Extensions.WebSocket4Net</id> | |||||
<version>0.0.0</version> | |||||
<authors>Christian Kratky</authors> | |||||
<owners>Christian Kratky</owners> | |||||
<license type="file">LICENSE</license> | |||||
<projectUrl>https://github.com/chkr1011/MQTTnet</projectUrl> | |||||
<iconUrl>https://raw.githubusercontent.com/chkr1011/MQTTnet/master/Images/Logo_128x128.png</iconUrl> | |||||
<requireLicenseAcceptance>false</requireLicenseAcceptance> | |||||
<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> | |||||
<copyright>Copyright Christian Kratky 2016-2019</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</tags> | |||||
<dependencies> | |||||
<dependency id="MQTTnet" version="$nugetVersion" /> | |||||
</dependencies> | |||||
</metadata> | |||||
<files> | |||||
<!-- License --> | |||||
<file src="..\LICENSE" /> | |||||
<!-- .NET Standard 1.3 --> | |||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard1.3\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard1.3\"/> | |||||
<!-- .NET Standard 2.0 --> | |||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\netstandard2.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\netstandard2.0\"/> | |||||
<!-- Universal Windows --> | |||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\uap10.0\MQTTnet.Extensions.WebSocket4Net.*" target="lib\uap10.0\"/> | |||||
<!-- .NET Framework --> | |||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net452\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net452\"/> | |||||
<!-- .NET Framework 4.6.0 will use binaries from 4.5.2. --> | |||||
<file src="..\Source\MQTTnet.Extensions.WebSocket4Net\bin\Release\net461\MQTTnet.Extensions.WebSocket4Net.*" target="lib\net461\"/> | |||||
<!-- Everything above .NET Framework 4.6.1 will use the binaries from 4.6.1. --> | |||||
</files> | |||||
</package> |
@@ -12,6 +12,7 @@ | |||||
<description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description> | <description>MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker).</description> | ||||
<releaseNotes> | <releaseNotes> | ||||
* [Core] Fixed issues in MQTTv5 message encoding and decoding. | * [Core] Fixed issues in MQTTv5 message encoding and decoding. | ||||
* [Core] Added extension method to allow usage of _WebSocket4Net_ in clients to fix issues with AWS and Xamarin. | |||||
* [Client] Added support for extended authentication exchange. | * [Client] Added support for extended authentication exchange. | ||||
* [Client] Exposed MQTTv5 CONNACK values to client. | * [Client] Exposed MQTTv5 CONNACK values to client. | ||||
* [Client] Added _MqttClientSubscribeOptionsBuilder_. | * [Client] Added _MqttClientSubscribeOptionsBuilder_. | ||||
@@ -36,6 +36,14 @@ Write-Host | |||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | &$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | ||||
&$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | &$msbuild ..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | ||||
# Build the WebSocket4Net extension | |||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net452" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | |||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="net461" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | |||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard1.3" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | |||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netstandard2.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | |||||
&$msbuild ..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="uap10.0" /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | |||||
# Build MQTTnet.Server | # Build MQTTnet.Server | ||||
Remove-Item ..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2 -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item ..\Source\MQTTnet.Server\bin\Release\netcoreapp2.2 -Recurse -Force -ErrorAction SilentlyContinue | ||||
&$msbuild ..\Source\MQTTnet.Server\MQTTnet.Server.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp2.2" /p:publishprofile=FolderProfile /p:deployonbuild=true /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | &$msbuild ..\Source\MQTTnet.Server\MQTTnet.Server.csproj /t:Build /p:Configuration="Release" /p:TargetFramework="netcoreapp2.2" /p:publishprofile=FolderProfile /p:deployonbuild=true /p:FileVersion=$assemblyVersion /p:AssemblyVersion=$assemblyVersion /verbosity:m /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=".\..\..\Build\codeSigningKey.pfx" | ||||
@@ -55,6 +63,8 @@ Copy-Item MQTTnet.Extensions.Rpc.nuspec -Destination MQTTnet.Extensions.Rpc.nusp | |||||
(Get-Content MQTTnet.Extensions.Rpc.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.Rpc.nuspec | (Get-Content MQTTnet.Extensions.Rpc.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.Rpc.nuspec | ||||
Copy-Item MQTTnet.Extensions.ManagedClient.nuspec -Destination MQTTnet.Extensions.ManagedClient.nuspec.old -Force | Copy-Item MQTTnet.Extensions.ManagedClient.nuspec -Destination MQTTnet.Extensions.ManagedClient.nuspec.old -Force | ||||
(Get-Content MQTTnet.Extensions.ManagedClient.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.ManagedClient.nuspec | (Get-Content MQTTnet.Extensions.ManagedClient.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.ManagedClient.nuspec | ||||
Copy-Item MQTTnet.Extensions.WebSocket4Net.nuspec -Destination MQTTnet.Extensions.WebSocket4Net.nuspec.old -Force | |||||
(Get-Content MQTTnet.Extensions.WebSocket4Net.nuspec) -replace '\$nugetVersion', $nugetVersion | Set-Content MQTTnet.Extensions.WebSocket4Net.nuspec | |||||
New-Item -ItemType Directory -Force -Path .\NuGet | New-Item -ItemType Directory -Force -Path .\NuGet | ||||
.\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | .\nuget.exe pack MQTTnet.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | ||||
@@ -62,7 +72,9 @@ New-Item -ItemType Directory -Force -Path .\NuGet | |||||
.\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | .\nuget.exe pack MQTTnet.AspNetCore.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | ||||
.\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | .\nuget.exe pack MQTTnet.Extensions.Rpc.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | ||||
.\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | .\nuget.exe pack MQTTnet.Extensions.ManagedClient.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | ||||
.\nuget.exe pack MQTTnet.Extensions.WebSocket4Net.nuspec -Verbosity detailed -Symbols -OutputDir "NuGet" -Version $nugetVersion | |||||
Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force | Move-Item MQTTnet.AspNetCore.nuspec.old -Destination MQTTnet.AspNetCore.nuspec -Force | ||||
Move-Item MQTTnet.Extensions.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force | Move-Item MQTTnet.Extensions.Rpc.nuspec.old -Destination MQTTnet.Extensions.Rpc.nuspec -Force | ||||
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force | |||||
Move-Item MQTTnet.Extensions.ManagedClient.nuspec.old -Destination MQTTnet.Extensions.ManagedClient.nuspec -Force | |||||
Move-Item MQTTnet.Extensions.WebSocket4Net.nuspec.old -Destination MQTTnet.Extensions.WebSocket4Net.nuspec -Force |
@@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{67C28AC1 | |||||
Build\MQTTnet.AspNetCore.nuspec = Build\MQTTnet.AspNetCore.nuspec | Build\MQTTnet.AspNetCore.nuspec = Build\MQTTnet.AspNetCore.nuspec | ||||
Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec | Build\MQTTnet.Extensions.ManagedClient.nuspec = Build\MQTTnet.Extensions.ManagedClient.nuspec | ||||
Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec | Build\MQTTnet.Extensions.Rpc.nuspec = Build\MQTTnet.Extensions.Rpc.nuspec | ||||
Build\MQTTnet.Extensions.WebSocket4Net.nuspec = Build\MQTTnet.Extensions.WebSocket4Net.nuspec | |||||
Build\MQTTnet.NETStandard.nuspec = Build\MQTTnet.NETStandard.nuspec | Build\MQTTnet.NETStandard.nuspec = Build\MQTTnet.NETStandard.nuspec | ||||
Build\MQTTnet.nuspec = Build\MQTTnet.nuspec | Build\MQTTnet.nuspec = Build\MQTTnet.nuspec | ||||
Build\upload.ps1 = Build\upload.ps1 | Build\upload.ps1 = Build\upload.ps1 | ||||
@@ -50,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.AspNetCore.Tests", | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQTTnet.Server\MQTTnet.Server.csproj", "{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Server", "Source\MQTTnet.Server\MQTTnet.Server.csproj", "{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.Extensions.WebSocket4Net", "Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj", "{2BD01D53-4CA5-4142-BE8D-313876395E3E}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
@@ -245,6 +248,22 @@ Global | |||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x64.Build.0 = Release|Any CPU | {5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x64.Build.0 = Release|Any CPU | ||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.ActiveCfg = Release|Any CPU | {5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.ActiveCfg = Release|Any CPU | ||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.Build.0 = Release|Any CPU | {5699FB8C-838C-4AB0-80A5-9CA809F9B65B}.Release|x86.Build.0 = Release|Any CPU | ||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|ARM.ActiveCfg = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|ARM.Build.0 = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x64.ActiveCfg = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x64.Build.0 = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x86.ActiveCfg = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Debug|x86.Build.0 = Debug|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|ARM.ActiveCfg = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|ARM.Build.0 = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.ActiveCfg = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x64.Build.0 = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.ActiveCfg = Release|Any CPU | |||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E}.Release|x86.Build.0 = Release|Any CPU | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
@@ -261,6 +280,7 @@ Global | |||||
{C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587} | {C400533A-8EBA-4F0B-BF4D-295C3708604B} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587} | ||||
{61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4} | {61B62223-F5D0-48E4-BBD6-2CBA9353CB5E} = {9248C2E1-B9D6-40BF-81EC-86004D7765B4} | ||||
{5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {32A630A7-2598-41D7-B625-204CD906F5FB} | {5699FB8C-838C-4AB0-80A5-9CA809F9B65B} = {32A630A7-2598-41D7-B625-204CD906F5FB} | ||||
{2BD01D53-4CA5-4142-BE8D-313876395E3E} = {12816BCC-AF9E-44A9-9AE5-C246AF2A0587} | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(ExtensibilityGlobals) = postSolution | GlobalSection(ExtensibilityGlobals) = postSolution | ||||
SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894} | SolutionGuid = {07536672-5CBC-4BE3-ACE0-708A431A7894} | ||||
@@ -0,0 +1,34 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks> | |||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks> | |||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core'">$(TargetFrameworks);uap10.0</TargetFrameworks> | |||||
<Product /> | |||||
<Company /> | |||||
<Authors /> | |||||
<PackageId /> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0'"> | |||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies> | |||||
<NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker> | |||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier> | |||||
<TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion> | |||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion> | |||||
<TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier> | |||||
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion> | |||||
<DefineConstants>$(DefineConstants);WINDOWS_UWP</DefineConstants> | |||||
<DefaultLanguage>en</DefaultLanguage> | |||||
<LanguageTargets>$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets</LanguageTargets> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="WebSocket4Net" Version="0.15.2" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\MQTTnet\MQTTnet.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,14 @@ | |||||
using System; | |||||
namespace MQTTnet.Extensions.WebSocket4Net | |||||
{ | |||||
public static class MqttFactoryExtensions | |||||
{ | |||||
public static IMqttFactory UseWebSocket4Net(this IMqttFactory mqttFactory) | |||||
{ | |||||
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory)); | |||||
return mqttFactory.UseClientAdapterFactory(new WebSocket4NetMqttClientAdapterFactory()); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,231 @@ | |||||
using System; | |||||
using System.Collections.Concurrent; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Net; | |||||
using System.Security.Authentication; | |||||
using System.Security.Cryptography.X509Certificates; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using MQTTnet.Channel; | |||||
using MQTTnet.Client.Options; | |||||
using MQTTnet.Exceptions; | |||||
using MQTTnet.Internal; | |||||
using SuperSocket.ClientEngine; | |||||
using WebSocket4Net; | |||||
namespace MQTTnet.Extensions.WebSocket4Net | |||||
{ | |||||
public class WebSocket4NetMqttChannel : IMqttChannel | |||||
{ | |||||
private readonly BlockingCollection<byte> _receiveBuffer = new BlockingCollection<byte>(); | |||||
private readonly IMqttClientOptions _clientOptions; | |||||
private readonly MqttClientWebSocketOptions _webSocketOptions; | |||||
private WebSocket _webSocket; | |||||
public WebSocket4NetMqttChannel(IMqttClientOptions clientOptions, MqttClientWebSocketOptions webSocketOptions) | |||||
{ | |||||
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); | |||||
_webSocketOptions = webSocketOptions ?? throw new ArgumentNullException(nameof(webSocketOptions)); | |||||
} | |||||
public string Endpoint => _webSocketOptions.Uri; | |||||
public bool IsSecureConnection { get; private set; } | |||||
public async Task ConnectAsync(CancellationToken cancellationToken) | |||||
{ | |||||
var uri = _webSocketOptions.Uri; | |||||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase) && !uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase)) | |||||
{ | |||||
if (_webSocketOptions.TlsOptions?.UseTls == false) | |||||
{ | |||||
uri = "ws://" + uri; | |||||
} | |||||
else | |||||
{ | |||||
uri = "wss://" + uri; | |||||
} | |||||
} | |||||
var sslProtocols = _webSocketOptions?.TlsOptions?.SslProtocol ?? SslProtocols.None; | |||||
var subProtocol = _webSocketOptions.SubProtocols.FirstOrDefault() ?? string.Empty; | |||||
var cookies = new List<KeyValuePair<string, string>>(); | |||||
if (_webSocketOptions.CookieContainer != null) | |||||
{ | |||||
throw new NotSupportedException("Cookies are not supported."); | |||||
} | |||||
List<KeyValuePair<string, string>> customHeaders = null; | |||||
if (_webSocketOptions.RequestHeaders != null) | |||||
{ | |||||
customHeaders = _webSocketOptions.RequestHeaders.Select(i => new KeyValuePair<string, string>(i.Key, i.Value)).ToList(); | |||||
} | |||||
EndPoint proxy = null; | |||||
if (_webSocketOptions.ProxyOptions != null) | |||||
{ | |||||
throw new NotSupportedException("Proxies are not supported."); | |||||
} | |||||
// The user agent can be empty always because it is just added to the custom headers as "User-Agent". | |||||
var userAgent = string.Empty; | |||||
var origin = string.Empty; | |||||
var webSocketVersion = WebSocketVersion.None; | |||||
var receiveBufferSize = 0; | |||||
var certificates = new X509CertificateCollection(); | |||||
if (_webSocketOptions?.TlsOptions?.Certificates != null) | |||||
{ | |||||
foreach (var certificate in _webSocketOptions.TlsOptions.Certificates) | |||||
{ | |||||
certificates.Add(new X509Certificate(certificate)); | |||||
} | |||||
} | |||||
_webSocket = new WebSocket(uri, subProtocol, cookies, customHeaders, userAgent, origin, webSocketVersion, proxy, sslProtocols, receiveBufferSize) | |||||
{ | |||||
NoDelay = true, | |||||
Security = | |||||
{ | |||||
AllowUnstrustedCertificate = _webSocketOptions?.TlsOptions?.AllowUntrustedCertificates == true, | |||||
AllowCertificateChainErrors = _webSocketOptions?.TlsOptions?.IgnoreCertificateChainErrors == true, | |||||
Certificates = certificates | |||||
} | |||||
}; | |||||
await ConnectInternalAsync(cancellationToken).ConfigureAwait(false); | |||||
IsSecureConnection = uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase); | |||||
} | |||||
public Task DisconnectAsync(CancellationToken cancellationToken) | |||||
{ | |||||
if (_webSocket != null && _webSocket.State == WebSocketState.Open) | |||||
{ | |||||
_webSocket.Close(); | |||||
} | |||||
return Task.FromResult(0); | |||||
} | |||||
public Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |||||
{ | |||||
var readBytes = 0; | |||||
while (count > 0 && !cancellationToken.IsCancellationRequested) | |||||
{ | |||||
if (!_receiveBuffer.TryTake(out var @byte)) | |||||
{ | |||||
if (readBytes == 0) | |||||
{ | |||||
// Block until at least one byte was received. | |||||
@byte = _receiveBuffer.Take(cancellationToken); | |||||
} | |||||
else | |||||
{ | |||||
return Task.FromResult(readBytes); | |||||
} | |||||
} | |||||
buffer[offset] = @byte; | |||||
offset++; | |||||
count--; | |||||
readBytes++; | |||||
} | |||||
return Task.FromResult(readBytes); | |||||
} | |||||
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |||||
{ | |||||
_webSocket.Send(buffer, offset, count); | |||||
return Task.FromResult(0); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
if (_webSocket == null) | |||||
{ | |||||
return; | |||||
} | |||||
_webSocket.DataReceived -= OnDataReceived; | |||||
_webSocket.Error -= OnError; | |||||
_webSocket.Dispose(); | |||||
_webSocket = null; | |||||
} | |||||
private void OnError(object sender, ErrorEventArgs e) | |||||
{ | |||||
System.Diagnostics.Debug.Write(e.Exception.ToString()); | |||||
} | |||||
private void OnDataReceived(object sender, DataReceivedEventArgs e) | |||||
{ | |||||
foreach (var @byte in e.Data) | |||||
{ | |||||
_receiveBuffer.Add(@byte); | |||||
} | |||||
} | |||||
private async Task ConnectInternalAsync(CancellationToken cancellationToken) | |||||
{ | |||||
_webSocket.Error += OnError; | |||||
_webSocket.DataReceived += OnDataReceived; | |||||
var taskCompletionSource = new TaskCompletionSource<Exception>(); | |||||
void ErrorHandler(object sender, ErrorEventArgs e) | |||||
{ | |||||
taskCompletionSource.TrySetResult(e.Exception); | |||||
} | |||||
void SuccessHandler(object sender, EventArgs e) | |||||
{ | |||||
taskCompletionSource.TrySetResult(null); | |||||
} | |||||
try | |||||
{ | |||||
_webSocket.Opened += SuccessHandler; | |||||
_webSocket.Error += ErrorHandler; | |||||
_webSocket.Open(); | |||||
var exception = await MqttTaskTimeout.WaitAsync(c => | |||||
{ | |||||
c.Register(() => taskCompletionSource.TrySetCanceled()); | |||||
return taskCompletionSource.Task; | |||||
}, _clientOptions.CommunicationTimeout, cancellationToken).ConfigureAwait(false); | |||||
if (exception != null) | |||||
{ | |||||
if (exception is AuthenticationException authenticationException) | |||||
{ | |||||
throw new MqttCommunicationException(authenticationException.InnerException); | |||||
} | |||||
if (exception is OperationCanceledException) | |||||
{ | |||||
throw new MqttCommunicationTimedOutException(); | |||||
} | |||||
throw new MqttCommunicationException(exception); | |||||
} | |||||
} | |||||
catch (OperationCanceledException) | |||||
{ | |||||
throw new MqttCommunicationTimedOutException(); | |||||
} | |||||
finally | |||||
{ | |||||
_webSocket.Opened -= SuccessHandler; | |||||
_webSocket.Error -= ErrorHandler; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,36 @@ | |||||
using System; | |||||
using MQTTnet.Adapter; | |||||
using MQTTnet.Client.Options; | |||||
using MQTTnet.Diagnostics; | |||||
using MQTTnet.Formatter; | |||||
using MQTTnet.Implementations; | |||||
namespace MQTTnet.Extensions.WebSocket4Net | |||||
{ | |||||
public class WebSocket4NetMqttClientAdapterFactory : IMqttClientAdapterFactory | |||||
{ | |||||
public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options, IMqttNetChildLogger logger) | |||||
{ | |||||
if (options == null) throw new ArgumentNullException(nameof(options)); | |||||
if (logger == null) throw new ArgumentNullException(nameof(logger)); | |||||
switch (options.ChannelOptions) | |||||
{ | |||||
case MqttClientTcpOptions _: | |||||
{ | |||||
return new MqttChannelAdapter(new MqttTcpChannel(options), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger); | |||||
} | |||||
case MqttClientWebSocketOptions webSocketOptions: | |||||
{ | |||||
return new MqttChannelAdapter(new WebSocket4NetMqttChannel(options, webSocketOptions), new MqttPacketFormatterAdapter(options.ProtocolVersion), logger); | |||||
} | |||||
default: | |||||
{ | |||||
throw new NotSupportedException(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -5,6 +5,8 @@ namespace MQTTnet.Client | |||||
{ | { | ||||
public interface IMqttClientFactory | public interface IMqttClientFactory | ||||
{ | { | ||||
IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory); | |||||
IMqttClient CreateMqttClient(); | IMqttClient CreateMqttClient(); | ||||
IMqttClient CreateMqttClient(IMqttNetLogger logger); | IMqttClient CreateMqttClient(IMqttNetLogger logger); | ||||
@@ -10,6 +10,8 @@ namespace MQTTnet | |||||
{ | { | ||||
public class MqttFactory : IMqttFactory | public class MqttFactory : IMqttFactory | ||||
{ | { | ||||
private IMqttClientAdapterFactory _clientAdapterFactory = new MqttClientAdapterFactory(); | |||||
public MqttFactory() : this(new MqttNetLogger()) | public MqttFactory() : this(new MqttNetLogger()) | ||||
{ | { | ||||
} | } | ||||
@@ -21,6 +23,12 @@ namespace MQTTnet | |||||
public IMqttNetLogger DefaultLogger { get; } | public IMqttNetLogger DefaultLogger { get; } | ||||
public IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory) | |||||
{ | |||||
_clientAdapterFactory = clientAdapterFactory ?? throw new ArgumentNullException(nameof(clientAdapterFactory)); | |||||
return this; | |||||
} | |||||
public IMqttClient CreateMqttClient() | public IMqttClient CreateMqttClient() | ||||
{ | { | ||||
return CreateMqttClient(DefaultLogger); | return CreateMqttClient(DefaultLogger); | ||||
@@ -30,22 +38,22 @@ namespace MQTTnet | |||||
{ | { | ||||
if (logger == null) throw new ArgumentNullException(nameof(logger)); | if (logger == null) throw new ArgumentNullException(nameof(logger)); | ||||
return new MqttClient(new MqttClientAdapterFactory(), logger); | |||||
return new MqttClient(_clientAdapterFactory, logger); | |||||
} | } | ||||
public IMqttClient CreateMqttClient(IMqttClientAdapterFactory adapterFactory) | |||||
public IMqttClient CreateMqttClient(IMqttClientAdapterFactory clientAdapterFactory) | |||||
{ | { | ||||
if (adapterFactory == null) throw new ArgumentNullException(nameof(adapterFactory)); | |||||
if (clientAdapterFactory == null) throw new ArgumentNullException(nameof(clientAdapterFactory)); | |||||
return new MqttClient(adapterFactory, DefaultLogger); | |||||
return new MqttClient(clientAdapterFactory, DefaultLogger); | |||||
} | } | ||||
public IMqttClient CreateMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory adapterFactory) | |||||
public IMqttClient CreateMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory clientAdapterFactory) | |||||
{ | { | ||||
if (logger == null) throw new ArgumentNullException(nameof(logger)); | if (logger == null) throw new ArgumentNullException(nameof(logger)); | ||||
if (adapterFactory == null) throw new ArgumentNullException(nameof(adapterFactory)); | |||||
if (clientAdapterFactory == null) throw new ArgumentNullException(nameof(clientAdapterFactory)); | |||||
return new MqttClient(adapterFactory, logger); | |||||
return new MqttClient(clientAdapterFactory, logger); | |||||
} | } | ||||
public IMqttServer CreateMqttServer() | public IMqttServer CreateMqttServer() | ||||
@@ -60,19 +68,19 @@ namespace MQTTnet | |||||
return CreateMqttServer(new List<IMqttServerAdapter> { new MqttTcpServerAdapter(logger.CreateChildLogger()) }, logger); | return CreateMqttServer(new List<IMqttServerAdapter> { new MqttTcpServerAdapter(logger.CreateChildLogger()) }, logger); | ||||
} | } | ||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger) | |||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters, IMqttNetLogger logger) | |||||
{ | { | ||||
if (adapters == null) throw new ArgumentNullException(nameof(adapters)); | |||||
if (serverAdapters == null) throw new ArgumentNullException(nameof(serverAdapters)); | |||||
if (logger == null) throw new ArgumentNullException(nameof(logger)); | if (logger == null) throw new ArgumentNullException(nameof(logger)); | ||||
return new MqttServer(adapters, logger.CreateChildLogger()); | |||||
return new MqttServer(serverAdapters, logger.CreateChildLogger()); | |||||
} | } | ||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> adapters) | |||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters) | |||||
{ | { | ||||
if (adapters == null) throw new ArgumentNullException(nameof(adapters)); | |||||
if (serverAdapters == null) throw new ArgumentNullException(nameof(serverAdapters)); | |||||
return new MqttServer(adapters, DefaultLogger.CreateChildLogger()); | |||||
return new MqttServer(serverAdapters, DefaultLogger.CreateChildLogger()); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -17,6 +17,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" /> | <ProjectReference Include="..\..\Source\MQTTnet.Extensions.ManagedClient\MQTTnet.Extensions.ManagedClient.csproj" /> | ||||
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj" /> | |||||
<ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj" /> | <ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -1,10 +1,13 @@ | |||||
using MQTTnet.Client; | using MQTTnet.Client; | ||||
using System; | using System; | ||||
using System.IO; | using System.IO; | ||||
using System.Net; | |||||
using System.Security.Authentication; | |||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using MQTTnet.Client.Options; | using MQTTnet.Client.Options; | ||||
using MQTTnet.Client.Receiving; | using MQTTnet.Client.Receiving; | ||||
using MQTTnet.Extensions.WebSocket4Net; | |||||
using MQTTnet.Formatter; | using MQTTnet.Formatter; | ||||
using MQTTnet.Protocol; | using MQTTnet.Protocol; | ||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
@@ -77,6 +80,7 @@ namespace MQTTnet.TestApp.NetCore | |||||
{ | { | ||||
Write("Testing '" + name + "'... ", ConsoleColor.Gray); | Write("Testing '" + name + "'... ", ConsoleColor.Gray); | ||||
var factory = new MqttFactory(); | var factory = new MqttFactory(); | ||||
//factory.UseWebSocket4Net(); | |||||
var client = factory.CreateMqttClient(); | var client = factory.CreateMqttClient(); | ||||
var topic = Guid.NewGuid().ToString(); | var topic = Guid.NewGuid().ToString(); | ||||
@@ -135,6 +135,10 @@ | |||||
<Project>{c444e9c8-95fa-430e-9126-274129de16cd}</Project> | <Project>{c444e9c8-95fa-430e-9126-274129de16cd}</Project> | ||||
<Name>MQTTnet.Extensions.Rpc</Name> | <Name>MQTTnet.Extensions.Rpc</Name> | ||||
</ProjectReference> | </ProjectReference> | ||||
<ProjectReference Include="..\..\Source\MQTTnet.Extensions.WebSocket4Net\MQTTnet.Extensions.WebSocket4Net.csproj"> | |||||
<Project>{2BD01D53-4CA5-4142-BE8D-313876395E3E}</Project> | |||||
<Name>MQTTnet.Extensions.WebSocket4Net</Name> | |||||
</ProjectReference> | |||||
<ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj"> | <ProjectReference Include="..\..\Source\MQTTnet\MQTTnet.csproj"> | ||||
<Project>{3587e506-55a2-4eb3-99c7-dc01e42d25d2}</Project> | <Project>{3587e506-55a2-4eb3-99c7-dc01e42d25d2}</Project> | ||||
<Name>MQTTnet</Name> | <Name>MQTTnet</Name> | ||||
@@ -63,6 +63,7 @@ | |||||
<StackPanel Grid.Column="1" Grid.Row="6" Orientation="Horizontal"> | <StackPanel Grid.Column="1" Grid.Row="6" Orientation="Horizontal"> | ||||
<RadioButton x:Name="UseTcp" IsChecked="True" GroupName="transport">TCP</RadioButton> | <RadioButton x:Name="UseTcp" IsChecked="True" GroupName="transport">TCP</RadioButton> | ||||
<RadioButton x:Name="UseWs" GroupName="transport">WS</RadioButton> | <RadioButton x:Name="UseWs" GroupName="transport">WS</RadioButton> | ||||
<RadioButton x:Name="UseWs4Net" GroupName="transport">WS (WebSocket4Net)</RadioButton> | |||||
<CheckBox x:Name="UseTls">Use TLS</CheckBox> | <CheckBox x:Name="UseTls">Use TLS</CheckBox> | ||||
</StackPanel> | </StackPanel> | ||||
@@ -1,8 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||
using System.Net.Security; | |||||
using System.Security.Cryptography.X509Certificates; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using Windows.Security.Cryptography.Certificates; | using Windows.Security.Cryptography.Certificates; | ||||
@@ -23,6 +21,7 @@ using MQTTnet.Server; | |||||
using MQTTnet.Server.Status; | using MQTTnet.Server.Status; | ||||
using MqttClientConnectedEventArgs = MQTTnet.Client.Connecting.MqttClientConnectedEventArgs; | using MqttClientConnectedEventArgs = MQTTnet.Client.Connecting.MqttClientConnectedEventArgs; | ||||
using MqttClientDisconnectedEventArgs = MQTTnet.Client.Disconnecting.MqttClientDisconnectedEventArgs; | using MqttClientDisconnectedEventArgs = MQTTnet.Client.Disconnecting.MqttClientDisconnectedEventArgs; | ||||
using MQTTnet.Extensions.WebSocket4Net; | |||||
namespace MQTTnet.TestApp.UniversalWindows | namespace MQTTnet.TestApp.UniversalWindows | ||||
{ | { | ||||
@@ -83,6 +82,8 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
private async void Connect(object sender, RoutedEventArgs e) | private async void Connect(object sender, RoutedEventArgs e) | ||||
{ | { | ||||
var mqttFactory = new MqttFactory(); | |||||
var tlsOptions = new MqttClientTlsOptions | var tlsOptions = new MqttClientTlsOptions | ||||
{ | { | ||||
UseTls = UseTls.IsChecked == true, | UseTls = UseTls.IsChecked == true, | ||||
@@ -116,6 +117,17 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
}; | }; | ||||
} | } | ||||
if (UseWs4Net.IsChecked == true) | |||||
{ | |||||
options.ChannelOptions = new MqttClientWebSocketOptions | |||||
{ | |||||
Uri = Server.Text, | |||||
TlsOptions = tlsOptions | |||||
}; | |||||
mqttFactory.UseWebSocket4Net(); | |||||
} | |||||
if (options.ChannelOptions == null) | if (options.ChannelOptions == null) | ||||
{ | { | ||||
throw new InvalidOperationException(); | throw new InvalidOperationException(); | ||||
@@ -156,11 +168,9 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
_mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | ||||
} | } | ||||
var factory = new MqttFactory(); | |||||
if (UseManagedClient.IsChecked == true) | if (UseManagedClient.IsChecked == true) | ||||
{ | { | ||||
_managedMqttClient = factory.CreateManagedMqttClient(); | |||||
_managedMqttClient = mqttFactory.CreateManagedMqttClient(); | |||||
_managedMqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage); | _managedMqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage); | ||||
_managedMqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x)); | _managedMqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x)); | ||||
_managedMqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | _managedMqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | ||||
@@ -172,7 +182,7 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
_mqttClient = factory.CreateMqttClient(); | |||||
_mqttClient = mqttFactory.CreateMqttClient(); | |||||
_mqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage); | _mqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage); | ||||
_mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x)); | _mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x)); | ||||
_mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x)); | ||||
@@ -204,7 +214,7 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
private async Task HandleReceivedApplicationMessage(MqttApplicationMessageReceivedEventArgs eventArgs) | private async Task HandleReceivedApplicationMessage(MqttApplicationMessageReceivedEventArgs eventArgs) | ||||
{ | { | ||||
var item = $"Timestamp: {DateTime.Now:O} | Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel}"; | |||||
var item = $"Timestamp: {DateTime.Now:O} | Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {eventArgs.ApplicationMessage.ConvertPayloadToString()} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel}"; | |||||
await Dispatcher.RunAsync(CoreDispatcherPriority.Low, () => | await Dispatcher.RunAsync(CoreDispatcherPriority.Low, () => | ||||
{ | { | ||||
@@ -524,6 +534,13 @@ namespace MQTTnet.TestApp.UniversalWindows | |||||
Console.WriteLine(); | Console.WriteLine(); | ||||
}); | }); | ||||
void Handler(MqttApplicationMessageReceivedEventArgs args) | |||||
{ | |||||
//... | |||||
} | |||||
client.UseApplicationMessageReceivedHandler(Handler); | |||||
// Subscribe after connect | // Subscribe after connect | ||||
client.UseConnectedHandler(async e => | client.UseConnectedHandler(async e => | ||||