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通讯的更多相关文章

  1. Docker 发布 Abp net core web 服务

    Docker 发布 Abp net core web 服务 准备工作:Abp 项目,这个是模板下载地址 https://aspnetboilerplate.com/Templates (本例使用的是S ...

  2. Asp.Net Core使用SignalR进行服务间调用

    网上查询过很多关于ASP.NET core使用SignalR的简单例子,但是大部分都是简易聊天功能,今天心血来潮就搞了个使用SignalR进行服务间调用的简单DEMO. 至于SignalR是什么我就不 ...

  3. ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed

    1.  问题描述 最近使用ABP .Net Core框架做一个微信开发,同时采用了一个微信开发框架集成到ABP,在微信用户关注的推送事件里调用了一个async 方法,由于没有返回值,也没做任何处理,本 ...

  4. abp(net core)+easyui+efcore仓储系统——解决方案介绍(二)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) ABP框架 首先介绍一下abp框架,abp其 ...

  5. abp(net core)+easyui+efcore仓储系统——展现层实现增删改查之控制器(六)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...

  6. abp(net core)+easyui+efcore仓储系统——领域层创建实体(三)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...

  7. abp(net core)+easyui+efcore仓储系统——定义仓储并实现 (四)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...

  8. abp(net core)+easyui+efcore仓储系统——创建应用服务(五)

    abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...

  9. abp(net core)+easyui+efcore实现仓储管理系统——展现层实现增删改查之列表视图(七)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

随机推荐

  1. Springboot实现上传文件接口,使用python的requests进行组装报文上传文件的方法

    记录瞬间 近段时间使用Springboot实现了文件的上传服务,但是在使用python的requests进行post上传时,总是报错. 比如: 1.Current request is not a m ...

  2. python网络爬虫(8)多媒体文件抽取

    目的 批量下载网页图片 导入库 urllib中的request中的urlretrieve方法,可以下载图片 lxml用于解析网页 requests用于获取网站信息 import urllib from ...

  3. 图片哈希概论及python中如何实现对比两张相似的图片

    Google 以图搜图的原理,其中的获取图片 hash 值的方法就是 AHash. 每张图片都可以通过某种算法得到一个 hash 值,称为图片指纹,两张指纹相近的图片可以认为是相似图片. 以图搜图的原 ...

  4. javaScript中 数组的新方法(reduce)

    定义和用法 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. reduce() 可以作为一个高阶函数,用于函数的 compose. 注意: redu ...

  5. ubuntu - 如何以root身份使用图形界面管理文件?

    nautilus 是gnome的文件管理器,但是如果不是root账号下,权限受限,我们可以通过以下方式以root权限使用! 一,快捷键“ctrl+alt+t”,调出shell. 二,在shell中输入 ...

  6. 基于Zabbix 3.2.6版本的Discovery

    作用:用于发现某IP网段内存活并且满足一定条件的主机,发现后进行加入到zabbix server进行监控. 操作步骤: 创建[自动发现规则] 为新建的自动发现规则创建[Action]   操作步骤图文 ...

  7. 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 ...

  8. docker容器内安装 rz、sz

    操作系统:ubuntu rz.sz命令找不到: 执行命令:apt-get update && apt-get install lrzsz

  9. linux系统很卡的基本排查方法

    1. 查看内存使用情况 free -g 当观察到free栏已为0的时候,表示内存基本被吃完了,那就释放内存吧(释放内存参考上篇文章) 2. 查看磁盘使用情况 df -h 当发现磁盘使用率很高时,那就要 ...

  10. 7款js文件上传插件

    1.  jQuery File Upload 具有多文件上传.拖拽.进度条和图像预览功能的文件上传插件,支持跨域.分块.暂停恢复和客户端图像缩放.可与任何服务端平台(如PHP.Python.Ruby ...