ConsultationRecipient.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using Vinno.IUS.Common.Log;
  7. using Vinno.IUS.Common.Network;
  8. using Vinno.IUS.Common.Network.Leaf;
  9. using Vinno.IUS.Common.Network.Transfer;
  10. using Vinno.vCloud.Protocol.Infrastructures;
  11. using Vinno.vCloud.Protocol.Messages.Client.RemoteDiagnosis;
  12. using Vinno.vCloud.Protocol.Messages.Live;
  13. namespace Vinno.vCloud.Common.FIS.Consultation
  14. {
  15. internal class ConsultationRecipient : ConsultationClient
  16. {
  17. private readonly ManualResetEvent _timingManualResetEvent = new ManualResetEvent(false);
  18. private readonly string _terminalId;
  19. private readonly string _uniqueId;
  20. private string _initiatorId;
  21. private bool _isEmergencyRequesting;
  22. private string _cameraId;
  23. private string _micId;
  24. private string _speakerId;
  25. /// <summary>
  26. /// Raised when receive a Consultation request from server.
  27. /// </summary>
  28. public event EventHandler<ConsultationInfo> ConsultationRequestArrived;
  29. public ConsultationRecipient(ConsultationLiveVideoProvider videoProvider, string terminalId, string uniqueId) : base(videoProvider)
  30. {
  31. _terminalId = terminalId;
  32. _uniqueId = uniqueId;
  33. }
  34. /// <summary>
  35. /// Send a join Rtc Consultation Live request
  36. /// </summary>
  37. /// <returns></returns>
  38. public LiveStates AcceptConsultation(string cameraHardwareId, string micHardwareId, string speakerHardwareId)
  39. {
  40. var liveState = LiveStates.UnknowException;
  41. try
  42. {
  43. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  44. {
  45. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  46. return LiveStates.TalkIsBusy;
  47. }
  48. CurrentLiveStatus = LiveStates.RecipientAcceptting;
  49. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} accept Consultation request begin");
  50. using (var request = new AcceptMeetingRequest())
  51. {
  52. request.RoomId = ConsultationInfo.RoomId;
  53. request.InitiatorId = _initiatorId;
  54. request.RecipientId = FLYINSONOUser.AccountId;
  55. request.FeatureSource = FeatureSource.RemoteDiagnosis;
  56. request.Source = FLYINSONOUser.LoginSource;
  57. request.PushLiveState = ConsultationInfo.State;
  58. request.ClientLanguage = GetCurrentLanguage();
  59. var result = ClientLeaf.Send(request);
  60. Logger.WriteLineInfo($"Send AcceptMeetingRequest To Server");
  61. if (result != null)
  62. {
  63. var resultMessage = AcceptMeetingResult.Convert(result);
  64. if (resultMessage != null)
  65. {
  66. liveState = resultMessage.State;
  67. if (resultMessage != null && resultMessage.State == LiveStates.OK)
  68. {
  69. lock (ConsultationInfoLocker)
  70. {
  71. ConsultationInfo.State = resultMessage.State;
  72. }
  73. StartConsultation(cameraHardwareId, micHardwareId, speakerHardwareId);
  74. CurrentLiveStatus = LiveStates.RecipientAcceptted;
  75. return CurrentLiveStatus;
  76. }
  77. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} accept meeConsultationting request end");
  78. }
  79. }
  80. }
  81. }
  82. catch (ConnectionTimeoutException ex)
  83. {
  84. Logger.WriteLineError($"ConnectionTimeoutException happened when accept Consultation{ex}");
  85. }
  86. catch (Exception ex)
  87. {
  88. Logger.WriteLineError($"Exception happened when accept Consultation{ex}");
  89. }
  90. var recipientId = ConsultationInfo?.ConsultationMemberInfos?.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Recipient)?.Id;
  91. if (recipientId == FLYINSONOUser.AccountId)
  92. {
  93. Hangup(true);
  94. }
  95. else
  96. {
  97. Hangup(false);
  98. }
  99. return liveState;
  100. }
  101. /// <summary>
  102. /// Send a Rtc Consultation Live rejectation request
  103. /// </summary>
  104. /// <returns></returns>
  105. public LiveStates RejectConsultation()
  106. {
  107. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} reject meet request begin");
  108. CurrentLiveStatus = LiveStates.RecipientRejected;
  109. StopConsultation();
  110. var roomId = ConsultationInfo.RoomId;
  111. var initiatorId = ConsultationInfo.ConsultationMemberInfos.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Initiator)?.Id;
  112. lock (ConsultationInfoLocker)
  113. {
  114. ConsultationInfo = null;
  115. }
  116. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} reject Consultation request end");
  117. using (var request = new RejectMeetingRequest())
  118. {
  119. request.RoomId = roomId;
  120. request.RecipientId = FLYINSONOUser.AccountId;
  121. request.InitiatorId = initiatorId;
  122. request.LoginSource = FLYINSONOUser.LoginSource;
  123. request.ClientLanguage = GetCurrentLanguage();
  124. var result = ClientLeaf.Send(request);
  125. Logger.WriteLineInfo($"Send RejectMeetingRequest To Server");
  126. if (result != null)
  127. {
  128. var resultMessage = MeetingResult.Convert(result); //拒绝会诊result
  129. if (resultMessage != null)
  130. {
  131. return resultMessage.State;
  132. }
  133. }
  134. }
  135. return LiveStates.UnknowException;
  136. }
  137. protected override void HandleConsultationMemberNotificationArrived(MeetingMemberNotification meetingMemberNotification)
  138. {
  139. if (ConsultationInfo != null)
  140. {
  141. var mem = meetingMemberNotification.Members.FirstOrDefault(f => f.RoleType == MeetingRoleType.Recipient && f.OperationType == ClientMessageOperationType.Delete);
  142. if (mem != null)
  143. {
  144. OnDisconnected(ConsultationDisconnectedType.HangupByOther);
  145. }
  146. else
  147. {
  148. ConsultationMemberChange(meetingMemberNotification);
  149. foreach (var member in meetingMemberNotification.Members)
  150. {
  151. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == member.Id);
  152. if (member.OperationType == ClientMessageOperationType.Add)
  153. {
  154. ConsultationRoleType roleType = ConsultationRoleType.Initiator;
  155. switch (member.RoleType)
  156. {
  157. case MeetingRoleType.Initiator:
  158. roleType = ConsultationRoleType.Initiator;
  159. break;
  160. case MeetingRoleType.Recipient:
  161. roleType = ConsultationRoleType.Recipient;
  162. break;
  163. case MeetingRoleType.Expert:
  164. roleType = ConsultationRoleType.Expert;
  165. break;
  166. case MeetingRoleType.Administrator:
  167. roleType = ConsultationRoleType.Administrator;
  168. break;
  169. }
  170. var meetingMemberInfo = new ConsultationMemberInfo
  171. {
  172. OperationType = member.OperationType,
  173. RoleType = roleType,
  174. RoomId = member.RoomId,
  175. LoginSource = member.LoginSource,
  176. State = member.State,
  177. Id = member.Id,
  178. Name = member.Name,
  179. DisplayName = member.DisplayName,
  180. Avatar = member.Avatar,
  181. UserSign = member.UserSign,
  182. PushUrl = member.PushUrl,
  183. PullRtmpUrl = member.PullRtmpUrl,
  184. PullFlvUrl = member.PullFlvUrl,
  185. PullHlsUrl = member.PullHlsUrl,
  186. PushLiveState = member.PushLiveState,
  187. };
  188. if (memberInfo == null)
  189. {
  190. ConsultationInfo.ConsultationMemberInfos.Add(meetingMemberInfo);
  191. }
  192. else
  193. {
  194. memberInfo = meetingMemberInfo;
  195. }
  196. }
  197. else if (member.OperationType == ClientMessageOperationType.Delete)
  198. {
  199. if (memberInfo != null)
  200. {
  201. ConsultationInfo?.ConsultationMemberInfos.Remove(memberInfo);
  202. }
  203. }
  204. }
  205. base.HandleConsultationMemberNotificationArrived(meetingMemberNotification);
  206. }
  207. }
  208. }
  209. protected override void OnMessageArrived(object sender, Message e)
  210. {
  211. try
  212. {
  213. base.OnMessageArrived(sender, e);
  214. var startMeetingNotification = StartMeetingNotification.Convert(e); //接收者收到被邀请通知
  215. if (startMeetingNotification != null)
  216. {
  217. HandleStartMeetingNotification(startMeetingNotification);
  218. }
  219. var cancelStartMeetingNotification = CancelStartMeetingNotification.Convert(e); //取消会诊通知
  220. if (cancelStartMeetingNotification != null)
  221. {
  222. HandleCancelStartMeetingNotification();
  223. }
  224. var rejectEmergencyConsultationNotification = RejectEmergencyConsultationNotification.Convert(e); //专家拒绝紧急会诊通知
  225. if (rejectEmergencyConsultationNotification != null)
  226. {
  227. HandleRejectEmergencyConsultationNotification(rejectEmergencyConsultationNotification);
  228. }
  229. }
  230. catch (Exception ex)
  231. {
  232. Logger.WriteLineError($"Consultation Recipient OnMessageArrived Error:{ex}");
  233. }
  234. }
  235. private void HandleRejectEmergencyConsultationNotification(RejectEmergencyConsultationNotification rejectEmergencyConsultationNotification)
  236. {
  237. Logger.WriteLineInfo($"MeetingRecipient OnRejectEmergencyConsultationNotificationArrived,reason:{rejectEmergencyConsultationNotification.Reason}");
  238. if (EmergencyConsultationInfo != null && EmergencyConsultationInfo.SortExperts != null && EmergencyConsultationInfo.ConsultationId == rejectEmergencyConsultationNotification.ConsultationId)
  239. {
  240. _timingManualResetEvent.Set();
  241. var prevSortExpert = EmergencyConsultationInfo.SortExperts.FirstOrDefault(f => f.UserId == rejectEmergencyConsultationNotification.ExpertId);
  242. if (prevSortExpert != null)
  243. {
  244. var nextSortExpert = EmergencyConsultationInfo.SortExperts.FirstOrDefault(f => f.Sort == prevSortExpert.Sort + 1);
  245. if (nextSortExpert != null)
  246. {
  247. if (!CreateAndStartEmergencyConsultation(nextSortExpert))
  248. {
  249. _timingManualResetEvent.Set();
  250. _isEmergencyRequesting = false;
  251. CurrentLiveStatus = LiveStates.RecipientRejected;
  252. OnRejectConsultationNotifyArrived(new ConsultationSubscriberInfo
  253. {
  254. RoomId = null,
  255. Id = rejectEmergencyConsultationNotification.ExpertId
  256. });
  257. lock (EmergencyConsultationLocker)
  258. {
  259. EmergencyConsultationInfo = null;
  260. }
  261. }
  262. }
  263. else
  264. {
  265. _isEmergencyRequesting = false;
  266. CurrentLiveStatus = LiveStates.RecipientRejected;
  267. OnRejectConsultationNotifyArrived(new ConsultationSubscriberInfo
  268. {
  269. RoomId = null,
  270. Id = rejectEmergencyConsultationNotification.ExpertId
  271. });
  272. lock (EmergencyConsultationLocker)
  273. {
  274. EmergencyConsultationInfo = null;
  275. }
  276. }
  277. }
  278. }
  279. }
  280. private void HandleCancelStartMeetingNotification()
  281. {
  282. if (ConsultationInfo != null)
  283. {
  284. OnDisconnected(ConsultationDisconnectedType.CancelledByInitiator);
  285. Logger.WriteLineInfo($"CancelStartMeetingNotification handled");
  286. }
  287. }
  288. private void HandleStartMeetingNotification(StartMeetingNotification startMeetingNotification)
  289. {
  290. Logger.WriteLineInfo("LiveMeeting StartMeetingNotification Arrived");
  291. CurrentLiveStatus = LiveStates.ChatRequestArrived;
  292. var mode = startMeetingNotification.Mode;
  293. var roomId = startMeetingNotification.RoomId;
  294. var protocol = startMeetingNotification.LiveProtocol;
  295. List<ConsultationMemberInfo> meetingMemberInfos = new List<ConsultationMemberInfo>();
  296. foreach (var member in startMeetingNotification.Members)
  297. {
  298. ConsultationRoleType roleType = ConsultationRoleType.Initiator;
  299. switch (member.RoleType)
  300. {
  301. case MeetingRoleType.Initiator:
  302. roleType = ConsultationRoleType.Initiator;
  303. break;
  304. case MeetingRoleType.Recipient:
  305. roleType = ConsultationRoleType.Recipient;
  306. break;
  307. case MeetingRoleType.Expert:
  308. roleType = ConsultationRoleType.Expert;
  309. break;
  310. case MeetingRoleType.Administrator:
  311. roleType = ConsultationRoleType.Administrator;
  312. break;
  313. }
  314. var meetingMemberInfo = new ConsultationMemberInfo
  315. {
  316. OperationType = member.OperationType,
  317. RoleType = roleType,
  318. RoomId = member.RoomId,
  319. LoginSource = member.LoginSource,
  320. State = member.State,
  321. Id = member.Id,
  322. Name = member.Name,
  323. DisplayName = member.DisplayName,
  324. Avatar = member.Avatar,
  325. UserSign = member.UserSign,
  326. PushUrl = member.PushUrl,
  327. PullRtmpUrl = member.PullRtmpUrl,
  328. PullFlvUrl = member.PullFlvUrl,
  329. PullHlsUrl = member.PullHlsUrl,
  330. PushLiveState = member.PushLiveState,
  331. };
  332. meetingMemberInfos.Add(meetingMemberInfo);
  333. }
  334. var terminalInfo = new TerminalInfo();
  335. var liveTerminal = startMeetingNotification.LiveTerminals.FirstOrDefault();
  336. var channels = new List<PullChannnelUrl>();
  337. if (liveTerminal.Channels != null)
  338. {
  339. foreach (var channelInfo in liveTerminal.Channels)
  340. {
  341. var channel = new PullChannnelUrl
  342. {
  343. Enable = channelInfo.Enable,
  344. FlvUrl = channelInfo.FlvUrl,
  345. Height = channelInfo.Height,
  346. HlsUrl = channelInfo.HlsUrl,
  347. Name = channelInfo.Name,
  348. RtmpUrl = channelInfo.RtmpUrl,
  349. UserId = channelInfo.UserId,
  350. Width = channelInfo.Width,
  351. };
  352. channels.Add(channel);
  353. }
  354. }
  355. if (liveTerminal.IsMultiChannels)//Windows魔盒
  356. {
  357. var mainTerminalInfo = liveTerminal.Channels.Select(f => f.Name).Contains("Main") ? liveTerminal.Channels.FirstOrDefault(f => f.Name == "Main") : liveTerminal.Channels.FirstOrDefault();
  358. var cameraInfo = liveTerminal.Channels.Count > 1 ? liveTerminal.Channels.FirstOrDefault(x => x.Name != "Main") : null;
  359. terminalInfo = new TerminalInfo()
  360. {
  361. OperationType = liveTerminal.OperationType,
  362. TerminalLiveEnabled = mainTerminalInfo.Enable,
  363. CameraLiveEnabled = cameraInfo?.Enable ?? false,
  364. IsMergeChannel = liveTerminal.IsMergeChannel,
  365. TerminalWidth = mainTerminalInfo.Width,
  366. TerminalHeight = mainTerminalInfo.Height,
  367. TerminalUrl = mainTerminalInfo.RtmpUrl,
  368. CameraWidth = cameraInfo?.Width ?? 0,
  369. CameraHeight = cameraInfo?.Height ?? 0,
  370. CameraUrl = cameraInfo?.RtmpUrl,
  371. TerminalLiveProtocol = liveTerminal.LiveProtocol,
  372. IntegerRoomId = liveTerminal.IntegerRoomId,
  373. TerminalIntegerRoomId = liveTerminal.TerminalIntegerRoomId,
  374. State = liveTerminal.State,
  375. Id = string.IsNullOrEmpty(mainTerminalInfo.UserId) ? liveTerminal.Id : mainTerminalInfo.UserId,
  376. CameraId = cameraInfo?.UserId,
  377. IsMultiChannels = liveTerminal.IsMultiChannels,
  378. PullDataMode = liveTerminal.PullDataMode,
  379. TerminalRoomId = liveTerminal.RoomId,
  380. Channels = channels,
  381. };
  382. }
  383. else
  384. {
  385. terminalInfo = new TerminalInfo()
  386. {
  387. OperationType = liveTerminal.OperationType,
  388. TerminalLiveEnabled = liveTerminal.TerminalLiveEnabled,
  389. CameraLiveEnabled = liveTerminal.CameraLiveEnabled,
  390. IsMergeChannel = liveTerminal.IsMergeChannel,
  391. TerminalWidth = liveTerminal.TerminalWidth,
  392. TerminalHeight = liveTerminal.TerminalHeight,
  393. TerminalUrl = liveTerminal.TerminalUrl,
  394. CameraWidth = liveTerminal.CameraWidth,
  395. CameraHeight = liveTerminal.CameraHeight,
  396. CameraUrl = liveTerminal.CameraUrl,
  397. TerminalLiveProtocol = liveTerminal.LiveProtocol,
  398. IntegerRoomId = liveTerminal.IntegerRoomId,
  399. TerminalIntegerRoomId = liveTerminal.TerminalIntegerRoomId,
  400. State = liveTerminal.State,
  401. Id = liveTerminal.Id,
  402. IsMultiChannels = liveTerminal.IsMultiChannels,
  403. PullDataMode = liveTerminal.PullDataMode,
  404. TerminalRoomId = liveTerminal.RoomId,
  405. Channels = channels,
  406. };
  407. }
  408. lock (ConsultationInfoLocker)
  409. {
  410. var info = new ConsultationInfo(ChatRole.Recipient);
  411. info.AppId = startMeetingNotification.AppId;
  412. info.RoomId = startMeetingNotification.RoomId;
  413. info.LiveTalkingMode = mode;
  414. info.IntegerRoomId = startMeetingNotification.IntegerRoomId;
  415. info.LiveProtocol = startMeetingNotification.LiveProtocol;
  416. info.ConsultationMemberInfos = meetingMemberInfos;
  417. info.TerminalInfo = terminalInfo;
  418. info.IsCurrentTerminal = info.TerminalInfo?.Id == _terminalId;
  419. ConsultationInfo = info;
  420. _initiatorId = ConsultationInfo?.ConsultationMemberInfos?.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Initiator)?.Id;
  421. }
  422. var userName = GetAccoutNameByAccountId(startMeetingNotification.InitiatorId);
  423. Logger.WriteLineInfo($"StartMeetingNotification handled RoomId:{ConsultationInfo.RoomId}");
  424. if (!_isEmergencyRequesting)
  425. {
  426. ConsultationRequestArrived?.Invoke(this, ConsultationInfo);
  427. }
  428. else
  429. {
  430. _timingManualResetEvent.Set();
  431. _isEmergencyRequesting = false;
  432. AcceptConsultation(_cameraId, _micId, _speakerId);
  433. if (CurrentLiveStatus == LiveStates.RecipientAcceptted)
  434. {
  435. OnJoinConsultationNotifyArrived();
  436. }
  437. }
  438. }
  439. public EnumEmergencyConsultationResult RequestEmergencyConsultation(string cameraId, string micId, string speakerId)
  440. {
  441. var liveState = EnumEmergencyConsultationResult.UnknowException;
  442. try
  443. {
  444. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  445. {
  446. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} Request Emergency Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  447. return EnumEmergencyConsultationResult.IsBusy;
  448. }
  449. if (_isEmergencyRequesting)
  450. {
  451. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} Request Emergency Consultation failed due to is Requesting Emergency Consultation");
  452. return EnumEmergencyConsultationResult.IsBusy;
  453. }
  454. _cameraId = cameraId;
  455. _micId = micId;
  456. _speakerId = speakerId;
  457. var emergencyConsultationInfo = GetEmergencyConsultationExpertsInfo();
  458. lock (EmergencyConsultationLocker)
  459. {
  460. EmergencyConsultationInfo = emergencyConsultationInfo;
  461. }
  462. switch (EmergencyConsultationInfo.NoExpertCause)
  463. {
  464. case NoExpertCause.ExpertsOfflineAll:
  465. return EnumEmergencyConsultationResult.ExpertsOfflineAll;
  466. case NoExpertCause.ExpertsDeficiencyOfTimeAll:
  467. return EnumEmergencyConsultationResult.ExpertsDeficiencyOfTimeAll;
  468. case NoExpertCause.ExpertsOfflineOrDeficiencyOfTime:
  469. return EnumEmergencyConsultationResult.ExpertsOfflineOrDeficiencyOfTime;
  470. }
  471. if (EmergencyConsultationInfo.SortExperts == null || EmergencyConsultationInfo.SortExperts.Count == 0)
  472. {
  473. return EnumEmergencyConsultationResult.ExpertsIsNotExist;
  474. }
  475. CurrentLiveStatus = LiveStates.InitiatorRequestingChat;
  476. Logger.WriteLineInfo($"Consultation Live-- {FLYINSONOUser.Name} request Emergency Consultation request begin");
  477. if (CreateAndStartEmergencyConsultation(EmergencyConsultationInfo.SortExperts.FirstOrDefault()))
  478. {
  479. _isEmergencyRequesting = true;
  480. return EnumEmergencyConsultationResult.OK;
  481. }
  482. else
  483. {
  484. _isEmergencyRequesting = false;
  485. _timingManualResetEvent.Set();
  486. return EnumEmergencyConsultationResult.Failed;
  487. }
  488. }
  489. catch (Exception ex)
  490. {
  491. Logger.WriteLineError($"Exception happened when RequestEmergencyConsultation Consultation{ex}");
  492. }
  493. _isEmergencyRequesting = false;
  494. return liveState;
  495. }
  496. private void StartTimingTask()
  497. {
  498. _timingManualResetEvent.Reset();
  499. Task.Run(() =>
  500. {
  501. try
  502. {
  503. var currentSort = EmergencyConsultationInfo.CurrentSort;
  504. var currentExpert = EmergencyConsultationInfo.SortExperts.FirstOrDefault(f => f.Sort == currentSort);
  505. Logger.WriteLineInfo($"Consultation Recipient Timing Task Start,Current Sort is {currentSort},ExpertName:{currentExpert?.UserName},ExpertId:{currentExpert?.UserId}");
  506. if (!_timingManualResetEvent.WaitOne(20000))
  507. {
  508. Logger.WriteLineError($"Consultation Emergency Consultation Call Time out,Will Cancel and Request Next Automatic");
  509. if (EmergencyConsultationInfo != null)
  510. {
  511. CancelEmergencyConsultation();
  512. var emergencyConsultationInfo = GetEmergencyConsultationExpertsInfo();
  513. lock (EmergencyConsultationLocker)
  514. {
  515. EmergencyConsultationInfo = emergencyConsultationInfo;
  516. }
  517. var nextSortExpert = EmergencyConsultationInfo.SortExperts.FirstOrDefault(f => f.Sort == currentSort + 1);
  518. if (nextSortExpert != null)
  519. {
  520. if (CreateAndStartEmergencyConsultation(nextSortExpert))
  521. {
  522. _isEmergencyRequesting = true;
  523. }
  524. else
  525. {
  526. _timingManualResetEvent.Set();
  527. _isEmergencyRequesting = false;
  528. CurrentLiveStatus = LiveStates.RecipientRejected;
  529. OnRejectConsultationNotifyArrived(new ConsultationSubscriberInfo
  530. {
  531. RoomId = null,
  532. Id = currentExpert?.UserId,
  533. });
  534. lock (EmergencyConsultationLocker)
  535. {
  536. EmergencyConsultationInfo = null;
  537. }
  538. }
  539. }
  540. else
  541. {
  542. _timingManualResetEvent.Set();
  543. _isEmergencyRequesting = false;
  544. CurrentLiveStatus = LiveStates.RecipientRejected;
  545. OnRejectConsultationNotifyArrived(new ConsultationSubscriberInfo
  546. {
  547. RoomId = null,
  548. Id = currentExpert?.UserId,
  549. });
  550. lock (EmergencyConsultationLocker)
  551. {
  552. EmergencyConsultationInfo = null;
  553. }
  554. }
  555. }
  556. }
  557. else
  558. {
  559. Logger.WriteLineInfo($"Consultation Recipient Timing Task Ended");
  560. }
  561. }
  562. catch (Exception ex)
  563. {
  564. Logger.WriteLineError($"ConsultationRecipient Timing Task Error:{ex}");
  565. }
  566. });
  567. }
  568. /// <summary>
  569. /// 发起紧急会诊接口
  570. /// </summary>
  571. private bool CreateAndStartEmergencyConsultation(EmergencyConsultationExpertInfo expertDoctor)
  572. {
  573. try
  574. {
  575. if (expertDoctor == null)
  576. {
  577. Logger.WriteLineError($"Consultation Recipient CreateAndStartEmergencyConsultation Failed,ExpertDoctor is null");
  578. return false;
  579. }
  580. EmergencyConsultationInfo.CurrentSort = expertDoctor.Sort;
  581. StartTimingTask();
  582. using (var request = new CreateAndStartEmergencyConsultationRequest())
  583. {
  584. request.EquCode = _uniqueId;
  585. request.ApplyDoctor = FLYINSONOUser.Name;
  586. request.ExpertDoctor = expertDoctor.UserName;
  587. var result = ClientLeaf?.Send(request);
  588. if (result != null)
  589. {
  590. var resultMessage = CreateAndStartEmergencyConsultationResult.Convert(result);
  591. if (resultMessage != null)
  592. {
  593. EmergencyConsultationInfo.ConsultationId = resultMessage.Id;
  594. return resultMessage.IsSuccess;
  595. }
  596. }
  597. }
  598. }
  599. catch (Exception ex)
  600. {
  601. Logger.WriteLineError($"CreateAndStartEmergencyConsultation Error:{ex}");
  602. }
  603. return false;
  604. }
  605. public LiveStates CancelEmergencyConsultation()
  606. {
  607. var livestates = LiveStates.Failed;
  608. try
  609. {
  610. Logger.WriteLineInfo($"Consultation Recipient-- {FLYINSONOUser.Name} CancelEmergencyConsultation begin");
  611. using (var request = new CancelEmergencyConsultationRequest())
  612. {
  613. request.ConsultationId = EmergencyConsultationInfo.ConsultationId;
  614. request.ExpertId = EmergencyConsultationInfo.SortExperts.FirstOrDefault(x => x.Sort == EmergencyConsultationInfo.CurrentSort)?.UserId;
  615. var result = ClientLeaf.Send(request);
  616. if (result != null)
  617. {
  618. var resultMessage = CancelEmergencyConsultationResult.Convert(request);
  619. if (resultMessage != null)
  620. {
  621. if (resultMessage.IsSuccess)
  622. {
  623. CurrentLiveStatus = LiveStates.Cancelled;
  624. }
  625. }
  626. }
  627. }
  628. lock (EmergencyConsultationLocker)
  629. {
  630. EmergencyConsultationInfo = null;
  631. }
  632. _timingManualResetEvent.Set();
  633. _isEmergencyRequesting = false;
  634. Logger.WriteLineInfo($"Consultation Recipient-- {FLYINSONOUser.Name} CancelEmergencyConsultation end");
  635. return livestates;
  636. }
  637. catch (Exception ex)
  638. {
  639. Logger.WriteLineError($"Consultation Recipient-- {FLYINSONOUser.Name} CancelEmergencyConsultation error:{ex}");
  640. return LiveStates.UnknowException;
  641. }
  642. }
  643. public override void Dispose()
  644. {
  645. Logger.WriteLineInfo("Consultation Recipient is dispose begin");
  646. _timingManualResetEvent?.Set();
  647. _isEmergencyRequesting = false;
  648. base.Dispose();
  649. Logger.WriteLineInfo("Consultation Recipient is dispose end");
  650. }
  651. }
  652. }