平安校园
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.
 
 
 
 
 
 

700 lignes
36 KiB

  1. using System.Drawing;
  2. using System.Drawing.Imaging;
  3. using System.Net.WebSockets;
  4. using System.Text;
  5. using Dm;
  6. using Masuit.Tools.Systems;
  7. using MoYu.DataEncryption;
  8. using MoYu.RemoteRequest.Extensions;
  9. using MoYu.Templates;
  10. using NewLife.Caching;
  11. using Newtonsoft.Json;
  12. using Newtonsoft.Json.Linq;
  13. using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
  14. using SafeCampus.Application.Services.Business.AttendanceService;
  15. using SafeCampus.Application.Services.Business.ClassRoomCallService;
  16. using SafeCampus.Application.Services.Business.Warn.Dto;
  17. using SafeCampus.Application.Services.Business.Warn.Service;
  18. using SafeCampus.Core.Utils.TXYSMS;
  19. using TencentCloud.Nlp.V20190408.Models;
  20. namespace SafeCampus.Application.Manager.DeepelephManager;
  21. /// <summary>
  22. /// 深象智能对接实现
  23. /// </summary>
  24. public class DeepelephManager : IDeepelephManager, IScoped
  25. {
  26. private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
  27. private bool _isConnected = false;
  28. private Timer _pingTimer;
  29. private List<ClientWebSocket> webScokets=new List<ClientWebSocket>();
  30. private readonly ISimpleCacheService _simpleCacheService;
  31. public DeepelephManager(ISimpleCacheService simpleCacheService)
  32. {
  33. _simpleCacheService = simpleCacheService;
  34. }
  35. //获取地址
  36. //建立请求,发送订阅参数
  37. //遍历等待接收消息
  38. public string GetToken()
  39. {
  40. var cacheToken = _simpleCacheService.Get<string>(AuthConstants.SXTOKEN);
  41. if (cacheToken != null) return cacheToken;
  42. return GenSXToken();
  43. }
  44. /// <summary>
  45. /// 获取深象智能Token
  46. /// </summary>
  47. /// <returns></returns>
  48. private string GenSXToken()
  49. {
  50. var token = "";
  51. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  52. var nonce = Guid.NewGuid().ToString("N");
  53. var timestamp =DateTimeOffset.Now.ToUnixTimeMilliseconds();
  54. var list = $"{setting.SXAPIURL}/user/center/v1/login/client"
  55. .SetBody(new
  56. {
  57. appKey = setting.AppKey,
  58. appSecret = setting.AppSecret,
  59. nonce ,
  60. timestamp,
  61. sign = MD5Encryption.Encrypt($"{setting.AppSecret}appKey{setting.AppKey}nonce{nonce}timestamp{timestamp}{setting.AppSecret}",true)
  62. })
  63. .SetContentType("application/json")
  64. .PostAsAsync<string>().Result;
  65. var model = JsonConvert.DeserializeObject<JObject>(list);
  66. if (model["success"]!=null)
  67. {
  68. if ((bool)model["success"])
  69. {
  70. token = model["data"]["token"].ToString();
  71. //token有效期2小时,提前20分钟失效
  72. _simpleCacheService.Set(AuthConstants.SXTOKEN, token, 100*60);
  73. }
  74. else
  75. {
  76. LogHelper.WriteToLog("token请求失败", model["message"].ToString());
  77. }
  78. }
  79. return token;
  80. }
  81. /// <summary>
  82. /// 订阅预警更新
  83. /// </summary>
  84. /// <returns></returns>
  85. public async Task SubscribeAlarm()
  86. {
  87. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  88. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  89. var url = GetWebSocketUrl(AuthConstants.SXALARM, AuthConstants.SXALARM_Grpup);
  90. var subscribeJson = JsonConvert.SerializeObject(new
  91. {
  92. token = GetToken(),
  93. type = "subscribe",
  94. timestamp,
  95. payload = new
  96. {
  97. topic = AuthConstants.SXALARM, consumerGroup = AuthConstants.SXALARM_Grpup, tags = setting.TenantCode
  98. }
  99. });
  100. ClientWebSocket _webSocket = new ClientWebSocket();
  101. webScokets.Add(_webSocket);
  102. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  103. //LogHelper.WriteToLog($"预警WebSocket 地址:{url}");
  104. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  105. byte[] buffer = new byte[1024*8];
  106. while (_webSocket.State == WebSocketState.Open)
  107. {
  108. //try
  109. //{
  110. // var jsonstr =
  111. // "{\"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\"}";
  112. // var json = JsonConvert.DeserializeObject<JObject>(jsonstr);
  113. // if (json["type"].ToString() == "msg")
  114. // {
  115. // var body = json["body"];
  116. // if (body != null)
  117. // {
  118. // PersonType personEnum;
  119. // if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  120. // {
  121. // dayEnum = AlarmType.visual_fence;
  122. // }
  123. // if (body["extend"] != null)
  124. // {
  125. // var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  126. // if (extend["personType"] != null)
  127. // {
  128. // if (!Enum.TryParse(body["extend"]?["personType"]?.ToString(), out personEnum))
  129. // {
  130. // personEnum = PersonType.unkonwn;
  131. // }
  132. // }
  133. // else
  134. // {
  135. // personEnum = PersonType.unkonwn;
  136. // }
  137. // }
  138. // else
  139. // {
  140. // personEnum = PersonType.unkonwn;
  141. // }
  142. // var model = new WarnInfoDto
  143. // {
  144. // TenantCode = body["tenantCode"]?.ToString(),
  145. // PoiId = body["poiId"]?.ToString(),
  146. // AlarmId = body["alarmId"]?.ToString(),
  147. // AlarmType = body["alarmType"]?.ToString(),
  148. // AlarmTypeDesc = dayEnum.GetDescription(),
  149. // CameraId = body["cameraId"]?.ToString(),
  150. // Tick = TimestampToDateTime(body["tick"].ToString()),
  151. // SnapshotUrl = body["snapshotUrl"]?.ToString(),
  152. // Rects = body["rects"]?.ToString(),
  153. // Tags = body["tags"]?.ToString(),
  154. // Extend = body["extend"]?.ToString(),
  155. // PersonType = personEnum.GetDescription(),
  156. // WarnHand = 0,
  157. // };
  158. // var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.AlarmId + ".jpg");
  159. // var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  160. // model.SnapshotUrl = $"http://192.168.10.186:8003/Files/alarmImg/{model.AlarmId}.jpg";
  161. // using (MemoryStream ms = new MemoryStream(steam))
  162. // {
  163. // using (Bitmap bmp = new Bitmap(ms))
  164. // {
  165. // using (Graphics g = Graphics.FromImage(bmp))
  166. // {
  167. // using (Pen pen = new Pen(Color.Red, 3))
  168. // {
  169. // foreach (var item in body["rects"])
  170. // {
  171. // Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  172. // g.DrawRectangle(pen, rect);
  173. // }
  174. // }
  175. // }
  176. // bmp.Save(signImg, ImageFormat.Jpeg);
  177. // }
  178. // }
  179. // //await model.SnapshotUrl.GetToSaveAsync(signImg);
  180. // Scoped.Create((_, scope) =>
  181. // {
  182. // var services = scope.ServiceProvider;
  183. // var _repository = services.GetService<IWarnInfoService>();
  184. // _repository.Add(model);
  185. // });
  186. // }
  187. // }
  188. //}
  189. //catch (Exception e)
  190. //{
  191. //}
  192. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  193. if (result.MessageType == WebSocketMessageType.Text)
  194. {
  195. try
  196. {
  197. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  198. var json = JsonConvert.DeserializeObject<JObject>(message);
  199. if (json["type"].ToString() == "msg")
  200. {
  201. //TODO 发送短信
  202. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  203. var body = json["body"];
  204. if (body != null)
  205. {
  206. PersonType personEnum;
  207. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  208. {
  209. dayEnum = AlarmType.visual_fence;
  210. }
  211. if (body["extend"] != null)
  212. {
  213. var extend = JsonConvert.DeserializeObject<JObject>(body["extend"].ToString());
  214. if (extend["personType"] != null)
  215. {
  216. if (!Enum.TryParse(body["extend"]?["personType"]?.ToString(), out personEnum))
  217. {
  218. personEnum = PersonType.unkonwn;
  219. }
  220. }
  221. else
  222. {
  223. personEnum = PersonType.unkonwn;
  224. }
  225. }
  226. else
  227. {
  228. personEnum = PersonType.unkonwn;
  229. }
  230. var model = new WarnInfoDto
  231. {
  232. TenantCode = body["tenantCode"]?.ToString(),
  233. PoiId = body["poiId"]?.ToString(),
  234. AlarmId = body["alarmId"]?.ToString(),
  235. AlarmType = body["alarmType"]?.ToString(),
  236. AlarmTypeDesc = dayEnum.GetDescription(),
  237. CameraId = body["cameraId"]?.ToString(),
  238. Tick = TimestampToDateTime(body["tick"].ToString()),
  239. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  240. Rects = body["rects"]?.ToString(),
  241. Tags = body["tags"]?.ToString(),
  242. Extend = body["extend"]?.ToString(),
  243. PersonType = personEnum.GetDescription(),
  244. WarnHand = 0,
  245. };
  246. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.AlarmId + ".jpg");
  247. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  248. model.SnapshotUrl = $"http://192.168.10.186:8003/Files/alarmImg/{model.AlarmId}.jpg";
  249. using (MemoryStream ms = new MemoryStream(steam))
  250. {
  251. using (Bitmap bmp = new Bitmap(ms))
  252. {
  253. using (Graphics g = Graphics.FromImage(bmp))
  254. {
  255. using (Pen pen = new Pen(Color.Red, 3))
  256. {
  257. foreach (var item in body["rects"])
  258. {
  259. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  260. g.DrawRectangle(pen, rect);
  261. }
  262. }
  263. }
  264. bmp.Save(signImg, ImageFormat.Jpeg);
  265. }
  266. }
  267. Scoped.Create((_, scope) =>
  268. {
  269. var services = scope.ServiceProvider;
  270. var _repository = services.GetService<IWarnInfoService>();
  271. _repository.Add(model);
  272. });
  273. }
  274. }
  275. else if (json["type"].ToString() == "cmd")
  276. {
  277. if ((bool)json["success"])
  278. {
  279. if (json["message"].ToString().Contains("connect success"))
  280. {
  281. LogHelper.WriteToLog("预警连接成功");
  282. }
  283. else if (json["message"].ToString().Contains("subscribe success"))
  284. {
  285. LogHelper.WriteToLog("预警订阅成功");
  286. }
  287. }
  288. }
  289. }
  290. catch (Exception e)
  291. {
  292. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  293. LogHelper.WriteToLog("预警webSocket处理异常");
  294. LogHelper.WriteToLog(e, "预警webSocket处理异常");
  295. }
  296. }
  297. else if (result.MessageType == WebSocketMessageType.Close)
  298. {
  299. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  300. break;
  301. }
  302. }
  303. LogHelper.WriteToLog("预警webSocket关闭");
  304. }
  305. /// <summary>
  306. /// 订阅点名事件
  307. /// </summary>
  308. /// <returns></returns>
  309. public async Task SubscriberRoomCall()
  310. {
  311. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  312. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  313. var url = GetWebSocketUrl(AuthConstants.SXROOM_CALL, AuthConstants.SXROOM_CAL_Group);
  314. var subscribeJson = JsonConvert.SerializeObject(new
  315. {
  316. token = GetToken(),
  317. type = "subscribe",
  318. timestamp,
  319. payload = new
  320. {
  321. topic = AuthConstants.SXROOM_CALL, consumerGroup = AuthConstants.SXROOM_CAL_Group, tags = setting.TenantCode
  322. }
  323. });
  324. ClientWebSocket _webSocket = new ClientWebSocket();
  325. webScokets.Add(_webSocket);
  326. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  327. //LogHelper.WriteToLog($"点名WebSocket 地址:{url}");
  328. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  329. byte[] buffer = new byte[1024*8];
  330. while (_webSocket.State == WebSocketState.Open)
  331. {
  332. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  333. if (result.MessageType == WebSocketMessageType.Text)
  334. {
  335. try
  336. {
  337. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  338. //LogHelper.WriteToLog($"收到: {message}");
  339. var json = JsonConvert.DeserializeObject<JObject>(message);
  340. if (json["type"].ToString() == "msg")
  341. {
  342. var body = json["body"];
  343. if (body != null)
  344. {
  345. //TODO 发送短信
  346. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  347. //TODO 由于未知道数据格式暂不写处理
  348. if (!Enum.TryParse(body["alarmType"].ToString(), out AlarmType dayEnum))
  349. {
  350. dayEnum = AlarmType.class_room_call;
  351. }
  352. var model = new ClassRoomCallDto
  353. {
  354. TenantCode = body["tenantCode"]?.ToString(),
  355. PoiId = body["poiId"]?.ToString(),
  356. TaskId = body["taskId"]?.ToString(),
  357. AlarmType = body["alarmType"].ToString(),
  358. AlarmTypeDesc = dayEnum.GetDescription(),
  359. EventId = body["eventId"]?.ToString(),
  360. CameraId = body["cameraId"]?.ToString(),
  361. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  362. PersonSetId = body["personSetId"]?.ToString(),
  363. PersonId = body["personId"]?.ToString(),
  364. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  365. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  366. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  367. SnapshotData = body["snapshotData"]?.ToString(),
  368. Rects = body["rects"]?.ToString(),
  369. Extend = body["extend"]?.ToString(),
  370. CreateTime = DateTime.Now,
  371. TrackId = body["TrackId"]?.ToString()
  372. };
  373. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.EventId + ".jpg");
  374. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  375. model.SnapshotUrl = $"http://192.168.10.186:8003/Files/roomCallImg/{model.EventId}.jpg";
  376. using (MemoryStream ms = new MemoryStream(steam))
  377. {
  378. using (Bitmap bmp = new Bitmap(ms))
  379. {
  380. using (Graphics g = Graphics.FromImage(bmp))
  381. {
  382. using (Pen pen = new Pen(Color.Red, 3))
  383. {
  384. foreach (var item in body["rects"])
  385. {
  386. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  387. g.DrawRectangle(pen, rect);
  388. }
  389. }
  390. }
  391. bmp.Save(signImg, ImageFormat.Jpeg);
  392. }
  393. }
  394. Scoped.Create((_, scope) =>
  395. {
  396. var services = scope.ServiceProvider;
  397. var _repository = services.GetService<IClassRoomCallService>();
  398. _repository.Add(model);
  399. });
  400. }
  401. }
  402. else if (json["type"].ToString() == "cmd")
  403. {
  404. if ((bool)json["success"])
  405. {
  406. if (json["message"].ToString().Contains("connect success"))
  407. {
  408. LogHelper.WriteToLog("点名连接成功");
  409. }
  410. else if (json["message"].ToString().Contains("subscribe success"))
  411. {
  412. LogHelper.WriteToLog("点名订阅成功");
  413. }
  414. }
  415. }
  416. }
  417. catch (Exception e)
  418. {
  419. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  420. LogHelper.WriteToLog("点名webSocket处理异常");
  421. LogHelper.WriteToLog(e, "点名webSocket处理异常");
  422. }
  423. }
  424. else if (result.MessageType == WebSocketMessageType.Close)
  425. {
  426. LogHelper.WriteToLog("点名WebSocket 连接已被服务器关闭");
  427. break;
  428. }
  429. }
  430. LogHelper.WriteToLog("点名webSocket已关闭");
  431. }
  432. public async Task SubscriberAttendance()
  433. {
  434. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  435. var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  436. var url = GetWebSocketUrl(AuthConstants.SXECOLOGY_ATTENDANCE, AuthConstants.SXECOLOGY_ATTENDANCE_Group);
  437. var subscribeJson = JsonConvert.SerializeObject(new
  438. {
  439. token = GetToken(),
  440. type = "subscribe",
  441. timestamp,
  442. payload = new
  443. {
  444. topic = AuthConstants.SXECOLOGY_ATTENDANCE,
  445. consumerGroup = AuthConstants.SXECOLOGY_ATTENDANCE_Group,
  446. tags = setting.TenantCode
  447. }
  448. });
  449. ClientWebSocket _webSocket = new ClientWebSocket();
  450. webScokets.Add(_webSocket);
  451. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  452. //LogHelper.WriteToLog($"考勤WebSocket 已连接:{url}");
  453. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(subscribeJson)), WebSocketMessageType.Text, true, CancellationToken.None);
  454. byte[] buffer = new byte[1024 * 8];
  455. while (_webSocket.State == WebSocketState.Open)
  456. {
  457. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  458. if (result.MessageType == WebSocketMessageType.Text)
  459. {
  460. try
  461. {
  462. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  463. //LogHelper.WriteToLog($"收到: {message}");
  464. var json = JsonConvert.DeserializeObject<JObject>(message);
  465. if (json["type"].ToString() == "msg")
  466. {
  467. var body = json["body"];
  468. if (body != null)
  469. {
  470. //TODO 发送短信
  471. //TxySmsUtil.SendSms(new[] { "" }, new[] { "" });
  472. //TODO 由于未知道数据格式暂不写处理
  473. var model = new AttendanceDto()
  474. {
  475. TenantCode = body["tenantCode"]?.ToString(),
  476. PoiId = body["poiId"]?.ToString(),
  477. EventId = body["eventId"]?.ToString(),
  478. CameraId = body["cameraId"]?.ToString(),
  479. Tick = TimestampToDateTime(body["tick"]?.ToString()),
  480. PersonSetId = body["personSetId"]?.ToString(),
  481. PersonId = body["personId"]?.ToString(),
  482. Similarity = body["similarity"] != null ? (float)body["similarity"] : 0,
  483. FaceScore = body["faceScore"] != null ? (float)body["faceScore"] : 0,
  484. SnapshotUrl = body["snapshotUrl"]?.ToString(),
  485. SnapshotData = body["snapshotData"]?.ToString(),
  486. Rects = body["rects"]?.ToString(),
  487. Extend = body["extend"]?.ToString(),
  488. CreateTime = DateTime.Now,
  489. TrackId = body["TrackId"]?.ToString(),
  490. };
  491. var signImg = Path.Combine(Directory.GetCurrentDirectory(), "Files", App.Configuration["AppInfo:AlarmImg"], model.EventId + ".jpg");
  492. var steam = await model.SnapshotUrl.GetAsByteArrayAsync();
  493. model.SnapshotUrl = $"http://192.168.10.186:8003/Files/attendanceImg/{model.EventId}.jpg";
  494. using (MemoryStream ms = new MemoryStream(steam))
  495. {
  496. using (Bitmap bmp = new Bitmap(ms))
  497. {
  498. using (Graphics g = Graphics.FromImage(bmp))
  499. {
  500. using (Pen pen = new Pen(Color.Red, 3))
  501. {
  502. foreach (var item in body["rects"])
  503. {
  504. Rectangle rect = new Rectangle((int)item["left"], (int)item["top"], (int)item["width"], (int)item["height"]);
  505. g.DrawRectangle(pen, rect);
  506. }
  507. }
  508. }
  509. bmp.Save(signImg, ImageFormat.Jpeg);
  510. }
  511. }
  512. Scoped.Create((_, scope) =>
  513. {
  514. var services = scope.ServiceProvider;
  515. var repository = services.GetService<IAttendanceService>();
  516. repository.Add(model);
  517. });
  518. }
  519. }else if (json["type"].ToString()=="cmd")
  520. {
  521. if ((bool)json["success"])
  522. {
  523. if (json["message"].ToString().Contains("connect success"))
  524. {
  525. LogHelper.WriteToLog("考勤连接成功");
  526. }else if (json["message"].ToString().Contains("subscribe success"))
  527. {
  528. LogHelper.WriteToLog("考勤订阅成功");
  529. }
  530. }
  531. }
  532. }
  533. catch (Exception e)
  534. {
  535. LogHelper.WriteToLog($"收到: {Encoding.UTF8.GetString(buffer, 0, result.Count)}");
  536. LogHelper.WriteToLog("考勤webSocket处理异常");
  537. LogHelper.WriteToLog(e, "考勤webSocket处理异常");
  538. }
  539. }
  540. else if (result.MessageType == WebSocketMessageType.Close)
  541. {
  542. LogHelper.WriteToLog("考勤WebSocket 连接已被服务器关闭");
  543. break;
  544. }
  545. }
  546. LogHelper.WriteToLog("考勤webSocket已关闭");
  547. }
  548. private async Task GetWebSocketData(string url, string json)
  549. {
  550. ClientWebSocket _webSocket = new ClientWebSocket();
  551. while (!_cancellationTokenSource.IsCancellationRequested)
  552. {
  553. try
  554. {
  555. await _webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
  556. LogHelper.WriteToLog("WebSocket 已连接");
  557. _isConnected = true;
  558. //订阅预警消息
  559. await _webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)), WebSocketMessageType.Text, true, CancellationToken.None);
  560. //_pingTimer = new Timer(async (state) =>
  561. //{
  562. // if (_webSocket.State == WebSocketState.Open)
  563. // {
  564. // try
  565. // {
  566. // LogHelper.WriteToLog("发送 ping...");
  567. // byte[] emptyPingMessage = Array.Empty<byte>();
  568. // await _webSocket.SendAsync(new ArraySegment<byte>(emptyPingMessage), WebSocketMessageType.Binary, true, CancellationToken.None);
  569. // //byte[] pingMessage = Encoding.UTF8.GetBytes("pong");
  570. // //await _webSocket.SendAsync(new ArraySegment<byte>(pingMessage), WebSocketMessageType.Text, true, CancellationToken.None);
  571. // }
  572. // catch (Exception ex)
  573. // {
  574. // LogHelper.WriteToLog($"发送ping失败: {ex.Message}");
  575. // }
  576. // }
  577. //}, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
  578. await ReceiveLoop(_webSocket);
  579. _isConnected = false;
  580. LogHelper.WriteToLog("WebSocket 连接已关闭,正在重连。。。");
  581. }
  582. catch (Exception ex)
  583. {
  584. LogHelper.WriteToLog($"WebSocket连接失败: {ex.Message}");
  585. }
  586. await Task.Delay(GetReconnectInterval());
  587. }
  588. }
  589. private async Task ReceiveLoop(ClientWebSocket _webSocket)
  590. {
  591. byte[] buffer = new byte[1024];
  592. while (_webSocket.State == WebSocketState.Open)
  593. {
  594. WebSocketReceiveResult result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  595. if (result.MessageType == WebSocketMessageType.Text)
  596. {
  597. string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
  598. LogHelper.WriteToLog($"收到: {message}");
  599. var json= JsonConvert.DeserializeObject<JObject>(message);
  600. if (json["type"].ToString()=="msg")
  601. {
  602. var body = json["body"];
  603. if (body!=null)
  604. {
  605. }
  606. }
  607. }
  608. else if (result.MessageType == WebSocketMessageType.Close)
  609. {
  610. LogHelper.WriteToLog("WebSocket 连接已被服务器关闭");
  611. break;
  612. }
  613. }
  614. }
  615. private TimeSpan GetReconnectInterval()
  616. {
  617. // You can implement your own logic for calculating reconnect interval, e.g., exponential backoff
  618. return TimeSpan.FromSeconds(10); // Example: Attempt to reconnect every 10 seconds
  619. }
  620. public async Task DisconnectAsync()
  621. {
  622. foreach (var clientWebSocket in webScokets.Where(clientWebSocket => clientWebSocket.State == WebSocketState.Open))
  623. {
  624. await clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
  625. }
  626. }
  627. private string GetWebSocketUrl(string topic, string consumerGroup)
  628. {
  629. var serverAddr = "";
  630. var setting = App.GetOptionsMonitor<AppInfoOptions>();
  631. var list = $"{setting.SXAPIURL}/emitter/connection/get"
  632. .SetBody(new
  633. {
  634. token = GetToken(),
  635. topic ,
  636. consumerGroup,
  637. })
  638. .SetContentType("application/json")
  639. .PostAsAsync<string>().Result;
  640. var model = JsonConvert.DeserializeObject<JObject>(list);
  641. if (model["data"]["serverAddr"]!=null)
  642. {
  643. serverAddr = model["data"]["serverAddr"].ToString();
  644. }
  645. return serverAddr;
  646. }
  647. //public async Task<bool> GetData()
  648. //{
  649. // //var setting = App.GetOptionsMonitor<AppInfoOptions>();
  650. // //var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  651. // ////订阅预警消息
  652. // //var warnUrl = GetWebSocketUrl(AuthConstants.SXALARM, AuthConstants.SXALARM_Grpup);
  653. // //GetWebSocketData(warnUrl,
  654. // // JsonConvert.SerializeObject(new
  655. // // {
  656. // // token = GetToken(), type = "subscribe", timestamp,
  657. // // payload = new { topic = AuthConstants.SXALARM, consumerGroup= AuthConstants.SXALARM_Grpup, tags= setting.TenantCode }
  658. // // }));
  659. // //订阅预警更新消息
  660. // await SubscribeAlarm();
  661. // //订阅点名事件
  662. // //await SubscriberRoomCall();
  663. // return true;
  664. //}
  665. /// <summary>
  666. /// 时间戳转本时区日期时间
  667. /// </summary>
  668. /// <param name="timeStamp"></param>
  669. /// <returns></returns>
  670. public static DateTime TimestampToDateTime(string timeStamp)
  671. {
  672. DateTimeOffset utcDateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(timeStamp));
  673. return utcDateTimeOffset.LocalDateTime;
  674. }
  675. }