vCloudTerminalV2.cs 29 KB

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