vCloudTerminalV2.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. using JsonRpcLite.Network;
  2. using JsonRpcLite.Rpc;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using Vinno.IUS.Common.Log;
  8. using Vinno.vCloud.Common.FIS.AfterSales;
  9. using Vinno.vCloud.Common.FIS.Consultation;
  10. using Vinno.vCloud.Common.FIS.Helper;
  11. using Vinno.vCloud.Common.FIS.LiveVideos;
  12. using Vinno.vCloud.Common.FIS.Notification;
  13. using Vinno.vCloud.Common.FIS.Remedicals;
  14. using Vinno.vCloud.Common.FIS.Upgraders;
  15. using Vinno.vCloud.FIS.CrossPlatform.Common;
  16. using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
  17. using Vinno.vCloud.FIS.CrossPlatform.Common.Helper;
  18. using Vinno.vCloud.FIS.CrossPlatform.Common.SQLite;
  19. using WingInterfaceLibrary.DTO.Device;
  20. using WingInterfaceLibrary.Enum;
  21. using WingInterfaceLibrary.Enum.NotificationEnum;
  22. using WingInterfaceLibrary.Interface;
  23. using WingInterfaceLibrary.LiveConsultation;
  24. using WingInterfaceLibrary.Notifications.Live;
  25. using WingInterfaceLibrary.Request;
  26. using WingInterfaceLibrary.Request.Device;
  27. using WingInterfaceLibrary.Request.Remote;
  28. using WingInterfaceLibrary.Request.User;
  29. namespace Vinno.vCloud.Common.FIS
  30. {
  31. internal class vCloudTerminalV2 : IvCloudTerminalV2
  32. {
  33. private readonly Dictionary<TerminalFeatureType, object> _features = new Dictionary<TerminalFeatureType, object>();
  34. private readonly ConnectionInfo _connectionInfo;
  35. private readonly string _deviceName;
  36. private readonly string _password;
  37. private readonly bool _isUserDefined;
  38. private readonly LoginSource _loginSource;
  39. private readonly Platform _platform;
  40. private readonly string _deviceType;
  41. private readonly string _url;
  42. private readonly int _usScreenWidth;
  43. private readonly int _usScreenHeight;
  44. private readonly bool _isUseHttps;
  45. private readonly int _connectionCheckCycle;
  46. private readonly bool _isUseOldTerminalSdk;
  47. private string _token;
  48. private string _prefix;
  49. private JsonRpcClient _client;
  50. private JsonRpcHttpClientEngine _clientEngine;
  51. private IConnectService _connectService;
  52. private ILiveConsultationService _liveConsultationService;
  53. private IVinnoServerService _vinnoServerService;
  54. private IDeviceService _deviceService;
  55. private IOrganizationService _organizationService;
  56. private TerminalStatus _status;
  57. private ConnectionCheckerV2 _connectionChecker;
  58. private HeartRateKeeperV2 _heartRateKeeper;
  59. private bool _disposed;
  60. private int _reconnectCounter;
  61. private FISWebSocket _webSocket;
  62. private CacheDeviceDTO _deviceInfo;
  63. /// <summary>
  64. /// Gets the global remedical working folder.
  65. /// </summary>
  66. internal static string WorkingFolder { get; private set; }
  67. /// <summary>
  68. /// Raised when the status is changed.
  69. /// </summary>
  70. public event EventHandler StatusChanged;
  71. /// <summary>
  72. /// Gets the unique id.
  73. /// </summary>
  74. public string UniqueId { get; private set; }
  75. /// <inheritdoc />
  76. /// <summary>
  77. /// Gets the status of the Terminal
  78. /// </summary>
  79. /// <remarks>
  80. /// </remarks>
  81. public TerminalStatus Status
  82. {
  83. get => _status;
  84. private set
  85. {
  86. if (_status != value)
  87. {
  88. _status = value;
  89. CommonParameter.Instance.DeviceStatus = (EnumDeviceStatus)_status;
  90. OnStatusChanged();
  91. }
  92. }
  93. }
  94. public bool IsSupportResearchMode
  95. {
  96. get
  97. {
  98. return Status == TerminalStatus.Logon && vCloudServerConfig.Instance.IsSupportResearchMode;
  99. }
  100. }
  101. public string DeviceCode => _deviceInfo?.DeviceCode;
  102. public string Url => _url;
  103. public bool UseSSL => _isUseHttps;
  104. public vCloudTerminalV2(ConnectionInfo connectionInfo, bool isUseHttps, bool isUseOldTerminalSdk)
  105. {
  106. _usScreenHeight = connectionInfo.USScreenHeight;
  107. _usScreenWidth = connectionInfo.USScreenWidth;
  108. _isUseOldTerminalSdk = isUseOldTerminalSdk;
  109. _isUseHttps = isUseHttps;
  110. _prefix = "http://";
  111. if (_isUseHttps)
  112. {
  113. _prefix = "https://";
  114. }
  115. _connectionInfo = connectionInfo;
  116. _deviceName = connectionInfo.Account.Name;
  117. _password = connectionInfo.Account.Password;
  118. _isUserDefined = connectionInfo.Account.IsUserDefined;
  119. _url = connectionInfo.ServerUrl;
  120. _loginSource = connectionInfo.LoginSource;
  121. _deviceType = connectionInfo.DeviceType;
  122. //Set the default value 10 seconds.
  123. _connectionCheckCycle = 10;
  124. _status = TerminalStatus.Offline;
  125. switch (CrossPlatformHelper.Instance.Platform)
  126. {
  127. case EnumPlatform.Windows:
  128. if (CommonParameter.Instance.IsSonopost)
  129. {
  130. WorkingFolder = connectionInfo.FISFolder;
  131. }
  132. else
  133. {
  134. if (Directory.Exists("D:"))
  135. {
  136. WorkingFolder = @"D:\FISRepository";
  137. }
  138. else
  139. {
  140. WorkingFolder = connectionInfo.FISFolder;
  141. }
  142. }
  143. break;
  144. case EnumPlatform.Linux:
  145. WorkingFolder = @"/userdata/FISRepository";
  146. break;
  147. default:
  148. WorkingFolder = connectionInfo.FISFolder;
  149. break;
  150. }
  151. DirectoryHelper.CreateDirectory(WorkingFolder);
  152. CreateJsonrpcClient();
  153. if (!_isUseOldTerminalSdk)
  154. {
  155. CreateConnectionKeeper();
  156. }
  157. }
  158. /// <inheritdoc />
  159. /// <summary>
  160. /// Get the feature instance by feature enum.
  161. /// </summary>
  162. /// <typeparam name="T">The interface of the feature</typeparam>
  163. /// <param name="featureType">The feature type</param>
  164. /// <returns>The instance of the feature</returns>
  165. /// <remarks>
  166. /// If the feature doesn't exist, this method will return null.
  167. /// </remarks>
  168. public T GetFeature<T>(TerminalFeatureType featureType) where T : IFeatureV2
  169. {
  170. if (_features.ContainsKey(featureType))
  171. {
  172. var feature = _features[featureType];
  173. if (feature is T t)
  174. {
  175. return t;
  176. }
  177. }
  178. return default(T);
  179. }
  180. /// <summary>
  181. /// Connect to server.
  182. /// </summary>
  183. internal void Connect(string uniqueId = "", string terminalId = "")
  184. {
  185. try
  186. {
  187. Logger.WriteLineError($"vCloudTerminalV2 connect begin {_deviceName} login url:{_prefix}{_url}");
  188. if (!_isUseOldTerminalSdk)
  189. {
  190. var connectRequest = new ConnectRequest
  191. {
  192. DeviceUniqueCode = CommonParameter.Instance.MachineId,
  193. Password = _isUserDefined ? _password : string.Empty,
  194. DeviceModel = _connectionInfo.DeviceMode,
  195. DeviceType = _deviceType.ToString(),
  196. SoftwareVersion = _connectionInfo.SoftwareVersion,
  197. SystemVersion = _connectionInfo.USOS,
  198. CPUModel = _connectionInfo.USCPU,
  199. SystemLanguage = _connectionInfo.LanguageName,
  200. Description = "",
  201. Name = _deviceName,
  202. OrganizationCode = "",
  203. DepartmentCode = "",
  204. LoginSource = _connectionInfo.LoginSource,
  205. Platform = _connectionInfo.Platform,
  206. InstallVersion = CommonParameter.Instance.IsSonopost ? string.Empty : _connectionInfo.FISIMPLVersion?.ToString(),
  207. };
  208. ConnectResultInfo result = JsonRpcHelper.Connect(_connectService, connectRequest);
  209. if (result == null)
  210. {
  211. throw new InvalidDataException("vCloudTerminalV2 Connect Result is null");
  212. }
  213. else if (!result.IsSuccess)
  214. {
  215. if (result.ErrorCode == 2035)
  216. {
  217. Status = TerminalStatus.WrongAccount;
  218. }
  219. else if (result.ErrorCode == 2036)
  220. {
  221. Status = TerminalStatus.WrongPassword;
  222. }
  223. else
  224. {
  225. throw new InvalidDataException($"vCloudTerminalV2 Connect Fail,Error Code is {result.ErrorCode}");
  226. }
  227. }
  228. else
  229. {
  230. UniqueId = result.UniqueCode;
  231. _token = result.Token;
  232. HandleLoginResult();
  233. }
  234. }
  235. else
  236. {
  237. UniqueId = uniqueId;
  238. _deviceInfo = new CacheDeviceDTO
  239. {
  240. DeviceCode = terminalId
  241. };
  242. RemedicalSQLiteHelperV2.Instance.Initialize(WorkingFolder);
  243. ReleaseFeatures();
  244. UpdateFeatures(_connectionInfo.EnabledFeatures);
  245. Status = TerminalStatus.Logon;
  246. }
  247. }
  248. catch (Exception e)
  249. {
  250. Logger.WriteLineError($"vCloudTerminalV2 {_deviceName} login url:{_url} failed {e}");
  251. Status = TerminalStatus.LoginFailed;
  252. }
  253. }
  254. public void Disconnect()
  255. {
  256. var status = TerminalStatus.Logoff;
  257. try
  258. {
  259. var tokenRequest = new TokenRequest
  260. {
  261. Token = _token,
  262. };
  263. bool result = JsonRpcHelper.Disconnect(_connectService, tokenRequest);
  264. if (!result)
  265. {
  266. throw new Exception($"vCloudTerminalV2 Disconnect Result is fail");
  267. }
  268. else if (result)
  269. {
  270. Logger.WriteLineInfo($"vCloudTerminalV2 Disconnect Success");
  271. status = TerminalStatus.Logoff;
  272. }
  273. }
  274. catch (Exception e)
  275. {
  276. Logger.WriteLineError($"Disconnect terminal {_deviceName} error {e}");
  277. }
  278. finally
  279. {
  280. Release();
  281. Status = status;
  282. }
  283. }
  284. /// <summary>
  285. /// Update enabled feature types.
  286. /// </summary>
  287. /// <param name="enabledFeatureTypes">The enabled feature types.</param>
  288. public void UpdateFeatures(IEnumerable<TerminalFeatureType> enabledFeatureTypes)
  289. {
  290. CommonParameter.Instance.IsFeatureReleased = false;
  291. var removedFeatures = _features.Keys.Where(f => !enabledFeatureTypes.Contains(f)).ToList();
  292. foreach (var feature in removedFeatures)
  293. {
  294. var disposable = _features[feature] as IDisposable;
  295. disposable?.Dispose();
  296. _features.Remove(feature);
  297. }
  298. foreach (var enabledFeature in enabledFeatureTypes)
  299. {
  300. if (!_features.ContainsKey(enabledFeature))
  301. {
  302. var feature = GetFeature(enabledFeature);
  303. _features.Add(enabledFeature, feature);
  304. }
  305. }
  306. }
  307. /// <summary>
  308. /// Get Device Info
  309. /// </summary>
  310. /// <returns></returns>
  311. public void GetDeviceByToken()
  312. {
  313. var tokenRequest = new TokenRequest
  314. {
  315. Token = _token,
  316. };
  317. var cacheDeviceDTO = JsonRpcHelper.GetDeviceByToken(_connectService, tokenRequest);
  318. if (cacheDeviceDTO == null)
  319. {
  320. throw new InvalidOperationException("vCloudTerminalV2 GetDeviceByToken Result is null");
  321. }
  322. else
  323. {
  324. _deviceInfo = cacheDeviceDTO;
  325. }
  326. }
  327. /// <summary>
  328. /// Set Device Is Encrypted Show
  329. /// </summary>
  330. /// <param name="isEncryptedShow"></param>
  331. /// <returns></returns>
  332. public bool SetIsEncryptedShow(bool isEncryptedShow)
  333. {
  334. try
  335. {
  336. var setDeviceIsEncryptedShowRequest = new SetDeviceIsEncryptedShowRequest
  337. {
  338. IsEncryptedShow = isEncryptedShow,
  339. Token = _token
  340. };
  341. bool result = JsonRpcHelper.SetDeviceIsEncryptedShow(_connectService, setDeviceIsEncryptedShowRequest);
  342. if (!result)
  343. {
  344. throw new Exception($"vCloudTerminalV2 SetDeviceIsEncryptedShowAsync Result is false");
  345. }
  346. else
  347. {
  348. return true; ;
  349. }
  350. }
  351. catch (Exception ex)
  352. {
  353. Logger.WriteLineError($"vCloudTerminalV2 SetDeviceIsEncryptedShow Error:{ex}");
  354. return false;
  355. }
  356. }
  357. public void Dispose()
  358. {
  359. if (!_disposed)
  360. {
  361. Release();
  362. _disposed = true;
  363. }
  364. GC.SuppressFinalize(this);
  365. }
  366. private void HandleLoginResult()
  367. {
  368. Status = TerminalStatus.Logoning;
  369. var tokenRequest = new TokenRequest
  370. {
  371. Token = _token
  372. };
  373. var result = JsonRpcHelper.QueryServerConfig(_deviceService, tokenRequest);
  374. if (result == null)
  375. {
  376. throw new InvalidDataException($"vCloudTerminalV2 QueryServerConfig Result is null");
  377. }
  378. else
  379. {
  380. vCloudServerConfig.Instance.IsUploadThumbnail = result.IsUploadThumbnail;
  381. vCloudServerConfig.Instance.PatientType = result.PatientType;
  382. vCloudServerConfig.Instance.HeartRateSeconds = result.HeartRateSeconds;
  383. vCloudServerConfig.Instance.NotificationUrl = result.NotificationUrl;
  384. vCloudServerConfig.Instance.MergedChannel = result.MergedChannel;
  385. vCloudServerConfig.Instance.LiveConsultationRateSeconds = result.LiveConsultationRateSeconds;
  386. vCloudServerConfig.Instance.MergedVideoOutputHeight = result.MergedVideoOutputHeight;
  387. vCloudServerConfig.Instance.MergedVideoOutputWidth = result.MergedVideoOutputWidth;
  388. vCloudServerConfig.Instance.IsSelfRtcService = result.IsSelfRtcService;
  389. vCloudServerConfig.Instance.RemoteControlHeartRateSeconds = result.RemoteControlHeartRateSeconds;
  390. vCloudServerConfig.Instance.LiveProtocol = result.LiveProtocol;
  391. vCloudServerConfig.Instance.LiveProtocolType = result.LiveProtocolType;
  392. vCloudServerConfig.Instance.FISWebUrl = result.FISWebUrl;
  393. vCloudServerConfig.Instance.IsSupportResearchMode = result.IsResearchEditionService;
  394. Logger.WriteLineInfo($"vCloudServerConfig:{vCloudServerConfig.Instance}");
  395. if (result.ServerConfigList != null)
  396. {
  397. foreach (var kp in result.ServerConfigList)
  398. {
  399. Logger.WriteLineInfo($"ServerConfigList Key:{kp.Key},Value:{kp.Value} ");
  400. }
  401. }
  402. }
  403. GetDeviceByToken();
  404. if (_deviceInfo == null)
  405. {
  406. throw new ArgumentNullException($"GetDeviceByToken Failed,Result is null");
  407. }
  408. if (_deviceInfo.IsEncryptedShow)
  409. {
  410. Logger.WriteLineInfo("Start SetIsEncryptedShow False");
  411. SetIsEncryptedShow(false);
  412. _deviceInfo.IsEncryptedShow = false;
  413. Logger.WriteLineInfo("SetIsEncryptedShow False Finish");
  414. }
  415. CreateHeartRateKeeper();
  416. CreateWebSocket();
  417. RemedicalSQLiteHelperV2.Instance.Initialize(WorkingFolder);
  418. ReleaseFeatures();
  419. UpdateFeatures(_connectionInfo.EnabledFeatures);
  420. _reconnectCounter = 0;
  421. Status = TerminalStatus.Logon;
  422. Logger.WriteLineInfo($"{_deviceName} Login url:{_url} successed, Token:{_token}, UniqueId:{UniqueId}");
  423. }
  424. private void CreateWebSocket()
  425. {
  426. if (string.IsNullOrWhiteSpace(vCloudServerConfig.Instance.NotificationUrl))
  427. {
  428. Logger.WriteLineError($"CreateWebSocket Error Because The Notificaion Url is null");
  429. return;
  430. }
  431. if (_webSocket == null)
  432. {
  433. var uri = vCloudServerConfig.Instance.NotificationUrl.Replace("{0}", _token);
  434. uri = uri.Replace("{1}", "0");
  435. Logger.WriteLineInfo($"Websocket uri :{uri}");
  436. _webSocket = new FISWebSocket(uri);
  437. _webSocket.NotificationReceived += OnNoitificationReceived;
  438. _webSocket.Connect();
  439. }
  440. }
  441. private void DisposeWebSocket()
  442. {
  443. try
  444. {
  445. if (_webSocket != null)
  446. {
  447. _webSocket.NotificationReceived -= OnNoitificationReceived;
  448. _webSocket.Dispose();
  449. _webSocket = null;
  450. }
  451. }
  452. catch (Exception ex)
  453. {
  454. Logger.WriteLineError($"VCloudTerminalV2 Dispose WebSocket Error:{ex}");
  455. }
  456. }
  457. private void OnNoitificationReceived(object sender, NotificationArgs e)
  458. {
  459. switch (e.NotificationType)
  460. {
  461. case NotificationTypeEnum.ConnectionNotification:
  462. Logger.WriteLineInfo($"VCloudTerminalV2 ConnectionNotification Receive");
  463. break;
  464. case NotificationTypeEnum.DisconnectNotification:
  465. Logger.WriteLineInfo($"VCloudTerminalV2 DisconnectNotification Receive");
  466. break;
  467. case NotificationTypeEnum.ConnectStatusToDeviceNotification:
  468. try
  469. {
  470. if (e.Params is ConnectStatusToDeviceNotification connectStatusToDeviceNotification)
  471. {
  472. HandleConnectStatusToDeviceNotification(connectStatusToDeviceNotification);
  473. }
  474. }
  475. catch (Exception ex)
  476. {
  477. Logger.WriteLineError($"AfterSalesV2 Handle ConnectStatusToDeviceNotification Error:{ex}");
  478. }
  479. break;
  480. }
  481. }
  482. private void HandleConnectStatusToDeviceNotification(ConnectStatusToDeviceNotification connectStatusToDeviceNotification)
  483. {
  484. if (connectStatusToDeviceNotification.ControlType == ControlDeviceParameterEnum.Start)
  485. {
  486. Logger.WriteLineInfo($"VCloudTerminalV2 ConnectStatusToDeviceNotification StartControl Receive");
  487. var isConsultationLiveService = connectStatusToDeviceNotification.TransactionType == TransactionTypeEnum.Consultion;
  488. var afterSales = GetFeature<IAfterSalesV2>(TerminalFeatureType.AfterSales);
  489. if (afterSales != null)
  490. {
  491. bool result;
  492. var controlDeviceResponseRequest = new ControlDeviceResponseRequest
  493. {
  494. ControlType = ControlDeviceParameterEnum.Start,
  495. UserCode = connectStatusToDeviceNotification.ControlUserCode,
  496. UserName = connectStatusToDeviceNotification.ControlUserName,
  497. Token = _token,
  498. LoginSource = connectStatusToDeviceNotification.LoginSource,
  499. };
  500. if (isConsultationLiveService)
  501. {
  502. result = JsonRpcHelper.AcceptRemoteConnnectionInLiveConsultationService(_liveConsultationService, controlDeviceResponseRequest);
  503. }
  504. else
  505. {
  506. result = JsonRpcHelper.AcceptRemoteConnnectionInDeviceService(_deviceService, controlDeviceResponseRequest);
  507. }
  508. if (result)
  509. {
  510. afterSales.UpdateAfterSalesInfo(connectStatusToDeviceNotification.ControlUserCode, connectStatusToDeviceNotification.ControlUserName, connectStatusToDeviceNotification.LoginSource);
  511. }
  512. }
  513. else
  514. {
  515. var controlDeviceResponseRequest = new ControlDeviceResponseRequest
  516. {
  517. ControlType = ControlDeviceParameterEnum.RejectConnect,
  518. UserCode = connectStatusToDeviceNotification.ControlUserCode,
  519. UserName = connectStatusToDeviceNotification.ControlUserName,
  520. Token = _token,
  521. LoginSource = connectStatusToDeviceNotification.LoginSource,
  522. };
  523. bool result;
  524. if (isConsultationLiveService)
  525. {
  526. result = JsonRpcHelper.AcceptRemoteConnnectionInLiveConsultationService(_liveConsultationService, controlDeviceResponseRequest);
  527. }
  528. else
  529. {
  530. result = JsonRpcHelper.AcceptRemoteConnnectionInDeviceService(_deviceService, controlDeviceResponseRequest);
  531. }
  532. if (result)
  533. {
  534. Logger.WriteLineInfo($"VCloudTerminalV2 RejectRemoteControl Success");
  535. }
  536. else
  537. {
  538. Logger.WriteLineError($"VCloudTerminalV2 RejectRemoteControl Failed");
  539. }
  540. }
  541. }
  542. }
  543. private void CreateHeartRateKeeper()
  544. {
  545. if (_heartRateKeeper == null)
  546. {
  547. _heartRateKeeper = new HeartRateKeeperV2(_deviceService, _token, vCloudServerConfig.Instance.HeartRateSeconds);
  548. _heartRateKeeper.Start();
  549. }
  550. }
  551. private void DisposeHeartRateKeeper()
  552. {
  553. try
  554. {
  555. if (_heartRateKeeper != null)
  556. {
  557. _heartRateKeeper.Stop();
  558. _heartRateKeeper = null;
  559. }
  560. }
  561. catch (Exception ex)
  562. {
  563. Logger.WriteLineError($"vCloudTerminalV2 DisposeHeartRateKeeper Error:{ex}");
  564. }
  565. }
  566. private void OnStatusChanged()
  567. {
  568. Logger.WriteLineInfo($"VCloudTerminalV2 Status Changed:{_status}");
  569. StatusChanged?.Invoke(this, EventArgs.Empty);
  570. }
  571. private void CreateConnectionKeeper()
  572. {
  573. _connectionChecker = new ConnectionCheckerV2(_vinnoServerService, _connectionCheckCycle);
  574. var defaultStatus = false;
  575. if (!_connectionChecker.Check(false))
  576. {
  577. Status = TerminalStatus.Offline;
  578. }
  579. else
  580. {
  581. Status = TerminalStatus.Online;
  582. defaultStatus = true;
  583. }
  584. if (_connectionChecker != null)//当网络异常或者Server无法访问时,_connectionChecker.Check()一般会消耗十几秒,此时用户可能已经修改服务器地址,并重新登录,此时_connectionChecker已经被Dispose
  585. {
  586. _connectionChecker.Offlined += OnOfflined;
  587. _connectionChecker.Start(defaultStatus);
  588. }
  589. }
  590. private void DisposeConnectionKeeper()
  591. {
  592. try
  593. {
  594. if (_connectionChecker != null)
  595. {
  596. _connectionChecker.Offlined -= OnOfflined;
  597. _connectionChecker.Stop();
  598. _connectionChecker = null;
  599. }
  600. }
  601. catch (Exception ex)
  602. {
  603. Logger.WriteLineError($"VCloudTerminalV2 Dispose WebSocket Error:{ex}");
  604. }
  605. }
  606. private void OnOfflined(object sender, EventArgs e)
  607. {
  608. Release();
  609. Status = TerminalStatus.Offline;
  610. //No need to reconnect after instance release
  611. if (_disposed) return;
  612. //Reconnect
  613. if (_reconnectCounter < 5)
  614. {
  615. if (!string.IsNullOrEmpty(_deviceName) && !string.IsNullOrEmpty(_password))
  616. {
  617. CreateJsonrpcClient();
  618. CreateConnectionKeeper();
  619. if (Status == TerminalStatus.Online)
  620. {
  621. Status = TerminalStatus.Reconnecting;
  622. Connect();
  623. _reconnectCounter++;
  624. }
  625. }
  626. }
  627. else
  628. {
  629. Dispose();
  630. }
  631. }
  632. private void Release()
  633. {
  634. DisposeConnectionKeeper();
  635. DisposeHeartRateKeeper();
  636. DisposeWebSocket();
  637. ReleaseFeatures();
  638. ReleaseJsonrpcClient();
  639. }
  640. private void CreateJsonrpcClient()
  641. {
  642. try
  643. {
  644. _client = new JsonRpcClient();
  645. _clientEngine = new JsonRpcHttpClientEngine($"{_prefix}{_url}");
  646. _client.UseEngine(_clientEngine);
  647. _connectService = _client.CreateProxy<IConnectService>(8000);
  648. _vinnoServerService = _client.CreateProxy<IVinnoServerService>(6000);
  649. _deviceService = _client.CreateProxy<IDeviceService>();
  650. _liveConsultationService = _client.CreateProxy<ILiveConsultationService>();
  651. _organizationService = _client.CreateProxy<IOrganizationService>();
  652. }
  653. catch (Exception ex)
  654. {
  655. Logger.WriteLineError($"VCloudTerminalV2 CreateJsonrpcClient Error:{ex}");
  656. }
  657. }
  658. private void ReleaseJsonrpcClient()
  659. {
  660. try
  661. {
  662. if (_client != null)
  663. {
  664. _client.Dispose();
  665. _client = null;
  666. _clientEngine = null;
  667. _connectService = null;
  668. _vinnoServerService = null;
  669. _deviceService = null;
  670. _liveConsultationService = null;
  671. }
  672. }
  673. catch (Exception ex)
  674. {
  675. Logger.WriteLineError($"VCloudTerminal V2 ReleaseJsonrpcClient Error:{ex}");
  676. }
  677. }
  678. private void ReleaseFeatures()
  679. {
  680. CommonParameter.Instance.IsFeatureReleased = true;
  681. foreach (var type in _features.Keys.ToList())
  682. {
  683. var feature = _features[type];
  684. var disposable = feature as IDisposable;
  685. disposable?.Dispose();
  686. _features.Remove(type);
  687. }
  688. }
  689. private IFeatureV2 GetFeature(TerminalFeatureType terminalFeatureType)
  690. {
  691. switch (terminalFeatureType)
  692. {
  693. case TerminalFeatureType.Remedical:
  694. return new RemedicalV2(_token, _client);
  695. case TerminalFeatureType.LiveVideo:
  696. return new LiveVideoV2(_token, UniqueId, _usScreenWidth, _usScreenHeight, _webSocket, _client, _connectionInfo.DeviceMode, _deviceType, _connectionInfo.SoftwareVersion);
  697. case TerminalFeatureType.AfterSales:
  698. return new AfterSalesV2(_token, _client, _webSocket, _deviceInfo, _deviceType);
  699. case TerminalFeatureType.Upgrade:
  700. return new UpgradersV2(_client);
  701. case TerminalFeatureType.Consultation:
  702. return new ConsultationV2(_client, _token, _deviceInfo);
  703. default:
  704. return null;
  705. }
  706. }
  707. public bool IsEncryptedShow()
  708. {
  709. if (_deviceInfo == null)
  710. {
  711. return false;
  712. }
  713. else
  714. {
  715. return _deviceInfo.IsEncryptedShow;
  716. }
  717. }
  718. /// <summary>
  719. /// get terminal Organization name after this must login successed
  720. /// </summary>
  721. /// <returns></returns>
  722. public string GetOrganizationName()
  723. {
  724. try
  725. {
  726. if (_deviceInfo == null)
  727. {
  728. return null;
  729. }
  730. var getOrganizationByCodeRequest = new GetOrganizationByCodeRequest
  731. {
  732. OrganizationCode = _deviceInfo.OrganizationCode,
  733. Token = _token,
  734. };
  735. var result = JsonRpcHelper.GetOrganizationByCode(_organizationService, getOrganizationByCodeRequest);
  736. if (result == null)
  737. {
  738. Logger.WriteLineError($"vCloudTerminalV2 GetOrganizationName Fail:result is null");
  739. return null;
  740. }
  741. else
  742. {
  743. return result.OrganizationName;
  744. }
  745. }
  746. catch (Exception ex)
  747. {
  748. Logger.WriteLineError($"vCloudTerminalV2 GetOrganizationName Error:{ex}");
  749. return null;
  750. }
  751. }
  752. }
  753. }