ABP .net Core MQTT+signalr通讯
abp版本: 4.3.0.0
.net core 版本 2.2
1、Mqtt
1.1 添加程序集:M2MqttDotnetCore(差点以为没有.net core 的)
2.2 实现代码:抄了个单例模式,并将服务器断开和消息接收事件委托给外层
public class MqttClientService
{
private IConfiguration _config;
private static volatile MqttClientService _instance = null; private static readonly object LockHelper = new object(); /// <summary>
/// 创建单例模式
/// </summary>
public static MqttClientService CreateInstance(IConfiguration config)
{
if (_instance == null)
{
lock (LockHelper)
{
if (_instance == null)
_instance = new MqttClientService(config);
}
}
return _instance;
} /// <summary>
/// 实例化订阅客户端
/// </summary>
public MqttClient SubscribeClient { get; set; } public Action<Object, MqttMsgPublishEventArgs> ReceivedMsg { get; set; }
public Action<object, EventArgs> ClosedCon; public MqttClientService(IConfiguration config)
{
_config = config;
//生成客户端ID并连接服务器
string ClientId = _config["MqttService:ClientId"];
string HostIP = _config["MqttService:HostIP"];
string Port= _config["MqttService:Port"];
// create client instance
SubscribeClient = new MqttClient(IPAddress.Parse(HostIP), int.Parse(Port), false, new X509Certificate(), new X509Certificate(), MqttSslProtocols.None); // 消息接收处理事件
SubscribeClient.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
//与服务器断开事件
SubscribeClient.ConnectionClosed += Client_ConnectionClosed; SubscribeClient.Connect(ClientId); // 在这里初始化订阅,从数据库取出所有需要订阅的设备信息,进行订阅
// SubscribeClient.Subscribe(new string[] { "avatar/uploaded" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
} void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// handle message received
ReceivedMsg?.Invoke(sender, e);
} /// <summary>
/// 与服务器断开
/// </summary>
private void Client_ConnectionClosed(object sender, EventArgs e)
{
ClosedCon?.Invoke(sender, e);
} /// <summary>
/// 发布
/// </summary>
/// <param name="Topic">发布的主题</param>
/// <param name="Data">发布的消息内容</param>
public void Publish(string Topic, string Data)
{
SubscribeClient.Publish(Topic, Encoding.UTF8.GetBytes(Data), MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, false);
} /// <summary>
/// 订阅
/// </summary>
/// <param name="Topic">订阅的主题</param>
public void Subscribe(string[] Topic)
{
// 订阅主题"/home/temperature" 消息质量为 2(只有一次)
SubscribeClient.Subscribe(Topic, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
} /// <summary>
/// 取消订阅
/// </summary>
public void Unsubscribe(string[] Topic)
{
SubscribeClient.Unsubscribe(Topic);
}
}
2.signalr,继承 AbpHubBase, ISingletonDependency(实现依赖注入的单例模式),这里只是为了做测试,所以代码有点丑
public class MqttHub : AbpHubBase, ISingletonDependency//AbpHubBase
{
// 使用GetByUserIdOrNull、GetAllClients和IsOnline方法 获取在线用户信息
private readonly IOnlineClientManager _onlineClient;
private readonly IConfiguration _config;
public MqttHub(IConfiguration config,IOnlineClientManager onlineClient):base()
{
_config = config;
_onlineClient = onlineClient;
} static List<MqttUserModel> userList = new List<MqttUserModel>();
/// <summary>
/// 订阅 这个方法名字是自定义的。参数也是自定义的
/// </summary>
public async Task SubscribeMessage(string Topic)
{
MqttClientService service = MqttClientService.CreateInstance(_config);
service.ReceivedMsg += MqttHelper_ReceivedMsg;
service.ClosedCon += MqttHelper_ClosedCon;
await Task.Run(() => service.Subscribe(new string[] { Topic }));
}
/// <summary>
/// 取消订阅
/// </summary>
/// <param name="Topic"></param>
public void Unsubscribe(string Topic)
{
MqttClientService service = MqttClientService.CreateInstance(_config);
service.ReceivedMsg += MqttHelper_ReceivedMsg;
service.ClosedCon += MqttHelper_ClosedCon;
service.Unsubscribe(new string[] { Topic });
}
/// <summary>
/// 发布
/// </summary>
/// <param name="Topic"></param>
/// <param name="Data"></param>
public void PublishMessage(string Topic, string Data)
{
MqttClientService service = MqttClientService.CreateInstance(_config);
service.ReceivedMsg += MqttHelper_ReceivedMsg;
service.ClosedCon += MqttHelper_ClosedCon;
service.Publish(Topic, Data);//发布 var clientConnectionId = Context.ConnectionId; //这是与我连接的客户端的连接ID(浏览器端)
}
/// <summary>
/// 添加在线人员
/// </summary>
public void AddOnlineUser()
{
//直接从当前登录者信息里面取
var user = userList.FirstOrDefault(x => x.Id == AbpSession.GetUserId());
if (user == null)
{
//添加在线人员
userList.Add(new MqttUserModel
{
ConnectionId = Context.ConnectionId,
Id = AbpSession.GetUserId(),//随机用户id
UserName = AbpSession.GetUserName(),
});
}
else
{
user.ConnectionId = Context.ConnectionId;
}
Clients.All.SendAsync("getMessage",new { msg = "当前登录用户:" + user.UserName + "\r\n" }); var clientConnectionId = Context.ConnectionId; //这是与我连接的客户端的连接ID(浏览器端)
Clients.Client(clientConnectionId).SendAsync("getMessage", new { msg = "您好,欢迎登陆!" });//指定接收者
}
/// <summary>
///
/// </summary>
private void MqttHelper_ClosedCon(object sender, EventArgs e)
{
Clients.All.SendAsync("getMessage", new { msg = "服务器已断开链接\r\n" });
}
/// <summary>
/// 接收到服务器端的返回
/// </summary>>
private void MqttHelper_ReceivedMsg(object sender, MqttMsgPublishEventArgs e)
{
byte[] b = e.Message;
string str = System.Text.Encoding.UTF8.GetString(b); //All表示监听所有连接上来的客户端。
//getMessage是一个动态的方法,名字我们可以随意定的。这里我仅仅是给他取名叫getMessage而已,我们也可以叫Clients.All.ABC();
Clients.All.SendAsync("getMessage", new { msg = str + "\r\n" });//调用所有连接上来的客户端(包括自己)监听的getMessage事件。All是一个dynamic属性,所以可以随意的监听
} public void SendMessage(string message)
{
Clients.All.SendAsync("getMessage", new { msg = string.Format("User {0}: {1}", AbpSession.UserId, message) });
} /// <summary>
///
/// </summary>
/// <returns></returns>
public async override Task OnConnectedAsync()
{
await base.OnConnectedAsync();
Logger.Debug("A client connected to MyChatHub: " + Context.ConnectionId);
} /// <summary>
/// 重写父类OnDisconnected方法 :OnConnected方法客户端断开连接的时候会调用此方法
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public async override Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
Logger.Debug("A client disconnected from MyChatHub: " + Context.ConnectionId);
}
3、前端:
<div class="layui-fluid">
<div class="layui-col-sm3">
<textarea id="TextArea1" rows="30" cols="900" style=" width:100%;height:100%;max-width:inherit;"></textarea>
</div>
<div class="layui-col-sm6">
<h5>订阅测试</h5>
@*<p>服务器地址:</p>
<p><input id="txtIP" type="text" /></p>*@
<p>订阅主题:</p>
<p><input id="txtTopic" type="text" value="12/deviceStatus/12190101999" /></p>
<p><input id="btnSubscribe" type="button" value="订阅" /><input id="btnSubscribeNo" type="button" value="取消订阅" /></p>
<h5>发布测试</h5>
<p>发布主题:</p>
<p><input id="txtTopicPub" type="text" /></p>
<p>发布内容</p>
<p><textarea id="txtPublish" rows="10" cols="20" style=" width:100%;height:100%;max-width:inherit;"></textarea></p>
<p><input id="btnPublic" type="button" value="发布" /></p>
<input type="button" id="btn1" value="提交" />
</div>
</div>
4 JS
var chatHub = null; abp.signalr.startConnection(abp.appPath + 'signalr-mqttHub', function (connection) {
chatHub = connection; // Save a reference to the hub connection.on('getMessage', function (message) { // Register for incoming messages
$("#TextArea1").text($("#TextArea1").text() + message.msg + "");
//console.log('received message: ' + message);
});
}).then(function (connection) {
$("#TextArea1").text($("#TextArea1").text() + "连接MyHub成功\r\n");
//abp.log.debug('Connected to mqttHub server!');
abp.event.trigger('mqttHub.connected');
}); abp.event.on('mqttHub.connected', function () { // Register for connect event
chatHub.invoke('sendMessage', "Hi everybody, I'm connected to the chat!"); // Send a message to the server
}); $("#btnSubscribe").click(function () {
chatHub.invoke('subscribeMessage', $("#txtTopic").val());
}); $("#btnSubscribeNo").click(function () {
chatHub.invoke('unsubscribe', $("#txtTopic").val());
}); $("#btnPublic").click(function () {
chatHub.invoke('publishMessage', $("#txtPublish").val())
});
5.Startup Configure
app.UseSignalR(routes =>
{
routes.MapHub<AbpCommonHub>("/signalr");
routes.MapHub<MqttHub>("/signalr-mqttHub"); // Prefix with '/signalr'
});
原谅我写得太匆忙,15分钟居然没有写完,只能后面再补细节
ABP .net Core MQTT+signalr通讯的更多相关文章
- Docker 发布 Abp net core web 服务
Docker 发布 Abp net core web 服务 准备工作:Abp 项目,这个是模板下载地址 https://aspnetboilerplate.com/Templates (本例使用的是S ...
- Asp.Net Core使用SignalR进行服务间调用
网上查询过很多关于ASP.NET core使用SignalR的简单例子,但是大部分都是简易聊天功能,今天心血来潮就搞了个使用SignalR进行服务间调用的简单DEMO. 至于SignalR是什么我就不 ...
- ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed
1. 问题描述 最近使用ABP .Net Core框架做一个微信开发,同时采用了一个微信开发框架集成到ABP,在微信用户关注的推送事件里调用了一个async 方法,由于没有返回值,也没做任何处理,本 ...
- abp(net core)+easyui+efcore仓储系统——解决方案介绍(二)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) ABP框架 首先介绍一下abp框架,abp其 ...
- abp(net core)+easyui+efcore仓储系统——展现层实现增删改查之控制器(六)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...
- abp(net core)+easyui+efcore仓储系统——领域层创建实体(三)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...
- abp(net core)+easyui+efcore仓储系统——定义仓储并实现 (四)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...
- abp(net core)+easyui+efcore仓储系统——创建应用服务(五)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...
- abp(net core)+easyui+efcore实现仓储管理系统——展现层实现增删改查之列表视图(七)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...
随机推荐
- Springboot实现上传文件接口,使用python的requests进行组装报文上传文件的方法
记录瞬间 近段时间使用Springboot实现了文件的上传服务,但是在使用python的requests进行post上传时,总是报错. 比如: 1.Current request is not a m ...
- python网络爬虫(8)多媒体文件抽取
目的 批量下载网页图片 导入库 urllib中的request中的urlretrieve方法,可以下载图片 lxml用于解析网页 requests用于获取网站信息 import urllib from ...
- 图片哈希概论及python中如何实现对比两张相似的图片
Google 以图搜图的原理,其中的获取图片 hash 值的方法就是 AHash. 每张图片都可以通过某种算法得到一个 hash 值,称为图片指纹,两张指纹相近的图片可以认为是相似图片. 以图搜图的原 ...
- javaScript中 数组的新方法(reduce)
定义和用法 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. reduce() 可以作为一个高阶函数,用于函数的 compose. 注意: redu ...
- ubuntu - 如何以root身份使用图形界面管理文件?
nautilus 是gnome的文件管理器,但是如果不是root账号下,权限受限,我们可以通过以下方式以root权限使用! 一,快捷键“ctrl+alt+t”,调出shell. 二,在shell中输入 ...
- 基于Zabbix 3.2.6版本的Discovery
作用:用于发现某IP网段内存活并且满足一定条件的主机,发现后进行加入到zabbix server进行监控. 操作步骤: 创建[自动发现规则] 为新建的自动发现规则创建[Action] 操作步骤图文 ...
- Python time、datetime、os、random、sys、hashlib、json、shutil、logging、paramiko、subprocess、ConfigParser、xml、shelve模块的使用
文章目录: 1. time & datetime模块 2. os模块 3. random模块 4. sys模块 5. hashlib模块 6. json模块 7. shutil模块 8. lo ...
- docker容器内安装 rz、sz
操作系统:ubuntu rz.sz命令找不到: 执行命令:apt-get update && apt-get install lrzsz
- linux系统很卡的基本排查方法
1. 查看内存使用情况 free -g 当观察到free栏已为0的时候,表示内存基本被吃完了,那就释放内存吧(释放内存参考上篇文章) 2. 查看磁盘使用情况 df -h 当发现磁盘使用率很高时,那就要 ...
- 7款js文件上传插件
1. jQuery File Upload 具有多文件上传.拖拽.进度条和图像预览功能的文件上传插件,支持跨域.分块.暂停恢复和客户端图像缩放.可与任何服务端平台(如PHP.Python.Ruby ...