• Abp vNext 集成 MQTT


    Abp vNext 集成 MQTT

    Broker

    ApsNet Core 集成 MQTT

    引用包

        <PackageReference Include="MQTTnet.AspNetCore" Version="3.1.2" />
    

    添加服务

    代码清单:Artisan.IotHub.HttpApi.Host/IotHubHttpApiHostModule.cs

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        // ......
         ConfigureMqttService(context, configuration);
    }
    
    private void ConfigureMqttService(ServiceConfigurationContext context, IConfiguration configuration)
    {
        var settings = configuration.GetSection("MqttServer").Get<MqttServerSettings>();
        context.Services.ConfigureMqttService(settings);
    }
    

    appsettings.json 中的配置:

      "MqttServer": {
        "IpAddress": "localhost",
        "DomainName": "",
        "Port": 2883,
        "EnableTls": false,
        "TlsPort": 8883
      },
    

    其中:

    方法 ConfigureMqttServic() 是扩展方法,如下所示:

    代码清单:Artisan.IotHub.Application/Mqtts/Extensions/MqttConfiguration.cs

      public static class MqttConfiguration
      {
                public static void ConfigureMqttService(
                    this IServiceCollection services, 
                    MqttServerSettings settings)
                {
                    services.AddHostedMqttServerWithServices(options =>
                    {
                        options.WithDefaultEndpointPort(settings.Port).WithDefaultEndpoint();
                        var mqttService = services.GetRequiredService<MqttServerService>();
                        mqttService.ConfigureMqttServerOptions(options);
                    });
    
                    services.AddMqttConnectionHandler();
                    services.AddMqttWebSocketServerAdapter();
                    services.AddConnections();
                }
          
             // .....
        }
    

    添加 MQTT Endpoint

    代码清单:Artisan.IotHub.HttpApi.Host/IotHubHttpApiHostModule.cs

    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
            app.UseAbpRequestLocalization();
            app.UseCorrelationId();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors();
            app.UseAuthentication();
            app.UseAuthorization();
            // 添加 MQTT 中间件
            app.UseMqttServer();
            app.UseSwagger();
    }
    

    其中:方法UseMqttServe()是自定义的扩展方法,如下所示:

    代码清单:Artisan.IotHub.Application/Mqtts/Extensions/MqttConfiguration.cs

      public static class MqttConfiguration
        {
            //......
          
            public static void UseMqttServer(this IApplicationBuilder app)
            {
                app.UseMqttServer(mqttServer =>
                {
                    app.ApplicationServices
                        .GetRequiredService<MqttServerService>()
                        .ConfigureMqttServer(mqttServer);
                });
    
                app.UseEndpoints(endpoint =>
                {
                    endpoint.MapMqtt("/mqtt");
                });
            }
        }
    

    ConfigureMqttServer()调用:

    代码清单:Artisan.IotHub.Application/Mqtts/MqttServerService.cs

    public class MqttServerService : IMqttServerService, ISingletonDependency
    {
        private readonly IMqttConnectionService  _mqttConnectionService;
        private readonly IMqttSubscriptionService _mqttSubscriptionService;
        private readonly IMqttPublishingService _mqttPublishingService;
    
        public MqttServerService(
            IMqttConnectionService mqttConnectionService,
            IMqttSubscriptionService mqttSubscriptionService,
            IMqttPublishingService mqttPublishingService)
        {
            _mqttConnectionService = mqttConnectionService;
            _mqttSubscriptionService = mqttSubscriptionService;
            _mqttPublishingService = mqttPublishingService;
        }
    
        public void ConfigureMqttServer(IMqttServer mqttServer)
        {
            _mqttConnectionService.ConfigureMqttServer(mqttServer);
            _mqttSubscriptionService.ConfigureMqttServer(mqttServer);
            _mqttPublishingService.ConfigureMqttServer(mqttServer);
        }
    
        public void ConfigureMqttServerOptions(AspNetMqttServerOptionsBuilder options)
        {
            _mqttConnectionService.ConfigureMqttServerOptions(options);
            _mqttSubscriptionService.ConfigureMqttServerOptions(options);
            _mqttPublishingService.ConfigureMqttServerOptions(options);
            options.WithoutDefaultEndpoint();
        }
    }
    

    设置 MQTT监听端口

    通过ConfigureKestrel()方法在 Kestrel 上设置MQTT的监听端口,如下代码所示:

    代码清单:Artisan.IotHub.HttpApi.Host/Program.cs

                var builder = WebApplication.CreateBuilder(args);
                // ......
                builder.WebHost.ConfigureKestrel(option =>
                {
                    option.ConfigureMqttServer();
                });
    

    其中:方法 ConfigureMqttServer()是扩展方法,如下所示:

    代码清单:Artisan.IotHub.HttpApi.Host/KestrelServerOptionsExtensions.cs

    public static class KestrelServerOptionsExtensions
    {
            /// <summary>
            /// 在 KestrelServer 中设置 MqttServer 的监听端口
            /// </summary>
            /// <param name="option"></param>
            public static void ConfigureMqttServer(this KestrelServerOptions option)
            {
                var configuration = option.ApplicationServices.GetRequiredService<IConfiguration>();
                var mqttSettings = configuration.GetSection("MqttServer").Get<MqttServerSettings>();
                
                //option.ListenAnyIP(mqttSettings.Port, opt => opt.UseMqtt());
                if (mqttSettings.IpAddress.ToLower() == "localhost")
                {
                    option.ListenLocalhost(mqttSettings.Port, opt => opt.UseMqtt());
                }
                else
                {
                    option.Listen(
                        IPAddress.Parse(mqttSettings.IpAddress), 
                        mqttSettings.Port, opt => opt.UseMqtt()
                    );
                }
            }
    }
    

    修复 Http和Https 的监听端口

    通过ConfigureKestrel()方法在 Kestrel 上设置MQTT的监听端口,如下代码所示:

              builder.WebHost.ConfigureKestrel(option =>
                {
                    option.ConfigureMqttServer();
                });
    
     =>           option.Listen(
                        IPAddress.Parse(mqttSettings.IpAddress), 
                        mqttSettings.Port, opt => opt.UseMqtt()
                    );
    

    但是这样做,会出现一个BugHttp和Https 的监听端口将会失效 !!!
    通过Http和Https 监听端口(比如:https://localhost:44359)是无法访问 Api的。

    原因:

    通过 ConfigureKestrel() 方法在 Kestrel 上设置的Http和Https 监听端口后,其它地方设置(例如:在launchSettings.json 文件)的监听方式会被覆盖而失效!

    而我们又没有在ConfigureKestrel()的方法中重新设置Http和Https 的监听端口。
    在日志中也能看到提示警告:

    [11:17:46 WRN] Overriding address(es) 'https://localhost:44359'. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead.
    

    如何修复呢?

    可通过修改配置文件appsettings.json来设置Http和Https的监听端口,具体操作如下:

    在配置文件appsettings.json中添加如下 Kestrel 配置节点:

    {
      "Kestrel": {
        "Endpoints": {
          "Http": {
            "Url": "http://localhost:7059",
            "Protocols": "Http1AndHttp2" 
          },
          "Https": {
            "Url": "https://localhost:44359",
            "Protocols": "Http1AndHttp2" 
          },
        }
      }
      // .....   
    }
    

    这样就通过配置文件的方式为Kestrel 设置了Http和Https的监听端口

  • 相关阅读:
    3.3 React Hooks
    ES6高阶函数
    ES6扩展运算符
    4.0不用npm,cnpm。使用yarn包启动react项目
    4.3 webpack打包学习
    4.2 Node.js模块化教程
    4.1React模块化
    vue组件化开发
    js箭头函数
    weblogic_exploit
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/16288211.html
Copyright © 2020-2023  润新知