Consultation.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Vinno.IUS.Common.Args;
  5. using Vinno.IUS.Common.Log;
  6. using Vinno.IUS.Common.Network.Leaf;
  7. using Vinno.vCloud.Common.FIS.FLYINSONOLogin;
  8. using Vinno.vCloud.FIS.CrossPlatform.Common;
  9. using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
  10. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
  11. using Vinno.vCloud.Protocol.Infrastructures;
  12. using Vinno.vCloud.Protocol.Messages.Live;
  13. namespace Vinno.vCloud.Common.FIS.Consultation
  14. {
  15. internal class Consultation : IConsultation
  16. {
  17. private readonly string _terminalId;
  18. private readonly string _terminalName;
  19. private readonly string _url;
  20. private readonly LoginSource _loginSource;
  21. private readonly string _qrTagString = "TAG_QRLogin|";
  22. private FLYINSONOUser _flyinsonoUser;
  23. private ClientLeaf _leaf;
  24. private bool _disposed;
  25. private bool _isPrimaryDoctor;
  26. private string _currentConsultationDeviceId;
  27. private ScanLogin _scanLogin;
  28. /// <summary>
  29. /// Raised when the flyinsono user status is changed.
  30. /// </summary>
  31. public event EventHandler<FLYINSONOUserLoginStatusArgs> UserStatusChanged;
  32. /// <summary>
  33. /// device image frame arrived
  34. /// </summary>
  35. public event EventHandler<CPVideoFrameData> UltrasoundImageFrameArrived;
  36. /// <summary>
  37. /// device camera frame arrived
  38. /// </summary>
  39. public event EventHandler<CPVideoFrameData> UltrasoundCameraFrameArrived;
  40. /// <summary>
  41. /// Local camera video frame arrived only for consultation
  42. /// </summary>
  43. public event EventHandler<ConsultationVideoFrameData> ConsultationLocalVideoFrameArrived;
  44. /// <summary>
  45. /// Remote camera frame arrived only for consultation
  46. /// </summary>
  47. public event EventHandler<ConsultationVideoFrameData> ConsultationRemoteVideoFrameArrived;
  48. /// <summary>
  49. /// Raised when receive a consultation request from server.
  50. /// </summary>
  51. public event EventHandler<ConsultationInfo> ConsultationRequestArrived;
  52. /// <summary>
  53. /// Other one join the consultation notification Arrived from server
  54. /// </summary>
  55. public event EventHandler<ConsultationInfo> JoinConsultationNotifyArrived;
  56. /// <summary>
  57. /// other reject notify arrived from server
  58. /// </summary>
  59. public event EventHandler<ConsultationSubscriberInfo> RejectConsultationNotifyArrived;
  60. /// <summary>
  61. /// Raised when the consultation is disconnect.
  62. /// </summary>
  63. public event EventHandler<ConsultationDisconnectedType> ConsultationDisconnected;
  64. /// <summary>
  65. /// Raised when consultation records collection changed.
  66. /// </summary>
  67. public event EventHandler<CollectionChangedArgs<ConsultationRecord>> ConsultationRecordsChanged;
  68. /// <summary>
  69. /// Raised when a consultation record updated.
  70. /// </summary>
  71. public event EventHandler<ConsultationRecord> ConsultationRecordUpdated;
  72. /// <summary>
  73. /// Raised when consultation Member Changed
  74. /// </summary>
  75. public event EventHandler<ConsultationMemberNotificaiton> ConsultationMemberChangedNotificationArrived;
  76. /// <summary>
  77. /// FLYINOSO User
  78. /// </summary>
  79. public FLYINSONOUser FLYINSONOUser => _flyinsonoUser;
  80. /// <summary>
  81. /// The consultation initiator
  82. /// </summary>
  83. public ConsultationIntiator ConsultationIntiator { get; }
  84. /// <summary>
  85. /// The consultation recipient
  86. /// </summary>
  87. public ConsultationRecipient ConsultationRecipient { get; }
  88. /// <summary>
  89. /// Chat live video provider, handle different video
  90. /// </summary>
  91. public ConsultationLiveVideoProvider ConsultationLiveVideoProvider { get; }
  92. /// <summary>
  93. /// Gets the manager for consultations.
  94. /// </summary>
  95. public ConsultationManager ConsultationManager { get; }
  96. /// <summary>
  97. /// 接收到其他用户的白板信息
  98. /// </summary>
  99. public event EventHandler<InteractiveBoardInfo> InteractiveBoardInfoArrived;
  100. /// <summary>
  101. /// 接收到清除白板信息
  102. /// </summary>
  103. public event EventHandler<string> ClearInteractiveBoardArrived;
  104. /// <summary>
  105. /// 收到即时会诊的通知
  106. /// </summary>
  107. public event EventHandler<DoctorInfo> EmergencyConsultationRequestArrived;
  108. /// <summary>
  109. /// 收到关闭摄像头的通知
  110. /// </summary>
  111. public event EventHandler<List<string>> MuteVideoUserListNotifyArrived;
  112. public Consultation(string terminalId, string terminalName, string url, LoginSource loginSource, string uniqueId)
  113. {
  114. _terminalId = terminalId;
  115. _terminalName = terminalName;
  116. _url = url;
  117. _loginSource = loginSource;
  118. ConsultationLiveVideoProvider = new ConsultationLiveVideoProvider();
  119. ConsultationLiveVideoProvider.OnTRTCRoomEnterError += OnTRTCRoomEnterErrorHappened;
  120. ConsultationLiveVideoProvider.ConsultationLocalVideoFrameArrived += OnConsultationLocalVideoFrameArrived;
  121. ConsultationLiveVideoProvider.ConsultationRemoteVideoFrameArrived += OnConsultationRemoteVideoFrameArrived;
  122. ConsultationLiveVideoProvider.TerminalImageFrameArrived += OnUltrasoundImageFrameArrived;
  123. ConsultationLiveVideoProvider.TerminalCameraFrameArrived += OnUltrasoundCameraFrameArrived;
  124. ConsultationIntiator = new ConsultationIntiator(ConsultationLiveVideoProvider, terminalId);
  125. ConsultationIntiator.ConsultationDisconnected += OnConsultationDisconnected;
  126. ConsultationIntiator.ConsultationMemberChangedNotificationArrived += OnConsultationMemberChangedNotificationArrived;
  127. ConsultationIntiator.JoinConsultationNotifyArrived += OnJoinConsultationNotifyArrived;
  128. ConsultationIntiator.RejectConsultationNotifyArrived += OnRejectConsultationNotifyArrived;
  129. ConsultationIntiator.InteractiveBoardInfoArrived += OnInteractiveBoardInfoArrived;
  130. ConsultationIntiator.ClearInteractiveBoardArrived += OnClearInteractiveBoardArrived;
  131. ConsultationIntiator.EmergencyConsultationRequestArrived += OnEmergencyConsultationRequestArrived;
  132. ConsultationIntiator.MuteVideoUserListNotifyArrived += OnMuteVideoUserListNotifyArrived;
  133. ConsultationRecipient = new ConsultationRecipient(ConsultationLiveVideoProvider, terminalId, uniqueId);
  134. ConsultationRecipient.ConsultationDisconnected += OnConsultationDisconnected;
  135. ConsultationRecipient.ConsultationRequestArrived += OnConcultationRequestArrived;
  136. ConsultationRecipient.JoinConsultationNotifyArrived += OnJoinConsultationNotifyArrived;
  137. ConsultationRecipient.ConsultationMemberChangedNotificationArrived += OnConsultationMemberChangedNotificationArrived;
  138. ConsultationRecipient.RejectConsultationNotifyArrived += OnRejectConsultationNotifyArrived;
  139. ConsultationRecipient.InteractiveBoardInfoArrived += OnInteractiveBoardInfoArrived;
  140. ConsultationRecipient.ClearInteractiveBoardArrived += OnClearInteractiveBoardArrived;
  141. ConsultationRecipient.MuteVideoUserListNotifyArrived += OnMuteVideoUserListNotifyArrived;
  142. ConsultationManager = new ConsultationManager(_terminalId, _terminalName);
  143. ConsultationManager.ConsultationRecordsChanged += OnConsultationRecordsChanged;
  144. ConsultationManager.ConsultationRecordUpdated += OnConsultationRecordUpdated;
  145. CreateScanLogin();
  146. }
  147. private void OnMuteVideoUserListNotifyArrived(object sender, List<string> muteVideoUserList)
  148. {
  149. MuteVideoUserListNotifyArrived?.Invoke(this, muteVideoUserList);
  150. }
  151. private void OnEmergencyConsultationRequestArrived(object sender, DoctorInfo e)
  152. {
  153. EmergencyConsultationRequestArrived?.Invoke(this, e);
  154. }
  155. public void CreateScanLogin()
  156. {
  157. if (_scanLogin == null)
  158. {
  159. _scanLogin = new ScanLogin(_url);
  160. _scanLogin.ScanLoginEvent += OnScanLoginEvent;
  161. }
  162. }
  163. public void CloseScanLogin()
  164. {
  165. if (_scanLogin != null)
  166. {
  167. _scanLogin.ScanLoginEvent -= OnScanLoginEvent;
  168. _scanLogin.Dispose();
  169. _scanLogin = null;
  170. }
  171. }
  172. private void OnScanLoginEvent(object sender, QRLoginInfo e)
  173. {
  174. if (e != null)
  175. {
  176. if (FLYINSONOUser == null)
  177. {
  178. Login(e.UserName, e.EncryptedPassword, true);
  179. return;
  180. }
  181. switch (FLYINSONOUser.Status)
  182. {
  183. case FLYINSONOUserLoginStatus.Online:
  184. case FLYINSONOUserLoginStatus.Logon:
  185. case FLYINSONOUserLoginStatus.ReLogin:
  186. break;
  187. case FLYINSONOUserLoginStatus.Offline:
  188. case FLYINSONOUserLoginStatus.DuplicateLogin:
  189. case FLYINSONOUserLoginStatus.Replaced:
  190. case FLYINSONOUserLoginStatus.LoginFailed:
  191. case FLYINSONOUserLoginStatus.WrongAccount:
  192. case FLYINSONOUserLoginStatus.WrongPassword:
  193. case FLYINSONOUserLoginStatus.Unknown:
  194. case FLYINSONOUserLoginStatus.IsNotDoctor:
  195. case FLYINSONOUserLoginStatus.Logoff:
  196. case FLYINSONOUserLoginStatus.HasNoPermission:
  197. default:
  198. Login(e.UserName, e.EncryptedPassword, true);
  199. return;
  200. }
  201. }
  202. }
  203. private void OnInteractiveBoardInfoArrived(object sender, InteractiveBoardInfo e)
  204. {
  205. InteractiveBoardInfoArrived?.Invoke(this, e);
  206. }
  207. private void OnClearInteractiveBoardArrived(object sender, string e)
  208. {
  209. ClearInteractiveBoardArrived?.Invoke(this, e);
  210. }
  211. /// <summary>
  212. /// Flyinsono user login
  213. /// </summary>
  214. /// <param name="userName">The flyinsono user name.</param>
  215. /// <param name="password">The password</param>
  216. /// <param name="isScanLogin">Is scan Login</param>
  217. public void Login(string userName, string password, bool isScanLogin)
  218. {
  219. DisposeFLYINSONOUser();
  220. _flyinsonoUser = FLYINSONOUserManager.Instance.CreateFLYINSONOUser(_url, userName, password, _loginSource, TerminalFeatureType.Consultation, isScanLogin);
  221. _flyinsonoUser.StatusChanged += OnUserStatusChanged;
  222. _flyinsonoUser.Login();
  223. }
  224. /// <summary>
  225. /// Flyinsono user log off.
  226. /// </summary>
  227. public void LogOff()
  228. {
  229. if (_flyinsonoUser != null)
  230. {
  231. _flyinsonoUser.LogOff();
  232. DisposeFLYINSONOUser();
  233. }
  234. }
  235. /// <summary>
  236. /// Get QRCode Info For Scan Login
  237. /// </summary>
  238. /// <returns></returns>
  239. public string GetQRCodeInfoForScanLogin()
  240. {
  241. if (_scanLogin != null)
  242. {
  243. return _qrTagString + _scanLogin.LeafId;
  244. }
  245. else
  246. {
  247. return "";
  248. }
  249. }
  250. /// <summary>
  251. /// Accept the consultation request.
  252. /// </summary>
  253. /// <param name="videoHardwareId">The camera id.</param>
  254. /// <param name="micHardwareId">The micphone id.</param>
  255. /// <param name="speakerHardwareId">The speakder id.</param>
  256. /// <returns>The chat live states.</returns>
  257. public LiveStates AcceptConsultation(string videoHardwareId, string micHardwareId, string speakerHardwareId)
  258. {
  259. return ConsultationRecipient.AcceptConsultation(videoHardwareId, micHardwareId, speakerHardwareId);
  260. }
  261. /// <summary>
  262. /// Reject the consultation request.
  263. /// </summary>
  264. public LiveStates RejectConsultation()
  265. {
  266. return ConsultationRecipient.RejectConsultation();
  267. }
  268. /// <summary>
  269. /// Hang up a chating.
  270. /// </summary>
  271. public LiveStates HangupConsultation()
  272. {
  273. var result = LiveStates.UnknowException;
  274. if (ConsultationRecipient.ConsultationInfo != null)
  275. {
  276. var recipientId = ConsultationRecipient?.ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Recipient)?.Id;
  277. if (recipientId == FLYINSONOUser.AccountId)
  278. {
  279. result = ConsultationRecipient.Hangup(true);
  280. }
  281. else
  282. {
  283. result = ConsultationRecipient.Hangup(false);
  284. }
  285. OnConsultationDisconnected(this, ConsultationDisconnectedType.HangUpBySelf);
  286. }
  287. else if (ConsultationIntiator.ConsultationInfo != null)
  288. {
  289. result = ConsultationIntiator.Hangup(true);
  290. ConsultationManager.UpdateCurrentConsultationToWaitForReportUpload();
  291. OnConsultationDisconnected(this, ConsultationDisconnectedType.HangUpBySelf);
  292. }
  293. else
  294. {
  295. Logger.WriteLineInfo($"Didn't do hang up since no consultation info");
  296. }
  297. return result;
  298. }
  299. /// <summary>
  300. /// 发送画板数据
  301. /// </summary>
  302. /// <param name="jsonData"></param>
  303. /// <returns></returns>
  304. public bool SendInteractiveBoardData(string jsonData)
  305. {
  306. if (ConsultationRecipient.ConsultationInfo != null)
  307. {
  308. return ConsultationRecipient.SendInteractiveBoardData(jsonData);
  309. }
  310. else if (ConsultationIntiator.ConsultationInfo != null)
  311. {
  312. return ConsultationIntiator.SendInteractiveBoardData(jsonData);
  313. }
  314. else
  315. {
  316. Logger.WriteLineInfo($"Didn't Send Interactive BoardData since no consultation info");
  317. return false;
  318. }
  319. }
  320. /// <summary>
  321. /// 清除画板数据
  322. /// </summary>
  323. /// <returns></returns>
  324. public bool ClearInteractiveBoardData()
  325. {
  326. if (ConsultationRecipient.ConsultationInfo != null)
  327. {
  328. return ConsultationRecipient.ClearInteractiveBoardData();
  329. }
  330. else if (ConsultationIntiator.ConsultationInfo != null)
  331. {
  332. return ConsultationIntiator.ClearInteractiveBoardData();
  333. }
  334. else
  335. {
  336. Logger.WriteLineInfo($"Didn't Clear Interactive BoardData since no consultation info");
  337. return false;
  338. }
  339. }
  340. /// <summary>
  341. /// Start a chat request.
  342. /// </summary>
  343. /// <param name="recipientIds">The ids of the recipient.</param>
  344. /// <returns>The chat live status</returns>
  345. public LiveStates RequestConsultation(List<RecipientInfo> recipientIds, string cameraHardwareId, string micHardwareId, string speakerHardwareId)
  346. {
  347. CrossPlatformHelper.Instance.HardwareDetector.StopCameraPreview();
  348. _currentConsultationDeviceId = ConsultationManager.CurrentConsultationRecord?.TerminalInfo?.Id;
  349. var result = ConsultationIntiator.RequestConsultation(recipientIds, cameraHardwareId, micHardwareId, speakerHardwareId, ConsultationManager.CurrentConsultationRecord?.TerminalInfo?.Id);
  350. if (result == null)
  351. {
  352. return LiveStates.UnknowException;
  353. }
  354. return result.State;
  355. }
  356. /// <summary>
  357. /// Cancel chat request
  358. /// </summary>
  359. public LiveStates CancelConsultationRequest(bool forceClosed)
  360. {
  361. return ConsultationIntiator.CancelConsultationRequest(forceClosed);
  362. }
  363. /// <summary>
  364. /// Gets the hospital info of the flyinsono user.
  365. /// </summary>
  366. /// <returns></returns>
  367. public OrganizationInfo GetHospitalInfo()
  368. {
  369. return _flyinsonoUser?.Hospital;
  370. }
  371. /// <summary>
  372. /// Doctor apply consultation.
  373. /// </summary>
  374. /// <param name="consultationRecord">The consultation record info to apply.</param>
  375. /// <returns>True: success. False: falied./returns>
  376. public bool ApplyConsultationRecord(ConsultationRecord consultationRecord)
  377. {
  378. return ConsultationManager.AddConsultationRecord(consultationRecord);
  379. }
  380. /// <summary>
  381. /// Doctor delete consultation
  382. /// </summary>
  383. /// <param name="consultationId"></param>
  384. /// <returns></returns>
  385. public bool DeleteConsultationRecord(string consultationId)
  386. {
  387. return ConsultationManager.DeleteConsultationRecord(consultationId);
  388. }
  389. /// <summary>
  390. /// Doctor withdraw consultation.
  391. /// </summary>
  392. /// <param name="consultationId">The consultation id.</param>
  393. /// <returns>True: success. False: falied.</returns>
  394. public bool WithDrawConsultationRecord(string consultationId)
  395. {
  396. return ConsultationManager.WithDrawConsultationRecord(consultationId);
  397. }
  398. /// <summary>
  399. /// Doctor update consultation.
  400. /// </summary>
  401. /// <param name="consultationRecord">The consultation record info to update.</param>
  402. /// <returns>True: success. False: falied./returns>
  403. public bool UpdateConsultationRecord(ConsultationRecord consultationRecord)
  404. {
  405. return ConsultationManager.UpdateConsultation(consultationRecord);
  406. }
  407. /// <summary>
  408. /// Expert arrange consultation.
  409. /// </summary>
  410. /// <param name="consultationRecord">The consultation to be arranged.</param>
  411. /// <returns>True: success. False: falied./returns>
  412. public bool ArrangeConsultationRecord(ConsultationRecord consultationRecord)
  413. {
  414. return ConsultationManager.ArrangeConsultation(consultationRecord);
  415. }
  416. /// <summary>
  417. /// Gets the experts list by hospital id.
  418. /// </summary>
  419. /// <param name="hospitalId">The hospital id.</param>
  420. /// <returns>The experts of the hospital.</returns>
  421. public IEnumerable<DoctorInfo> GetExperts(string hospitalId)
  422. {
  423. return ConsultationManager.GetExperts(hospitalId);
  424. }
  425. /// <summary>
  426. /// Gets the live states of the current chat.
  427. /// </summary>
  428. /// <returns></returns>
  429. public LiveStates GetCurrentConsultationLiveStates()
  430. {
  431. var isInitiator = false;
  432. var consultationInfo = ConsultationIntiator.ConsultationInfo;
  433. if (consultationInfo != null)
  434. {
  435. isInitiator = true;
  436. }
  437. if (isInitiator)
  438. {
  439. return ConsultationIntiator.CurrentLiveStatus;
  440. }
  441. else
  442. {
  443. return ConsultationRecipient.CurrentLiveStatus;
  444. }
  445. }
  446. /// <summary>
  447. /// Set current consultation record.
  448. /// </summary>
  449. /// <param name="consultationId">The current consultation record id.</param>
  450. public void SetCurrentConsultationRecord(string consultationId)
  451. {
  452. ConsultationManager.SetCurrentConsultationRecord(consultationId);
  453. }
  454. /// <summary>
  455. /// Dispose consultation
  456. /// </summary>
  457. public void Dispose()
  458. {
  459. DoDispose();
  460. GC.SuppressFinalize(this);
  461. }
  462. private void DoDispose()
  463. {
  464. if (!_disposed)
  465. {
  466. ConsultationLiveVideoProvider.OnTRTCRoomEnterError -= OnTRTCRoomEnterErrorHappened;
  467. ConsultationLiveVideoProvider.ConsultationLocalVideoFrameArrived -= OnConsultationLocalVideoFrameArrived;
  468. ConsultationLiveVideoProvider.ConsultationRemoteVideoFrameArrived -= OnConsultationRemoteVideoFrameArrived;
  469. ConsultationLiveVideoProvider.TerminalImageFrameArrived -= OnUltrasoundImageFrameArrived;
  470. ConsultationLiveVideoProvider.TerminalCameraFrameArrived -= OnUltrasoundCameraFrameArrived;
  471. ConsultationLiveVideoProvider.Dispose();
  472. ConsultationIntiator.ConsultationDisconnected -= OnConsultationDisconnected;
  473. ConsultationIntiator.JoinConsultationNotifyArrived -= OnJoinConsultationNotifyArrived;
  474. ConsultationIntiator.RejectConsultationNotifyArrived -= OnRejectConsultationNotifyArrived;
  475. ConsultationIntiator.ConsultationMemberChangedNotificationArrived -= OnConsultationMemberChangedNotificationArrived;
  476. ConsultationIntiator.InteractiveBoardInfoArrived -= OnInteractiveBoardInfoArrived;
  477. ConsultationIntiator.ClearInteractiveBoardArrived -= OnClearInteractiveBoardArrived;
  478. ConsultationIntiator.EmergencyConsultationRequestArrived -= OnEmergencyConsultationRequestArrived;
  479. ConsultationIntiator.MuteVideoUserListNotifyArrived -= OnMuteVideoUserListNotifyArrived;
  480. ConsultationIntiator.Dispose();
  481. ConsultationRecipient.ConsultationDisconnected -= OnConsultationDisconnected;
  482. ConsultationRecipient.ConsultationRequestArrived -= OnConcultationRequestArrived;
  483. ConsultationRecipient.JoinConsultationNotifyArrived -= OnJoinConsultationNotifyArrived;
  484. ConsultationRecipient.ConsultationMemberChangedNotificationArrived -= OnConsultationMemberChangedNotificationArrived;
  485. ConsultationRecipient.RejectConsultationNotifyArrived -= OnRejectConsultationNotifyArrived;
  486. ConsultationRecipient.InteractiveBoardInfoArrived -= OnInteractiveBoardInfoArrived;
  487. ConsultationRecipient.ClearInteractiveBoardArrived -= OnClearInteractiveBoardArrived;
  488. ConsultationRecipient.MuteVideoUserListNotifyArrived -= OnMuteVideoUserListNotifyArrived;
  489. ConsultationRecipient.Dispose();
  490. ConsultationManager.ClearConsultationRecordCache();
  491. ConsultationManager.ConsultationRecordsChanged -= OnConsultationRecordsChanged;
  492. ConsultationManager.ConsultationRecordUpdated -= OnConsultationRecordUpdated;
  493. ConsultationManager.Dispose();
  494. DisposeFLYINSONOUser();
  495. CloseScanLogin();
  496. _disposed = true;
  497. }
  498. }
  499. private void OnConsultationMemberChangedNotificationArrived(object sender, ConsultationMemberNotificaiton e)
  500. {
  501. ConsultationMemberChangedNotificationArrived?.Invoke(this, e);
  502. }
  503. private void OnTRTCRoomEnterErrorHappened(object sender, EnumTRTCRoomError e)
  504. {
  505. Logger.WriteLineError($"Consultation TRTCRoomEnterErrorHappened:{e}");
  506. }
  507. private void OnUltrasoundImageFrameArrived(object sender, CPVideoFrameData e)
  508. {
  509. if (!_isPrimaryDoctor || (_isPrimaryDoctor && _terminalId != _currentConsultationDeviceId))
  510. {
  511. UltrasoundImageFrameArrived?.Invoke(this, e);
  512. }
  513. }
  514. private void OnUltrasoundCameraFrameArrived(object sender, CPVideoFrameData e)
  515. {
  516. UltrasoundCameraFrameArrived?.Invoke(this, e);
  517. }
  518. private void OnConsultationRemoteVideoFrameArrived(object sender, ConsultationVideoFrameData e)
  519. {
  520. ConsultationRemoteVideoFrameArrived?.Invoke(this, e);
  521. }
  522. private void OnConsultationLocalVideoFrameArrived(object sender, ConsultationVideoFrameData e)
  523. {
  524. ConsultationLocalVideoFrameArrived?.Invoke(this, e);
  525. }
  526. private void DisposeFLYINSONOUser()
  527. {
  528. if (_flyinsonoUser != null)
  529. {
  530. _flyinsonoUser.Dispose();
  531. _flyinsonoUser.StatusChanged -= OnUserStatusChanged;
  532. _flyinsonoUser = null;
  533. }
  534. }
  535. private void OnUserStatusChanged(object sender, FLYINSONOUserLoginStatusArgs e)
  536. {
  537. try
  538. {
  539. switch (FLYINSONOUser.Status)
  540. {
  541. case FLYINSONOUserLoginStatus.Logon:
  542. CloseScanLogin();
  543. _leaf = _flyinsonoUser.ClientLeaf;
  544. ConsultationIntiator.Update(_leaf, _flyinsonoUser);
  545. ConsultationRecipient.Update(_leaf, _flyinsonoUser);
  546. ConsultationManager.Update(_leaf, _flyinsonoUser);
  547. break;
  548. case FLYINSONOUserLoginStatus.Offline:
  549. case FLYINSONOUserLoginStatus.Logoff:
  550. case FLYINSONOUserLoginStatus.Replaced:
  551. var consultationtatus = GetCurrentConsultationLiveStates();
  552. var isConsultation = consultationtatus == LiveStates.RecipientAcceptted
  553. || consultationtatus == LiveStates.ChatRequestArrived
  554. || consultationtatus == LiveStates.InitiatorRequestingChat
  555. || consultationtatus == LiveStates.RecipientAcceptting;
  556. if (isConsultation)
  557. {
  558. HangupConsultation();
  559. }
  560. ConsultationManager.ClearConsultationRecordCache();
  561. CreateScanLogin();
  562. break;
  563. }
  564. UserStatusChanged?.Invoke(this, e);
  565. }
  566. catch (Exception ex)
  567. {
  568. Logger.WriteLineError($"Consultation OnUserStatus Changed Error:{ex}");
  569. }
  570. }
  571. /// <summary>
  572. /// GetConsultationRecordList
  573. /// </summary>
  574. /// <param name="startIndex">Start Index</param>
  575. /// <param name="pageSize">page Size</param>
  576. /// <param name="consultationRecordFilter">Filter</param>
  577. public bool GetConsultationRecordList(int startIndex, int pageSize, ConsultationRecordFilter consultationRecordFilter)
  578. {
  579. return ConsultationManager.GetConsultationRecordList(startIndex, pageSize, consultationRecordFilter);
  580. }
  581. /// <summary>
  582. /// 获取当前会诊记录的报告
  583. /// </summary>
  584. /// <returns></returns>
  585. public IEnumerable<byte[]> GetCurrentConsultationRecordReportImage()
  586. {
  587. return ConsultationManager.GetReportImagesByConsultationId();
  588. }
  589. private void OnConsultationRecordUpdated(object sender, ConsultationRecord e)
  590. {
  591. ConsultationRecordUpdated?.Invoke(this, e);
  592. }
  593. private void OnConsultationRecordsChanged(object sender, CollectionChangedArgs<ConsultationRecord> e)
  594. {
  595. ConsultationRecordsChanged?.Invoke(this, e);
  596. }
  597. private void OnConcultationRequestArrived(object sender, ConsultationInfo e)
  598. {
  599. var primaryDoctorId = e?.ConsultationMemberInfos?.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Recipient)?.Id;
  600. if (primaryDoctorId == FLYINSONOUser.AccountId)
  601. {
  602. _isPrimaryDoctor = true;
  603. }
  604. else
  605. {
  606. _isPrimaryDoctor = false;
  607. }
  608. _currentConsultationDeviceId = e?.TerminalInfo?.Id;
  609. CrossPlatformHelper.Instance.HardwareDetector.StopCameraPreview();
  610. ConsultationRequestArrived?.Invoke(this, e);
  611. }
  612. private void OnRejectConsultationNotifyArrived(object sender, ConsultationSubscriberInfo e)
  613. {
  614. RejectConsultationNotifyArrived?.Invoke(this, e);
  615. }
  616. private void OnJoinConsultationNotifyArrived(object sender, ConsultationInfo e)
  617. {
  618. var primaryDoctorId = e?.ConsultationMemberInfos?.FirstOrDefault(x => x.RoleType == ConsultationRoleType.Recipient)?.Id;
  619. if (primaryDoctorId == FLYINSONOUser.AccountId)
  620. {
  621. _isPrimaryDoctor = true;
  622. }
  623. else
  624. {
  625. _isPrimaryDoctor = false;
  626. }
  627. JoinConsultationNotifyArrived?.Invoke(this, e);
  628. if (ConsultationIntiator.ConsultationInfo != null)
  629. {
  630. ConsultationManager.UpdateCurrentConsultationToStarted();
  631. }
  632. }
  633. private void OnConsultationDisconnected(object sender, ConsultationDisconnectedType e)
  634. {
  635. _currentConsultationDeviceId = null;
  636. ConsultationDisconnected?.Invoke(this, e);
  637. if (ConsultationIntiator.ConsultationInfo != null)
  638. {
  639. ConsultationManager.UpdateCurrentConsultationToWaitForReportUpload();
  640. }
  641. }
  642. /// <summary>
  643. /// 开始即时呼叫
  644. /// </summary>
  645. /// <param name="cameraId"></param>
  646. /// <param name="micId"></param>
  647. /// <param name="speakerId"></param>
  648. /// <returns></returns>
  649. public EnumEmergencyConsultationResult RequestEmergencyConsultation(string cameraId, string micId, string speakerId)
  650. {
  651. _currentConsultationDeviceId = _terminalId;
  652. return ConsultationRecipient.RequestEmergencyConsultation(cameraId, micId, speakerId);
  653. }
  654. /// <summary>
  655. /// 发起者取消即时呼叫
  656. /// </summary>
  657. public LiveStates CancelEmergencyConsultation()
  658. {
  659. return ConsultationRecipient.CancelEmergencyConsultation();
  660. }
  661. public LiveStates AcceptEmergencyConsultation(string cameraHardwareId, string micHardwareId, string speakerHardwareId)
  662. {
  663. return ConsultationIntiator.AcceptEmergencyConsultation(cameraHardwareId, micHardwareId, speakerHardwareId);
  664. }
  665. public LiveStates RejectEmergencyConsultation()
  666. {
  667. return ConsultationIntiator.RejectEmergencyConsultation();
  668. }
  669. }
  670. }