mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-31 03:02:39 +08:00
Add more function mappings for MQTTnet Server.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Server.Logging;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
public class CustomMqttFactory
|
||||
{
|
||||
private readonly MqttFactory _mqttFactory;
|
||||
|
||||
public CustomMqttFactory(ILogger<MqttServer> logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
Logger = new MqttNetLoggerWrapper(logger);
|
||||
|
||||
_mqttFactory = new MqttFactory(Logger);
|
||||
}
|
||||
|
||||
public IMqttNetLogger Logger { get; }
|
||||
|
||||
public IMqttServer CreateMqttServer(List<IMqttServerAdapter> adapters)
|
||||
{
|
||||
if (adapters == null) throw new ArgumentNullException(nameof(adapters));
|
||||
|
||||
return _mqttFactory.CreateMqttServer(adapters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace MQTTnet.Server.Mqtt
|
||||
public class MqttApplicationMessageInterceptor : IMqttServerApplicationMessageInterceptor
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger<MqttApplicationMessageInterceptor> _logger;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttApplicationMessageInterceptor(PythonScriptHostService pythonScriptHostService, ILogger<MqttApplicationMessageInterceptor> logger)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ namespace MQTTnet.Server.Mqtt
|
||||
{ "qos", (int)context.ApplicationMessage.QualityOfServiceLevel },
|
||||
{ "retain", context.ApplicationMessage.Retain }
|
||||
};
|
||||
|
||||
|
||||
_pythonScriptHostService.InvokeOptionalFunction("on_intercept_application_message", pythonContext);
|
||||
|
||||
context.AcceptPublish = (bool)pythonContext.get("accept_publish", context.AcceptPublish);
|
||||
@@ -46,5 +46,21 @@ namespace MQTTnet.Server.Mqtt
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// TODO: Create dump(object) method in wrapper (creates JSON and prints it).
|
||||
public class PythonMqttApplicationMessageInterceptorContext
|
||||
{
|
||||
public bool accept_connection;
|
||||
|
||||
public bool accept_publish;
|
||||
|
||||
public string client_id;
|
||||
|
||||
public string topic;
|
||||
|
||||
public int qos;
|
||||
|
||||
public bool retain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using IronPython.Runtime;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet.Server.Scripting;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
public class MqttClientConnectedHandler : IMqttServerClientConnectedHandler
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttClientConnectedHandler(PythonScriptHostService pythonScriptHostService, ILogger<MqttClientConnectedHandler> logger)
|
||||
{
|
||||
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public Task HandleClientConnectedAsync(MqttServerClientConnectedEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pythonEventArgs = new PythonDictionary
|
||||
{
|
||||
{ "client_id", eventArgs.ClientId }
|
||||
};
|
||||
|
||||
_pythonScriptHostService.InvokeOptionalFunction("on_client_connected", pythonEventArgs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogError(exception, "Error while handling client connected event.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using IronPython.Runtime;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet.Server.Scripting;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
public class MqttClientDisconnectedHandler : IMqttServerClientDisconnectedHandler
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttClientDisconnectedHandler(PythonScriptHostService pythonScriptHostService, ILogger<MqttClientDisconnectedHandler> logger)
|
||||
{
|
||||
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public Task HandleClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pythonEventArgs = new PythonDictionary
|
||||
{
|
||||
{ "client_id", eventArgs.ClientId },
|
||||
{ "type", PythonConvert.Pythonfy(eventArgs.DisconnectType) }
|
||||
};
|
||||
|
||||
_pythonScriptHostService.InvokeOptionalFunction("on_client_disconnected", pythonEventArgs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogError(exception, "Error while handling client disconnected event.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using IronPython.Runtime;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet.Server.Scripting;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
public class MqttClientSubscribedTopicHandler : IMqttServerClientSubscribedTopicHandler
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttClientSubscribedTopicHandler(PythonScriptHostService pythonScriptHostService, ILogger<MqttClientSubscribedTopicHandler> logger)
|
||||
{
|
||||
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public Task HandleClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pythonEventArgs = new PythonDictionary
|
||||
{
|
||||
{ "client_id", eventArgs.ClientId },
|
||||
{ "topic", eventArgs.TopicFilter.Topic },
|
||||
{ "qos", (int)eventArgs.TopicFilter.QualityOfServiceLevel }
|
||||
};
|
||||
|
||||
_pythonScriptHostService.InvokeOptionalFunction("on_client_subscribed_topic", pythonEventArgs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogError(exception, "Error while handling client subscribed topic event.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using IronPython.Runtime;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet.Server.Scripting;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
public class MqttClientUnsubscribedTopicHandler : IMqttServerClientUnsubscribedTopicHandler
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttClientUnsubscribedTopicHandler(PythonScriptHostService pythonScriptHostService, ILogger<MqttClientUnsubscribedTopicHandler> logger)
|
||||
{
|
||||
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public Task HandleClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pythonEventArgs = new PythonDictionary
|
||||
{
|
||||
{ "client_id", eventArgs.ClientId },
|
||||
{ "topic", eventArgs.TopicFilter }
|
||||
};
|
||||
|
||||
_pythonScriptHostService.InvokeOptionalFunction("on_client_unsubscribed_topic", pythonEventArgs);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogError(exception, "Error while handling client unsubscribed topic event.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace MQTTnet.Server.Mqtt
|
||||
public class MqttConnectionValidator : IMqttServerConnectionValidator
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger<MqttConnectionValidator> _logger;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttConnectionValidator(PythonScriptHostService pythonScriptHostService, ILogger<MqttConnectionValidator> logger)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@ using MQTTnet.Adapter;
|
||||
using MQTTnet.AspNetCore;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server.Logging;
|
||||
using MQTTnet.Server.Scripting;
|
||||
|
||||
namespace MQTTnet.Server.Mqtt
|
||||
@@ -17,6 +16,10 @@ namespace MQTTnet.Server.Mqtt
|
||||
{
|
||||
private readonly ILogger<MqttServerService> _logger;
|
||||
|
||||
private readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
|
||||
private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
|
||||
private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
|
||||
private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
|
||||
private readonly MqttConnectionValidator _mqttConnectionValidator;
|
||||
private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
|
||||
private readonly MqttApplicationMessageInterceptor _mqttApplicationMessageInterceptor;
|
||||
@@ -25,15 +28,22 @@ namespace MQTTnet.Server.Mqtt
|
||||
private readonly IMqttServer _mqttServer;
|
||||
|
||||
public MqttServerService(
|
||||
IMqttServerFactory mqttServerFactory,
|
||||
CustomMqttFactory mqttFactory,
|
||||
MqttWebSocketServerAdapter webSocketServerAdapter,
|
||||
MqttNetLoggerWrapper mqttNetLogger,
|
||||
MqttClientConnectedHandler mqttClientConnectedHandler,
|
||||
MqttClientDisconnectedHandler mqttClientDisconnectedHandler,
|
||||
MqttClientSubscribedTopicHandler mqttClientSubscribedTopicHandler,
|
||||
MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
|
||||
MqttConnectionValidator mqttConnectionValidator,
|
||||
MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
|
||||
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
|
||||
PythonScriptHostService pythonScriptHostService,
|
||||
ILogger<MqttServerService> logger)
|
||||
{
|
||||
_mqttClientConnectedHandler = mqttClientConnectedHandler ?? throw new ArgumentNullException(nameof(mqttClientConnectedHandler));
|
||||
_mqttClientDisconnectedHandler = mqttClientDisconnectedHandler ?? throw new ArgumentNullException(nameof(mqttClientDisconnectedHandler));
|
||||
_mqttClientSubscribedTopicHandler = mqttClientSubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientSubscribedTopicHandler));
|
||||
_mqttClientUnsubscribedTopicHandler = mqttClientUnsubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientUnsubscribedTopicHandler));
|
||||
_mqttConnectionValidator = mqttConnectionValidator ?? throw new ArgumentNullException(nameof(mqttConnectionValidator));
|
||||
_mqttSubscriptionInterceptor = mqttSubscriptionInterceptor ?? throw new ArgumentNullException(nameof(mqttSubscriptionInterceptor));
|
||||
_mqttApplicationMessageInterceptor = mqttApplicationMessageInterceptor ?? throw new ArgumentNullException(nameof(mqttApplicationMessageInterceptor));
|
||||
@@ -42,11 +52,11 @@ namespace MQTTnet.Server.Mqtt
|
||||
|
||||
var adapters = new List<IMqttServerAdapter>
|
||||
{
|
||||
new MqttTcpServerAdapter(new MqttNetChildLoggerWrapper(null, mqttNetLogger)),
|
||||
new MqttTcpServerAdapter(mqttFactory.Logger.CreateChildLogger(nameof(MqttTcpServerAdapter))),
|
||||
webSocketServerAdapter
|
||||
};
|
||||
|
||||
_mqttServer = mqttServerFactory.CreateMqttServer(adapters);
|
||||
_mqttServer = mqttFactory.CreateMqttServer(adapters);
|
||||
}
|
||||
|
||||
public void Configure()
|
||||
@@ -61,6 +71,11 @@ namespace MQTTnet.Server.Mqtt
|
||||
.WithSubscriptionInterceptor(_mqttSubscriptionInterceptor)
|
||||
.Build();
|
||||
|
||||
_mqttServer.ClientConnectedHandler = _mqttClientConnectedHandler;
|
||||
_mqttServer.ClientDisconnectedHandler = _mqttClientDisconnectedHandler;
|
||||
_mqttServer.ClientSubscribedTopicHandler = _mqttClientSubscribedTopicHandler;
|
||||
_mqttServer.ClientUnsubscribedTopicHandler = _mqttClientUnsubscribedTopicHandler;
|
||||
|
||||
_mqttServer.StartAsync(options).GetAwaiter().GetResult();
|
||||
|
||||
_logger.LogInformation("MQTT server started.");
|
||||
@@ -68,34 +83,48 @@ namespace MQTTnet.Server.Mqtt
|
||||
|
||||
private void Publish(PythonDictionary parameters)
|
||||
{
|
||||
var applicationMessageBuilder = new MqttApplicationMessageBuilder()
|
||||
.WithTopic((string)parameters.get("topic", null))
|
||||
.WithRetainFlag((bool)parameters.get("retain", false))
|
||||
.WithQualityOfServiceLevel((MqttQualityOfServiceLevel)(int)parameters.get("qos", 0));
|
||||
|
||||
var payload = parameters.get("payload", null);
|
||||
var binaryPayload = new byte[0];
|
||||
|
||||
if (payload is string stringPayload)
|
||||
try
|
||||
{
|
||||
binaryPayload = Encoding.UTF8.GetBytes(stringPayload);
|
||||
var applicationMessageBuilder = new MqttApplicationMessageBuilder()
|
||||
.WithTopic((string)parameters.get("topic", null))
|
||||
.WithRetainFlag((bool)parameters.get("retain", false))
|
||||
.WithQualityOfServiceLevel((MqttQualityOfServiceLevel)(int)parameters.get("qos", 0));
|
||||
|
||||
var payload = parameters.get("payload", null);
|
||||
byte[] binaryPayload;
|
||||
|
||||
if (payload == null)
|
||||
{
|
||||
binaryPayload = new byte[0];
|
||||
}
|
||||
else if (payload is string stringPayload)
|
||||
{
|
||||
binaryPayload = Encoding.UTF8.GetBytes(stringPayload);
|
||||
}
|
||||
else if (payload is ByteArray byteArray)
|
||||
{
|
||||
binaryPayload = byteArray.ToArray();
|
||||
}
|
||||
else if (payload is IEnumerable<int> intArray)
|
||||
{
|
||||
binaryPayload = intArray.Select(Convert.ToByte).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Payload type not supported.");
|
||||
}
|
||||
|
||||
applicationMessageBuilder = applicationMessageBuilder
|
||||
.WithPayload(binaryPayload);
|
||||
|
||||
var applicationMessage = applicationMessageBuilder.Build();
|
||||
|
||||
_mqttServer.PublishAsync(applicationMessage).GetAwaiter().GetResult();
|
||||
}
|
||||
else if (payload is ByteArray byteArray)
|
||||
catch (Exception exception)
|
||||
{
|
||||
binaryPayload = byteArray.ToArray();
|
||||
_logger.LogError(exception, "Error while publishing application message from server.");
|
||||
}
|
||||
else if (payload is IEnumerable<int> intArray)
|
||||
{
|
||||
binaryPayload = intArray.Select(Convert.ToByte).ToArray();
|
||||
}
|
||||
|
||||
applicationMessageBuilder = applicationMessageBuilder
|
||||
.WithPayload(binaryPayload);
|
||||
|
||||
var applicationMessage = applicationMessageBuilder.Build();
|
||||
|
||||
_mqttServer.PublishAsync(applicationMessage).GetAwaiter().GetResult();
|
||||
_logger.LogInformation($"Published topic '{applicationMessage.Topic}' from server.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace MQTTnet.Server.Mqtt
|
||||
public class MqttSubscriptionInterceptor : IMqttServerSubscriptionInterceptor
|
||||
{
|
||||
private readonly PythonScriptHostService _pythonScriptHostService;
|
||||
private readonly ILogger<MqttSubscriptionInterceptor> _logger;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public MqttSubscriptionInterceptor(PythonScriptHostService pythonScriptHostService, ILogger<MqttSubscriptionInterceptor> logger)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user