DeviceService.cs 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using WingInterfaceLibrary.DTO.Device;
  6. using WingInterfaceLibrary.Interface;
  7. using WingInterfaceLibrary.Request.Device;
  8. using WingInterfaceLibrary.DTO.Dictionary;
  9. using WingServerCommon.Log;
  10. using WingServerCommon.Service;
  11. using WingInterfaceLibrary.Interface.DBInterface;
  12. using WingInterfaceLibrary.DB.Request;
  13. using WingServerCommon.Mapper;
  14. using WingInterfaceLibrary.Request;
  15. using WingInterfaceLibrary.Request.Authentication;
  16. using WingInterfaceLibrary.DTO.User;
  17. using WingInterfaceLibrary.DTO.Management;
  18. using WingServerCommon.Config;
  19. using WingDeviceService.Common;
  20. using WingInterfaceLibrary.Request.User;
  21. using WingInterfaceLibrary.Enum;
  22. using WingInterfaceLibrary.DTO.Organization;
  23. using WingInterfaceLibrary.DTO.DiagnosisModule;
  24. using WingServerCommon.Config.Parameters;
  25. using WingServerCommon.Interfaces.Cache;
  26. using WingInterfaceLibrary.LiveConsultation;
  27. using WingInterfaceLibrary.Result.Languge;
  28. using WingInterfaceLibrary.Internal.Interface;
  29. using WingInterfaceLibrary.Notifications;
  30. using WingInterfaceLibrary.Internal.Request;
  31. using WingInterfaceLibrary.Rtc;
  32. using WingInterfaceLibrary.Enum.CommentEnum;
  33. using WingInterfaceLibrary.DTO.RTC;
  34. using Newtonsoft.Json;
  35. using WingInterfaceLibrary.Notifications.Live;
  36. using WingInterfaceLibrary.Enum.NotificationEnum;
  37. using WingInterfaceLibrary.DTO.LiveRoom;
  38. using WingInterfaceLibrary.Request.DBRequest;
  39. using WingInterfaceLibrary.DTO.Record;
  40. using WingInterfaceLibrary.DTO.Consultation;
  41. using WingServerCommon.Interfaces.Cache;
  42. using System.Collections.Concurrent;
  43. namespace WingDeviceService.Service
  44. {
  45. /// <summary>
  46. /// 设备管理服务
  47. /// </summary>
  48. public partial class DeviceService : JsonRpcService, IDeviceService
  49. {
  50. private ConcurrentDictionary<string, CacheControllingParameter> _controllingParameterDevices = new ConcurrentDictionary<string, CacheControllingParameter>();
  51. private IUserDBService _userServiceProxy;
  52. private IDeviceInfoDBService _deviceInfoDBServiceProxy;
  53. private IAuthenticationService _authenticationService;
  54. private IOrganizationDBService _organizationDBService;
  55. private INotificationService _notificationService;
  56. private IRecordsInfoDBService _recordsInfoDBService;
  57. private IPatientInfoDBService _patientInfoDBService;
  58. private IDiagnosisModuleDBService _diagnosisModuleService;
  59. private IRemedicalService _remedicalService;
  60. private IWingRtcService _wingRtcService;
  61. private IRtcService _rtcService;
  62. private int _heartRateSeconds;
  63. private DeviceHeartRateManager _deviceHeartRateManager;
  64. private string _webSocketUrl = string.Empty;
  65. private int _liveConsultationRateSeconds = 0;
  66. private bool _isRTCSelf = false;
  67. private int _sdkAppId = 0;
  68. private int _remoteControlAskTimeoutSec = 0;
  69. private int _reportStateIntervalSeconds = 0;
  70. private int _reportStateTimeout = 0;
  71. private ILiveConsultationService _liveConsultationService;
  72. private IConsultationRecordDBService _consultationRecordDBService;
  73. private IRemedicalDBService _remedicalDBService;
  74. /// <summary>
  75. /// Init service
  76. /// </summary>
  77. public override void Load(JsonRpcClientPool jsonRpcClientPool)
  78. {
  79. base.Load(jsonRpcClientPool);
  80. _userServiceProxy = GetProxy<IUserDBService>();
  81. _authenticationService = GetProxy<IAuthenticationService>();
  82. _deviceInfoDBServiceProxy = GetProxy<IDeviceInfoDBService>();
  83. _organizationDBService = GetProxy<IOrganizationDBService>();
  84. _notificationService = GetProxy<INotificationService>();
  85. _recordsInfoDBService = GetProxy<IRecordsInfoDBService>();
  86. _patientInfoDBService = GetProxy<IPatientInfoDBService>();
  87. _diagnosisModuleService = GetProxy<IDiagnosisModuleDBService>();
  88. _remedicalService = GetProxy<IRemedicalService>();
  89. _wingRtcService = GetProxy<IWingRtcService>();
  90. _rtcService = GetProxy<IRtcService>();
  91. _liveConsultationService = GetProxy<ILiveConsultationService>();
  92. _consultationRecordDBService = GetProxy<IConsultationRecordDBService>();
  93. _remedicalDBService = GetProxy<IRemedicalDBService>();
  94. _heartRateSeconds = ConfigurationManager.GetParammeter<IntParameter>("Device", "HeartRateSeconds").Value;
  95. _deviceHeartRateManager = new DeviceHeartRateManager(SetOnlineState);
  96. _webSocketUrl = ConfigurationManager.GetParammeter<StringParameter>("Notification", "WebSocketUrl").Value;
  97. _liveConsultationRateSeconds = ConfigurationManager.GetParammeter<IntParameter>("Live", "HeartRateSeconds").Value;
  98. _isRTCSelf = ConfigurationManager.GetParammeter<BoolParameter>("Rtc", "IsSelf").Value;
  99. var sdkAppIdString = ConfigurationManager.GetParammeter<StringParameter>("Rtc", "RTCAppId").Value;
  100. if (int.TryParse(sdkAppIdString, out int sdkAppId))
  101. {
  102. _sdkAppId = sdkAppId;
  103. }
  104. _remoteControlAskTimeoutSec = ConfigurationManager.GetParammeter<IntParameter>("Device", "RemoteControlAskTimeoutSec").Value;
  105. _reportStateIntervalSeconds = ConfigurationManager.GetParammeter<IntParameter>("Live", "ReportStateIntervalSeconds").Value;
  106. _reportStateTimeout = ConfigurationManager.GetParammeter<IntParameter>("Live", "ReportStateTimeout").Value;
  107. }
  108. /// <summary>
  109. /// 设备心跳
  110. /// </summary>
  111. /// <param name="request"></param>
  112. /// <returns></returns>
  113. public async Task<bool> HeartRateAsync(TokenRequest request)
  114. {
  115. _deviceHeartRateManager.AddOrUpdate(request.Token);
  116. var result = SetOnlineState(request.Token, true);
  117. return result;
  118. }
  119. private bool SetOnlineState(string token, bool isOnline)
  120. {
  121. return _authenticationService.SetOnlineStateAsync(new SetOnlineStateRequest { Token = token, IsOnline = isOnline }).Result;
  122. }
  123. /// <summary>
  124. /// 添加分享设备关联用户请求
  125. /// </summary>
  126. /// <param name="request"></param>
  127. /// <returns></returns>
  128. public async Task<bool> CreateShareDeviceToUserAsync(CreateShareDeviceToUserRequest request)
  129. {
  130. var userCodes = request.UserCodes;
  131. var deviceCode = request.DeviceCode;
  132. //检查设备编码不为空
  133. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  134. {
  135. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  136. }
  137. if (userCodes == null || userCodes.Count <= 0)
  138. {
  139. ThrowCustomerException(CustomerRpcCode.UserCodeEmptyError, "Required parameter:UserCodes cannot be empty");
  140. }
  141. //查询设备对象
  142. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(deviceCode);
  143. if (deviceDb == null)
  144. {
  145. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  146. }
  147. foreach (var userCode in userCodes)
  148. {
  149. var existUser = await _userServiceProxy.FindUserByCodeAsync(userCode);
  150. if (existUser == null)
  151. {
  152. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  153. }
  154. }
  155. await _userServiceProxy.BingDevicesToUsersAsync(new BingDevicesToUsersRequest
  156. {
  157. DeviceCodes = new List<string> { deviceCode },
  158. UserCodes = userCodes.ToList()
  159. });
  160. return true;
  161. }
  162. /// <summary>
  163. /// 根据设备code获取设备信息
  164. /// </summary>
  165. /// <param name="request">设备code请求实体</param>
  166. /// <returns>返回查询到的设备对象信息</returns>
  167. public async Task<DeviceExtendInfoDTO> GetDeviceInfoAsync(GetDeviceRequest request)
  168. {
  169. //验证
  170. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  171. {
  172. ThrowCustomerException(CustomerRpcCode.DeviceCodeEmpty, "DeviceCode empty error");
  173. }
  174. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(request.DeviceCode);
  175. if (deviceDb == null || deviceDb.DeviceCode != request.DeviceCode)
  176. {
  177. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  178. }
  179. //根据机构编号查询机构名称
  180. var organizationName = "";
  181. if (!string.IsNullOrEmpty(deviceDb.OrganizationCode))
  182. {
  183. var organization = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = deviceDb.OrganizationCode });
  184. organizationName = organization?.OrganizationName ?? string.Empty;
  185. }
  186. //根据机构编号查询科室名称
  187. var departmentName = "";
  188. if (!string.IsNullOrEmpty(deviceDb.DepartmentCode))
  189. {
  190. var department = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = deviceDb.DepartmentCode });
  191. departmentName = department?.OrganizationName ?? string.Empty;
  192. }
  193. //是否在线 todo
  194. var deviceTypeModel = await _deviceInfoDBServiceProxy.FindDictionaryByCodeAsync(deviceDb.DeviceType);
  195. var result = new DeviceExtendInfoDTO()
  196. {
  197. DepartmentName = departmentName,
  198. OrganizationName = organizationName,
  199. IsOnline = await GetDeviceOnlineState(deviceDb.DeviceCode),
  200. DeviceCode = deviceDb.DeviceCode,
  201. SerialNumber = deviceDb.SerialNumber,
  202. Name = deviceDb.Name,
  203. Description = deviceDb.Description,
  204. DeviceModel = deviceDb.DeviceModel,
  205. DeviceType = deviceDb.DeviceType,
  206. HeadPicUrl = deviceDb.HeadPicUrl,
  207. DeviceSoftwareVersion = deviceDb.DeviceSoftwareVersion,
  208. SDKSoftwareVersion = deviceDb.SDKSoftwareVersion,
  209. OrganizationCode = deviceDb.OrganizationCode,
  210. DepartmentCode = deviceDb.DepartmentCode,
  211. ShortCode = deviceDb.ShortCode,
  212. LanguageConfigs = deviceTypeModel.LanguageConfigs
  213. };
  214. return result;
  215. }
  216. /// <summary>
  217. /// 根据设备动态唯一码获取设备信息
  218. /// </summary>
  219. /// <param name="request"></param>
  220. /// <returns></returns>
  221. public async Task<DeviceExtendInfoDTO> GetDeviceByShortCodeAsync(GetDeviceByShortCodeRequest request)
  222. {
  223. //验证
  224. if (string.IsNullOrWhiteSpace(request.ShortCode))
  225. {
  226. ThrowCustomerException(CustomerRpcCode.ShortCodeEmpty, "ShortCode empty error");
  227. }
  228. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByShortCodeAsync(request.ShortCode);
  229. if (deviceDb == null || deviceDb.ShortCode != request.ShortCode)
  230. {
  231. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  232. }
  233. return await MapToExtendDTO(deviceDb);
  234. }
  235. public async Task<PageCollection<DeviceInfoDTO>> GetDeviceInfoPageAsync(PageFilterRequest request)
  236. {
  237. throw new System.NotImplementedException();
  238. }
  239. public async Task<bool> DeleteShareDeviceToUserAsync(DeleteShareDeviceToUserRequest request)
  240. {
  241. var userCodes = request.UserCodes;
  242. var deviceCode = request.DeviceCode;
  243. //检查设备编码不为空
  244. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  245. {
  246. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  247. }
  248. //用户编码集合检查
  249. if (userCodes == null || userCodes.Count <= 0)
  250. {
  251. ThrowCustomerException(CustomerRpcCode.UserCodeEmptyError, "Required parameter:UserCodes cannot be empty");
  252. }
  253. //查询设备对象
  254. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(deviceCode);
  255. if (deviceDb == null)
  256. {
  257. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  258. }
  259. var updateUsers = new List<TableDataItem<UserPasswordDTO>>();
  260. foreach (var userCode in userCodes)
  261. {
  262. var user = await _userServiceProxy.FindUserByCodeAsync(userCode);
  263. if (user != null)
  264. {
  265. if (user.BindDevices.Contains(deviceCode))
  266. {
  267. user.BindDevices.Remove(deviceCode);
  268. updateUsers.Add(new TableDataItem<UserPasswordDTO>()
  269. {
  270. Data = user.MappingTo<UserPasswordDTO>(),
  271. });
  272. }
  273. }
  274. }
  275. if (updateUsers.Count > 0)
  276. {
  277. var updateUsersDBRequest = new UpdateUsersDBRequest() { Users = updateUsers };
  278. await _userServiceProxy.UpdateUsersAsync(updateUsersDBRequest);
  279. }
  280. return true;
  281. }
  282. /// <summary>
  283. /// 机构设备移除-根据机构code和设备code解除其绑定关系
  284. /// </summary>
  285. /// <param name="request">移除设备请求实体</param>
  286. /// <returns>移除是否成功:true-成功;false-失败</returns>
  287. public async Task<bool> RemoveDeviceRelevancyAsync(RemoveDeviceRelevancyRequest request)
  288. {
  289. //验证
  290. if (string.IsNullOrWhiteSpace(request.DeviceCode) || string.IsNullOrWhiteSpace(request.OrganizationCode))
  291. {
  292. ThrowCustomerException(CustomerRpcCode.DeviceCodeOrOrganizationCodeEmpty, "DeviceCode Or OrganizationCode empty error");
  293. }
  294. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(request.DeviceCode);
  295. if (deviceDb == null || deviceDb.OrganizationCode != request.OrganizationCode || deviceDb.DepartmentCode != request.DepartmentCode)
  296. {
  297. ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "DeviceInfo not exist error");
  298. }
  299. //根据设备code和机构code查询相关数据,查到则删除关联
  300. if (!string.IsNullOrEmpty(deviceDb.DepartmentCode))
  301. {
  302. deviceDb.DepartmentCode = "";
  303. deviceDb.OrganizationCode = "";
  304. }
  305. else
  306. {
  307. deviceDb.OrganizationCode = "";
  308. }
  309. bool removeDeviceResult = await _deviceInfoDBServiceProxy.UpdateDeviceInfoByCodeAsync(deviceDb.DeviceCode, deviceDb, string.Empty, true);
  310. return removeDeviceResult;
  311. }
  312. private async Task<string> GetClientIdByTokenAsync(string token)
  313. {
  314. var request = new TokenRequest() { Token = token };
  315. var result = await _authenticationService.GetTokenAsync(request);
  316. return result.ClientId; //return User code
  317. }
  318. /// <summary>
  319. /// 查询个人名下所有设备列表接口
  320. /// </summary>
  321. /// <param name="request">查询个人名下所有设备列表请求实体</param>
  322. /// <returns>返回设备信息列表</returns>
  323. public async Task<PageCollection<DeviceExtendInfoDTO>> GetPersonDeviceListAsync(GetPersonDeviceRequest request)
  324. {
  325. //验证
  326. var userCode = await GetClientIdByTokenAsync(request.Token);
  327. //查询用户是否存在
  328. var userInfoDO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  329. if (userInfoDO == null)
  330. {
  331. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  332. }
  333. //查询用户的医院是否存在
  334. if (string.IsNullOrWhiteSpace(userInfoDO.OrganizationCode))
  335. {
  336. ThrowCustomerException(CustomerRpcCode.OrganizationNotExist, "Org does not exist");
  337. }
  338. var deviceInfoDOList = new List<DeviceInfoDTO>();
  339. if (!userInfoDO.IsDirector)
  340. {
  341. //普通用户,查询用户绑定的设备
  342. if (userInfoDO.BindDevices != null && userInfoDO.BindDevices.Any())
  343. {
  344. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByCodeListAsync(userInfoDO.BindDevices);
  345. }
  346. }
  347. else
  348. {
  349. //机构负责人
  350. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByOrganizationCodeAsync(userInfoDO.RootOrganizationCode);
  351. }
  352. if (!deviceInfoDOList.Any())
  353. {
  354. return new PageCollection<DeviceExtendInfoDTO>() { CurrentPage = request.PageIndex, PageSize = request.PageSize, DataCount = 0, PageData = new List<DeviceExtendInfoDTO>() };
  355. }
  356. var deviceList = await MapToExtendDTO(deviceInfoDOList);
  357. //条件筛选
  358. if (!string.IsNullOrWhiteSpace(request.DeviceType))
  359. {
  360. deviceList = deviceList.Where(d => d.DeviceType == request.DeviceType)?.ToList() ?? new List<DeviceExtendInfoDTO>();
  361. }
  362. if (!string.IsNullOrWhiteSpace(request.DeviceModel))
  363. {
  364. deviceList = deviceList.Where(d => d.DeviceModel == request.DeviceModel)?.ToList() ?? new List<DeviceExtendInfoDTO>();
  365. }
  366. if (!string.IsNullOrWhiteSpace(request.KeyWord))
  367. {
  368. var keyword = request.KeyWord.Trim().ToLower();
  369. deviceList = deviceList.Where(d => d.Name.ToLower().Contains(keyword) || d.ShortCode.ToLower().Contains(keyword))?.ToList() ?? new List<DeviceExtendInfoDTO>();
  370. }
  371. if (request.IsOnline != null)
  372. {
  373. deviceList = deviceList.Where(d => d.IsOnline == request.IsOnline)?.ToList() ?? new List<DeviceExtendInfoDTO>();
  374. }
  375. var pagedResult = new PageCollection<DeviceExtendInfoDTO>
  376. {
  377. CurrentPage = request.PageIndex,
  378. PageSize = request.PageSize,
  379. DataCount = deviceList.Count,
  380. PageData = deviceList.Skip(request.PageSize * (request.PageIndex - 1)).Take(request.PageSize)?.ToList() ?? new List<DeviceExtendInfoDTO>()
  381. };
  382. return pagedResult;
  383. }
  384. /// <summary>
  385. /// 绑定设备
  386. /// </summary>
  387. /// <param name="request"></param>
  388. /// <returns></returns>
  389. public async Task<bool> BindDeviceAsync(BindDeviceRequest request)
  390. {
  391. //验证
  392. var userCode = await GetClientIdByTokenAsync(request.Token);
  393. //查询用户是否存在
  394. var userInfoDO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  395. if (userInfoDO == null)
  396. {
  397. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  398. }
  399. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByShortCodeAsync(request.ShortCode);
  400. if (deviceDb == null)
  401. {
  402. ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device");
  403. }
  404. if (userInfoDO.BindDevices != null && userInfoDO.BindDevices.Contains(deviceDb.DeviceCode))
  405. {
  406. ThrowCustomerException(CustomerRpcCode.HasAddedDevice, "The device has been Added");
  407. }
  408. try
  409. {
  410. var isInvented = (string.IsNullOrWhiteSpace(deviceDb.OrganizationCode) || deviceDb.OrganizationCode == $"invented_{deviceDb.ShortCode}") ? true : false;
  411. deviceDb.Name = request.Name;
  412. deviceDb.SerialNumber = request.SerialNumber;
  413. deviceDb.Description = request.Description;
  414. if (!string.IsNullOrEmpty(request.HeadPicUrl))
  415. {
  416. deviceDb.HeadPicUrl = request.HeadPicUrl.ToUrlToken();
  417. }
  418. deviceDb.DepartmentCode = request.DepartmentCode;
  419. deviceDb.IsAutoShared = request.IsAutoShared;
  420. deviceDb.OrganizationCode = request.OrganizationCode;
  421. await _deviceInfoDBServiceProxy.UpdateDeviceInfoByCodeAsync(deviceDb.DeviceCode, deviceDb, string.Empty);
  422. if (isInvented && !string.IsNullOrWhiteSpace(request.OrganizationCode)) //虚拟机构改为正常机构
  423. {
  424. var newOrgCode = string.IsNullOrWhiteSpace(request.DepartmentCode) ? request.OrganizationCode : request.DepartmentCode;
  425. //迁移数据超声机上传检查记录
  426. await _recordsInfoDBService.UpdateRecordsWithOrgCodeAsync(new List<string>() { deviceDb.DeviceCode }, newOrgCode);
  427. //迁移数据超声机上传病人
  428. await _patientInfoDBService.UpdatePatientWithOrgCodeAsync(new List<string>() { deviceDb.DeviceCode }, newOrgCode);
  429. }
  430. if (deviceDb.IsAutoShared)
  431. {
  432. var users = new List<UserDTO>();
  433. if (!string.IsNullOrEmpty(deviceDb.DepartmentCode))
  434. {
  435. users = await _userServiceProxy.FindUserListByOrganizationCodesAsync(new List<string> { deviceDb.DepartmentCode });
  436. }
  437. else
  438. {
  439. users = await _userServiceProxy.GetUserListAsync(new GetUserListDBRequest { OrganizationQueryType = OrganizationQueryTypeEnum.All, OrganizationCode = deviceDb.OrganizationCode });
  440. }
  441. var userCodes = users.Select(f => f.UserCode).ToList();
  442. await _userServiceProxy.BingDevicesToUsersAsync(new BingDevicesToUsersRequest
  443. {
  444. DeviceCodes = new List<string> { deviceDb.DeviceCode.ToString() },
  445. UserCodes = userCodes.Select(f => f.ToString()).ToList()
  446. });
  447. }
  448. return true;
  449. }
  450. catch (Exception ex)
  451. {
  452. Logger.WriteLineError($"BindDeviceAsync error {ex}");
  453. }
  454. return false;
  455. }
  456. /// <summary>
  457. /// 修改设备
  458. /// </summary>
  459. /// <param name="request"></param>
  460. /// <returns></returns>
  461. public async Task<bool> ModifyDeviceAsync(ModifyDeviceRequest request)
  462. {
  463. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(request.DeviceCode);
  464. if (deviceDb == null)
  465. {
  466. ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device");
  467. }
  468. if (string.IsNullOrWhiteSpace(request.Name))
  469. {
  470. ThrowCustomerException(CustomerRpcCode.DeviceNameEmpty, "Device name cannot be empty");
  471. }
  472. deviceDb.Name = request.Name;
  473. if (!string.IsNullOrWhiteSpace(request.HeadPicUrl))
  474. {
  475. deviceDb.HeadPicUrl = request.HeadPicUrl.ToUrlToken();
  476. }
  477. else
  478. {
  479. deviceDb.HeadPicUrl = string.Empty;
  480. }
  481. deviceDb.DepartmentCode = request.DepartmentCode;
  482. //修改自动分享
  483. deviceDb.IsAutoShared = request.IsAutoShared;
  484. if (deviceDb.IsAutoShared)
  485. {
  486. var users = new List<UserDTO>();
  487. if (!string.IsNullOrEmpty(deviceDb.DepartmentCode))
  488. {
  489. users = await _userServiceProxy.FindUserListByOrganizationCodesAsync(new List<string> { deviceDb.DepartmentCode });
  490. }
  491. else
  492. {
  493. users = await _userServiceProxy.GetUserListAsync(new GetUserListDBRequest { OrganizationQueryType = OrganizationQueryTypeEnum.All, OrganizationCode = deviceDb.OrganizationCode });
  494. }
  495. var userCodes = users.Select(f => f.UserCode).ToList();
  496. //先解绑,再绑定,避免绑定重复设备code
  497. var updateUsers = new List<TableDataItem<UserPasswordDTO>>();
  498. foreach (var user in users)
  499. {
  500. var userPasswordDTO = user.MappingTo<UserPasswordDTO>();
  501. user.BindDevices?.Remove(deviceDb.DeviceCode);
  502. await _userServiceProxy.UpdateUserAsync(userPasswordDTO.UserCode, userPasswordDTO, string.Empty);
  503. }
  504. await _userServiceProxy.BingDevicesToUsersAsync(new BingDevicesToUsersRequest
  505. {
  506. DeviceCodes = new List<string> { deviceDb.DeviceCode.ToString() },
  507. UserCodes = userCodes.Select(f => f.ToString()).ToList()
  508. });
  509. }
  510. return await _deviceInfoDBServiceProxy.UpdateDeviceInfoByCodeAsync(deviceDb.DeviceCode, deviceDb, string.Empty, true);
  511. }
  512. /// <summary>
  513. /// 创建字典
  514. /// </summary>
  515. /// <param name="request"></param>
  516. /// <returns></returns>
  517. public async Task<string> CreateDictionaryItemAsync(CreateDictionaryItemRequest request)
  518. {
  519. return await _deviceInfoDBServiceProxy.CreateDictionaryItemAsync(new CreateDictionaryItemDBRequest
  520. {
  521. Data = new DictionaryDTO { DictionaryType = request.DictionaryType, Value = request.DictionaryItemValue, ParentCode = request.ParentCode },
  522. ExtensionData = string.Empty
  523. });
  524. }
  525. /// <summary>
  526. /// 查找设备型号所有字典项
  527. /// </summary>
  528. /// <param name="request"></param>
  529. /// <returns></returns>
  530. public async Task<List<DictionaryDTO>> FindDeviceModelItemsAsync(FindDeviceModelItemsRequest request)
  531. {
  532. var dictionaryDOList = await _deviceInfoDBServiceProxy.FindDictionaryItemsAsync(new FindDictionaryItemsDBRequest
  533. {
  534. DictionaryType = (int)request.DictionaryType,
  535. ParentCode = request.DeviceTypeCode
  536. });
  537. return dictionaryDOList;
  538. }
  539. /// <summary>
  540. /// 查找设备类型所有字典项
  541. /// </summary>
  542. /// <param name="request"></param>
  543. /// <returns></returns>
  544. public async Task<List<DictionaryDTO>> FindDeviceTypeItemsAsync(FindDeviceTypeItemsRequest request)
  545. {
  546. var dictionaryDOList = await _deviceInfoDBServiceProxy.FindDictionaryItemsAsync(new FindDictionaryItemsDBRequest
  547. {
  548. DictionaryType = (int)request.DictionaryType
  549. });
  550. return dictionaryDOList;
  551. }
  552. /// <summary>
  553. /// 根据组织编码查询所属全部设备信息
  554. /// </summary>
  555. /// <param name="request"></param>
  556. /// <returns></returns>
  557. public async Task<List<DeviceExtendInfoDTO>> FindDevicesByOrganizationCodeAsync(FindDevicesByOrganizationCodeRequest request)
  558. {
  559. var result = new List<DeviceExtendInfoDTO>();
  560. var deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByOrganizationCodeAsync(request.OrganizationCode);
  561. if (deviceInfoDOList?.Count > 0)
  562. {
  563. //根据机构编号查询机构名称
  564. var organizationCode = deviceInfoDOList.FindAll(c => !string.IsNullOrEmpty(c.OrganizationCode)).Select(c => c.OrganizationCode).FirstOrDefault() ?? string.Empty;
  565. var organization = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = organizationCode });
  566. var organizationName = organization?.OrganizationName ?? string.Empty;
  567. //根据机构编号查询科室名称
  568. var organizationFilter = new Dictionary<string, string>();
  569. organizationFilter.Add("RootCode", organizationCode);
  570. var organizations = await _organizationDBService.GetOrganizationPageAsync((new PageFilterRequest { CurrentPage = 1, PageSize = 999999, Filter = organizationFilter, IsFuzzy = false }));
  571. var deviceCodes = deviceInfoDOList.Select(x => x.DeviceCode).ToList();
  572. var deviceTokens = await _authenticationService.GetTokenWithClientIdsAsync(new GetTokenWithClientIdsRequest { ClientIds = deviceCodes });
  573. var deviceTypeList = await _deviceInfoDBServiceProxy.FindDictionaryItemsAsync(new FindDictionaryItemsDBRequest { DictionaryType = (int)DictionaryTypeEnum.DeviceType });
  574. foreach (var c in deviceInfoDOList)
  575. {
  576. var deviceTypeModel = deviceTypeList.FirstOrDefault(t => t.DictionaryCode == c.DeviceType);
  577. result.Add(new DeviceExtendInfoDTO
  578. {
  579. DepartmentName = organizations.PageData.FirstOrDefault(o => o.OrganizationCode == c.DepartmentCode)?.OrganizationName,
  580. OrganizationName = organizationName,
  581. IsOnline = deviceTokens.FirstOrDefault(x => x.ClientId == c.DeviceCode)?.IsOnline ?? false,
  582. DeviceCode = c.DeviceCode,
  583. SerialNumber = c.SerialNumber,
  584. Name = c.Name,
  585. Description = c.Description,
  586. DeviceModel = c.DeviceModel,
  587. DeviceType = c.DeviceType,
  588. HeadPicUrl = c.HeadPicUrl,
  589. DeviceSoftwareVersion = c.DeviceSoftwareVersion,
  590. SDKSoftwareVersion = c.SDKSoftwareVersion,
  591. OrganizationCode = c.OrganizationCode,
  592. DepartmentCode = c.DepartmentCode,
  593. ShortCode = c.ShortCode,
  594. LanguageConfigs = deviceTypeModel?.LanguageConfigs
  595. });
  596. }
  597. }
  598. return result;
  599. }
  600. public Task<DeviceInfoDTO> CreateDeviceInfoAsync(CreateDeviceRequest request)
  601. {
  602. throw new NotImplementedException();
  603. }
  604. public async Task<List<SelectItemDTO>> GetPersonDeviceDropdownListAsync(TokenRequest request)
  605. {
  606. //验证
  607. var userCode = await GetClientIdByTokenAsync(request.Token);
  608. //查询用户是否存在
  609. var userInfoDO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  610. if (userInfoDO == null)
  611. {
  612. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  613. }
  614. var result = new List<SelectItemDTO>();
  615. //查询用户的医院是否存在
  616. if (string.IsNullOrEmpty(userInfoDO.OrganizationCode))
  617. {
  618. ThrowCustomerException(CustomerRpcCode.OrganizationNotExist, "Org does not exist");
  619. }
  620. var deviceInfoDOList = new List<DeviceInfoDTO>();
  621. if (userInfoDO.IsDirector)
  622. {
  623. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByOrganizationCodeAsync(userInfoDO.RootOrganizationCode);
  624. }
  625. else if (!userInfoDO.RoleCodes.Contains("Role_ExpertAssistant"))
  626. {
  627. //查询用户绑定的设备
  628. if (userInfoDO.BindDevices == null || userInfoDO.BindDevices.Count <= 0)
  629. {
  630. return result;
  631. }
  632. //根据用户名下的设备id查询所有的设备信息
  633. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByCodeListAsync(userInfoDO.BindDevices);
  634. }
  635. else
  636. {
  637. var experts = await _userServiceProxy.GetBindExpertsAsync(userCode);
  638. if (experts.Any())
  639. {
  640. var bindDeviceCodes = experts.SelectMany(x => x.BindDevices ?? new List<string>()).Distinct().ToList();
  641. if (bindDeviceCodes.Any())
  642. {
  643. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByCodeListAsync(bindDeviceCodes);
  644. }
  645. }
  646. else
  647. {
  648. deviceInfoDOList = await _deviceInfoDBServiceProxy.FindDeviceInfoListByOrganizationCodeAsync(userInfoDO.RootOrganizationCode);
  649. }
  650. }
  651. if (deviceInfoDOList?.Count > 0)
  652. {
  653. result = deviceInfoDOList.Select(c => new SelectItemDTO()
  654. {
  655. Key = c.DeviceCode,
  656. Value = c.Name
  657. }).ToList();
  658. }
  659. return result;
  660. }
  661. /// <summary>
  662. /// 设备端调用,查询获取服务器配置信息接口
  663. /// </summary>
  664. /// <param name="request">Token验证</param>
  665. /// <returns>服务器配置信息结果:key:字段,value:数据值,复杂类型可为json</returns>
  666. public async Task<DeviceServerSettingResult> QueryServerConfigAsync(TokenRequest request)
  667. {
  668. var deviceCode = await GetClientIdByTokenAsync(request.Token);
  669. var deviceInfo = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(deviceCode);
  670. if (deviceInfo == null || string.IsNullOrWhiteSpace(deviceInfo.DeviceCode))
  671. {
  672. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  673. }
  674. var org = new OrganizationDTO();
  675. if (!string.IsNullOrWhiteSpace(deviceInfo.OrganizationCode))
  676. {
  677. org = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = deviceInfo.OrganizationCode });
  678. if (org == null)
  679. {
  680. org = new OrganizationDTO();
  681. }
  682. }
  683. var dictionary = new Dictionary<string, string>();
  684. //定义配置字段 并扩充字段,返回数据可持续更新接口文档,如果数据是复杂类型可以转成json
  685. //TODO 配置信息: 直播配置、存储配置、
  686. //存储上传图像或者视频是 是否本地上传缩略图
  687. var isUploadThumbnail = ConfigurationManager.RemedicalSettings.IsUploadThumbnail;
  688. dictionary.Add("IsUploadThumbnail", isUploadThumbnail.ToString());
  689. dictionary.Add("PatientType", org.PatientType.ToString());
  690. dictionary.Add("HeartRateSeconds", _heartRateSeconds.ToString());
  691. dictionary.Add("NotificationUrl", _webSocketUrl);
  692. dictionary.Add("MergedChannel", deviceInfo.MergedChannel.ToString());
  693. dictionary.Add("LiveConsultationRateSeconds", _liveConsultationRateSeconds.ToString());
  694. var result = new DeviceServerSettingResult()
  695. {
  696. ServerConfigList = dictionary,
  697. IsUploadThumbnail = isUploadThumbnail,
  698. PatientType = org.PatientType,
  699. HeartRateSeconds = _heartRateSeconds,
  700. NotificationUrl = _webSocketUrl,
  701. LiveConsultationRateSeconds = _liveConsultationRateSeconds,
  702. MergedChannel = deviceInfo.MergedChannel,
  703. MergedVideoOutputWidth = deviceInfo.MergedVideoOutputWidth,
  704. MergedVideoOutputHeight = deviceInfo.MergedVideoOutputHeight,
  705. IsSelfRtcService = _isRTCSelf,
  706. RemoteControlAskTimeoutSec = _remoteControlAskTimeoutSec
  707. };
  708. return result;
  709. }
  710. /// <summary>
  711. /// 添加或迁移设备到医院请求
  712. /// </summary>
  713. /// <param name="request"></param>
  714. /// <returns></returns>
  715. public async Task<bool> AddDeviceToOrgAsync(AddDeviceToOrgRequest request)
  716. {
  717. var shortCode = request.UniqueCode;
  718. #region Params Check
  719. var userCode = await GetClientIdByTokenAsync(request.Token);
  720. if (string.IsNullOrEmpty(shortCode))
  721. {
  722. ThrowCustomerException(CustomerRpcCode.UniqueCodeIsEmpty, "UniqueCode is empty");
  723. }
  724. var device = await _deviceInfoDBServiceProxy.FindDeviceInfoByShortCodeAsync(shortCode);
  725. if (device == null)
  726. {
  727. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  728. }
  729. var oldOrg = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = device.OrganizationCode });
  730. if (oldOrg == null || string.IsNullOrWhiteSpace(oldOrg.OrganizationCode))
  731. {
  732. ThrowCustomerException(CustomerRpcCode.OrganizationNotExist, "Org does not exist");
  733. }
  734. //用户
  735. var userDTO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  736. if (userDTO == null)
  737. {
  738. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  739. }
  740. if (!userDTO.IsDirector)
  741. {
  742. ThrowCustomerException(CustomerRpcCode.NotOrgAdmin, "not org admin");
  743. }
  744. var org = await _organizationDBService.GetOrganizationDetailAsync(new GetOrganizationDBRequest { OrganizationCode = userDTO.OrganizationCode });
  745. if (org == null || string.IsNullOrWhiteSpace(org.OrganizationCode))
  746. {
  747. ThrowCustomerException(CustomerRpcCode.OrganizationNotExist, "Org does not exist");
  748. }
  749. #endregion
  750. try
  751. {
  752. var newOrgode = org.OrganizationCode;
  753. //设备更新医院
  754. if (!string.IsNullOrEmpty(device.DepartmentCode))
  755. {
  756. device.DepartmentCode = "";
  757. }
  758. if (!string.IsNullOrEmpty(device.Name))
  759. {
  760. device.Name = "";
  761. }
  762. device.HeadPicUrl = "";
  763. device.Description = "";
  764. device.IsAutoShared = false;
  765. device.OrganizationCode = newOrgode;
  766. bool success = await _deviceInfoDBServiceProxy.UpdateDeviceInfoByCodeAsync(device.DeviceCode, device, string.Empty, true);
  767. if (success)
  768. {
  769. // 删除已知绑定的用户
  770. var users = await _userServiceProxy.GetUsersByDeviceAsync(device.DeviceCode);
  771. var updateUsers = new List<TableDataItem<UserPasswordDTO>>();
  772. foreach (var user in users)
  773. {
  774. user.BindDevices.Remove(device.DeviceCode);
  775. updateUsers.Add(new TableDataItem<UserPasswordDTO>()
  776. {
  777. Data = user.MappingTo<UserPasswordDTO>(),
  778. });
  779. }
  780. if (updateUsers.Count > 0)
  781. {
  782. var updateUsersDBRequest = new UpdateUsersDBRequest() { Users = updateUsers };
  783. await _userServiceProxy.UpdateUsersAsync(updateUsersDBRequest);
  784. }
  785. if (oldOrg.Isinvented) // 虚拟医院
  786. {
  787. //迁移数据超声机上传检查记录
  788. await _recordsInfoDBService.UpdateRecordsWithOrgCodeAsync(new List<string>() { device.DeviceCode }, newOrgode);
  789. //迁移数据超声机上传病人
  790. await _patientInfoDBService.UpdatePatientWithOrgCodeAsync(new List<string>() { device.DeviceCode }, newOrgode);
  791. }
  792. }
  793. return success;
  794. }
  795. catch (System.Exception ex)
  796. {
  797. Logger.WriteLineError($"AddDeviceToOrgAsync error {ex}");
  798. }
  799. return false;
  800. }
  801. /// <summary>
  802. /// 补齐设备扩展信息
  803. /// </summary>
  804. /// <param name="deviceInfoDOList"></param>
  805. /// <returns></returns>
  806. private async Task<List<DeviceExtendInfoDTO>> MapToExtendDTO(List<DeviceInfoDTO> deviceInfoDOList)
  807. {
  808. var deviceList = new List<DeviceExtendInfoDTO>();
  809. if (deviceInfoDOList != null && deviceInfoDOList.Any())
  810. {
  811. //查询机构
  812. var orgCodes = deviceInfoDOList.Select(x => x.OrganizationCode).ToList();
  813. orgCodes.AddRange(deviceInfoDOList.Select(x => x.DepartmentCode));
  814. var organizations = await _organizationDBService.FindOrganizationListByCodesAsync(orgCodes.Distinct().ToList());
  815. //查询机构负责人
  816. var organizationDirectorCodes = new List<string>();
  817. foreach (var org in organizations)
  818. {
  819. if (org.Directors != null && org.Directors.Any())
  820. {
  821. organizationDirectorCodes.AddRange(org.Directors);
  822. }
  823. }
  824. var organizationDirectors = await _userServiceProxy.FindUserListByUserCodesAsync(organizationDirectorCodes);
  825. var deviceCodes = deviceInfoDOList.Select(x => x.DeviceCode).ToList();
  826. var deviceTokens = await _authenticationService.GetTokenWithClientIdsAsync(new GetTokenWithClientIdsRequest { ClientIds = deviceCodes });
  827. var deviceTypeList = await _deviceInfoDBServiceProxy.FindDictionaryItemsAsync(new FindDictionaryItemsDBRequest { DictionaryType = (int)DictionaryTypeEnum.DeviceType });
  828. foreach (var dto in deviceInfoDOList)
  829. {
  830. var device = dto.MappingTo<DeviceExtendInfoDTO>();
  831. device.IsOnline = deviceTokens.FirstOrDefault(x => x.ClientId == dto.DeviceCode)?.IsOnline ?? false;
  832. device.DepartmentName = organizations.FirstOrDefault(x => x.OrganizationCode == dto.DepartmentCode)?.OrganizationName;
  833. device.LanguageConfigs = deviceTypeList.FirstOrDefault(t => t.DictionaryCode == device.DeviceType)?.LanguageConfigs;
  834. var organization = organizations.FirstOrDefault(x => x.OrganizationCode == dto.OrganizationCode);
  835. if (organization != null)
  836. {
  837. device.OrganizationName = organization.OrganizationName;
  838. if (organization.Directors != null && organization.Directors.Any())
  839. {
  840. var director = organizationDirectors.FirstOrDefault(x => x.UserCode == organization.Directors.FirstOrDefault());
  841. device.OrganizationDirectorCode = director?.UserCode;
  842. device.OrganizationDirectorUserName = director?.UserName;
  843. device.OrganizationDirectorFullName = director?.FullName;
  844. }
  845. }
  846. deviceList.Add(device);
  847. }
  848. }
  849. return deviceList;
  850. }
  851. /// <summary>
  852. /// 补齐设备扩展信息
  853. /// </summary>
  854. /// <param name="deviceInfoDOList"></param>
  855. /// <returns></returns>
  856. private async Task<DeviceExtendInfoDTO> MapToExtendDTO(DeviceInfoDTO deviceInfoDO)
  857. {
  858. var deviceList = await MapToExtendDTO(new List<DeviceInfoDTO> { deviceInfoDO });
  859. return deviceList.FirstOrDefault();
  860. }
  861. /// <summary>
  862. /// 获取设备绑定用户codes
  863. /// </summary>
  864. /// <param name="request">获取设备绑定用户codes请求实体</param>
  865. /// <returns>test01,test02</returns>
  866. public async Task<List<string>> GetDeviceBindUsersCodesAsync(GetDeviceRequest request)
  867. {
  868. //检查设备编码不为空
  869. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  870. {
  871. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  872. }
  873. //查询设备对象
  874. var deviceDb = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(request.DeviceCode);
  875. if (deviceDb == null)
  876. {
  877. ThrowCustomerException(CustomerRpcCode.NoExistDevice, "Device does not exist");
  878. }
  879. var userListResult = await _userServiceProxy.GetUsersByDeviceAsync(request.DeviceCode);
  880. if (userListResult != null && userListResult.Count > 0)
  881. {
  882. return userListResult.Select(u => u.UserCode).ToList();
  883. }
  884. return new List<string>();
  885. }
  886. /// <summary>
  887. /// 查询设备AI应用的状态
  888. /// </summary>
  889. /// <param name="request">请求参数</param>
  890. /// <returns>AI应用集合</returns>
  891. public async Task<List<DiagnosisModuleDTO>> FindDeviceDiagnosisModulesAsync(FindDeviceDiagnosisModulesRequest request)
  892. {
  893. //检查设备编码不为空
  894. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  895. {
  896. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  897. }
  898. return await _diagnosisModuleService.GetDeviceDiagnosisModulesAsync(new GetDeviceDiagnosisModulesDBRequest { DeviceCode = request.DeviceCode });
  899. }
  900. /// <summary>
  901. /// 修改设备AI应用启用状态
  902. /// </summary>
  903. /// <param name="request">修改设备AI应用启用状态请求实体</param>
  904. /// <returns>是否成功</returns>
  905. /// <para>DeviceErrorCodeEnum</para>
  906. public async Task<bool> ModifyDeviceDiagnosisModuleStateAsync(ModifyDeviceDiagnosisModuleStateRequest request)
  907. {
  908. //检查设备编码不为空
  909. if (string.IsNullOrWhiteSpace(request.DeviceCode))
  910. {
  911. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  912. }
  913. if (string.IsNullOrWhiteSpace(request.DiagnosisModule))
  914. {
  915. ThrowCustomerException(CustomerRpcCode.DeviceAIDiagnosisModule, "Required parameter:DeviceCode cannot be empty");
  916. }
  917. var result = await _diagnosisModuleService.UpdateDeviceDiagnosisModuleStateAsync(new UpdateDeviceDiagnosisModuleStateDBRequest
  918. {
  919. DeviceCode = request.DeviceCode,
  920. DiagnosisModule = request.DiagnosisModule,
  921. Enabled = request.Enabled
  922. });
  923. CacheMaintenance.Instance.Get<IDeviceInfosManager>().Remove(request.DeviceCode);
  924. return result;
  925. }
  926. /// <summary>
  927. /// 设备离开会诊房间
  928. /// </summary>
  929. /// <param name="request">设备离开会诊房间请求实体</param>
  930. /// <returns></returns>
  931. public async Task<DeviceLeaveLiveConsultationResult> DeviceLeaveLiveConsultationAsync(DeviceLeaveLiveConsultationRequest request)
  932. {
  933. var deviceCode = await GetClientIdByTokenAsync(request.Token);
  934. var result = new DeviceLeaveLiveConsultationResult
  935. {
  936. Success = false,
  937. };
  938. return result;
  939. }
  940. /// <summary>
  941. /// 通用异常处理方法
  942. /// </summary>
  943. /// <param name="customerRpcCodeEnum">异常标识码</param>
  944. /// <param name="msg">异常信息</param>
  945. /// <param name="internalMessage">内部异常信息,非必填</param>
  946. private void ThrowCustomerException(CustomerRpcCode customerRpcCodeEnum, string msg, string internalMessage = null)
  947. {
  948. ThrowRpcException((int)customerRpcCodeEnum, msg, internalMessage);
  949. }
  950. /// <summary>
  951. /// 上报设备画面尺寸相关信息
  952. /// </summary>
  953. /// <param name="request"></param>
  954. /// <docFirstDirectory>设备端API</docFirstDirectory>
  955. /// <docSecondDirectory>实时会诊服务接口</docSecondDirectory>
  956. /// <docThirdDirectory>会诊</docThirdDirectory>
  957. /// <returns></returns>
  958. public async Task<ReportVideoDeviceInfoResult> ReportVideoDeviceInfoAsync(ReportVideoDeviceInfoRequest request)
  959. {
  960. var result = new ReportVideoDeviceInfoResult();
  961. request.VideoDeviceInfos = request.VideoDeviceInfos?.ToList() ?? new List<VideoDeviceInfo>();
  962. if (request.VideoDeviceInfos.Any())
  963. {
  964. if (request.VideoDeviceInfos.Any(x => string.IsNullOrWhiteSpace(x.VideoDeviceId)))
  965. {
  966. //视屏设备ID为空
  967. ThrowCustomerException(CustomerRpcCode.VideoDeviceIdEmpty, "VideoDeviceIdEmpty");
  968. }
  969. var videoDeviceIdCount = request.VideoDeviceInfos.Select(x => x.VideoDeviceId).Distinct().Count();
  970. if (videoDeviceIdCount < request.VideoDeviceInfos.Count)
  971. {
  972. //视屏设备ID重复
  973. ThrowCustomerException(CustomerRpcCode.VideoDeviceIdRepeatError, "VideoDeviceIdRepeatError");
  974. }
  975. }
  976. var deviceCode = await GetClientIdByTokenAsync(request.Token);
  977. var deviceDTO = await _deviceInfoDBServiceProxy.FindDeviceInfoByCodeAsync(deviceCode);
  978. var screenAndCamera = request.VideoDeviceInfos.Any(x => x.VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Camera);
  979. var outputWidth = deviceDTO.MergedVideoOutputWidth;
  980. var outputHeight = deviceDTO.MergedVideoOutputHeight;
  981. if (outputWidth <= 0 || outputHeight <= 0)
  982. {
  983. outputWidth = 1280;
  984. outputHeight = 720;
  985. }
  986. var videoDeviceInfos = new List<VideoDeviceDTO>();
  987. foreach (var video in request.VideoDeviceInfos)
  988. {
  989. var videoDeviceInfo = InitOutputInfo(video, deviceDTO.MergedChannel, screenAndCamera, outputWidth, outputHeight);
  990. videoDeviceInfos.Add(videoDeviceInfo);
  991. }
  992. deviceDTO.VideoDeviceInfos = videoDeviceInfos;
  993. var updateVideoDeviceInfosDBRequest = new UpdateVideoDeviceInfosDBRequest
  994. {
  995. DeviceCode = deviceDTO.DeviceCode,
  996. LiveOpened = request.LiveOpened,
  997. VideoDeviceInfos = videoDeviceInfos
  998. };
  999. await _deviceInfoDBServiceProxy.UpdateVideoDeviceInfosAsync(updateVideoDeviceInfosDBRequest);
  1000. CacheMaintenance.Instance.Get<IDeviceInfosManager>().Remove(deviceDTO.DeviceCode);
  1001. result.Success = true;
  1002. result.VideoDeviceOutputInfos = videoDeviceInfos;
  1003. return result;
  1004. }
  1005. private VideoDeviceDTO InitOutputInfo(VideoDeviceInfo videoDeviceInfo, bool mergedChannel, bool screenAndCamera, int maxWidth, int maxHeight)
  1006. {
  1007. // 给到设备端的输出尺寸,一定需要保持上报设备分辨率的宽高比
  1008. // CPU好的输出尺寸不能超过1080P,CPU较差的输出尺寸不能超过720P
  1009. // 单路情况,主频画面小于推荐尺寸,保持不变;主屏画面大于推荐尺寸,保持上报设备分辨率宽高比缩小
  1010. // (CPU好的情况帧率20,码率3000,最小帧率设为0(SDK自由设置)
  1011. // (CPU较差的情况)帧率15,码率2000,最小帧率设为0(SDK自由设置)
  1012. // 多路情况:1080P降到1280*720,720P降到1280*540
  1013. // 多路分流,保持上报设备分辨率宽高比缩小
  1014. // 多路合流(摄像头):640*480(CPU好的情况);640*360(CPU较差的情况)
  1015. // (CPU好的情况帧率20,码率3000,最小帧率设为2000
  1016. // (CPU较差的情况)帧率15,码率2000,最小帧率设为1000
  1017. var bestCpu = maxWidth == 1920;
  1018. var outputInfo = new VideoDeviceDTO
  1019. {
  1020. VideoDeviceId = videoDeviceInfo.VideoDeviceId,
  1021. VideoDeviceSourceType = videoDeviceInfo.VideoDeviceSourceType,
  1022. Width = videoDeviceInfo.Width,
  1023. Height = videoDeviceInfo.Height,
  1024. OutputWidth = videoDeviceInfo.Width,
  1025. OutputHeight = videoDeviceInfo.Height,
  1026. };
  1027. //输出分辨率
  1028. var width = videoDeviceInfo.Width;
  1029. var height = Math.Max(videoDeviceInfo.Height, 1);
  1030. if (!screenAndCamera)
  1031. {
  1032. //单路
  1033. if (bestCpu)
  1034. {
  1035. InitFpsAndBitrate(outputInfo, 20, 3000, 0);
  1036. InitDesktopOutputSize(outputInfo, 1920, 1080);
  1037. }
  1038. else
  1039. {
  1040. InitFpsAndBitrate(outputInfo, 15, 2000, 0);
  1041. InitDesktopOutputSize(outputInfo, 1280, 720);
  1042. }
  1043. }
  1044. else
  1045. {
  1046. if (mergedChannel)
  1047. {
  1048. //多路合流
  1049. if (bestCpu)
  1050. {
  1051. InitFpsAndBitrate(outputInfo, 20, 3000, 2000);
  1052. InitDesktopOutputSize(outputInfo, 1280, 720);
  1053. InitCameraOutputSize(outputInfo, 640, 480);
  1054. }
  1055. else
  1056. {
  1057. InitFpsAndBitrate(outputInfo, 15, 2000, 1000);
  1058. InitDesktopOutputSize(outputInfo, 1280, 540);
  1059. InitCameraOutputSize(outputInfo, 640, 360);
  1060. }
  1061. }
  1062. else
  1063. {
  1064. //多路分流
  1065. if (bestCpu)
  1066. {
  1067. InitFpsAndBitrate(outputInfo, 20, 3000, 2000);
  1068. InitDesktopOutputSize(outputInfo, 1280, 720);
  1069. InitCameraOutputSize(outputInfo, 1280, 720);
  1070. }
  1071. else
  1072. {
  1073. InitFpsAndBitrate(outputInfo, 15, 2000, 1000);
  1074. InitDesktopOutputSize(outputInfo, 1280, 540);
  1075. InitCameraOutputSize(outputInfo, 1280, 540);
  1076. }
  1077. }
  1078. }
  1079. return outputInfo;
  1080. }
  1081. private void InitFpsAndBitrate(VideoDeviceDTO outputInfo, int videoFps, int videoBitrate, int minVideoBitrate)
  1082. {
  1083. outputInfo.VideoFps = videoFps;
  1084. outputInfo.VideoBitrate = videoBitrate;
  1085. outputInfo.MinVideoBitrate = minVideoBitrate;
  1086. }
  1087. private void InitDesktopOutputSize(VideoDeviceDTO outputInfo, int maxWidth, int maxHeight)
  1088. {
  1089. if (outputInfo.VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Desktop)
  1090. {
  1091. if (outputInfo.Width <= maxWidth && outputInfo.Height <= maxHeight)
  1092. {
  1093. outputInfo.OutputWidth = outputInfo.Width;
  1094. outputInfo.OutputHeight = outputInfo.Height;
  1095. }
  1096. else
  1097. {
  1098. var radio = (double)outputInfo.Width / Math.Max(outputInfo.Height, 1);
  1099. if (outputInfo.Height > maxHeight)
  1100. {
  1101. outputInfo.OutputHeight = maxHeight;
  1102. outputInfo.OutputWidth = (int)(maxHeight * radio);
  1103. }
  1104. if (outputInfo.OutputWidth > maxWidth)
  1105. {
  1106. outputInfo.OutputWidth = maxWidth;
  1107. outputInfo.OutputHeight = (int)(maxWidth / radio);
  1108. }
  1109. }
  1110. }
  1111. }
  1112. private void InitCameraOutputSize(VideoDeviceDTO outputInfo, int maxWidth, int maxHeight)
  1113. {
  1114. if (outputInfo.VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Camera)
  1115. {
  1116. if (outputInfo.Width <= maxWidth && outputInfo.Height <= maxHeight)
  1117. {
  1118. outputInfo.OutputWidth = outputInfo.Width;
  1119. outputInfo.OutputHeight = outputInfo.Height;
  1120. }
  1121. else
  1122. {
  1123. var radio = (double)outputInfo.Width / Math.Max(outputInfo.Height, 1);
  1124. if (outputInfo.Height > maxHeight)
  1125. {
  1126. outputInfo.OutputHeight = maxHeight;
  1127. outputInfo.OutputWidth = (int)(maxHeight * radio);
  1128. }
  1129. if (outputInfo.OutputWidth > maxWidth)
  1130. {
  1131. outputInfo.OutputWidth = maxWidth;
  1132. outputInfo.OutputWidth = (int)(maxWidth / radio);
  1133. }
  1134. }
  1135. }
  1136. }
  1137. /// <summary>
  1138. /// 查找有效设备总数量
  1139. /// </summary>
  1140. /// <returns></returns>
  1141. public async Task<long> GetActiveDeviceCount()
  1142. {
  1143. return await _deviceInfoDBServiceProxy.GetActiveDeviceCount();
  1144. }
  1145. /// <summary>
  1146. /// 设备发送调参初始化数据
  1147. /// </summary>
  1148. /// <param name="request">调参数据请求</param>
  1149. /// <returns></returns>
  1150. public async Task<bool> SendControlParameterByDeviceAsync(SendControlParameterByDeviceRequest request)
  1151. {
  1152. var deviceCode = await GetClientIdByTokenAsync(request.Token);
  1153. var userCode = request.ControlUserCode;
  1154. //发送控制人通知
  1155. if (string.IsNullOrWhiteSpace(userCode))
  1156. {
  1157. ThrowCustomerException(CustomerRpcCode.UsercodeIsEmpty, "User code is empty");
  1158. }
  1159. var userDTO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  1160. if (userDTO == null)
  1161. {
  1162. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  1163. }
  1164. var notify = new DeviceParametersNotification()
  1165. {
  1166. DeviceCode = deviceCode,
  1167. IsResponse = true
  1168. };
  1169. var cacheControllingParameter = new CacheControllingParameter()
  1170. {
  1171. Code = deviceCode,
  1172. ProbeApplication = Newtonsoft.Json.JsonConvert.SerializeObject(request.ProbeApplication),
  1173. Parameter = Newtonsoft.Json.JsonConvert.SerializeObject(request.Parameter),
  1174. };
  1175. _controllingParameterDevices.AddOrUpdate(deviceCode, (k) => cacheControllingParameter, (k, exist) =>
  1176. {
  1177. return cacheControllingParameter;
  1178. });
  1179. var notificationRequest = new SendNotificationRequest()
  1180. {
  1181. ClientId = userCode,
  1182. Message = notify,
  1183. JsonMessage = Newtonsoft.Json.JsonConvert.SerializeObject(notify),
  1184. NotificationType = notify.NotificationType,
  1185. TransactionType = TransactionTypeEnum.ControlParameter,
  1186. RelevanceCode = userCode,
  1187. ReceiverType = ApplicantTypeEnum.Client
  1188. };
  1189. await _notificationService.PostMessageAsync(notificationRequest);
  1190. return true;
  1191. }
  1192. /// <summary>
  1193. /// 获取设备参数调节数据请求
  1194. /// </summary>
  1195. /// <param name="request"></param>
  1196. /// <returns></returns>
  1197. public async Task<DeviceControlParameterDataDTO> GetControlParametersAsync(GetControlParametersRequest request)
  1198. {
  1199. var deviceCode = request.DeviceCode;
  1200. //检查设备编码不为空
  1201. if (string.IsNullOrWhiteSpace(deviceCode))
  1202. {
  1203. ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "Required parameter:DeviceCode cannot be empty");
  1204. }
  1205. _controllingParameterDevices.TryGetValue(deviceCode, out var controlParameterData);
  1206. if (controlParameterData != null)
  1207. {
  1208. return new DeviceControlParameterDataDTO()
  1209. {
  1210. DeviceCode = controlParameterData.Code,
  1211. ProbeApplication = controlParameterData.ProbeApplication,
  1212. Parameter = controlParameterData.Parameter
  1213. };
  1214. }
  1215. return null;
  1216. }
  1217. /// <summary>
  1218. /// 用户进入设备直播房间
  1219. /// </summary>
  1220. /// <param name="request">用户进入设备直播房间请求实体</param>
  1221. /// <returns></returns>
  1222. public async Task<JoinDeviceLiveRoomResult> JoinDeviceLiveRoomAsync(JoinDeviceLiveRoomRequest request)
  1223. {
  1224. var userInfo = await _authenticationService.GetTokenAsync(request);
  1225. var deviceCode = request.DeviceCode;
  1226. var deviceInfo = CacheMaintenance.Instance.Get<IDeviceInfosManager>().Get(deviceCode);
  1227. var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest
  1228. {
  1229. DeviceCode = deviceCode
  1230. });
  1231. LiveMemberDTO deviceMemberInfo;
  1232. if (liveRoom != null)
  1233. {
  1234. if (liveRoom.LiveRoomCode == deviceCode)
  1235. {
  1236. //设备正在推流
  1237. deviceMemberInfo = liveRoom.DeviceInfos.FirstOrDefault(x => x.Code == deviceCode);
  1238. if (deviceMemberInfo?.Status == LiveMemberStatus.Joined)
  1239. {
  1240. //添加观众
  1241. await _rtcService.SaveViewerAsync(new SaveViewerRequest
  1242. {
  1243. LiveRoomCode = liveRoom.LiveRoomCode,
  1244. UserCode = userInfo.ClientId,
  1245. UserName = userInfo.AccountName,
  1246. });
  1247. return new JoinDeviceLiveRoomResult
  1248. {
  1249. RoomNo = liveRoom.RtcRoomId,
  1250. ReportStateIntervalSeconds = _reportStateIntervalSeconds,
  1251. VideoDeviceInfos = deviceMemberInfo.VideoDeviceInfos?.Select(x => new VideoDeviceInfoDTO
  1252. {
  1253. VideoDeviceId = x.VideoDeviceId,
  1254. VideoDeviceSourceType = x.VideoDeviceSourceType,
  1255. LiveData = x.LiveData
  1256. })?.ToList() ?? new List<VideoDeviceInfoDTO>(),
  1257. };
  1258. }
  1259. }
  1260. }
  1261. //新增或更新设备直播间
  1262. var deviceName = !string.IsNullOrWhiteSpace(deviceInfo.Name) ? deviceInfo.Name : deviceInfo.ShortCode;
  1263. var deviceLiveInfo = new LiveMemberDTO
  1264. {
  1265. Code = deviceCode,
  1266. Name = deviceName,
  1267. MemberType = LiveMemberEnum.Device,
  1268. HeadImageToken = deviceInfo.HeadPicUrl,
  1269. Status = LiveMemberStatus.Accepted,
  1270. };
  1271. var room = new LiveRoomDTO
  1272. {
  1273. LiveRoomCode = deviceCode,
  1274. Name = deviceName,
  1275. RelatedCode = deviceCode,
  1276. BusinessModule = BusinessModuleEnum.DeviceLiving,
  1277. Status = LiveRoomStatus.Default,
  1278. UserInfos = new List<LiveMemberDTO>(),
  1279. DeviceInfos = new List<LiveMemberDTO> { deviceLiveInfo }
  1280. };
  1281. await _rtcService.AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest
  1282. {
  1283. LiveRoom = room,
  1284. });
  1285. var initiateResult = await _rtcService.InitiateAsync(new InitiateRequest
  1286. {
  1287. LiveRoomCode = deviceCode,
  1288. InitiatorCode = deviceCode,
  1289. });
  1290. deviceMemberInfo = initiateResult.DeviceInfos.FirstOrDefault(x => x.Code == deviceCode);
  1291. //添加观众
  1292. await _rtcService.SaveViewerAsync(new SaveViewerRequest
  1293. {
  1294. LiveRoomCode = initiateResult.LiveRoomCode,
  1295. UserCode = userInfo.ClientId,
  1296. UserName = userInfo.AccountName,
  1297. });
  1298. return new JoinDeviceLiveRoomResult
  1299. {
  1300. RoomNo = initiateResult.RtcRoomId,
  1301. ReportStateIntervalSeconds = _reportStateIntervalSeconds,
  1302. VideoDeviceInfos = deviceMemberInfo.VideoDeviceInfos?.Select(x => new VideoDeviceInfoDTO
  1303. {
  1304. VideoDeviceId = x.VideoDeviceId,
  1305. VideoDeviceSourceType = x.VideoDeviceSourceType,
  1306. LiveData = x.LiveData
  1307. })?.ToList() ?? new List<VideoDeviceInfoDTO>(),
  1308. };
  1309. }
  1310. /// <summary>
  1311. /// 用户离开设备直播房间
  1312. /// </summary>
  1313. /// <param name="request">用户离开设备直播房间请求实体</param>
  1314. /// <returns></returns>
  1315. public async Task<bool> LeaveDeviceLiveRoomAsync(LeaveDeviceLiveRoomRequest request)
  1316. {
  1317. var userInfo = await _authenticationService.GetTokenAsync(request);
  1318. var userCode = userInfo.ClientId;
  1319. var deviceCode = request.DeviceCode;
  1320. var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest
  1321. {
  1322. DeviceCode = deviceCode
  1323. });
  1324. if (liveRoom != null)
  1325. {
  1326. //移除观众
  1327. var removeViewerResult = await _rtcService.RemoveViewerAsync(new RemoveViewerRequest
  1328. {
  1329. LiveRoomCode = liveRoom.LiveRoomCode,
  1330. UserCode = userInfo.ClientId,
  1331. });
  1332. var expireTime = DateTime.UtcNow.AddSeconds(_reportStateTimeout * -1);
  1333. if (!liveRoom.ViewerInfos.Any(x => x.UserCode != userCode && x.LastReportTime >= expireTime))
  1334. {
  1335. await _rtcService.CloseAsync(new CloseRequest
  1336. {
  1337. LiveRoomCode = liveRoom.LiveRoomCode
  1338. });
  1339. }
  1340. }
  1341. return true;
  1342. }
  1343. /// <summary>
  1344. /// 上报观看直播状态
  1345. /// </summary>
  1346. /// <param name="request">上报观看直播状态请求实体</param>
  1347. /// <returns></returns>
  1348. public async Task<bool> ReportLiveViewStateAsync(ReportLiveViewStateRequest request)
  1349. {
  1350. var userInfo = await _authenticationService.GetTokenAsync(request);
  1351. var deviceCode = request.DeviceCode;
  1352. var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest
  1353. {
  1354. DeviceCode = deviceCode
  1355. });
  1356. if (liveRoom != null)
  1357. {
  1358. //添加观众
  1359. var addOrUpdateViewerResult = await _rtcService.SaveViewerAsync(new SaveViewerRequest
  1360. {
  1361. LiveRoomCode = liveRoom.LiveRoomCode,
  1362. UserCode = userInfo.ClientId,
  1363. UserName = userInfo.AccountName,
  1364. });
  1365. }
  1366. return true;
  1367. }
  1368. /// <summary>
  1369. /// 上报直播状态
  1370. /// </summary>
  1371. /// <param name="request">上报直播状态请求实体</param>
  1372. /// <returns></returns>
  1373. public async Task<bool> ReportLiveStateAsync(ReportLiveStateRequest request)
  1374. {
  1375. var tokenInfo = await _authenticationService.GetTokenAsync(request);
  1376. var deviceCode = tokenInfo.ClientId;
  1377. switch (request.LiveState)
  1378. {
  1379. case DeviceLiveStateEnum.Error:
  1380. case DeviceLiveStateEnum.Warning:
  1381. Logger.WriteLineWarn($"DeviceService ReportLiveStateAsync, [{tokenInfo.AccountType.ToString()}]{tokenInfo.AccountName}, state:{request.LiveState.ToString()}, message:{request.Message}");
  1382. break;
  1383. default:
  1384. Logger.WriteLineInfo($"DeviceService ReportLiveStateAsync, [{tokenInfo.AccountType.ToString()}]{tokenInfo.AccountName}, state:{request.LiveState.ToString()}, message:{request.Message}");
  1385. break;
  1386. }
  1387. if (request.LiveState == DeviceLiveStateEnum.Closed)
  1388. {
  1389. var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest
  1390. {
  1391. DeviceCode = deviceCode
  1392. });
  1393. if (liveRoom != null)
  1394. {
  1395. var expireTime = DateTime.UtcNow.AddSeconds(_reportStateTimeout * -1);
  1396. var validViewers = liveRoom.ViewerInfos.Where(x => x.LastReportTime >= expireTime)?.ToList() ?? new List<LiveViewerDTO>();
  1397. if (validViewers.Any())
  1398. {
  1399. //关闭直播 to users
  1400. var message = new DeviceLiveFinishedNotification
  1401. {
  1402. LiveRoomCode = liveRoom.LiveRoomCode,
  1403. };
  1404. await BroadcastNotificationAsync(liveRoom.LiveRoomCode, validViewers.Select(x => x.UserCode).ToList(), message);
  1405. }
  1406. await _rtcService.CloseAsync(new CloseRequest
  1407. {
  1408. LiveRoomCode = liveRoom.LiveRoomCode
  1409. });
  1410. }
  1411. }
  1412. return await Task.FromResult(true);
  1413. }
  1414. /// <summary>
  1415. /// 获取实时音视频参数
  1416. /// </summary>
  1417. /// <param name="request">获取实时音视频参数请求实体</param>
  1418. /// <returns></returns>
  1419. public async Task<CreateLiveRoomInfoResult> CreateLiveRoomInfoAsync(CreateLiveRoomInfoRequest request)
  1420. {
  1421. Logger.WriteLineInfo($"DeviceService CreateLiveRoomInfoAsync, DeviceUniqueCode:{request.DeviceUniqueCode}, DeviceType:{request.DeviceType}, DeviceModel:{request.DeviceModel}, SoftwareVersion:{request.SoftwareVersion}");
  1422. var userCode = Guid.NewGuid().ToString("N");
  1423. var getUserSignRequest = new GetUserSignRequest
  1424. {
  1425. UserId = userCode,
  1426. };
  1427. var getUserSignResult = await _wingRtcService.GetUserSignAsync(getUserSignRequest);
  1428. var userSign = getUserSignResult.UserSign;
  1429. var getRoomIdRequest = new GetRoomIdRequest
  1430. {
  1431. UniqueId = userCode,
  1432. };
  1433. var getRoomIdResult = await _wingRtcService.GetRoomIdAsync(getRoomIdRequest);
  1434. var intRoomNo = (int)getRoomIdResult.RoomId;
  1435. Logger.WriteLineInfo($"DeviceService CreateLiveRoomInfoAsync, DeviceUniqueCode:{request.DeviceUniqueCode}, UserCode:{userCode}, roomNo:{intRoomNo}");
  1436. return new CreateLiveRoomInfoResult
  1437. {
  1438. IsTrtc = !_isRTCSelf,
  1439. UserCode = userCode,
  1440. UserSign = userSign,
  1441. AppId = _sdkAppId,
  1442. RoomNo = intRoomNo,
  1443. };
  1444. }
  1445. private async Task<bool> BroadcastNotificationAsync(string roomId, IList<string> clientIds, NotificationDTO message)
  1446. {
  1447. var broadcastNotificationRequest = new BroadcastNotificationRequest
  1448. {
  1449. ClientIds = clientIds,
  1450. Message = message,
  1451. TransactionType = TransactionTypeEnum.Live,
  1452. RelevanceCode = roomId,
  1453. ReceiverType = ApplicantTypeEnum.Client,
  1454. WSConnectType = WSConnectTypeEnum.Default
  1455. };
  1456. return await _notificationService.BroadcastMessageAsync(broadcastNotificationRequest);
  1457. }
  1458. /// <summary>
  1459. /// 拒绝远程控制
  1460. /// </summary>
  1461. /// <param name="request"></param>
  1462. /// <returns></returns>
  1463. public async Task<bool> RejectRemoteControl(RemoteControlRequest request)
  1464. {
  1465. string deviceCode = await GetClientIdByTokenAsync(request.Token);
  1466. string userCode = request.ControlUserCode;
  1467. //发送控制人通知
  1468. if (string.IsNullOrWhiteSpace(userCode))
  1469. {
  1470. ThrowCustomerException(CustomerRpcCode.UsercodeIsEmpty, "User code is empty");
  1471. }
  1472. var userDTO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  1473. if (userDTO == null)
  1474. {
  1475. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  1476. }
  1477. var notify = new DeviceRejectRemoteControlNotification()
  1478. {
  1479. DeviceCode = deviceCode,
  1480. };
  1481. var notificationRequest = new SendNotificationRequest()
  1482. {
  1483. ClientId = userCode,
  1484. Message = notify,
  1485. JsonMessage = Newtonsoft.Json.JsonConvert.SerializeObject(notify),
  1486. NotificationType = notify.NotificationType,
  1487. TransactionType = TransactionTypeEnum.RemoteControl,
  1488. RelevanceCode = userCode,
  1489. ReceiverType = ApplicantTypeEnum.Client
  1490. };
  1491. await _notificationService.PostMessageAsync(notificationRequest);
  1492. //更改房间调参状态
  1493. // var getRoomRequest = new FindRoomByCodeRequest { DeviceCode = deviceCode, UserCode = userCode };
  1494. // var room = await _rtcService.GetLiveRoomByCodeAsync(getRoomRequest);
  1495. // if (room != null && !string.IsNullOrWhiteSpace(room.RoomId))
  1496. // {
  1497. // var changeControllingParameterStateRequest = new SetLiveParamsRequest { UserCode = userCode, RoomId = room.RoomId, IsControllingParameter = false };
  1498. // await _rtcService.ChangeControllingParameterStateAsync(changeControllingParameterStateRequest);
  1499. // }
  1500. var roomRequest = new ChangeConsultationControllingStateRequest { DeviceCode = deviceCode, UserCode = userCode, IsControllingParameter = false };
  1501. await _liveConsultationService.ChangeConsultationControllingStateAsync(roomRequest);
  1502. return true;
  1503. }
  1504. /// <summary>
  1505. /// 断开远程控制
  1506. /// </summary>
  1507. /// <param name="request"></param>
  1508. /// <returns></returns>
  1509. public async Task<bool> DisconnectRemoteControl(RemoteControlRequest request)
  1510. {
  1511. string deviceCode = await GetClientIdByTokenAsync(request.Token);
  1512. string userCode = request.ControlUserCode;
  1513. //发送控制人通知
  1514. if (string.IsNullOrWhiteSpace(userCode))
  1515. {
  1516. ThrowCustomerException(CustomerRpcCode.UsercodeIsEmpty, "User code is empty");
  1517. }
  1518. var userDTO = await _userServiceProxy.FindUserByCodeAsync(userCode);
  1519. if (userDTO == null)
  1520. {
  1521. ThrowCustomerException(CustomerRpcCode.UserNotExistError, "User does not exist");
  1522. }
  1523. var notify = new DeviceDisconnectRemoteControlNotification()
  1524. {
  1525. DeviceCode = deviceCode,
  1526. };
  1527. var notificationRequest = new SendNotificationRequest()
  1528. {
  1529. ClientId = userCode,
  1530. Message = notify,
  1531. JsonMessage = Newtonsoft.Json.JsonConvert.SerializeObject(notify),
  1532. NotificationType = notify.NotificationType,
  1533. TransactionType = TransactionTypeEnum.RemoteControl,
  1534. RelevanceCode = userCode,
  1535. ReceiverType = ApplicantTypeEnum.Client
  1536. };
  1537. await _notificationService.PostMessageAsync(notificationRequest);
  1538. //更改房间调参状态
  1539. // var getRoomRequest = new FindRoomByCodeRequest { DeviceCode = deviceCode, UserCode = userCode };
  1540. // var room = await _rtcService.GetLiveRoomByCodeAsync(getRoomRequest);
  1541. // if (room != null && !string.IsNullOrWhiteSpace(room.RoomId))
  1542. // {
  1543. // var changeControllingParameterStateRequest = new SetLiveParamsRequest { UserCode = userCode, RoomId = room.RoomId, IsControllingParameter = false };
  1544. // await _rtcService.ChangeControllingParameterStateAsync(changeControllingParameterStateRequest);
  1545. // }
  1546. var roomRequest = new ChangeConsultationControllingStateRequest { DeviceCode = deviceCode, UserCode = userCode, IsControllingParameter = false };
  1547. await _liveConsultationService.ChangeConsultationControllingStateAsync(roomRequest);
  1548. return true;
  1549. }
  1550. public async Task<bool> UploadConsultationDataAsync(UploadConsultationDataRequest request)
  1551. {
  1552. var deviceInfo = await GetDeviceByTokenAsync(request);
  1553. var consultationCode = request.ConsultationCode;
  1554. if (string.IsNullOrWhiteSpace(consultationCode))
  1555. {
  1556. ThrowCustomerException(CustomerRpcCode.ConsultationCodeIsEmpty, "ConsultationCode is empty");
  1557. }
  1558. if (string.IsNullOrWhiteSpace(request.FileToken))
  1559. {
  1560. ThrowCustomerException(CustomerRpcCode.FileTokenIsEmpty, "FileToken is empty");
  1561. }
  1562. var findConsultationRequest = new ConsultationRecordCodeDBRequest { Code = consultationCode };
  1563. var consultationRecord = await _consultationRecordDBService.FindConsultationRecordByCodeAsync(findConsultationRequest);
  1564. if (consultationRecord == null || string.IsNullOrWhiteSpace(consultationRecord.ConsultationCode))
  1565. {
  1566. ThrowCustomerException(CustomerRpcCode.ConsultationNotExisted, "Consultation not exist");
  1567. }
  1568. var dataDTO = new RemedicalInfoDTO();
  1569. dataDTO.DeviceCode = deviceInfo.DeviceCode;
  1570. dataDTO.RecordCode = consultationRecord.ConsultationCode;
  1571. dataDTO.ApplicationCategory = request.ApplicationCategory;
  1572. dataDTO.Application = request.Application;
  1573. dataDTO.TerminalImages = new TerminalImageDTO();
  1574. var originImageUrl = request.FileToken;
  1575. dataDTO.TerminalImages.OriginImageUrl = originImageUrl;//源站地址
  1576. dataDTO.TerminalImages.ImageUrl = request.FileToken.ToUrlToken();//CDN 地址
  1577. dataDTO.TerminalImages.PreviewUrl = request.PreviewFileToken.ToUrlToken();
  1578. dataDTO.TerminalImages.CoverImageUrl = request.CoverImageToken.ToUrlToken();
  1579. dataDTO.TerminalImages.ImageSize = request.FileSize;
  1580. dataDTO.FileDataType = request.FileDataType;
  1581. dataDTO.MeasuredResult = request.MeasuredResult;
  1582. dataDTO.CommentResult = request.CommentResult;
  1583. dataDTO.BusinessType = BusinessTypeEnum.LiveConsultation;
  1584. dataDTO.RemedicalCode = await _remedicalDBService.InsertRemedicalInfoAsync(new CreateRemedicalInfoDBRequest { Data = dataDTO });
  1585. //更新会诊记录
  1586. if (consultationRecord.ConsultationFileList == null)
  1587. {
  1588. consultationRecord.ConsultationFileList = new List<ConsultationFileDTO>();
  1589. }
  1590. var consultationFileDTO = new ConsultationFileDTO
  1591. {
  1592. SourceUrl = originImageUrl,
  1593. CoverImageUrl = dataDTO.TerminalImages.CoverImageUrl,
  1594. PreviewImageUrl = dataDTO.TerminalImages.PreviewUrl,
  1595. FileDataType = request.FileDataType,
  1596. CreateTime = DateTime.UtcNow,
  1597. ConsultationFileType = ConsultationFileTypeEnum.UltrasoundImage,
  1598. RemedicalCode = dataDTO.RemedicalCode
  1599. };
  1600. consultationRecord.ConsultationFileList.Add(consultationFileDTO);
  1601. var result = await _consultationRecordDBService.UpdateConsultationRecordAsync(consultationRecord);
  1602. return !string.IsNullOrWhiteSpace(dataDTO.RemedicalCode);
  1603. }
  1604. }
  1605. }