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. 使用Python基于HyperLPR/Mask-RCNN的中文车牌识别

    基于HyperLPR的中文车牌识别 Bolg:https://blog.csdn.net/lsy17096535/article/details/78648170 https://www.jiansh ...

  2. sql server concat()函数

    concat()函数 --用于将两个字符串连接起来,形成一个单一的字符串 --SELECT CONCAT('FIRST ', 'SECOND') as a;

  3. python 一键登录微信分析好友性别 地址 生成结果

    # -*- coding:utf- -*- """ author:Mr Yang data:// """ import itchat imp ...

  4. 分布式的几件小事(十一)分布式session如何实现

    1.分布式会话是什么? 首先,我们知道浏览器有个cookie,在一段时间内这个cookie都存在,然后每次发请求过来都带上一个特殊的jsessionid cookie,就根据这个东西,在服务端可以维护 ...

  5. Vue 路由拦截(对某些页面需要登陆才能访问)

    前言 做项目的时候有个需求,就是发现没有登录,竟然也可以进入我的主页,这样肯定是不能容忍的.于是就要让他进入主页的时候,加个判断是否有登录,若没有登录,则返回登录界面,登录成功后还可以跳转到之前进入的 ...

  6. python之BeautifulSoup4

    阅读目录 1.Beautiful Soup4的安装配置 2.BeautifulSoup的基本用法 (1)节点选择器(tag) (2)方法选择器 (3)CSS选择器 (4)tag修改方法 Beautif ...

  7. 2019-11-29-asp-dotnet-core-通过图片统计-csdn-用户访问

    title author date CreateTime categories asp dotnet core 通过图片统计 csdn 用户访问 lindexi 2019-11-29 08:26:58 ...

  8. SecureCRT 连接 Centos7.0 (NAT模式),且能连接公网。

    1.打开物理主机运行-输入cmd,输入ipconfig,获取物理主机ip地址. ip:192.168.11.138 2.点击网络适配器,选择NAT模式. 3.点击Centos界面左上角-编辑-虚拟网络 ...

  9. HQL实现模糊查询

    hibernate 实现模糊查询两种传参方式,其实各个方法的实质都是一样的,只不过传递参数的方法稍微有点区别  public List<User> getUsers(String id){ ...

  10. Systemctl和service、chkconfig命令的关系

      systemctl命令:是一个systemd工具,主要负责控制systemd系统和服务管理器. service命令:可以启动.停止.重新启动和关闭系统服务,还可以显示所有系统服务的当前状态. ch ...