ConsultationRecipientV2.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Vinno.IUS.Common.Log;
  5. using Vinno.vCloud.Common.FIS.Helper;
  6. using Vinno.vCloud.Protocol.Infrastructures;
  7. using Vinno.vCloud.Protocol.Messages.Client.LiveTalking;
  8. using WingInterfaceLibrary.Interface;
  9. using WingInterfaceLibrary.LiveConsultation;
  10. using WingInterfaceLibrary.Request.Device;
  11. using WingInterfaceLibrary.Request.User;
  12. namespace Vinno.vCloud.Common.FIS.Consultation
  13. {
  14. internal class ConsultationRecipientV2 : ConsultationClientV2
  15. {
  16. private readonly string _deviceId;
  17. /// <summary>
  18. /// Raised when receive a Consultation request from server.
  19. /// </summary>
  20. public event EventHandler<ConsultationInfo> ConsultationRequestArrived;
  21. /// <summary>
  22. /// 当开始Web会诊时
  23. /// </summary>
  24. public event EventHandler<string> StartWebConsultationEvent;
  25. /// <summary>
  26. /// 当切换病人时触发,病人信息与会诊code变更
  27. /// </summary>
  28. public event EventHandler<ChangeLiveConsultationrResult> ChangeLiveConsultationEvent;
  29. public ConsultationRecipientV2(ConsultationLiveVideoProviderV2 videoProvider, ConsultationManagerV2 consultationManager, string deviceId, ILiveConsultationService liveConsultationService, IUserService userService, IDeviceService deviceService) : base(videoProvider, consultationManager, liveConsultationService, userService, deviceService)
  30. {
  31. _deviceId = deviceId;
  32. }
  33. /// <summary>
  34. /// Send a join Rtc Consultation Live request
  35. /// </summary>
  36. /// <returns></returns>
  37. public ResultInfoDTO StartWebConsultation(FlutterLiveConsultationInfo flutterLiveConsultationInfo)
  38. {
  39. try
  40. {
  41. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  42. {
  43. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  44. return new ResultInfoDTO
  45. {
  46. IsSuccess = false,
  47. FailMessage = $"StartWebConsultation Fail,Consultation is busy.",
  48. ErrorCode = 861,
  49. };
  50. }
  51. if (string.IsNullOrEmpty(flutterLiveConsultationInfo.ConsulationId))
  52. {
  53. return new ResultInfoDTO
  54. {
  55. IsSuccess = false,
  56. FailMessage = $"StartWebConsultation Fail,Consultation id is null.",
  57. };
  58. }
  59. IsSecondViewMode = true;
  60. ConsultationInfo consultationInfo = new ConsultationInfo(ChatRole.Recipient)
  61. {
  62. ConsultationId = flutterLiveConsultationInfo.ConsulationId,
  63. };
  64. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(flutterLiveConsultationInfo.ConsulationId, AccountToken, out _);
  65. lock (ConsultationInfoLocker)
  66. {
  67. ConsultationInfo = consultationInfo;
  68. }
  69. StartWebConsultationEvent?.Invoke(this, flutterLiveConsultationInfo.LiveConsultationFlutterUrl);
  70. return new ResultInfoDTO
  71. {
  72. IsSuccess = true,
  73. };
  74. }
  75. catch (Exception ex)
  76. {
  77. Logger.WriteLineError($"Exception happened when StartWebConsultation {ex}");
  78. Hangup(true);
  79. return new ResultInfoDTO
  80. {
  81. IsSuccess = false,
  82. FailMessage = $"StartWebConsultation Error:{ex}",
  83. };
  84. }
  85. }
  86. /// <summary>
  87. /// Send a join Rtc Consultation Live request
  88. /// </summary>
  89. /// <returns></returns>
  90. public ResultInfoDTO StartLiveConsultation(LiveConsultationRequestDTO liveConsultationRequestDTO, string cameraHardwareId, string micHardwareId, string speakerHardwareId)
  91. {
  92. try
  93. {
  94. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted || IsSecondViewMode)
  95. {
  96. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus},IsSecondViewMode:{IsSecondViewMode}");
  97. if (liveConsultationRequestDTO.IsInvite)
  98. {
  99. return new ResultInfoDTO
  100. {
  101. IsSuccess = false,
  102. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  103. ErrorCode = 852,
  104. };
  105. }
  106. else
  107. {
  108. return new ResultInfoDTO
  109. {
  110. IsSuccess = false,
  111. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  112. ErrorCode = 861,
  113. };
  114. }
  115. }
  116. if (string.IsNullOrEmpty(AccountId))
  117. {
  118. CurrentLiveStatus = LiveStates.UnknowException;
  119. return new ResultInfoDTO
  120. {
  121. IsSuccess = false,
  122. FailMessage = $"AcceptConsultation Fail,AccountId is Null.",
  123. };
  124. }
  125. string deviceId = null;
  126. CurrentLiveStatus = LiveStates.RecipientAcceptting;
  127. Logger.WriteLineInfo($"Consultation Live-- {AccountName} start Consultation request begin");
  128. ConsultationInfo consultationInfo;
  129. if (liveConsultationRequestDTO.IsInvite)
  130. {
  131. var initiateLiveConsultationRequest = new InitiateLiveConsultationRequest
  132. {
  133. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  134. Token = AccountToken,
  135. CheckOnly = false,
  136. };
  137. var initiateLiveConsultationResult = JsonRpcHelper.InitiateLiveConsultation(LiveConsultationService, initiateLiveConsultationRequest, out var errorCode);
  138. if (initiateLiveConsultationResult == null)
  139. {
  140. CurrentLiveStatus = LiveStates.UnknowException;
  141. return new ResultInfoDTO
  142. {
  143. IsSuccess = false,
  144. FailMessage = $"Initiate Consultation Fail,result is null",
  145. ErrorCode = errorCode
  146. };
  147. }
  148. consultationInfo = DTOConverter.ConvertInitiateLiveConsultationResultToConsultationInfo(initiateLiveConsultationResult);
  149. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId);
  150. }
  151. else if (liveConsultationRequestDTO.IsJoin)
  152. {
  153. var joinLiveConsultationRequest = new JoinLiveConsultationRequest
  154. {
  155. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  156. Token = AccountToken,
  157. CheckOnly = false,
  158. };
  159. var joinLiveConsultationResult = JsonRpcHelper.JoinInLiveConsultation(LiveConsultationService, joinLiveConsultationRequest, out var errorCode);
  160. if (joinLiveConsultationResult == null)
  161. {
  162. CurrentLiveStatus = LiveStates.UnknowException;
  163. return new ResultInfoDTO
  164. {
  165. IsSuccess = false,
  166. FailMessage = $"Join Consultation Fail,result is null",
  167. ErrorCode = errorCode
  168. };
  169. }
  170. consultationInfo = DTOConverter.ConvertJoinLiveConsultationResultToConsultationInfo(joinLiveConsultationResult);
  171. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId); ;
  172. }
  173. else
  174. {
  175. var acceptLiveConsultationRequest = new AcceptLiveConsultationRequest
  176. {
  177. CheckOnly = false,
  178. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  179. Token = liveConsultationRequestDTO.Token,
  180. };
  181. var acceptLiveConsultationResult = JsonRpcHelper.AcceptLiveConsultation(LiveConsultationService, acceptLiveConsultationRequest, out var errorCode);
  182. if (acceptLiveConsultationResult == null)
  183. {
  184. CurrentLiveStatus = LiveStates.UnknowException;
  185. return new ResultInfoDTO
  186. {
  187. IsSuccess = false,
  188. FailMessage = $"AcceptConsultation Fail,result is null",
  189. ErrorCode = errorCode
  190. };
  191. }
  192. consultationInfo = DTOConverter.ConvertAcceptLiveConsultationResultToConsultationInfo(acceptLiveConsultationResult);
  193. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId);
  194. }
  195. if (consultationInfo.TerminalInfo != null && !string.IsNullOrEmpty(deviceId))
  196. {
  197. var getDeviceRequest = new GetDeviceRequest
  198. {
  199. DeviceCode = deviceId,
  200. Token = AccountToken,
  201. };
  202. var deviceModel = JsonRpcHelper.GetDeviceInfo(DeviceService, getDeviceRequest);
  203. consultationInfo.TerminalInfo.Model = deviceModel?.DeviceModel;
  204. }
  205. lock (ConsultationInfoLocker)
  206. {
  207. ConsultationInfo = consultationInfo;
  208. }
  209. StartConsultation(cameraHardwareId, micHardwareId, speakerHardwareId, false);
  210. CurrentLiveStatus = LiveStates.RecipientAcceptted;
  211. Logger.WriteLineInfo($"Consultation Live-- {AccountName} accept meeConsultationting request end");
  212. ConsultationRequestArrived?.Invoke(this, ConsultationInfo);
  213. return new ResultInfoDTO
  214. {
  215. IsSuccess = true,
  216. };
  217. }
  218. catch (Exception ex)
  219. {
  220. Logger.WriteLineError($"Exception happened when accept Consultation{ex}");
  221. Hangup();
  222. return new ResultInfoDTO
  223. {
  224. IsSuccess = false,
  225. FailMessage = $"AcceptConsultation Error:{ex}",
  226. };
  227. }
  228. }
  229. /// <summary>
  230. /// Send a join Rtc Consultation Live request
  231. /// </summary>
  232. /// <returns></returns>
  233. public ResultInfoDTO StartLiveConsultation(StartOnlyForRtmpPushingDTO startOnlyForRtmpPushingDTO, string cameraHardwareId, string micHardwareId)
  234. {
  235. try
  236. {
  237. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  238. {
  239. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  240. return new ResultInfoDTO
  241. {
  242. IsSuccess = false,
  243. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  244. ErrorCode = 861,
  245. };
  246. }
  247. if (string.IsNullOrEmpty(AccountId))
  248. {
  249. CurrentLiveStatus = LiveStates.UnknowException;
  250. return new ResultInfoDTO
  251. {
  252. IsSuccess = false,
  253. FailMessage = $"AcceptConsultation Fail,AccountId is Null.",
  254. };
  255. }
  256. CurrentLiveStatus = LiveStates.RecipientAcceptting;
  257. Logger.WriteLineInfo($"Consultation Live-- {AccountName} start Consultation request begin");
  258. ConsultationInfo consultationInfo;
  259. consultationInfo = new ConsultationInfo(ChatRole.Recipient)
  260. {
  261. ConsultationId = startOnlyForRtmpPushingDTO.ConsultationCode,
  262. State = LiveStates.OK,
  263. LiveProtocol = LiveProtocol.Rtmp,
  264. LiveTalkingMode = LiveTalkingMode.Video,
  265. IsCurrentTerminal = false,
  266. ConsultationMemberInfos = new List<ConsultationMemberInfo>
  267. {
  268. new ConsultationMemberInfo
  269. {
  270. PushLiveState = LiveStates.OK,
  271. PushUrl = startOnlyForRtmpPushingDTO.RtmpPushingUrl,
  272. Id = AccountId,
  273. Name = AccountName,
  274. DisplayName = AccountName,
  275. },
  276. },
  277. };
  278. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(startOnlyForRtmpPushingDTO.ConsultationCode, AccountToken, out _);
  279. lock (ConsultationInfoLocker)
  280. {
  281. ConsultationInfo = consultationInfo;
  282. }
  283. StartConsultation(cameraHardwareId, micHardwareId, null, true);
  284. IsOnlyForRtmpPushing = true;
  285. CurrentLiveStatus = LiveStates.RecipientAcceptted;
  286. Logger.WriteLineInfo($"Consultation Live-- {AccountName} accept only rtmp pushing end");
  287. return new ResultInfoDTO
  288. {
  289. IsSuccess = true,
  290. };
  291. }
  292. catch (Exception ex)
  293. {
  294. Logger.WriteLineError($"Exception happened when only rtmp pushing:{ex}");
  295. Hangup();
  296. return new ResultInfoDTO
  297. {
  298. IsSuccess = false,
  299. FailMessage = $"AcceptConsultation Error:{ex}",
  300. };
  301. }
  302. }
  303. internal ResultInfoDTO ChangeLiveConsultation(ChangeLiveConsultationRequestDTO changeLiveConsultation0RequestDTO)
  304. {
  305. try
  306. {
  307. if (ConsultationInfo == null)
  308. {
  309. Logger.WriteLineWarn($"ChangeLiveConsultation Fail: Current is not Consultating");
  310. return new ResultInfoDTO
  311. {
  312. IsSuccess = false,
  313. FailMessage = "ChangeLiveConsultation Fail: Current is not Consultating"
  314. };
  315. }
  316. ConsultationInfo.ConsultationId = changeLiveConsultation0RequestDTO.ConsultationCode;
  317. var patientInfo = ConsultationManager.FindConsultationDetail(changeLiveConsultation0RequestDTO.ConsultationCode, AccountToken, out _);
  318. lock (ConsultationInfoLocker)
  319. {
  320. ConsultationInfo.PatientInfo = patientInfo;
  321. }
  322. if (IsSecondViewMode && !IsOnlyForRtmpPushing)//第二屏且不是rtmp推流的情况下
  323. {
  324. return new ResultInfoDTO
  325. {
  326. IsSuccess = true,
  327. };
  328. }
  329. VideoProvider.ChangeConsultationCodeForConsultationConnectionKeeper(changeLiveConsultation0RequestDTO.ConsultationCode);
  330. if (IsOnlyForRtmpPushing)
  331. {
  332. return new ResultInfoDTO
  333. {
  334. IsSuccess = true,
  335. };
  336. }
  337. ChangeLiveConsultationEvent?.Invoke(this, new ChangeLiveConsultationrResult(changeLiveConsultation0RequestDTO.ConsultationCode, ConsultationInfo.PatientInfo));
  338. var currentConsultationMembers = ConsultationInfo?.ConsultationMemberInfos?.ToList();
  339. var leaveMemberList = currentConsultationMembers.Where(x => !changeLiveConsultation0RequestDTO.Members.Any(y => y.Id == x.Id));
  340. if (leaveMemberList != null)
  341. {
  342. foreach (var member in leaveMemberList)
  343. {
  344. member.OperationType = ClientMessageOperationType.Delete;
  345. var consultationMemberChangeDTO = new ConsultationMemberChangeDTO()
  346. {
  347. ConsultationCode = changeLiveConsultation0RequestDTO.ConsultationCode,
  348. MemberInfo = member
  349. };
  350. ConsultationMemberChange(consultationMemberChangeDTO);
  351. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  352. if (memberInfo != null)
  353. {
  354. memberInfo.OperationType = ClientMessageOperationType.Delete;
  355. ConsultationInfo?.ConsultationMemberInfos.Remove(memberInfo);
  356. }
  357. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  358. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  359. }
  360. }
  361. currentConsultationMembers = ConsultationInfo?.ConsultationMemberInfos?.ToList();
  362. var addMemberList = changeLiveConsultation0RequestDTO.Members.Where(x => !currentConsultationMembers.Any(y => y.Id == x.Id));
  363. if (addMemberList != null)
  364. {
  365. foreach (var member in addMemberList)
  366. {
  367. member.OperationType = ClientMessageOperationType.Add;
  368. var consultationMemberChangeDTO = new ConsultationMemberChangeDTO()
  369. {
  370. ConsultationCode = changeLiveConsultation0RequestDTO.ConsultationCode,
  371. MemberInfo = member
  372. };
  373. ConsultationMemberChange(consultationMemberChangeDTO);
  374. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  375. if (memberInfo == null)
  376. {
  377. ConsultationInfo?.ConsultationMemberInfos.Add(member);
  378. }
  379. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  380. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  381. }
  382. }
  383. return new ResultInfoDTO
  384. {
  385. IsSuccess = true,
  386. };
  387. }
  388. catch (Exception ex)
  389. {
  390. Logger.WriteLineWarn($"ChangeLiveConsultation error: {ex}");
  391. return new ResultInfoDTO
  392. {
  393. IsSuccess = false,
  394. FailMessage = $"ChangeLiveConsultation Fail: {ex}"
  395. };
  396. }
  397. }
  398. public string GetUserInfo(string token)
  399. {
  400. AccountToken = token;
  401. var getUserRequest = new GetUserInfoRequest
  402. {
  403. Token = token,
  404. };
  405. var userDTO = JsonRpcHelper.GetUserInfo(UserService, getUserRequest);
  406. if (userDTO == null)
  407. {
  408. AccountName = null;
  409. AccountId = null;
  410. Logger.WriteLineError($"GetUserInfo Error,result is null");
  411. return null;
  412. }
  413. else
  414. {
  415. AccountName = userDTO.DisplayName;
  416. AccountId = userDTO.UserCode;
  417. return AccountId;
  418. }
  419. }
  420. public override void Dispose()
  421. {
  422. Logger.WriteLineInfo("Consultation Recipient is dispose begin");
  423. base.Dispose();
  424. Logger.WriteLineInfo("Consultation Recipient is dispose end");
  425. }
  426. internal ResultInfoDTO LiveConsultationMemberChanged(ConsultationMemberChangeDTO consultationMemberChangeDTO)
  427. {
  428. if (ConsultationInfo == null)
  429. {
  430. Logger.WriteLineWarn($"LiveConsultationMemberChanged Fail: Current is not Consultating");
  431. return new ResultInfoDTO
  432. {
  433. IsSuccess = false,
  434. FailMessage = "LiveConsultationMemberChanged Fail: Current is not Consultating"
  435. };
  436. }
  437. if (ConsultationInfo.ConsultationId != consultationMemberChangeDTO.ConsultationCode)
  438. {
  439. Logger.WriteLineWarn($"LiveConsultationMemberChanged Fail: Current ConsultationCode is {ConsultationInfo.ConsultationId},not {consultationMemberChangeDTO.ConsultationCode}");
  440. return new ResultInfoDTO
  441. {
  442. IsSuccess = false,
  443. FailMessage = $"LiveConsultationMemberChanged Fail: Current ConsultationCode is {ConsultationInfo.ConsultationId},not {consultationMemberChangeDTO.ConsultationCode}"
  444. };
  445. }
  446. ConsultationMemberChange(consultationMemberChangeDTO);
  447. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  448. if (consultationMemberChangeDTO.MemberInfo.OperationType == ClientMessageOperationType.Add)
  449. {
  450. if (memberInfo == null)
  451. {
  452. ConsultationInfo.ConsultationMemberInfos.Add(consultationMemberChangeDTO.MemberInfo);
  453. }
  454. memberInfo = consultationMemberChangeDTO.MemberInfo;
  455. }
  456. else if (consultationMemberChangeDTO.MemberInfo.OperationType == ClientMessageOperationType.Delete)
  457. {
  458. if (memberInfo != null)
  459. {
  460. ConsultationInfo?.ConsultationMemberInfos.Remove(memberInfo);
  461. }
  462. }
  463. if (memberInfo != null)
  464. {
  465. consultationMemberChangeDTO.MemberInfo.RoleType = memberInfo.RoleType;
  466. }
  467. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  468. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  469. return new ResultInfoDTO
  470. {
  471. IsSuccess = true,
  472. };
  473. }
  474. }
  475. }