From 78ac4ae259e1b84cb7632fd2492cb421fa2c6c17 Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Fri, 21 Aug 2026 09:29:20 +0800 Subject: [PATCH] ww --- YD_YiLu.Commons/Dto/Running/RunningDtos.cs | 32 ++++ YD_YiLu/Controllers/RunningController.cs | 189 +++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 YD_YiLu.Commons/Dto/Running/RunningDtos.cs create mode 100644 YD_YiLu/Controllers/RunningController.cs diff --git a/YD_YiLu.Commons/Dto/Running/RunningDtos.cs b/YD_YiLu.Commons/Dto/Running/RunningDtos.cs new file mode 100644 index 0000000..df19941 --- /dev/null +++ b/YD_YiLu.Commons/Dto/Running/RunningDtos.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace YD_YiLu.Commons.Dto.Running +{ + /// + /// 阳光跑跑道人员状态上报。 + /// + public class RunningStageRequestDto + { + public string DeviceSerial { get; set; } + public List RunUserList { get; set; } = new List(); + } + + /// + /// 阳光跑跑道识别人员。 + /// + public class RunUserRecognizeDto + { + public string UserSerial { get; set; } + public string Nickname { get; set; } + public string Base64face { get; set; } + public int Status { get; set; } + public int TrackIndex { get; set; } + public int Result { get; set; } + public int Medal { get; set; } + public int GroupId { get; set; } + public int Uid { get; set; } + public int QuizId { get; set; } + public string DeviceSerial { get; set; } + public int ErrorStatus { get; set; } + } +} diff --git a/YD_YiLu/Controllers/RunningController.cs b/YD_YiLu/Controllers/RunningController.cs new file mode 100644 index 0000000..f5e1f45 --- /dev/null +++ b/YD_YiLu/Controllers/RunningController.cs @@ -0,0 +1,189 @@ +using System.Net.WebSockets; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using YD_YiLu.Api.WebSockets; +using YD_YiLu.Commons.Dto.Running; + +namespace YD_YiLu.Api.Controllers +{ + /// + /// 阳光跑接口。 + /// + [AllowAnonymous] + public class RunningController : ControllerBase + { + private readonly ICameraDeviceSocketRegistry _registry; + private readonly ILogger _logger; + + public RunningController(ICameraDeviceSocketRegistry registry, ILogger logger) + { + _registry = registry; + _logger = logger; + } + + /// + /// 跑道人员变更状态。 + /// + [HttpPost] + [Route("/running/result/stage")] + public object ResultStage([FromBody] RunningStageRequestDto dto) + { + _logger.LogInformation( + "Running stage changed. DeviceSerial: {DeviceSerial}, UserCount: {UserCount}", + dto?.DeviceSerial, + dto?.RunUserList?.Count ?? 0); + + return new { }; + } + + /// + /// 平台指定用户下发人脸通知(旧)。 + /// + [HttpPost] + [Route("/station:user:push")] + public async Task StationUserPush([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("station:user:push", body, deviceSerial); + } + + /// + /// 平台下发人脸通知。 + /// + [HttpPost] + [Route("/station:remind")] + public async Task StationRemind([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("station:remind", body, deviceSerial); + } + + /// + /// 跑步小组重启。 + /// + [HttpPost] + [Route("/running:group:restart")] + public async Task RunningGroupRestart([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("running:group:restart", body, deviceSerial); + } + + /// + /// 跑步小组推送。 + /// + [HttpPost] + [Route("/running:group:push")] + public async Task RunningGroupPush([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("running:group:push", body, deviceSerial); + } + + /// + /// 跑步小组自动分组。 + /// + [HttpPost] + [Route("/running:group:auto")] + public async Task RunningGroupAuto([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("running:group:auto", body, deviceSerial); + } + + /// + /// 设备指令。 + /// + [HttpPost] + [Route("/device:instruct")] + public async Task DeviceInstruct([FromBody] JObject body, [FromQuery] string deviceSerial = "") + { + return await SendSocketMessageAsync("device:instruct", body, deviceSerial); + } + + private async Task SendSocketMessageAsync(string request, JObject body, string deviceSerial) + { + body ??= new JObject(); + + var serial = FirstNotEmpty(deviceSerial, FindString(body, "serialNumber"), FindString(body, "deviceSerial")); + if (string.IsNullOrWhiteSpace(serial)) + { + return new + { + success = false, + message = "deviceSerial不能为空" + }; + } + + if (!_registry.TryGet(serial, out var socket) || socket.State != WebSocketState.Open) + { + return new + { + success = false, + serialNumber = serial, + message = "设备不在线" + }; + } + + var message = NormalizeSocketMessage(request, body); + await CameraDeviceWebSocketHandler.SendAsync( + socket, + message.ToString(Formatting.None), + HttpContext.RequestAborted); + + _logger.LogInformation("Running socket message sent. Request: {Request}, SerialNumber: {SerialNumber}", request, serial); + + return new + { + success = true, + serialNumber = serial + }; + } + + private static JObject NormalizeSocketMessage(string request, JObject body) + { + var message = (JObject)body.DeepClone(); + + if (string.IsNullOrWhiteSpace(message["msgId"]?.ToString())) + message["msgId"] = Guid.NewGuid().ToString("N"); + + message["request"] = request; + message["code"] ??= 0; + message["msg"] ??= ""; + message["data"] ??= new JObject(); + + return message; + } + + private static string FirstNotEmpty(params string[] values) + { + return values.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x)) ?? ""; + } + + private static string FindString(JToken token, string name) + { + if (token == null) + return ""; + + if (token.Type == JTokenType.Object) + { + var obj = (JObject)token; + foreach (var property in obj.Properties()) + { + if (string.Equals(property.Name, name, StringComparison.OrdinalIgnoreCase)) + { + var value = property.Value?.ToString(); + if (!string.IsNullOrWhiteSpace(value)) + return value; + } + } + } + + foreach (var child in token.Children()) + { + var value = FindString(child, name); + if (!string.IsNullOrWhiteSpace(value)) + return value; + } + + return ""; + } + } +}