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

DeepelephManager.cs 45 KiB

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