平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

854 line
45 KiB

  1. using System.Drawing;
  2. using System.Drawing.Imaging;
  3. using System.Net.WebSockets;
  4. using System.Text;
  5. using MoYu.DataEncryption;
  6. using MoYu.RemoteRequest.Extensions;
  7. using Newtonsoft.Json;
  8. using Newtonsoft.Json.Linq;
  9. using SafeCampus.Application.Services.Business.AttendanceService;
  10. using SafeCampus.Application.Services.Business.ClassRoomCallService;
  11. using SafeCampus.Application.Services.Business.Warn.Dto;
  12. using SafeCampus.Application.Services.Business.Warn.Service;
  13. namespace SafeCampus.Application.Manager.DeepelephManager;
  14. /// <summary>
  15. /// 深象智能对接实现
  16. /// </summary>
  17. public class DeepelephManager : IDeepelephManager, IScoped
  18. {
  19. private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
  20. private bool _isConnected = false;
  21. private Timer _pingTimer;
  22. private List<ClientWebSocket> webScokets=new List<ClientWebSocket>();
  23. private readonly ISimpleCacheService _simpleCacheService;
  24. public DeepelephManager(ISimpleCacheService simpleCacheService)
  25. {
  26. _simpleCacheService = simpleCacheService;
  27. }
  28. //获取地址
  29. //建立请求,发送订阅参数
  30. //遍历等待接收消息
  31. public string GetToken()
  32. {
  33. var cacheToken = _simpleCacheService.Get<string>(AuthConstants.SXTOKEN);
  34. if (cacheToken != null) return cacheToken;
  35. return GenSXToken();
  36. }
  37. /// <summary>
  38. /// 获取深象智能Token
  39. /// </summary>
  40. /// <returns></returns>
  41. private string GenSXToken()
  42. {
  43. var token = "";
  44. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  45. var nonce = Guid.NewGuid().ToString("N");
  46. var timestamp =DateTimeOffset.Now.ToUnixTimeMilliseconds();
  47. var list = $"{setting.SXAPIURL}/user/center/v1/login/client"
  48. .SetBody(new
  49. {
  50. appKey = setting.AppKey,
  51. appSecret = setting.AppSecret,
  52. nonce ,
  53. timestamp,
  54. sign = MD5Encryption.Encrypt($"{setting.AppSecret}appKey{setting.AppKey}nonce{nonce}timestamp{timestamp}{setting.AppSecret}",true)
  55. })
  56. .SetContentType("application/json")
  57. .PostAsAsync<string>().Result;
  58. var model = JsonConvert.DeserializeObject<JObject>(list);
  59. if (model["success"]!=null)
  60. {
  61. if ((bool)model["success"])
  62. {
  63. token = model["data"]["token"].ToString();
  64. //token有效期2小时,提前20分钟失效
  65. _simpleCacheService.Set(AuthConstants.SXTOKEN, token, 100*60);
  66. }
  67. else
  68. {
  69. LogHelper.WriteToLog("token请求失败", model["message"].ToString());
  70. }
  71. }
  72. return token;
  73. }
  74. /// <summary>
  75. /// 订阅预警更新
  76. /// </summary>
  77. /// <returns></returns>
  78. public async Task SubscribeAlarm()
  79. {
  80. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  81. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  82. var url = GetWebSocketUrl(AuthConstants.SXALARM, AuthConstants.SXALARM_Grpup);
  83. var subscribeJson = JsonConvert.SerializeObject(new
  84. {
  85. token = GetToken(),
  86. type = "subscribe",
  87. timestamp,
  88. payload = new
  89. {
  90. topic = AuthConstants.SXALARM, consumerGroup = AuthConstants.SXALARM_Grpup, tags = setting.TenantCode
  91. }
  92. });
  93. ClientWebSocket _webSocket = new ClientWebSocket();
  94. webScokets.Add(_webSocket);
  95. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  96. //LogHelper.WriteToLog($"预警WebSocket 地址:{url}");
  97. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  98. byte[] buffer = new byte[1024*8];
  99. while (_webSocket.State == WebSocketState.Open)
  100. {
  101. //try
  102. //{
  103. // var jsonstr =
  104. // "{\"body\":{\"extend\":\"{\\\"trackId\\\":\\\"7173252404809024768\\\",\\\"genderScore\\\":[0.0,1.0,0.0],\\\"faceSnapshot\\\":\\\"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/acp/quanjiang/DEMO00001/20240719/edge/group/SXT001_book_wm_1721360996798_55.jpg?Expires=1721368200&OSSAccessKeyId=STS.NSwBDiH7ZnNGS9m2ahE8XyuW6&Signature=dEBXyrWcz3FyXMqDueIkZL%2F9uhk%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5DCCf7dpeh72YysUR%2Fc1mE9Sbd0lrD81Dz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4zJySB7g0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxKTpyjlP%2FAxd8uAx9DyyfH1x3TObqd7jjqzaKs3NYdtswV4BUlvK5CGWEjhzQEO8mJtNIDT39ay%2BVK8NrfsIeBqAATzzKDWbI1DbvfIwuHS6%2BX5i%2FQ0%2BgbpA87Kw%2BQiZxZdvjHXLLqQaYmTRXkuFPxUqNR8BckkEiPPkSs%2B9UQm3Cwq6rnEFeZty8FvEKds5Wo3H2QevhGwkKNImDp%2BmIjF2gzxOSfDv5rBvJWanWW0ewZdlFeiIR88SRvtr10jyoV4OIAA%3D\\\",\\\"faceSnapshotPath\\\":\\\"deepvision:acp/quanjiang/DEMO00001/20240719/edge/group/SXT001_book_wm_1721360996798_55.jpg\\\",\\\"faceScore\\\":30.105469}\",\"alarmType\":\"mask_detect\",\"func\":\"mask_detect\",\"cameraId\":\"SXT001\",\"alarmId\":\"1600d5874d854f1da54e663ae56c845f\",\"snapshotUrl\":\"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/acp/quanjiang/DEMO00001/20240719/edge/group/SXT001/SXT001_69bde610-a957-434b-a7ce-834aee148b2b_wm_56.jpg?Expires=1721368200&OSSAccessKeyId=STS.NSwBDiH7ZnNGS9m2ahE8XyuW6&Signature=hb6DQLWwZqukNQdel0TsUctAwAE%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5DCCf7dpeh72YysUR%2Fc1mE9Sbd0lrD81Dz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4zJySB7g0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxKTpyjlP%2FAxd8uAx9DyyfH1x3TObqd7jjqzaKs3NYdtswV4BUlvK5CGWEjhzQEO8mJtNIDT39ay%2BVK8NrfsIeBqAATzzKDWbI1DbvfIwuHS6%2BX5i%2FQ0%2BgbpA87Kw%2BQiZxZdvjHXLLqQaYmTRXkuFPxUqNR8BckkEiPPkSs%2B9UQm3Cwq6rnEFeZty8FvEKds5Wo3H2QevhGwkKNImDp%2BmIjF2gzxOSfDv5rBvJWanWW0ewZdlFeiIR88SRvtr10jyoV4OIAA%3D\",\"rects\":[{\"top\":601,\"left\":1156,\"width\":235,\"height\":767}],\"poiId\":\"DEMO00001\",\"tenantCode\":\"quanjiang\",\"tick\":1721360953398},\"bornTimestamp\":1721361000758,\"consumerGroup\":\"GID_quanjiang_risk\",\"keys\":\"1600d5874d854f1da54e663ae56c845f\",\"messageId\":\"AC14058A00017A07C5B45F3C813680EC\",\"queueId\":4,\"queueOffset\":422853,\"tags\":\"quanjiang\",\"topic\":\"ECOLOGY_PAAS_RISK_ALARM\",\"type\":\"msg\"}";
  105. // var json = JsonConvert.DeserializeObject<JObject>(jsonstr);
  106. // if (json["type"].ToString() == "msg")
  107. // {
  108. // var body = json["body"];
  109. // if (body != null)
  110. // {
  111. // PersonType personEnum;
  112. // if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  113. // {
  114. // dayEnum = AlarmType.visual_fence;
  115. // }
  116. // if (body["extend"] != null)
  117. // {
  118. // var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  119. // if (extend["personType"] != null)
  120. // {
  121. // if (!Enum.TryParse(body["extend"]?["personType"]?.ToString(), out personEnum))
  122. // {
  123. // personEnum = PersonType.unkonwn;
  124. // }
  125. // }
  126. // else
  127. // {
  128. // personEnum = PersonType.unkonwn;
  129. // }
  130. // }
  131. // else
  132. // {
  133. // personEnum = PersonType.unkonwn;
  134. // }
  135. // var model = new WarnInfoDto
  136. // {
  137. // TenantCode = body["tenantCode"]?.ToString(),
  138. // PoiId = body["poiId"]?.ToString(),
  139. // AlarmId = body["alarmId"]?.ToString(),
  140. // AlarmType = body["alarmType"]?.ToString(),
  141. // AlarmTypeDesc = dayEnum.GetDescription(),
  142. // CameraId = body["cameraId"]?.ToString(),
  143. // Tick = TimestampToDateTime(body["tick"].ToString()),
  144. // SnapshotUrl = body["snapshotUrl"]?.ToString(),
  145. // Rects = body["rects"]?.ToString(),
  146. // Tags = body["tags"]?.ToString(),
  147. // Extend = body["extend"]?.ToString(),
  148. // PersonType = personEnum.GetDescription(),
  149. // WarnHand = 0,
  150. // };
  151. // var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.AlarmId + ".jpg");
  152. // var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  153. // model.SnapshotUrl = $"http://192.168.10.186:8003/Files/alarmImg/{model.AlarmId}.jpg";
  154. // using (MemoryStream ms = new MemoryStream(steam))
  155. // {
  156. // using (Bitmap bmp = new Bitmap(ms))
  157. // {
  158. // using (Graphics g = Graphics.FromImage(bmp))
  159. // {
  160. // using (Pen pen = new Pen(Color.Red, 3))
  161. // {
  162. // foreach (var item in body["rects"])
  163. // {
  164. // Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  165. // g.DrawRectangle(pen, rect);
  166. // }
  167. // }
  168. // }
  169. // bmp.Save(signImg, ImageFormat.Jpeg);
  170. // }
  171. // }
  172. // //await model.SnapshotUrl.GetToSaveAsync(signImg);
  173. // Scoped.Create((_, scope) =>
  174. // {
  175. // var services = scope.ServiceProvider;
  176. // var _repository = services.GetService<IWarnInfoService>();
  177. // _repository.Add(model);
  178. // });
  179. // }
  180. // }
  181. //}
  182. //catch (Exception e)
  183. //{
  184. //}
  185. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  186. if (result.MessageType == WebSocketMessageType.Text)
  187. {
  188. try
  189. {
  190. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  191. var json = JsonConvert.DeserializeObject<JObject>(message);
  192. if (json["type"].ToString() == "msg")
  193. {
  194. //TODO 发送短信
  195. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  196. var body = json["body"];
  197. if (body != null)
  198. {
  199. var model = new WarnInfoDto
  200. {
  201. TenantCode = body["tenantCode"]?.ToString(),
  202. PoiId = body["poiId"]?.ToString(),
  203. AlarmId = body["alarmId"]?.ToString(),
  204. AlarmType = body["alarmType"]?.ToString(),
  205. //AlarmTypeDesc = dayEnum.GetDescription(),
  206. CameraId = body["cameraId"]?.ToString(),
  207. Tick = TimestampToDateTime(body["tick"].ToString()),
  208. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  209. Rects = body["rects"]?.ToString(),
  210. Tags = body["tags"]?.ToString(),
  211. Extend = body["extend"]?.ToString(),
  212. //PersonType = personEnum.GetDescription(),
  213. WarnHand = 0,
  214. };
  215. PersonType personEnum;
  216. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  217. {
  218. dayEnum = AlarmType.visual_fence;
  219. }
  220. if (body["extend"] != null)
  221. {
  222. var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  223. model.PersonId = extend?["personId"]?.ToString();
  224. model.PersonSetId =extend?["personSetId"]?.ToString();
  225. model.ClothId =extend?["clothId"]?.ToString();
  226. model.ClothsSetId =extend?["clothsSetId"]?.ToString();
  227. model.Gender =extend?["genderScore"]?.ToString();
  228. model.TrackId =extend?["trackId"]?.ToString();
  229. model.SpeedLevel =extend?["speedLevel"]?.ToString();
  230. if (extend["clothSimilarity"] !=null)
  231. model.ClothSimilarity = extend?["clothSimilarity"]?.ParseToFloat();
  232. if (extend["count"] != null)
  233. model.Count = extend?["count"]?.ParseToInt();
  234. if (extend["duration"] != null)
  235. model.Duration = extend?["duration"]?.ParseToInt();
  236. if (extend["faceSimilarity"] != null)
  237. model.FaceSimilarity = extend?["faceSimilarity"]?.ParseToFloat();
  238. if (extend["maxAroundTracks"] != null)
  239. model.MaxAroundTracks = extend?["maxAroundTracks"]?.ParseToInt();
  240. if (extend["genderScore"] != null)
  241. {
  242. if ((float)extend["genderScore"][0] > 0.6)
  243. {
  244. model.Gender = "男性";
  245. }
  246. else if ((float)extend["genderScore"][1] > 0.6)
  247. {
  248. model.Gender = "女性";
  249. }
  250. else if ((float)extend["genderScore"][2] > 0.6)
  251. {
  252. model.Gender = "不确定";
  253. }
  254. }
  255. if (extend["personType"] != null)
  256. {
  257. if (!Enum.TryParse(extend?["personType"]?.ToString(), out personEnum))
  258. {
  259. personEnum = PersonType.unkonwn;
  260. }
  261. }
  262. else
  263. {
  264. personEnum = PersonType.unkonwn;
  265. }
  266. }
  267. else
  268. {
  269. personEnum = PersonType.unkonwn;
  270. }
  271. model.AlarmTypeDesc = dayEnum.GetDescription();
  272. model.PersonType = personEnum.GetDescription();
  273. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.AlarmId + ".jpg");
  274. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  275. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AlarmImg"]}/{model.AlarmId}.jpg";
  276. using (MemoryStream ms = new MemoryStream(steam))
  277. {
  278. using (Bitmap bmp = new Bitmap(ms))
  279. {
  280. using (Graphics g = Graphics.FromImage(bmp))
  281. {
  282. using (Pen pen = new Pen(Color.Red, 3))
  283. {
  284. foreach (var item in body["rects"])
  285. {
  286. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  287. g.DrawRectangle(pen, rect);
  288. }
  289. }
  290. }
  291. bmp.Save(signImg, ImageFormat.Jpeg);
  292. }
  293. }
  294. Scoped.Create((_, scope) =>
  295. {
  296. var services = scope.ServiceProvider;
  297. var _repository = services.GetService<IWarnInfoService>();
  298. _repository.Add(model);
  299. });
  300. }
  301. }
  302. else if (json["type"].ToString() == "cmd")
  303. {
  304. if ((bool)json["success"])
  305. {
  306. if (json["message"].ToString().Contains("connect success"))
  307. {
  308. LogHelper.WriteToLog("预警连接成功");
  309. }
  310. else if (json["message"].ToString().Contains("subscribe success"))
  311. {
  312. LogHelper.WriteToLog("预警订阅成功");
  313. }
  314. }
  315. }
  316. }
  317. catch (Exception e)
  318. {
  319. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  320. LogHelper.WriteToLog("预警webSocket处理异常");
  321. LogHelper.WriteToLog(e, "预警webSocket处理异常");
  322. }
  323. }
  324. else if (result.MessageType == WebSocketMessageType.Close)
  325. {
  326. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  327. break;
  328. }
  329. }
  330. LogHelper.WriteToLog("预警webSocket关闭");
  331. }
  332. /// <summary>
  333. /// 订阅点名事件
  334. /// </summary>
  335. /// <returns></returns>
  336. public async Task SubscriberRoomCall()
  337. {
  338. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  339. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  340. var url = GetWebSocketUrl(AuthConstants.SXROOM_CALL, AuthConstants.SXROOM_CAL_Group);
  341. var subscribeJson = JsonConvert.SerializeObject(new
  342. {
  343. token = GetToken(),
  344. type = "subscribe",
  345. timestamp,
  346. payload = new
  347. {
  348. topic = AuthConstants.SXROOM_CALL, consumerGroup = AuthConstants.SXROOM_CAL_Group, tags = setting.TenantCode
  349. }
  350. });
  351. ClientWebSocket _webSocket = new ClientWebSocket();
  352. webScokets.Add(_webSocket);
  353. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  354. //LogHelper.WriteToLog($"点名WebSocket 地址:{url}");
  355. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  356. byte[] buffer = new byte[1024*8];
  357. while (_webSocket.State == WebSocketState.Open)
  358. {
  359. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  360. if (result.MessageType == WebSocketMessageType.Text)
  361. {
  362. try
  363. {
  364. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  365. //LogHelper.WriteToLog($"收到: {message}");
  366. var json = JsonConvert.DeserializeObject<JObject>(message);
  367. if (json["type"].ToString() == "msg")
  368. {
  369. var body = json["body"];
  370. if (body != null)
  371. {
  372. //TODO 发送短信
  373. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  374. //TODO 由于未知道数据格式暂不写处理
  375. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  376. {
  377. dayEnum = AlarmType.class_room_call;
  378. }
  379. if (dayEnum==AlarmType.lie_on_table)
  380. {
  381. }
  382. else
  383. {
  384. #region 添加预警
  385. var ymmodel = new WarnInfoDto
  386. {
  387. TenantCode = body["tenantCode"]?.ToString(),
  388. PoiId = body["poiId"]?.ToString(),
  389. AlarmId = body["alarmId"]?.ToString(),
  390. AlarmType = body["alarmType"]?.ToString(),
  391. //AlarmTypeDesc = dayEnum.GetDescription(),
  392. CameraId = body["cameraId"]?.ToString(),
  393. Tick = TimestampToDateTime(body["tick"].ToString()),
  394. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  395. Rects = body["rects"]?.ToString(),
  396. Tags = body["tags"]?.ToString(),
  397. Extend = body["extend"]?.ToString(),
  398. //PersonType = personEnum.GetDescription(),
  399. WarnHand = 0,
  400. };
  401. PersonType personEnum;
  402. if (body["extend"] != null)
  403. {
  404. var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  405. ymmodel.PersonId = extend?["personId"]?.ToString();
  406. ymmodel.PersonSetId = extend?["personSetId"]?.ToString();
  407. ymmodel.ClothId = extend?["clothId"]?.ToString();
  408. ymmodel.ClothsSetId = extend?["clothsSetId"]?.ToString();
  409. ymmodel.Gender = extend?["genderScore"]?.ToString();
  410. ymmodel.TrackId = extend?["trackId"]?.ToString();
  411. ymmodel.SpeedLevel = extend?["speedLevel"]?.ToString();
  412. if (extend["clothSimilarity"] != null)
  413. ymmodel.ClothSimilarity = extend?["clothSimilarity"]?.ParseToFloat();
  414. if (extend["count"] != null)
  415. ymmodel.Count = extend?["count"]?.ParseToInt();
  416. if (extend["duration"] != null)
  417. ymmodel.Duration = extend?["duration"]?.ParseToInt();
  418. if (extend["faceSimilarity"] != null)
  419. ymmodel.FaceSimilarity = extend?["faceSimilarity"]?.ParseToFloat();
  420. if (extend["maxAroundTracks"] != null)
  421. ymmodel.MaxAroundTracks = extend?["maxAroundTracks"]?.ParseToInt();
  422. if (extend["genderScore"] != null)
  423. {
  424. if ((float)extend["genderScore"][0] > 0.6)
  425. {
  426. ymmodel.Gender = "男性";
  427. }
  428. else if ((float)extend["genderScore"][1] > 0.6)
  429. {
  430. ymmodel.Gender = "女性";
  431. }
  432. else if ((float)extend["genderScore"][2] > 0.6)
  433. {
  434. ymmodel.Gender = "不确定";
  435. }
  436. }
  437. if (extend["personType"] != null)
  438. {
  439. if (!Enum.TryParse(extend?["personType"]?.ToString(), out personEnum))
  440. {
  441. personEnum = PersonType.unkonwn;
  442. }
  443. }
  444. else
  445. {
  446. personEnum = PersonType.unkonwn;
  447. }
  448. }
  449. else
  450. {
  451. personEnum = PersonType.unkonwn;
  452. }
  453. ymmodel.AlarmTypeDesc = dayEnum.GetDescription();
  454. ymmodel.PersonType = personEnum.GetDescription();
  455. var yjsignImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], ymmodel.AlarmId + ".jpg");
  456. var yjsteam = await ymmodel.SnapshotUrl.GetAsByteArrayAsync();
  457. ymmodel.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AlarmImg"]}/{ymmodel.AlarmId}.jpg";
  458. using (MemoryStream ms = new MemoryStream(yjsteam))
  459. {
  460. using (Bitmap bmp = new Bitmap(ms))
  461. {
  462. using (Graphics g = Graphics.FromImage(bmp))
  463. {
  464. using (Pen pen = new Pen(Color.Red, 3))
  465. {
  466. foreach (var item in body["rects"])
  467. {
  468. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  469. g.DrawRectangle(pen, rect);
  470. }
  471. }
  472. }
  473. bmp.Save(yjsignImg, ImageFormat.Jpeg);
  474. }
  475. }
  476. Scoped.Create((_, scope) =>
  477. {
  478. var services = scope.ServiceProvider;
  479. var _repository = services.GetService<IWarnInfoService>();
  480. _repository.Add(ymmodel);
  481. });
  482. #endregion
  483. }
  484. #region 添加点名
  485. var model = new ClassRoomCallDto
  486. {
  487. TenantCode = body["tenantCode"]?.ToString(),
  488. PoiId = body["poiId"]?.ToString(),
  489. TaskId = body["taskId"]?.ToString(),
  490. AlarmType = body["alarmType"].ToString(),
  491. AlarmTypeDesc = dayEnum.GetDescription(),
  492. EventId = body["eventId"]?.ToString(),
  493. CameraId = body["cameraId"]?.ToString(),
  494. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  495. PersonSetId = body["personSetId"]?.ToString(),
  496. PersonId = body["personId"]?.ToString(),
  497. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  498. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  499. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  500. SnapshotData = body["snapshotData"]?.ToString(),
  501. Rects = body["rects"]?.ToString(),
  502. Extend = body["extend"]?.ToString(),
  503. CreateTime = DateTime.Now,
  504. TrackId = body["TrackId"]?.ToString()
  505. };
  506. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:RoomCallImg"], model.EventId + ".jpg");
  507. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  508. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:RoomCallImg"]}/{model.EventId}.jpg";
  509. using (MemoryStream ms = new MemoryStream(steam))
  510. {
  511. using (Bitmap bmp = new Bitmap(ms))
  512. {
  513. using (Graphics g = Graphics.FromImage(bmp))
  514. {
  515. using (Pen pen = new Pen(Color.Red, 3))
  516. {
  517. foreach (var item in body["rects"])
  518. {
  519. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  520. g.DrawRectangle(pen, rect);
  521. }
  522. }
  523. }
  524. bmp.Save(signImg, ImageFormat.Jpeg);
  525. }
  526. }
  527. Scoped.Create((_, scope) =>
  528. {
  529. var services = scope.ServiceProvider;
  530. var _repository = services.GetService<IClassRoomCallService>();
  531. _repository.Add(model);
  532. });
  533. #endregion
  534. }
  535. }
  536. else if (json["type"].ToString() == "cmd")
  537. {
  538. if ((bool)json["success"])
  539. {
  540. if (json["message"].ToString().Contains("connect success"))
  541. {
  542. LogHelper.WriteToLog("点名连接成功");
  543. }
  544. else if (json["message"].ToString().Contains("subscribe success"))
  545. {
  546. LogHelper.WriteToLog("点名订阅成功");
  547. }
  548. }
  549. }
  550. }
  551. catch (Exception e)
  552. {
  553. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  554. LogHelper.WriteToLog("点名webSocket处理异常");
  555. LogHelper.WriteToLog(e, "点名webSocket处理异常");
  556. }
  557. }
  558. else if (result.MessageType == WebSocketMessageType.Close)
  559. {
  560. LogHelper.WriteToLog("点名WebSocket 连接已被服务器关闭");
  561. break;
  562. }
  563. }
  564. LogHelper.WriteToLog("点名webSocket已关闭");
  565. }
  566. /// <summary>
  567. /// 订阅无感考勤
  568. /// </summary>
  569. /// <returns></returns>
  570. public async Task SubscriberAttendance()
  571. {
  572. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  573. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  574. var url = GetWebSocketUrl(AuthConstants.SXECOLOGY_ATTENDANCE, AuthConstants.SXECOLOGY_ATTENDANCE_Group);
  575. var subscribeJson = JsonConvert.SerializeObject(new
  576. {
  577. token = GetToken(),
  578. type = "subscribe",
  579. timestamp,
  580. payload = new
  581. {
  582. topic = AuthConstants.SXECOLOGY_ATTENDANCE,
  583. consumerGroup = AuthConstants.SXECOLOGY_ATTENDANCE_Group,
  584. tags = setting.TenantCode
  585. }
  586. });
  587. ClientWebSocket _webSocket = new ClientWebSocket();
  588. webScokets.Add(_webSocket);
  589. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  590. //LogHelper.WriteToLog($"考勤WebSocket 已连接:{url}");
  591. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  592. byte[] buffer = new byte[1024 * 8];
  593. while (_webSocket.State == WebSocketState.Open)
  594. {
  595. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  596. if (result.MessageType == WebSocketMessageType.Text)
  597. {
  598. try
  599. {
  600. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  601. //LogHelper.WriteToLog($"收到: {message}");
  602. var json = JsonConvert.DeserializeObject<JObject>(message);
  603. if (json["type"].ToString() == "msg")
  604. {
  605. var body = json["body"];
  606. if (body != null)
  607. {
  608. //TODO 发送短信
  609. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  610. //TODO 由于未知道数据格式暂不写处理
  611. var model = new AttendanceDto()
  612. {
  613. TenantCode = body["tenantCode"]?.ToString(),
  614. PoiId = body["poiId"]?.ToString(),
  615. EventId = body["eventId"]?.ToString(),
  616. CameraId = body["cameraId"]?.ToString(),
  617. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  618. PersonSetId = body["personSetId"]?.ToString(),
  619. PersonId = body["personId"]?.ToString(),
  620. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  621. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  622. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  623. SnapshotData = body["snapshotData"]?.ToString(),
  624. Rects = body["rects"]?.ToString(),
  625. Extend = body["extend"]?.ToString(),
  626. CreateTime = DateTime.Now,
  627. TrackId = body["trackId"]?.ToString(),
  628. IsAuto = true
  629. };
  630. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AttendanceImg"], model.EventId + ".jpg");
  631. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  632. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AttendanceImg"]}/{model.EventId}.jpg";
  633. using (MemoryStream ms = new MemoryStream(steam))
  634. {
  635. using (Bitmap bmp = new Bitmap(ms))
  636. {
  637. using (Graphics g = Graphics.FromImage(bmp))
  638. {
  639. using (Pen pen = new Pen(Color.Red, 3))
  640. {
  641. foreach (var item in body["rects"])
  642. {
  643. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  644. g.DrawRectangle(pen, rect);
  645. }
  646. }
  647. }
  648. bmp.Save(signImg, ImageFormat.Jpeg);
  649. }
  650. }
  651. Scoped.Create((_, scope) =>
  652. {
  653. var services = scope.ServiceProvider;
  654. var repository = services.GetService<IAttendanceService>();
  655. repository.Add(model);
  656. });
  657. }
  658. }else if (json["type"].ToString()=="cmd")
  659. {
  660. if ((bool)json["success"])
  661. {
  662. if (json["message"].ToString().Contains("connect success"))
  663. {
  664. LogHelper.WriteToLog("考勤连接成功");
  665. }else if (json["message"].ToString().Contains("subscribe success"))
  666. {
  667. LogHelper.WriteToLog("考勤订阅成功");
  668. }
  669. }
  670. }
  671. }
  672. catch (Exception e)
  673. {
  674. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  675. LogHelper.WriteToLog("考勤webSocket处理异常");
  676. LogHelper.WriteToLog(e, "考勤webSocket处理异常");
  677. }
  678. }
  679. else if (result.MessageType == WebSocketMessageType.Close)
  680. {
  681. LogHelper.WriteToLog("考勤WebSocket 连接已被服务器关闭");
  682. break;
  683. }
  684. }
  685. LogHelper.WriteToLog("考勤webSocket已关闭");
  686. }
  687. private async Task GetWebSocketData(string url, string json)
  688. {
  689. ClientWebSocket _webSocket = new ClientWebSocket();
  690. while (!_cancellationTokenSource.IsCancellationRequested)
  691. {
  692. try
  693. {
  694. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  695. LogHelper.WriteToLog("WebSocket 已连接");
  696. _isConnected = true;
  697. //订阅预警消息
  698. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)), WebSocketMessageType.Text, true, CancellationToken.None);
  699. //_pingTimer = new Timer(async (state) =>
  700. //{
  701. // if (_webSocket.State == WebSocketState.Open)
  702. // {
  703. // try
  704. // {
  705. // LogHelper.WriteToLog("发送 ping...");
  706. // byte[] emptyPingMessage = Array.Empty<byte>();
  707. // await _webSocket.SendAsync(new ArraySegment<byte>(emptyPingMessage), WebSocketMessageType.Binary, true, CancellationToken.None);
  708. // //byte[] pingMessage = Encoding.UTF8.GetBytes("pong");
  709. // //await _webSocket.SendAsync(new ArraySegment<byte>(pingMessage), WebSocketMessageType.Text, true, CancellationToken.None);
  710. // }
  711. // catch (Exception ex)
  712. // {
  713. // LogHelper.WriteToLog($"发送ping失败: {ex.Message}");
  714. // }
  715. // }
  716. //}, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
  717. await ReceiveLoop(_webSocket);
  718. _isConnected = false;
  719. LogHelper.WriteToLog("WebSocket 连接已关闭,正在重连。。。");
  720. }
  721. catch (Exception ex)
  722. {
  723. LogHelper.WriteToLog($"WebSocket连接失败: {ex.Message}");
  724. }
  725. await Task.Delay(GetReconnectInterval());
  726. }
  727. }
  728. private async Task ReceiveLoop(ClientWebSocket _webSocket)
  729. {
  730. byte[] buffer = new byte[1024];
  731. while (_webSocket.State == WebSocketState.Open)
  732. {
  733. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  734. if (result.MessageType == WebSocketMessageType.Text)
  735. {
  736. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  737. LogHelper.WriteToLog($"收到: {message}");
  738. var json= JsonConvert.DeserializeObject<JObject>(message);
  739. if (json["type"].ToString()=="msg")
  740. {
  741. var body = json["body"];
  742. if (body!=null)
  743. {
  744. }
  745. }
  746. }
  747. else if (result.MessageType == WebSocketMessageType.Close)
  748. {
  749. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  750. break;
  751. }
  752. }
  753. }
  754. private TimeSpan GetReconnectInterval()
  755. {
  756. // You can implement your own logic for calculating reconnect interval, e.g., exponential backoff
  757. return TimeSpan.FromSeconds(10); // Example: Attempt to reconnect every 10 seconds
  758. }
  759. public async Task DisconnectAsync()
  760. {
  761. foreach (var clientWebSocket in webScokets.Where(clientWebSocket => clientWebSocket.State == WebSocketState.Open))
  762. {
  763. await clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
  764. }
  765. }
  766. private string GetWebSocketUrl(string topic, string consumerGroup)
  767. {
  768. var serverAddr = "";
  769. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  770. var list = $"{setting.SXAPIURL}/emitter/connection/get"
  771. .SetBody(new
  772. {
  773. token = GetToken(),
  774. topic ,
  775. consumerGroup,
  776. })
  777. .SetContentType("application/json")
  778. .PostAsAsync<string>().Result;
  779. var model = JsonConvert.DeserializeObject<JObject>(list);
  780. if (model["data"]["serverAddr"]!=null)
  781. {
  782. serverAddr = model["data"]["serverAddr"].ToString();
  783. }
  784. return serverAddr;
  785. }
  786. //public async Task<bool> GetData()
  787. //{
  788. // //var setting = App.GetOptionsMonitor<AppInfoOptions>();
  789. // //var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  790. // ////订阅预警消息
  791. // //var warnUrl = GetWebSocketUrl(AuthConstants.SXALARM, AuthConstants.SXALARM_Grpup);
  792. // //GetWebSocketData(warnUrl,
  793. // // JsonConvert.SerializeObject(new
  794. // // {
  795. // // token = GetToken(), type = "subscribe", timestamp,
  796. // // payload = new { topic = AuthConstants.SXALARM, consumerGroup= AuthConstants.SXALARM_Grpup, tags= setting.TenantCode }
  797. // // }));
  798. // //订阅预警更新消息
  799. // await SubscribeAlarm();
  800. // //订阅点名事件
  801. // //await SubscriberRoomCall();
  802. // return true;
  803. //}
  804. /// <summary>
  805. /// 时间戳转本时区日期时间
  806. /// </summary>
  807. /// <param name="timeStamp"></param>
  808. /// <returns></returns>
  809. public static DateTime TimestampToDateTime(string timeStamp)
  810. {
  811. DateTimeOffset utcDateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(timeStamp));
  812. return utcDateTimeOffset.LocalDateTime;
  813. }
  814. }