using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Abp.Configuration; using Abp.Dependency; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Runtime.Caching; using IwbZero.ToolCommon; using IwbZero.ToolCommon.LogHelpers; using IwbZero.ToolCommon.StringModel; using Microsoft.AspNet.SignalR; using uPLibrary.Networking.M2Mqtt.Messages; using WeEngine.CommonDto; using WeEngine.Enum; using WeEngine.Message; using WeEngine.Packages; using WeMessageService; using WeOnlineApp.Configuration; using WeOnlineApp.Configuration.Cache; using WeOnlineApp.Hubs; using WeOnlineApp.TrainingCamp; namespace WeOnlineApp.MqttClient { public class WeOnlineAppMsgClientManager : ISingletonDependency { public WeOnlineAppMsgClientManager(ISettingManager settingManager, IUnitOfWorkManager unitOfWorkManager, ICacheManager cacheManager, IRepository campRepository, IRepository playRepository, IRepository plRepository, IRepository psRepository, IRepository puRepository) { SettingManager = settingManager; UnitOfWorkManager = unitOfWorkManager; CacheManager = cacheManager; CampRepository = campRepository; PlayRepository = playRepository; PlRepository = plRepository; PsRepository = psRepository; PuRepository = puRepository; IwbHubContext = GlobalHost.ConnectionManager.GetHubContext(); if (!Client.IsConnected) { RegisterClient(); } HasStartPushSender = false; } private static readonly Dictionary _scenePushes = new Dictionary(); private string _url => SettingManager.GetSettingValue(IwbSettingNames.WeDataCenterIp); private string _engineUrl => SettingManager.GetSettingValue(IwbSettingNames.WeEngineIp); private static M2MqttMsgClient Client = new M2MqttMsgClient(); private IUnitOfWorkManager UnitOfWorkManager { get; } private ISettingManager SettingManager { get; } private ICacheManager CacheManager { get; } private IRepository CampRepository { get; } private IRepository PlayRepository { get; } private IRepository PsRepository { get; } private IRepository PlRepository { get; } private IRepository PuRepository { get; } protected IHubContext IwbHubContext { get; } public bool HasStartPushSender { get; set; } #region MSG-CLIENT public string ClientId { get; set; } /// /// 强制刷新客户端 /// public void RefreshClient() { this.LogInfo($"客户端{ClientId}开始强制刷新!"); Client.DisConnect(); Client = new M2MqttMsgClient(); RegisterClient(); SendMessage(ClientId, $"客户端{ClientId}已强制刷新!"); SendMessage("WeEngine", $"客户端{ClientId}已强制刷新!"); } /// /// 注册客户端 /// public void RegisterClient() { ClientId = IwbConsts.ClientName; this.LogDebug($"ClientId-{ClientId}"); MsgClientDto result; if (IwbConsts.IsDebug) { result = new MsgClientDto() { AppId = ClientId, Name = "在线分布式智慧演练系统", SecretKey = "WePlatformWeOnlineApp", ServerIp = "localhost", ServerPort = 1885, }; } else { result = CacheManager.GetMsgClientDto(ClientId, _url); if (result == null) { //throw new UserFriendlyException("未查询到消息客户端配置!"); this.LogError($"未查询到消息客户端{ClientId}的配置!"); return; } } this.LogDebug($"Client-{result.Obj2String()}"); Client.SetOptions(result.ServerIp, result.ServerPort, ClientId, result.Name, result.SecretKey); Client.SetReceivedHandler(ReceivedHandler); Subscribe(); } private void Subscribe() { if (Client.CheckClient()) { Client.SubscribeTopic(ClientId, false); IwbHubContext.Clients.Group(ClientId).getMqttMsg(new { topic = ClientId, msg = "订阅主题" }); Client.SubscribeTopic("Heartbeat"); IwbHubContext.Clients.Group(ClientId).getMqttMsg(new { topic = $"{ClientId}/Heartbeat", msg = "订阅主题" }); var t = typeof(MessageType); var fts = t.GetFields(BindingFlags.Static | BindingFlags.Public); foreach (var f in fts) { string name = f.Name; Client.SubscribeTopic($"{name}/+"); IwbHubContext.Clients.Group(ClientId).getMqttMsg(new { topic = $"{ClientId}/{name}/+", msg = "订阅主题" }); //AsyncHelper.RunSync(() => Client.SubscribeTopic(name)); } } } public void SendMessage(WeMessage message, MessageType type, string clientId = null) { if (Client.NotValidate) { RegisterClient(); } var msg = message.Obj2String(); Client.SendMsg(type.ToString(), msg, clientId); IwbHubContext.Clients.Group(ClientId).getSendMqttMsg(new { topic = $"{ClientId}/{type}/", msg }); } public void SendMessage(WeMessage message) { if (Client.NotValidate) { RegisterClient(); } var msg = message.Obj2String(); Client.SendMsg(message.Type.ToString(), msg, message.TargetClientId); IwbHubContext.Clients.Group(ClientId).getSendMqttMsg(new { topic = $"{message.TargetClientId}/{message.Type}/", msg }); } public void SendMessage(string msg) { if (Client.NotValidate) { RegisterClient(); } Client.SendMessage(ClientId, msg); IwbHubContext.Clients.Group(ClientId).getSendMqttMsg(new { topic = $"{ClientId}", msg }); } public void SendMessage(string topic, string msg) { if (Client.NotValidate) { RegisterClient(); } Client.SendMessage(topic, msg); IwbHubContext.Clients.Group(ClientId).getSendMqttMsg(new { topic, msg }); } /// /// 消息接受回调处理 /// /// private void ReceiveMsgHandler(string msg) { try { var message = msg.Str2Obj(); if (message != null) { switch (message.Type) { case MessageType.Start: ReceiveStart(message); break; case MessageType.End: ReceiveEnd(message); break; case MessageType.RunningInfo: ReceiveRunningInfo(message); break; case MessageType.RoundScore: ReceiveRoundScore(message); break; case MessageType.SceneInfo: ReceiveScene(message); break; case MessageType.GuideInfo: ReceiveGuide(message); break; case MessageType.Environment: ReceiveEnvironment(message); break; case MessageType.CommandMatchSuccess: ReceiveMatchSuccess(message); break; case MessageType.CommonMessage: ReceiveCommonMsg(message); break; } } else { typeof(WeOnlineAppMsgClientManager).LogError("MSG ERROR:" + msg); } } catch (Exception e) { typeof(WeOnlineAppMsgClientManager).LogError(e); } } /// /// 消息接受回调处理 /// /// /// private void ReceivedHandler(object sender, MqttMsgPublishEventArgs e) { string msg = System.Text.Encoding.UTF8.GetString(e.Message); IwbHubContext.Clients.Group(IwbConsts.ClientName).getMqttMsg(new { topic = e.Topic, msg }); if (e.Topic == ClientId || e.Topic == $"{ClientId}/Heartbeat") { return; } ReceiveMsgHandler(msg); } //private IMqttApplicationMessageReceivedHandler ReceivedHandler => // new MqttApplicationMessageReceivedHandlerDelegate( // (arg) => // { // string payload = System.Text.Encoding.UTF8.GetString(arg.ApplicationMessage.Payload); // var message = payload.Str2Obj(); // if (message != null) // { // switch (message.MsgType) // { // case MessageType.Environment: // break; // case MessageType.RunningInfo: // ReceiveRunningInfo(message); // break; // case MessageType.RoundScore: // ReceiveRoundScore(message); // break; // case MessageType.CommonMessage: // break; // case MessageType.GuideInfo: // break; // } // } // else // { // typeof(WeAppMsgClientManager).LogError("Message ERROR:" + payload); // } // }); #endregion MSG-CLIENT public static string GetTargetClient() { var str = IwbConsts.ClientName; var others = ConfigurationManager.AppSettings["ThirdMessageClientIds"] ?? ""; if (others.IsNotEmpty()) { str += $"@{others}"; } return str; } [UnitOfWork] protected virtual void ReceiveStart(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.GetAllIncluding(a => a.CampInfo).FirstOrDefault(a => a.Id == playNo); if (play != null) { var date = DateTime.Now; play.PlayState = CampPlayStateDefinition.Run; play.StartDate = date; var users = PuRepository.GetAllList(a => a.PlayNo == play.Id); if (users.Any()) { foreach (var pu in users) { pu.PlayerState = CampPlayUserStateDefinition.Run; PuRepository.Update(pu); } UnitOfWorkManager.Current.SaveChanges(); } CacheManager.SetPlayInfo(play); IwbHubContext.Clients.Group(play.InvitationCode).getReloadPage(new { no = play.Id }.Obj2String()); //ScenePusher scenePusher = new ScenePusher(); //scenePusher.SendMsg += (msg) => { PushMessage(msg, play.InvitationCode); }; //_scenePushes[playNo] = scenePusher; PlayRepository.Update(play); UnitOfWorkManager.Current.SaveChanges(); } } [UnitOfWork] protected virtual void ReceiveEnd(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.GetAllIncluding(a => a.CampInfo).FirstOrDefault(a => a.Id == playNo); if (play != null) { var date = DateTime.Now; //try //{ // new TaskFactory().StartNew(() => { CacheManager.GetFullPackageDataNode(play.CampInfo.PackageNo, _url); }); //} //catch //{ // // //} play.PlayState = CampPlayStateDefinition.End; play.EndDate = date; play.TrainingMinute = play.StartDate?.GetTimeSpanMinute(date) ?? 0; var users = PuRepository.GetAllList(a => a.PlayNo == play.Id); if (users.Any()) { foreach (var pu in users) { pu.PlayerState = CampPlayUserStateDefinition.End; PuRepository.Update(pu); } } CacheManager.SetPlayInfo(play); PlayRepository.Update(play); UnitOfWorkManager.Current.SaveChanges(); IwbHubContext.Clients.Group(play.InvitationCode).getReloadPage(new { no = play.Id }.Obj2String()); StopPushScene(playNo); } } [UnitOfWork] protected virtual void ReceiveRunningInfo(WeMessage message) { var playNo = message.RunningId; //var runningInfo = message.Content.Str2Obj(); var runningInfo = GetRunningInfo(playNo); if (runningInfo != null) { var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play != null) { runningInfo.Name = play.Name; CacheManager.GetCache(IwbCacheNames.PlayRunningInfoCache).Set(playNo, runningInfo); play.RunningInfo = runningInfo.Obj2String(); play.RoundIndex = runningInfo.CurrentRoundIndex; IwbHubContext.Clients.Group(play.InvitationCode).getRunningChange(new { no = playNo }.Obj2String()); CacheManager.SetPlayInfo(play); PlayRepository.Update(play); UnitOfWorkManager.Current.SaveChanges(); } } } private PackageDataNode GetRunningInfo(string no) { var url = $"{_engineUrl.Ew("/")}api/services/Engine/Run/QueryPackageDataNode?id={no}"; var result = url.RequestPost(""); var info = result.Str2Obj(); if (info != null) { CacheManager.SetGroupRunningInfo(no, info); } return info; } [UnitOfWork] protected virtual void ReceiveRoundScore(WeMessage message) { var playNo = message.RunningId; var roundScoreInfo = message.Content.Str2Obj(); if (roundScoreInfo == null) { return; } var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play == null) { return; } //var gs = await GsRepository.FirstOrDefaultAsync(a => // a.GroupNo == groupNo && a.RoundIndex == roundScoreInfo.RoundIndex); var ps = CacheManager.GetGroupRoundScore(playNo, roundScoreInfo.RoundIndex, PsRepository); var tagScores = new List(); var oldTagScores = ps?.BehaviorTagScoreInfo.Str2Obj>(); var activeTag = CacheManager.GetCampTags(play.CampNo, CampRepository).Result; //var pushScores = new List(); if (roundScoreInfo.TagScores != null && activeTag != null) { foreach (var tNo in activeTag) { var tagScore = roundScoreInfo.TagScores.FirstOrDefault(a => a.TagNo.Trim() == tNo.Trim()); if (tagScore != null) { //pushScores.Add(new TagScoreInfo() //{ // TagNo = tNo, // SystemScore = tagScore.SystemScore, // TotalScore = tagScore.TotalScore //}); var oldTagScore = oldTagScores?.FirstOrDefault(a => a.TagNo.Trim() == tagScore.TagNo.Trim()); if (oldTagScore != null) { tagScore.SystemScore = oldTagScore.SystemScore + tagScore.SystemScore; tagScore.CorrectionScore = oldTagScore.CorrectionScore == 0 ? 0 : oldTagScore.CorrectionScore + tagScore.SystemScore; tagScore.SystemScore = tagScore.SystemScore > tagScore.TotalScore ? tagScore.TotalScore : tagScore.SystemScore; } } else { tagScore = oldTagScores?.FirstOrDefault(a => a.TagNo.Trim() == tNo.Trim()) ?? new TagScoreInfo() { TagNo = tNo, CorrectionScore = 0, SystemScore = 0, TotalScore = 0 }; } tagScores.Add(tagScore); } } if (roundScoreInfo.KeyWords.IsNotEmpty()) { var arr = roundScoreInfo.KeyWords.Split('|'); if (int.TryParse(arr[0], out var logId)) { var log = PlRepository.FirstOrDefault(a => a.Id == logId); if (log != null) { log.LogState = LogStateDefinition.HasMatch; PlRepository.Update(log); } } } if (ps == null) { ps = new CampPlayScoreInfo() { CampNo = play.CampNo, PlayNo = playNo, RoundIndex = roundScoreInfo.RoundIndex, SystemScore = roundScoreInfo.RoundScore, BehaviorTagScoreInfo = tagScores.Obj2StringCamelCase() }; PsRepository.Insert(ps); } else { ps.CampPlayInfo = null; ps.PlayNo = playNo; ps.SystemScore = roundScoreInfo.RoundScore; ps.BehaviorTagScoreInfo = tagScores.Obj2StringCamelCase(); PsRepository.Update(ps); } CacheManager.SetGroupRoundScore(playNo, roundScoreInfo.RoundIndex, ps); IwbHubContext.Clients.Group(play.InvitationCode) .getRoundScore(new { no = playNo, round = roundScoreInfo.RoundIndex, roundIndex = roundScoreInfo.RoundIndex, systemScore = roundScoreInfo.RoundScore, tagScores }.Obj2StringCamelCase()); } [UnitOfWork] protected virtual void ReceiveScene(WeMessage message) { var playNo = message.RunningId; var scene = message.Content.Str2Obj(); if (scene != null) { var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play != null) { var scenePathList = CacheManager.GetScenePathList(playNo, PlayRepository); scenePathList.hasChange = true; scenePathList.PathList = scenePathList.PathList ?? new List(); if (!scenePathList.PathList.Contains(scene.Path)) { scenePathList.PathList.Add(scene.Path); } CacheManager.SetScenePathList(playNo, scenePathList); SendScenePusher(playNo, play.InvitationCode, new ScenePushMessage(playNo, scene.Path)); } } } [UnitOfWork] protected virtual void ReceiveGuide(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play == null) { return; } SendScenePusher(playNo, play.InvitationCode, new ScenePushMessage(PushMessageDefinition.Guide) { content = message.Content }); } [UnitOfWork] protected virtual void ReceiveEnvironment(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play == null) { return; } SendScenePusher(playNo, play.InvitationCode, new ScenePushMessage(PushMessageDefinition.Environment) { content = message.Content }); } [UnitOfWork] protected virtual void ReceiveMatchSuccess(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play == null) { return; } IwbHubContext.Clients.Group(play.InvitationCode).getMatchSuccess(message.Content); } [UnitOfWork] protected virtual void ReceiveCommonMsg(WeMessage message) { var playNo = message.RunningId; var play = PlayRepository.FirstOrDefault(a => a.Id == playNo); if (play == null) { return; } SendScenePusher(playNo, play.InvitationCode, new ScenePushMessage(PushMessageDefinition.CommonMsg) { content = message.Content }); } /// /// 开始推送情景(解决页面还未加载时就推送情景) /// 需要页面第一次加载打开推送开关后再开始推送 /// /// public static bool StartPushScene(string playNo) { ScenePusher scenePusher = _scenePushes.ContainsKey(playNo) ? _scenePushes[playNo] : new ScenePusher(); _scenePushes[playNo] = scenePusher; return scenePusher.Start(); } public static void StopPushScene(string no) { if (_scenePushes.ContainsKey(no)) { _scenePushes[no].Stop(); } } private void SendScenePusher(string no, string code, ScenePushMessage pushMsg) { ScenePusher scenePusher; if (_scenePushes.ContainsKey(no)) { scenePusher = _scenePushes[no]; if (scenePusher.NeedHandel) { scenePusher.SendMsg += (msg) => { PushMessage(msg, code); }; } } else { scenePusher = new ScenePusher(); scenePusher.SendMsg += (msg) => { PushMessage(msg, code); }; _scenePushes[no] = scenePusher; } scenePusher.Push(pushMsg); } private void PushMessage(ScenePushMessage msg, string code) { switch (msg.type) { case PushMessageDefinition.Scene: IwbHubContext.Clients.Group(code).getNewScene(msg); break; case PushMessageDefinition.Guide: IwbHubContext.Clients.Group(code).getGuide(msg.content); break; case PushMessageDefinition.Environment: IwbHubContext.Clients.Group(code).getEnvironment(msg.content); break; case PushMessageDefinition.CommonMsg: IwbHubContext.Clients.Group(code).getCommonMsg(msg.content); break; } } } }