平安校园
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

DeepelephManager.cs 36 KiB

4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
3ヶ月前
4ヶ月前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  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. }