经过漫长的等待,MQTT专题终于等到了第七篇,本次将在ASP.NET Core框架下利用MQTTnet创建自有服务器。
由于最近刚开始接触ASP.NET Core,很多具体的用法还没有研究透彻,所以本篇重点在核心的几段代码,示例参考了MQTTnet官方源码。
本示例将融合ASP.NET Core WebAPI,以便在API接口调用中实现消息推送。
在VS2017中新建ASP.NET Core Web应用程序,打开NuGet管理器,搜索并安装MQTTnet.AspNetCore。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
#region MQTT配置
string hostIp = Configuration["MqttOption:HostIp"];//IP地址
int hostPort = int.Parse(Configuration["MqttOption:HostPort"]);//端口号
int timeout = int.Parse(Configuration["MqttOption:Timeout"]);//超时时间
string username = Configuration["MqttOption:UserName"];//用户名
string password = Configuration["MqttOption:Password"];//密码
//构建配置项
var optionBuilder = new MqttServerOptionsBuilder()
.WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(hostIp))
.WithDefaultEndpointPort(hostPort)
.WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(timeout))
.WithConnectionValidator(t =>
{
if (t.Username != username || t.Password != password)
{
t.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
}
t.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
});
var option = optionBuilder.Build();
//服务注入
services
.AddHostedMqttServer(option)
.AddMqttConnectionHandler()
.AddConnections();
#endregion
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
app.UseConnections(c => c.MapConnectionHandler<MqttConnectionHandler>("/data", options =>
{
options.WebSockets.SubProtocolSelector = MQTTnet.AspNetCore.ApplicationBuilderExtensions.SelectSubProtocol;
}));
app.UseMqttEndpoint("/data");
//MQTT声明周期事件
app.UseMqttServer(server =>
{
//服务启动事件
server.Started += async (sender, args) =>
{
var msg = new MqttApplicationMessageBuilder().WithPayload("welcome to mqtt").WithTopic("start");
while (true)
{
try
{
await server.PublishAsync(msg.Build());
msg.WithPayload("you are welcome to mqtt");
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
};
//服务停止事件
server.Stopped += (sender, args) =>
{
};
//客户端连接事件
server.ClientConnected += (sender, args) =>
{
var clientId = args.ClientId;
};
//客户端断开事件
server.ClientDisconnected += (sender, args) =>
{
var clientId = args.ClientId;
};
});
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"MqttOption": {
"HostIp": "127.0.0.1",
"HostPort": 61613,
"Timeout": 5000,
"UserName": "admin",
"Password": "passwod"
}
}
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
//上述方法与下方注释代码效果一致
//WebHost
// .CreateDefaultBuilder(args)
// .UseKestrel()
// .UseStartup()
// .Build()
// .Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(o =>
{
o.ListenAnyIP(61613, m => m.UseMqtt());//绑定MQTT服务端口
//o.ListenAnyIP(5000);
})
.UseStartup<Startup>();
}
由于ASP.NET Core使用依赖注入(Dependency Injection)来实现控制反转(IoC),MQTTServer正是通过依赖注入添加到应用程序的服务集合中去,同样通过ASP.NET Core中的机制可以在API控制器类中获取当前实例中的MQTT服务。具体实现要借助接口IServiceProvider。创建一个辅助类如下:
public static class ServiceLocator
{
public static IServiceProvider Instance { get; set; }
}
在Startup类的Configure方法中添加如下代码:
//获取当前应用的服务集合
ServiceLocator.Instance = app.ApplicationServices;
在API控制器中就可以通过ServiceLocator获取服务并使用了。
[Route("v1/api/values")]
[ApiController]
public class ValuesController : RootController
{
public string Test()
{
string result = "";
//从服务集合中获取MQTT服务
var service = ServiceLocator.Instance.GetService(typeof(MQTTnet.Server.MqttServer));
var messager = (MQTTnet.Server.MqttServer)service;
//这里你可以构建消息并发布
return result;
}
}
示例代码
经过上述过程中的探索研究,虽然暂未实现图形化界面,但基本了解了如何使用ASP.NET Core构建MQTT代理服务器,同时掌握了在API接口中使用MQTT服务的方法,后续将做更深一步的研究。