平安校园
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

851 lignes
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. var body = json["body"];
  195. if (body != null)
  196. {
  197. var model = new WarnInfoDto
  198. {
  199. TenantCode = body["tenantCode"]?.ToString(),
  200. PoiId = body["poiId"]?.ToString(),
  201. AlarmId = body["alarmId"]?.ToString(),
  202. AlarmType = body["alarmType"]?.ToString(),
  203. //AlarmTypeDesc = dayEnum.GetDescription(),
  204. CameraId = body["cameraId"]?.ToString(),
  205. Tick = TimestampToDateTime(body["tick"].ToString()),
  206. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  207. Rects = body["rects"]?.ToString(),
  208. Tags = body["tags"]?.ToString(),
  209. Extend = body["extend"]?.ToString(),
  210. //PersonType = personEnum.GetDescription(),
  211. WarnHand = 0,
  212. };
  213. PersonType personEnum;
  214. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  215. {
  216. dayEnum = AlarmType.visual_fence;
  217. }
  218. if (body["extend"] != null)
  219. {
  220. var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  221. model.PersonId = extend?["personId"]?.ToString();
  222. model.PersonSetId =extend?["personSetId"]?.ToString();
  223. model.ClothId =extend?["clothId"]?.ToString();
  224. model.ClothsSetId =extend?["clothsSetId"]?.ToString();
  225. model.Gender =extend?["genderScore"]?.ToString();
  226. model.TrackId =extend?["trackId"]?.ToString();
  227. model.SpeedLevel =extend?["speedLevel"]?.ToString();
  228. if (extend["clothSimilarity"] !=null)
  229. model.ClothSimilarity = extend?["clothSimilarity"]?.ParseToFloat();
  230. if (extend["count"] != null)
  231. model.Count = extend?["count"]?.ParseToInt();
  232. if (extend["duration"] != null)
  233. model.Duration = extend?["duration"]?.ParseToInt();
  234. if (extend["faceSimilarity"] != null)
  235. model.FaceSimilarity = extend?["faceSimilarity"]?.ParseToFloat();
  236. if (extend["maxAroundTracks"] != null)
  237. model.MaxAroundTracks = extend?["maxAroundTracks"]?.ParseToInt();
  238. if (extend["genderScore"] != null)
  239. {
  240. if ((float)extend["genderScore"][0] > 0.6)
  241. {
  242. model.Gender = "男性";
  243. }
  244. else if ((float)extend["genderScore"][1] > 0.6)
  245. {
  246. model.Gender = "女性";
  247. }
  248. else if ((float)extend["genderScore"][2] > 0.6)
  249. {
  250. model.Gender = "不确定";
  251. }
  252. }
  253. if (extend["personType"] != null)
  254. {
  255. if (!Enum.TryParse(extend?["personType"]?.ToString(), out personEnum))
  256. {
  257. personEnum = PersonType.unkonwn;
  258. }
  259. }
  260. else
  261. {
  262. personEnum = PersonType.unkonwn;
  263. }
  264. }
  265. else
  266. {
  267. personEnum = PersonType.unkonwn;
  268. }
  269. model.AlarmTypeDesc = dayEnum.GetDescription();
  270. model.PersonType = personEnum.GetDescription();
  271. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.AlarmId + ".jpg");
  272. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  273. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AlarmImg"]}/{model.AlarmId}.jpg";
  274. using (MemoryStream ms = new MemoryStream(steam))
  275. {
  276. using (Bitmap bmp = new Bitmap(ms))
  277. {
  278. using (Graphics g = Graphics.FromImage(bmp))
  279. {
  280. using (Pen pen = new Pen(Color.Red, 3))
  281. {
  282. foreach (var item in body["rects"])
  283. {
  284. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  285. g.DrawRectangle(pen, rect);
  286. }
  287. }
  288. }
  289. bmp.Save(signImg, ImageFormat.Jpeg);
  290. }
  291. }
  292. Scoped.Create((_, scope) =>
  293. {
  294. var services = scope.ServiceProvider;
  295. var _repository = services.GetService<IWarnInfoService>();
  296. _repository.Add(model);
  297. });
  298. }
  299. }
  300. else if (json["type"].ToString() == "cmd")
  301. {
  302. if ((bool)json["success"])
  303. {
  304. if (json["message"].ToString().Contains("connect success"))
  305. {
  306. LogHelper.WriteToLog("预警连接成功");
  307. }
  308. else if (json["message"].ToString().Contains("subscribe success"))
  309. {
  310. LogHelper.WriteToLog("预警订阅成功");
  311. }
  312. }
  313. }
  314. }
  315. catch (Exception e)
  316. {
  317. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  318. LogHelper.WriteToLog("预警webSocket处理异常");
  319. LogHelper.WriteToLog(e, "预警webSocket处理异常");
  320. }
  321. }
  322. else if (result.MessageType == WebSocketMessageType.Close)
  323. {
  324. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  325. break;
  326. }
  327. }
  328. LogHelper.WriteToLog("预警webSocket关闭");
  329. }
  330. /// <summary>
  331. /// 订阅点名事件
  332. /// </summary>
  333. /// <returns></returns>
  334. public async Task SubscriberRoomCall()
  335. {
  336. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  337. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  338. var url = GetWebSocketUrl(AuthConstants.SXROOM_CALL, AuthConstants.SXROOM_CAL_Group);
  339. var subscribeJson = JsonConvert.SerializeObject(new
  340. {
  341. token = GetToken(),
  342. type = "subscribe",
  343. timestamp,
  344. payload = new
  345. {
  346. topic = AuthConstants.SXROOM_CALL, consumerGroup = AuthConstants.SXROOM_CAL_Group, tags = setting.TenantCode
  347. }
  348. });
  349. ClientWebSocket _webSocket = new ClientWebSocket();
  350. webScokets.Add(_webSocket);
  351. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  352. //LogHelper.WriteToLog($"点名WebSocket 地址:{url}");
  353. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  354. byte[] buffer = new byte[1024*8];
  355. while (_webSocket.State == WebSocketState.Open)
  356. {
  357. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  358. if (result.MessageType == WebSocketMessageType.Text)
  359. {
  360. try
  361. {
  362. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  363. //LogHelper.WriteToLog($"收到: {message}");
  364. var json = JsonConvert.DeserializeObject<JObject>(message);
  365. if (json["type"].ToString() == "msg")
  366. {
  367. var body = json["body"];
  368. if (body != null)
  369. {
  370. //TODO 发送短信
  371. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  372. //TODO 由于未知道数据格式暂不写处理
  373. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  374. {
  375. dayEnum = AlarmType.class_room_call;
  376. }
  377. if (dayEnum==AlarmType.lie_on_table)
  378. {
  379. #region 添加预警
  380. var ymmodel = new WarnInfoDto
  381. {
  382. TenantCode = body["tenantCode"]?.ToString(),
  383. PoiId = body["poiId"]?.ToString(),
  384. AlarmId = body["alarmId"]?.ToString(),
  385. AlarmType = body["alarmType"]?.ToString(),
  386. //AlarmTypeDesc = dayEnum.GetDescription(),
  387. CameraId = body["cameraId"]?.ToString(),
  388. Tick = TimestampToDateTime(body["tick"].ToString()),
  389. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  390. Rects = body["rects"]?.ToString(),
  391. Tags = body["tags"]?.ToString(),
  392. Extend = body["extend"]?.ToString(),
  393. //PersonType = personEnum.GetDescription(),
  394. WarnHand = 0,
  395. };
  396. PersonType personEnum;
  397. if (body["extend"] != null)
  398. {
  399. var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  400. ymmodel.PersonId = extend?["personId"]?.ToString();
  401. ymmodel.PersonSetId = extend?["personSetId"]?.ToString();
  402. ymmodel.ClothId = extend?["clothId"]?.ToString();
  403. ymmodel.ClothsSetId = extend?["clothsSetId"]?.ToString();
  404. ymmodel.Gender = extend?["genderScore"]?.ToString();
  405. ymmodel.TrackId = extend?["trackId"]?.ToString();
  406. ymmodel.SpeedLevel = extend?["speedLevel"]?.ToString();
  407. if (extend["clothSimilarity"] != null)
  408. ymmodel.ClothSimilarity = extend?["clothSimilarity"]?.ParseToFloat();
  409. if (extend["count"] != null)
  410. ymmodel.Count = extend?["count"]?.ParseToInt();
  411. if (extend["duration"] != null)
  412. ymmodel.Duration = extend?["duration"]?.ParseToInt();
  413. if (extend["faceSimilarity"] != null)
  414. ymmodel.FaceSimilarity = extend?["faceSimilarity"]?.ParseToFloat();
  415. if (extend["maxAroundTracks"] != null)
  416. ymmodel.MaxAroundTracks = extend?["maxAroundTracks"]?.ParseToInt();
  417. if (extend["genderScore"] != null)
  418. {
  419. if ((float)extend["genderScore"][0] > 0.6)
  420. {
  421. ymmodel.Gender = "男性";
  422. }
  423. else if ((float)extend["genderScore"][1] > 0.6)
  424. {
  425. ymmodel.Gender = "女性";
  426. }
  427. else if ((float)extend["genderScore"][2] > 0.6)
  428. {
  429. ymmodel.Gender = "不确定";
  430. }
  431. }
  432. if (extend["personType"] != null)
  433. {
  434. if (!Enum.TryParse(extend?["personType"]?.ToString(), out personEnum))
  435. {
  436. personEnum = PersonType.unkonwn;
  437. }
  438. }
  439. else
  440. {
  441. personEnum = PersonType.unkonwn;
  442. }
  443. }
  444. else
  445. {
  446. personEnum = PersonType.unkonwn;
  447. }
  448. ymmodel.AlarmTypeDesc = dayEnum.GetDescription();
  449. ymmodel.PersonType = personEnum.GetDescription();
  450. var yjsignImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], ymmodel.AlarmId + ".jpg");
  451. var yjsteam = await ymmodel.SnapshotUrl.GetAsByteArrayAsync();
  452. ymmodel.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AlarmImg"]}/{ymmodel.AlarmId}.jpg";
  453. using (MemoryStream ms = new MemoryStream(yjsteam))
  454. {
  455. using (Bitmap bmp = new Bitmap(ms))
  456. {
  457. using (Graphics g = Graphics.FromImage(bmp))
  458. {
  459. using (Pen pen = new Pen(Color.Red, 3))
  460. {
  461. foreach (var item in body["rects"])
  462. {
  463. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  464. g.DrawRectangle(pen, rect);
  465. }
  466. }
  467. }
  468. bmp.Save(yjsignImg, ImageFormat.Jpeg);
  469. }
  470. }
  471. Scoped.Create((_, scope) =>
  472. {
  473. var services = scope.ServiceProvider;
  474. var _repository = services.GetService<IWarnInfoService>();
  475. _repository.Add(ymmodel);
  476. });
  477. #endregion
  478. }
  479. else
  480. {
  481. #region 添加点名
  482. var model = new ClassRoomCallDto
  483. {
  484. TenantCode = body["tenantCode"]?.ToString(),
  485. PoiId = body["poiId"]?.ToString(),
  486. TaskId = body["taskId"]?.ToString(),
  487. AlarmType = body["alarmType"].ToString(),
  488. AlarmTypeDesc = dayEnum.GetDescription(),
  489. EventId = body["eventId"]?.ToString(),
  490. CameraId = body["cameraId"]?.ToString(),
  491. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  492. PersonSetId = body["personSetId"]?.ToString(),
  493. PersonId = body["personId"]?.ToString(),
  494. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  495. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  496. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  497. SnapshotData = body["snapshotData"]?.ToString(),
  498. Rects = body["rects"]?.ToString(),
  499. Extend = body["extend"]?.ToString(),
  500. CreateTime = DateTime.Now,
  501. TrackId = body["TrackId"]?.ToString()
  502. };
  503. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:RoomCallImg"], model.EventId + ".jpg");
  504. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  505. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:RoomCallImg"]}/{model.EventId}.jpg";
  506. using (MemoryStream ms = new MemoryStream(steam))
  507. {
  508. using (Bitmap bmp = new Bitmap(ms))
  509. {
  510. using (Graphics g = Graphics.FromImage(bmp))
  511. {
  512. using (Pen pen = new Pen(Color.Red, 3))
  513. {
  514. foreach (var item in body["rects"])
  515. {
  516. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  517. g.DrawRectangle(pen, rect);
  518. }
  519. }
  520. }
  521. bmp.Save(signImg, ImageFormat.Jpeg);
  522. }
  523. }
  524. Scoped.Create((_, scope) =>
  525. {
  526. var services = scope.ServiceProvider;
  527. var _repository = services.GetService<IClassRoomCallService>();
  528. _repository.Add(model);
  529. });
  530. #endregion
  531. }
  532. }
  533. }
  534. else if (json["type"].ToString() == "cmd")
  535. {
  536. if ((bool)json["success"])
  537. {
  538. if (json["message"].ToString().Contains("connect success"))
  539. {
  540. LogHelper.WriteToLog("点名连接成功");
  541. }
  542. else if (json["message"].ToString().Contains("subscribe success"))
  543. {
  544. LogHelper.WriteToLog("点名订阅成功");
  545. }
  546. }
  547. }
  548. }
  549. catch (Exception e)
  550. {
  551. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  552. LogHelper.WriteToLog("点名webSocket处理异常");
  553. LogHelper.WriteToLog(e, "点名webSocket处理异常");
  554. }
  555. }
  556. else if (result.MessageType == WebSocketMessageType.Close)
  557. {
  558. LogHelper.WriteToLog("点名WebSocket 连接已被服务器关闭");
  559. break;
  560. }
  561. }
  562. LogHelper.WriteToLog("点名webSocket已关闭");
  563. }
  564. /// <summary>
  565. /// 订阅无感考勤
  566. /// </summary>
  567. /// <returns></returns>
  568. public async Task SubscriberAttendance()
  569. {
  570. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  571. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  572. var url = GetWebSocketUrl(AuthConstants.SXECOLOGY_ATTENDANCE, AuthConstants.SXECOLOGY_ATTENDANCE_Group);
  573. var subscribeJson = JsonConvert.SerializeObject(new
  574. {
  575. token = GetToken(),
  576. type = "subscribe",
  577. timestamp,
  578. payload = new
  579. {
  580. topic = AuthConstants.SXECOLOGY_ATTENDANCE,
  581. consumerGroup = AuthConstants.SXECOLOGY_ATTENDANCE_Group,
  582. tags = setting.TenantCode
  583. }
  584. });
  585. ClientWebSocket _webSocket = new ClientWebSocket();
  586. webScokets.Add(_webSocket);
  587. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  588. //LogHelper.WriteToLog($"考勤WebSocket 已连接:{url}");
  589. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  590. byte[] buffer = new byte[1024 * 8];
  591. while (_webSocket.State == WebSocketState.Open)
  592. {
  593. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  594. if (result.MessageType == WebSocketMessageType.Text)
  595. {
  596. try
  597. {
  598. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  599. //LogHelper.WriteToLog($"收到: {message}");
  600. var json = JsonConvert.DeserializeObject<JObject>(message);
  601. if (json["type"].ToString() == "msg")
  602. {
  603. var body = json["body"];
  604. if (body != null)
  605. {
  606. //TODO 发送短信
  607. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  608. //TODO 由于未知道数据格式暂不写处理
  609. var model = new AttendanceDto()
  610. {
  611. TenantCode = body["tenantCode"]?.ToString(),
  612. PoiId = body["poiId"]?.ToString(),
  613. EventId = body["eventId"]?.ToString(),
  614. CameraId = body["cameraId"]?.ToString(),
  615. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  616. PersonSetId = body["personSetId"]?.ToString(),
  617. PersonId = body["personId"]?.ToString(),
  618. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  619. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  620. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  621. SnapshotData = body["snapshotData"]?.ToString(),
  622. Rects = body["rects"]?.ToString(),
  623. Extend = body["extend"]?.ToString(),
  624. CreateTime = DateTime.Now,
  625. TrackId = body["trackId"]?.ToString(),
  626. IsAuto = true
  627. };
  628. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AttendanceImg"], model.EventId + ".jpg");
  629. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  630. model.SnapshotUrl = $"/Files/{App.Configuration["AppInfo:AttendanceImg"]}/{model.EventId}.jpg";
  631. using (MemoryStream ms = new MemoryStream(steam))
  632. {
  633. using (Bitmap bmp = new Bitmap(ms))
  634. {
  635. using (Graphics g = Graphics.FromImage(bmp))
  636. {
  637. using (Pen pen = new Pen(Color.Red, 3))
  638. {
  639. foreach (var item in body["rects"])
  640. {
  641. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  642. g.DrawRectangle(pen, rect);
  643. }
  644. }
  645. }
  646. bmp.Save(signImg, ImageFormat.Jpeg);
  647. }
  648. }
  649. Scoped.Create((_, scope) =>
  650. {
  651. var services = scope.ServiceProvider;
  652. var repository = services.GetService<IAttendanceService>();
  653. repository.Add(model);
  654. });
  655. }
  656. }else if (json["type"].ToString()=="cmd")
  657. {
  658. if ((bool)json["success"])
  659. {
  660. if (json["message"].ToString().Contains("connect success"))
  661. {
  662. LogHelper.WriteToLog("考勤连接成功");
  663. }else if (json["message"].ToString().Contains("subscribe success"))
  664. {
  665. LogHelper.WriteToLog("考勤订阅成功");
  666. }
  667. }
  668. }
  669. }
  670. catch (Exception e)
  671. {
  672. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  673. LogHelper.WriteToLog("考勤webSocket处理异常");
  674. LogHelper.WriteToLog(e, "考勤webSocket处理异常");
  675. }
  676. }
  677. else if (result.MessageType == WebSocketMessageType.Close)
  678. {
  679. LogHelper.WriteToLog("考勤WebSocket 连接已被服务器关闭");
  680. break;
  681. }
  682. }
  683. LogHelper.WriteToLog("考勤webSocket已关闭");
  684. }
  685. private async Task GetWebSocketData(string url, string json)
  686. {
  687. ClientWebSocket _webSocket = new ClientWebSocket();
  688. while (!_cancellationTokenSource.IsCancellationRequested)
  689. {
  690. try
  691. {
  692. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  693. LogHelper.WriteToLog("WebSocket 已连接");
  694. _isConnected = true;
  695. //订阅预警消息
  696. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)), WebSocketMessageType.Text, true, CancellationToken.None);
  697. //_pingTimer = new Timer(async (state) =>
  698. //{
  699. // if (_webSocket.State == WebSocketState.Open)
  700. // {
  701. // try
  702. // {
  703. // LogHelper.WriteToLog("发送 ping...");
  704. // byte[] emptyPingMessage = Array.Empty<byte>();
  705. // await _webSocket.SendAsync(new ArraySegment<byte>(emptyPingMessage), WebSocketMessageType.Binary, true, CancellationToken.None);
  706. // //byte[] pingMessage = Encoding.UTF8.GetBytes("pong");
  707. // //await _webSocket.SendAsync(new ArraySegment<byte>(pingMessage), WebSocketMessageType.Text, true, CancellationToken.None);
  708. // }
  709. // catch (Exception ex)
  710. // {
  711. // LogHelper.WriteToLog($"发送ping失败: {ex.Message}");
  712. // }
  713. // }
  714. //}, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
  715. await ReceiveLoop(_webSocket);
  716. _isConnected = false;
  717. LogHelper.WriteToLog("WebSocket 连接已关闭,正在重连。。。");
  718. }
  719. catch (Exception ex)
  720. {
  721. LogHelper.WriteToLog($"WebSocket连接失败: {ex.Message}");
  722. }
  723. await Task.Delay(GetReconnectInterval());
  724. }
  725. }
  726. private async Task ReceiveLoop(ClientWebSocket _webSocket)
  727. {
  728. byte[] buffer = new byte[1024];
  729. while (_webSocket.State == WebSocketState.Open)
  730. {
  731. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  732. if (result.MessageType == WebSocketMessageType.Text)
  733. {
  734. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  735. LogHelper.WriteToLog($"收到: {message}");
  736. var json= JsonConvert.DeserializeObject<JObject>(message);
  737. if (json["type"].ToString()=="msg")
  738. {
  739. var body = json["body"];
  740. if (body!=null)
  741. {
  742. }
  743. }
  744. }
  745. else if (result.MessageType == WebSocketMessageType.Close)
  746. {
  747. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  748. break;
  749. }
  750. }
  751. }
  752. private TimeSpan GetReconnectInterval()
  753. {
  754. // You can implement your own logic for calculating reconnect interval, e.g., exponential backoff
  755. return TimeSpan.FromSeconds(10); // Example: Attempt to reconnect every 10 seconds
  756. }
  757. public async Task DisconnectAsync()
  758. {
  759. foreach (var clientWebSocket in webScokets.Where(clientWebSocket => clientWebSocket.State == WebSocketState.Open))
  760. {
  761. await clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
  762. }
  763. }
  764. private string GetWebSocketUrl(string topic, string consumerGroup)
  765. {
  766. var serverAddr = "";
  767. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  768. var list = $"{setting.SXAPIURL}/emitter/connection/get"
  769. .SetBody(new
  770. {
  771. token = GetToken(),
  772. topic ,
  773. consumerGroup,
  774. })
  775. .SetContentType("application/json")
  776. .PostAsAsync<string>().Result;
  777. var model = JsonConvert.DeserializeObject<JObject>(list);
  778. if (model["data"]["serverAddr"]!=null)
  779. {
  780. serverAddr = model["data"]["serverAddr"].ToString();
  781. }
  782. return serverAddr;
  783. }
  784. //public async Task<bool> GetData()
  785. //{
  786. // //var setting = App.GetOptionsMonitor<AppInfoOptions>();
  787. // //var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  788. // ////订阅预警消息
  789. // //var warnUrl = GetWebSocketUrl(AuthConstants.SXALARM, AuthConstants.SXALARM_Grpup);
  790. // //GetWebSocketData(warnUrl,
  791. // // JsonConvert.SerializeObject(new
  792. // // {
  793. // // token = GetToken(), type = "subscribe", timestamp,
  794. // // payload = new { topic = AuthConstants.SXALARM, consumerGroup= AuthConstants.SXALARM_Grpup, tags= setting.TenantCode }
  795. // // }));
  796. // //订阅预警更新消息
  797. // await SubscribeAlarm();
  798. // //订阅点名事件
  799. // //await SubscriberRoomCall();
  800. // return true;
  801. //}
  802. /// <summary>
  803. /// 时间戳转本时区日期时间
  804. /// </summary>
  805. /// <param name="timeStamp"></param>
  806. /// <returns></returns>
  807. public static DateTime TimestampToDateTime(string timeStamp)
  808. {
  809. DateTimeOffset utcDateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(timeStamp));
  810. return utcDateTimeOffset.LocalDateTime;
  811. }
  812. }