using System.Net; using System.Net.Sockets; using Dlhis.Basic.Device.Dtos; using Dlhis.Basic.Device.Request; using Dlhis.Basic.Device.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; using Kurisu.AspNetCore.CustomClass; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using Mapster; using SqlSugar; namespace Dlhis.Basic.Device.Services.Implements; public class DeviceConnectService : IDeviceConnectService { private readonly IDbContext _dbContext; public DeviceConnectService(IDbContext dbContext) { _dbContext = dbContext; } public async Task RegisterAsync(DeviceRegisterRequest request) { var businessPlace = await _dbContext.Queryable() .Where(x => x.CustomCode == request.BusinessCustomCode) .SingleAsync(); businessPlace.ThrowIfNull("营业点不存在"); var device = await GetEnableDeviceAsync(request.UniqueNo, false, request.DeployPlace, businessPlace.TenantId); var registry = await _dbContext.Queryable().Where(x => x.DeviceUniqueNo == request.UniqueNo).SingleAsync(); if (registry != null) { registry.LastHeartbeatTime = DateTime.Now; registry.RegisterTime = DateTime.Now; registry.BusinessPlaceCode = businessPlace.Code; await _dbContext.UpdateAsync(registry); } else { registry = new DeviceRegistryEntity { DeviceUniqueNo = request.UniqueNo, LastHeartbeatTime = DateTime.Now, RegisterTime = DateTime.Now, BusinessPlaceCode = businessPlace.Code }; await _dbContext.InsertAsync(registry); } if (request.DeployPlace.Equals("AUTO", StringComparison.OrdinalIgnoreCase)) device.DeployPlace = businessPlace.Name; else device.DeployPlace = request.DeployPlace.IsPresent() ? request.DeployPlace : businessPlace.Name; await _dbContext.UpdateAsync(device); return "设备注册成功"; } public async Task> GetNotSetBusinessPlaceDevicesAsync() { var devices = await _dbContext.Queryable().Where(x => x.Enable).ToListAsync(); devices = devices.Where(x => x.Type == DeviceTypeEnumType.Meal).ToList(); return devices.Adapt>(); } public async Task SetRegisterBusinessPlaceAsync(DeviceSetResigterBusinessPlaceRequest request) { var device = await GetEnableDeviceAsync(request.UniqueNo); (device.Type != DeviceTypeEnumType.Meal).ThrowIfTrue("非就餐类型设备,无法设置"); var registry = await _dbContext.Queryable().Where(x => x.DeviceUniqueNo == request.UniqueNo).FirstAsync(); registry.ThrowIfNull($"{request.UniqueNo}的设备注册信息不存在,无法设置营业点"); if (request.BusinessPlaceCode.HasValue) { var businessPlace = await _dbContext.Queryable().Where(x => x.Code == request.BusinessPlaceCode).FirstAsync(); businessPlace.ThrowIfNull("营业点不存在,无法设置到设备注册信息中"); } //更新营业点信息 registry.BusinessPlaceCode = request.BusinessPlaceCode; await _dbContext.UpdateAsync(registry); } public async Task HeartbeatAsync(DeviceHeartbeatRequest request) { return await _dbContext.Updateable() .SetColumns(x => x.LastHeartbeatTime == DateTime.Now) .Where(x => x.DeviceUniqueNo == request.UniqueNo) .ExecuteCommandAsync(); } public async Task TryConnectAsync(DeviceConnectionTryRequest request) { try { var ipInfo = request.ConnectionInfo.ToObject(); //超时时间 var cancellationTokenSource = new CancellationTokenSource(300); await new TcpClient().ConnectAsync(IPAddress.Parse(ipInfo.IP), ipInfo.Port, cancellationTokenSource.Token); return true; } catch (Exception) { return false; } } public async Task> GetOnlineDeviceUniqueInfoAsync() { return await _dbContext.Queryable() .LeftJoin((d, dr) => d.UniqueNo == dr.DeviceUniqueNo) .Where((d, dr) => d.Enable && (d.HeartbeatInterval == 0 || SqlFunc.DateAdd(dr.LastHeartbeatTime, d.HeartbeatInterval, DateType.Second) > DateTime.Now)) .Select((d, dr) => new DeviceUniqueWithConnectionInfoDto { DeviceUnique = d.UniqueNo, ConnectionInfo = d.ConnectionInfo }) .ToListAsync(); } public async Task> GetDeviceUniqueInfoByBrandAsync(string brand, string factory) { var factories = factory.Split(",").ToList(); var results = await _dbContext.Queryable() .LeftJoin((d, dt) => d.TemplateCode == dt.Code) .Where((d, dt) => dt.Brand == brand && factories.Contains(d.TenantId)) .Where(d => d.IsElevatorAcs == false)//先排除梯控 .Where(d => d.Enable == true) .Select(d => new DeviceUniqueWithConnectionInfoDto { DeviceUnique = d.UniqueNo, ConnectionInfo = d.ConnectionInfo }) .ToListAsync(); var elevatorAcses = await _dbContext.Queryable() .LeftJoin((d, dt) => d.TemplateCode == dt.Code) .LeftJoin((d, dt, f) => d.UniqueNo == f.VirtualDeviceUniqueNo) .Where((d, dt) => dt.Brand == brand && factories.Contains(d.TenantId)) .Where(d => d.IsElevatorAcs == true) .Where(d => d.Enable == true) .Select((d, dt, f) => new DeviceUniqueWithConnectionInfoDto { DeviceUnique = f.RealDeviceUniqueNo, ConnectionInfo = d.ConnectionInfo }) .ToListAsync(); results.AddRange(elevatorAcses.DistinctBy(x => x.DeviceUnique).ToList()); return results; } //******************************************************** help methods ********************************************************** /// /// 获取启用的设备 /// /// /// /// /// /// private async Task GetEnableDeviceAsync(string uniqueNo, bool checkExists = true, string deployPlace = "", string tenantId = "") { var device = await _dbContext.Queryable().Where(x => x.UniqueNo == uniqueNo).SingleAsync(); if (checkExists) { device.ThrowIfNull($"未知的设备唯一编码{uniqueNo}"); device.Enable.ThrowIfFalse("设备尚未启用"); } else { if (device == null) { var templateCode = await _dbContext.Queryable().Where(x => x.Name == "其他").Select(x => x.Code).FirstAsync(); device = new DeviceEntity { Code = Guid.NewGuid(), ConnectionInfo = "{}", TemplateCode = templateCode, UniqueNo = uniqueNo, TenantId = tenantId, Supplier = string.Empty, Funcs = new List(), Type = DeviceTypeEnumType.Meal, DeployPlace = deployPlace, HeartbeatInterval = 0, DeployDirection = null, Enable = true, AsAttendance = false, DeployPosition = string.Empty, }; await _dbContext.InsertAsync(device); } } return device; } }