fix 任务根据设备心跳状态获取
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Dlhis.Basic.Device.Request;
|
||||
using Dlhis.Basic.Device.Dtos;
|
||||
using Dlhis.Basic.Device.Request;
|
||||
using Dlhis.Basic.Device.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -38,9 +39,9 @@ public class DevicesConnectController : ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("resigter")]
|
||||
[HttpPost("register")]
|
||||
[IgnoreTenant]
|
||||
public async Task<string> ResigterAsync(DeviceResigterRequest request)
|
||||
public async Task<string> RegisterAsync(DeviceResigterRequest request)
|
||||
{
|
||||
return await _deviceConnectService.RegisterAsync(request);
|
||||
}
|
||||
@@ -50,9 +51,19 @@ public class DevicesConnectController : ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("try-connect")]
|
||||
[HttpPost("tryConnect")]
|
||||
public async Task<bool> TryConnectAsync(DeviceConnectionTryRequest request)
|
||||
{
|
||||
return await _deviceConnectService.TryConnectAsync(request);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取在线设备
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("online-devices")]
|
||||
public async Task<List<DeviceUniqueWithConnectionInfoDto>> GetOnlineDeviceUniqueInfoAsync()
|
||||
{
|
||||
return await _deviceConnectService.GetOnlineDeviceUniqueInfoAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Dlhis.Basic.Device.Dtos;
|
||||
|
||||
public class DeviceUniqueWithConnectionInfoDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备号
|
||||
/// </summary>
|
||||
public string DeviceUnique { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连接信息
|
||||
/// </summary>
|
||||
public string ConnectionInfo { get; set; }
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class DevicePageResponse
|
||||
/// </summary>
|
||||
public bool Enable { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否作为考勤
|
||||
/// </summary>
|
||||
@@ -109,11 +109,11 @@ public class DevicePageResponse
|
||||
{
|
||||
if (!LastHeartbeatTime.HasValue)
|
||||
return false;
|
||||
|
||||
|
||||
if (HeartbeatInterval <= 0)
|
||||
return true;
|
||||
|
||||
return LastHeartbeatTime.Value.AddSeconds(HeartbeatInterval * 3) >= DateTime.Now;
|
||||
|
||||
return LastHeartbeatTime.Value.AddSeconds(HeartbeatInterval) >= DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,4 +126,4 @@ public class DevicePageResponse
|
||||
/// 营业点名称
|
||||
/// </summary>
|
||||
public string BusinessPlaceName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dlhis.Basic.Device.Request;
|
||||
using Dlhis.Basic.Device.Dtos;
|
||||
using Dlhis.Basic.Device.Request;
|
||||
using Dlhis.Basic.Device.Response;
|
||||
|
||||
namespace Dlhis.Basic.Device.Services;
|
||||
@@ -31,7 +32,7 @@ public interface IDeviceConnectService : IScopeDependency
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
Task HeartbeatAsync(DeviceHeartbeatRequest request);
|
||||
Task<int> HeartbeatAsync(DeviceHeartbeatRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// 尝试连接
|
||||
@@ -39,4 +40,10 @@ public interface IDeviceConnectService : IScopeDependency
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> TryConnectAsync(DeviceConnectionTryRequest request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取在线设备信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<DeviceUniqueWithConnectionInfoDto>> GetOnlineDeviceUniqueInfoAsync();
|
||||
}
|
||||
@@ -12,8 +12,6 @@ public interface IDeviceService : IScopeDependency
|
||||
|
||||
Task<bool> CheckExistsAsync(string deviceUniqueNo);
|
||||
|
||||
Task<DeviceResponse> GetDeviceByNoAsync(DeviceByNoRequest request);
|
||||
|
||||
Task<List<DeviceResponse>> GetAttendanceDevicesAsync();
|
||||
|
||||
Task<DeviceNumberResponse> GetDeviceNumberAsync();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
@@ -9,6 +10,7 @@ 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;
|
||||
|
||||
@@ -71,7 +73,7 @@ public class DeviceConnectService : IDeviceConnectService
|
||||
if (request.BusinessPlaceCode.HasValue)
|
||||
{
|
||||
var businessPlace = await _dbContext.Queryable<BusinessPlaceEntity>().Where(x => x.Code == request.BusinessPlaceCode).FirstAsync();
|
||||
businessPlace.ThrowIfNull("营业点不存在,无法设置到设备注册信息中");
|
||||
businessPlace.ThrowIfNull("营业点不存在,无法设置到设备注册信息中");
|
||||
}
|
||||
|
||||
//更新营业点信息
|
||||
@@ -81,13 +83,12 @@ public class DeviceConnectService : IDeviceConnectService
|
||||
}
|
||||
|
||||
|
||||
public async Task HeartbeatAsync(DeviceHeartbeatRequest request)
|
||||
public async Task<int> HeartbeatAsync(DeviceHeartbeatRequest request)
|
||||
{
|
||||
var registry = await _dbContext.Queryable<DeviceRegistryEntity>().Where(x => x.DeviceUniqueNo == request.UniqueNo).FirstAsync();
|
||||
registry.ThrowIfNull($"注册信息不存在,无法发起心跳");
|
||||
|
||||
registry.LastHeartbeatTime = DateTime.Now;
|
||||
await _dbContext.UpdateAsync(registry);
|
||||
return await _dbContext.Updateable<DeviceRegistryEntity>()
|
||||
.SetColumns(x => x.LastHeartbeatTime == DateTime.Now)
|
||||
.Where(x => x.DeviceUniqueNo == request.UniqueNo)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +111,20 @@ public class DeviceConnectService : IDeviceConnectService
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<DeviceUniqueWithConnectionInfoDto>> GetOnlineDeviceUniqueInfoAsync()
|
||||
{
|
||||
return await _dbContext.Queryable<DeviceEntity>()
|
||||
.LeftJoin<DeviceRegistryEntity>((d, dr) => d.UniqueNo == dr.DeviceUniqueNo)
|
||||
.Where((d, dr) => d.Enable && SqlFunc.DateAdd(dr.LastHeartbeatTime, SqlFunc.IIF(d.HeartbeatInterval == 0, 30, 30), DateType.Second) > DateTime.Now)
|
||||
.Select((d, dr) => new DeviceUniqueWithConnectionInfoDto
|
||||
{
|
||||
DeviceUnique = d.UniqueNo,
|
||||
ConnectionInfo = d.ConnectionInfo
|
||||
})
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
//******************************************************** help methods **********************************************************
|
||||
|
||||
/// <summary>
|
||||
@@ -123,8 +138,8 @@ public class DeviceConnectService : IDeviceConnectService
|
||||
private async Task<DeviceEntity> GetEnableDeviceAsync(string uniqueNo, bool checkExists = true, string deployPlace = "", string tenantId = "")
|
||||
{
|
||||
var device = await _dbContext.Queryable<DeviceEntity>()
|
||||
.Where(x => x.UniqueNo == uniqueNo)
|
||||
.FirstAsync();
|
||||
.Where(x => x.UniqueNo == uniqueNo)
|
||||
.FirstAsync();
|
||||
|
||||
if (checkExists)
|
||||
{
|
||||
@@ -165,4 +180,4 @@ public class DeviceConnectService : IDeviceConnectService
|
||||
|
||||
return device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,25 +274,7 @@ public class DeviceService : IDeviceService
|
||||
_dbContext.Client.QueryFilter.Restore();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<DeviceResponse> GetDeviceByNoAsync(DeviceByNoRequest request)
|
||||
{
|
||||
var device = await _dbContext.Queryable<DeviceEntity>()
|
||||
.Where(x => x.UniqueNo == request.UniqueNo)
|
||||
.Select(device => new DeviceResponse
|
||||
{
|
||||
FuncsStr = device.Funcs.ToString(),
|
||||
ConnectionInfoStr = device.ConnectionInfo
|
||||
}, true)
|
||||
.SingleAsync();
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<DeviceResponse>> GetAttendanceDevicesAsync()
|
||||
{
|
||||
@@ -347,7 +329,7 @@ public class DeviceService : IDeviceService
|
||||
var onlineDevices = deviceRegistries.Where(x =>
|
||||
{
|
||||
if (x.HeartbeatInterval <= 0) return true;
|
||||
return x.LastHeartbeatTime.AddSeconds(x.HeartbeatInterval * 3) >= now;
|
||||
return x.LastHeartbeatTime.AddSeconds(x.HeartbeatInterval) >= now;
|
||||
})
|
||||
.Select(x => new
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Device.Entities;
|
||||
using Dlhis.ScheduledTask.Attributes;
|
||||
using Kurisu.AspNetCore.CustomClass;
|
||||
using Kurisu.AspNetCore.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.ScheduledTask.Jobs;
|
||||
@@ -12,40 +11,33 @@ namespace Dlhis.ScheduledTask.Jobs;
|
||||
/// <summary>
|
||||
/// 设备心跳
|
||||
/// </summary>
|
||||
[RecurringJob(nameof(HeartbeatJob), "0/10 * * * * ?", Name = "设备心跳")]
|
||||
[RecurringJob(nameof(HeartbeatJob), "0/30 * * * * ?", Name = "设备心跳")]
|
||||
public class HeartbeatJob : BaseJob
|
||||
{
|
||||
private readonly RedisCache _redisCache;
|
||||
|
||||
public HeartbeatJob(IServiceProvider serviceProvider, RedisCache redisCache) : base(serviceProvider)
|
||||
public HeartbeatJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||
{
|
||||
_redisCache = redisCache;
|
||||
}
|
||||
|
||||
protected override async Task RunAsync(IServiceProvider serviceProvider)
|
||||
{
|
||||
const string key = "heartbeat-devices";
|
||||
await _redisCache.KeyDeleteAsync(key);
|
||||
|
||||
var devices = await DbContext.Queryable<DeviceEntity>().Where(x => x.Enable).Where(x => x.HeartbeatInterval > 0).ToListAsync();
|
||||
foreach (var device in devices)
|
||||
|
||||
devices.AsParallel().ForAll(device =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var ipInfo = JsonConvert.DeserializeObject<IPPortDto>(device.ConnectionInfo);
|
||||
new TcpClient().Connect(IPAddress.Parse(ipInfo.IP), ipInfo.Port);
|
||||
|
||||
//超时时间
|
||||
var cancellationTokenSource = new CancellationTokenSource(300);
|
||||
await new TcpClient().ConnectAsync(IPAddress.Parse(ipInfo.IP), ipInfo.Port, cancellationTokenSource.Token);
|
||||
|
||||
await DbContext.Updateable<DeviceRegistryEntity>().SetColumns(x => x.LastHeartbeatTime == DateTime.Now)
|
||||
.Where(x => x.DeviceUniqueNo == device.UniqueNo).ExecuteCommandAsync(cancellationTokenSource.Token);
|
||||
|
||||
await _redisCache.ListLeftPushAsync(key, device.UniqueNo);
|
||||
DbContext.Updateable<DeviceRegistryEntity>()
|
||||
.SetColumns(x => x.LastHeartbeatTime == DateTime.Now)
|
||||
.Where(x => x.DeviceUniqueNo == device.UniqueNo)
|
||||
.ExecuteCommand();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,6 +236,8 @@ public class AssignmentService : IAssignmentService
|
||||
.LeftJoin<GainfoLeaveEntity>((deviceTask, device, deviceTemplate, ga, gaLeave) => deviceTask.UserNo == gaLeave.No)
|
||||
.LeftJoin<DepartmentEntity>((deviceTask, device, deviceTemplate, ga, gaLeave, department) => department.No == ga.DepartmentNo)
|
||||
.LeftJoin<GainfoExternalEntity>((deviceTask, device, deviceTemplate, ga, gaLeave, department, gainfoEx) => deviceTask.UserNo == gainfoEx.No)
|
||||
.LeftJoin<DeviceRegistryEntity>((deviceTask, device, deviceTemplate, ga, gaLeave, department, gainfoEx, deviceRegistry) => deviceRegistry.DeviceUniqueNo == deviceTask.DeviceUniqueNo)
|
||||
.Where((deviceTask, device) => device.Enable)
|
||||
.WhereIF(!request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Wait)
|
||||
.WhereIF(request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Process
|
||||
&& SqlFunc.DateDiff(DateType.Minute, deviceTask.ModifiedTime, DateTime.Now) > 30)
|
||||
@@ -243,6 +245,8 @@ public class AssignmentService : IAssignmentService
|
||||
.WhereIF(request.Factory.IsPresent(), (deviceTask, device) => deviceTask.TenantId == request.Factory)
|
||||
.WhereIF(request.Types.IsPresent(), deviceTask => request.Types.Contains(deviceTask.Type))
|
||||
.WhereIF(request.Brand.IsPresent(), (deviceTask, device, deviceTemplate) => deviceTemplate.Brand == request.Brand)
|
||||
.Where((deviceTask, device, deviceTemplate, ga, gaLeave, department, gainfoEx, deviceRegistry) =>
|
||||
SqlFunc.DateAdd(deviceRegistry.LastHeartbeatTime, SqlFunc.IIF(device.HeartbeatInterval == 0, 30, 30), DateType.Second) > DateTime.Now)
|
||||
.OrderBy(deviceTask => new { Priority = SqlFunc.Desc(deviceTask.Priority), deviceTask.CreateTime })
|
||||
.Select((deviceTask, device, deviceTemplate, ga, gaLeave, department, gainfoEx) => new TaskDto
|
||||
{
|
||||
@@ -273,14 +277,14 @@ public class AssignmentService : IAssignmentService
|
||||
var where = LinqExpressionExtensions.False<DeviceTaskEntity>();
|
||||
taskIdVs.ForEach(p => { where = where.Or(x => x.Id == p.TaskId && x.Version == p.Version && x.Status == p.Status); });
|
||||
|
||||
var effecet = await _dbContext.Updateable<DeviceTaskEntity>()
|
||||
var effect = await _dbContext.Updateable<DeviceTaskEntity>()
|
||||
.SetColumns(x => x.Version == x.Version + 1)
|
||||
.SetColumns(x => x.Status == DeviceTaskStatusEnumType.Process)
|
||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||
.Where(where)
|
||||
.ExecuteCommandAsync();
|
||||
|
||||
(taskIdVs.Count != effecet).ThrowIfTrue("获取任务失败");
|
||||
(taskIdVs.Count != effect).ThrowIfTrue("获取任务失败");
|
||||
|
||||
return page.Data;
|
||||
}, 5);
|
||||
|
||||
Reference in New Issue
Block a user