vCloudTerminalV2.cs 26 KB

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