2025-03-22 12:16:22 +00:00
|
|
|
|
using LY.App.Common;
|
|
|
|
|
|
using LY.App.Common.Redis;
|
|
|
|
|
|
using LY.App.Common.WebSocket;
|
|
|
|
|
|
using LY.App.Extensions.DI;
|
|
|
|
|
|
using LY.App.Model;
|
|
|
|
|
|
using Mapster;
|
|
|
|
|
|
using Microsoft.AspNetCore.SignalR;
|
2025-03-26 02:47:56 +00:00
|
|
|
|
using NetTopologySuite.Geometries;
|
2025-04-12 09:46:40 +00:00
|
|
|
|
using NetTopologySuite.Index.HPRtree;
|
2025-03-26 02:47:56 +00:00
|
|
|
|
using NetTopologySuite.IO;
|
2025-03-22 12:16:22 +00:00
|
|
|
|
using SqlSugar;
|
|
|
|
|
|
using StackExchange.Redis;
|
2025-03-26 02:47:56 +00:00
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
using System.Reflection;
|
2025-03-22 12:16:22 +00:00
|
|
|
|
|
|
|
|
|
|
namespace LY.App.Service
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 报警服务
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ServiceInjection(InjectionType.Transient)]
|
|
|
|
|
|
public class AlarmService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly SqlSugarClient _db;
|
|
|
|
|
|
private readonly IConfiguration _config;
|
|
|
|
|
|
private readonly RedisService _redisService;
|
|
|
|
|
|
private readonly PushService _pushService;
|
|
|
|
|
|
public AlarmService(SqlSugarClient db, IConfiguration config, RedisService redisService, PushService pushService)
|
|
|
|
|
|
{
|
|
|
|
|
|
_db = db;
|
|
|
|
|
|
_config = config;
|
|
|
|
|
|
_redisService = redisService;
|
|
|
|
|
|
_pushService = pushService;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 新增报警信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<ApiResult> AddAlarm(RevData input)
|
|
|
|
|
|
{
|
|
|
|
|
|
await SetDeviceStataus(input);
|
2025-04-05 09:50:08 +00:00
|
|
|
|
var key = RedisKeyList.DeviceInfo(input.product_ad_id);
|
|
|
|
|
|
var deviceinfo = await _redisService.GetAsync<DeviceEntity>(key);
|
|
|
|
|
|
if (deviceinfo == null)
|
2025-03-22 12:16:22 +00:00
|
|
|
|
{
|
2025-04-05 09:50:08 +00:00
|
|
|
|
deviceinfo = await _db.CopyNew().Queryable<DeviceEntity>().Where(s => s.DeviceSN == input.product_ad_id).FirstAsync();
|
2025-03-22 12:16:22 +00:00
|
|
|
|
if (deviceinfo == null)
|
|
|
|
|
|
{
|
2025-04-05 09:50:08 +00:00
|
|
|
|
return new ApiResult() { code = 1, msg = "设备不存在" };
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
2025-04-05 09:50:08 +00:00
|
|
|
|
await _redisService.SetAsync(key, deviceinfo, TimeSpan.FromDays(1));
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
2025-04-05 13:08:36 +00:00
|
|
|
|
var entity = input.data.Adapt<List<Alarm>>();
|
2025-04-12 09:46:40 +00:00
|
|
|
|
entity = entity.Where(s => checkDistance(s.drone_lat, s.drone_lon, deviceinfo.Lat, deviceinfo.Lon) == true).ToList();
|
2025-04-06 13:56:20 +00:00
|
|
|
|
if (entity.Any())
|
2025-04-05 13:08:36 +00:00
|
|
|
|
{
|
2025-04-06 13:56:20 +00:00
|
|
|
|
foreach (var item in entity)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.BatchId = await GetBatId(item.serial_number);
|
|
|
|
|
|
item.DeviceId = deviceinfo.Id;
|
|
|
|
|
|
item.DeviceName = deviceinfo.Name;
|
|
|
|
|
|
item.positionId = deviceinfo.PositionId;
|
|
|
|
|
|
item.PostionName = deviceinfo.PositionName;
|
|
|
|
|
|
item.Time = input.time;
|
|
|
|
|
|
item.distance = GisHelper.HaversineDistance(item.drone_lat, item.drone_lon, item.app_lat, item.app_lon);
|
2025-04-12 15:17:49 +00:00
|
|
|
|
item.IsWhitelist = await Iswhitlist(item.serial_number, item.drone_lat, item.drone_lon);
|
|
|
|
|
|
item.alarmLevel = item.IsWhitelist == true ? 0 : await GetAlarmLevel(deviceinfo.PositionId, item.drone_lon, item.drone_lat);
|
2025-04-13 05:55:26 +00:00
|
|
|
|
item.centerdistance = await GetCenterDistance(item.drone_lat, item.drone_lon, item.positionId);
|
2025-04-06 13:56:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
await _db.CopyNew().Insertable(entity).SplitTable().ExecuteReturnSnowflakeIdListAsync();
|
|
|
|
|
|
//推送报警信息
|
|
|
|
|
|
await _pushService.SendMessageToAll(new { msgType = "event", data = entity });
|
2025-04-05 13:08:36 +00:00
|
|
|
|
}
|
2025-03-22 12:16:22 +00:00
|
|
|
|
return new ApiResult();
|
2025-03-26 02:47:56 +00:00
|
|
|
|
}
|
2025-04-13 05:55:26 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 防区中心距离
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="lat"></param>
|
|
|
|
|
|
/// <param name="lon"></param>
|
|
|
|
|
|
/// <param name="positioonId"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private async Task<double> GetCenterDistance(double lat, double lon, long positioonId)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var key = RedisKeyList.PositioinRegion(positioonId);
|
|
|
|
|
|
var pontion = await _redisService.GetAsync<PositionInfo>(key);
|
|
|
|
|
|
if (pontion == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
pontion = await _db.CopyNew().Queryable<PositionInfo>()
|
|
|
|
|
|
.Where(s => s.Id == positioonId)
|
|
|
|
|
|
.FirstAsync();
|
|
|
|
|
|
await _redisService.SetAsync(key, pontion);
|
|
|
|
|
|
}
|
|
|
|
|
|
var distance = GisHelper.HaversineDistance(lat, lon, pontion.lat, pontion.lat);
|
|
|
|
|
|
return distance;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine(ex.Message);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2025-04-12 09:46:40 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 判断 距离是否在范围内
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="lat"></param>
|
|
|
|
|
|
/// <param name="lon"></param>
|
|
|
|
|
|
/// <param name="d_lat"></param>
|
|
|
|
|
|
/// <param name="d_lon"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private bool checkDistance(double lat, double lon, double d_lat, double d_lon)
|
|
|
|
|
|
{
|
|
|
|
|
|
var maxDistance = Convert.ToDouble(_config["MaxDistance"]);
|
|
|
|
|
|
var distance = GisHelper.HaversineDistance(lat, lon, d_lat, d_lon);
|
|
|
|
|
|
return distance < maxDistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-12 15:17:49 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 判断是否在白名单中
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="serial_number"></param>
|
|
|
|
|
|
/// <param name="lat"></param>
|
|
|
|
|
|
/// <param name="lon"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private async Task<bool> Iswhitlist(string serial_number, double lat, double lon)
|
2025-04-12 09:46:40 +00:00
|
|
|
|
{
|
2025-04-12 15:17:49 +00:00
|
|
|
|
string key = RedisKeyList.white_list(serial_number);
|
|
|
|
|
|
if (!await _redisService.ExistsAsync(key))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
else
|
2025-04-12 09:46:40 +00:00
|
|
|
|
{
|
2025-04-12 15:17:49 +00:00
|
|
|
|
var entity = await _redisService.GetAsync<Whitelist>(key);
|
|
|
|
|
|
//判断 是否在防区内
|
|
|
|
|
|
if (entity.positionId.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in entity.positionId)
|
|
|
|
|
|
{
|
2025-04-13 05:55:26 +00:00
|
|
|
|
var region = await _redisService.GetAsync<PositionInfo>(RedisKeyList.PositioinRegion(item));
|
|
|
|
|
|
if (region != null)
|
2025-04-12 15:17:49 +00:00
|
|
|
|
{
|
2025-04-13 05:55:26 +00:00
|
|
|
|
region.SetRegionJson();
|
|
|
|
|
|
if (IsPointInGeoJson(lat, lon, region.RegionJson))
|
2025-04-12 15:17:49 +00:00
|
|
|
|
{
|
2025-04-13 05:55:26 +00:00
|
|
|
|
//判断时间是否在区在
|
|
|
|
|
|
if (entity.allDay)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return entity.startTime <= DateTime.Now && DateTime.Now <= entity.endTime;
|
|
|
|
|
|
}
|
2025-04-12 15:17:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-12 09:46:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-03-26 02:47:56 +00:00
|
|
|
|
|
2025-04-12 15:17:49 +00:00
|
|
|
|
static bool IsPointInGeoJson(double latitude, double longitude, string geoJson)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用 NetTopologySuite 解析 GeoJSON
|
|
|
|
|
|
var reader = new GeoJsonReader();
|
|
|
|
|
|
Geometry geometry = reader.Read<Geometry>(geoJson);
|
|
|
|
|
|
// 创建点
|
|
|
|
|
|
var point = new Point(longitude, latitude);
|
|
|
|
|
|
|
|
|
|
|
|
// 判断点是否在几何图形内
|
|
|
|
|
|
return geometry.Contains(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-03-26 02:47:56 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 计算入侵级别
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="positionId"></param>
|
|
|
|
|
|
/// <param name="lon"></param>
|
|
|
|
|
|
/// <param name="lat"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private async Task<int> GetAlarmLevel(long positionId, double lon, double lat)
|
|
|
|
|
|
{
|
|
|
|
|
|
int result = 0;
|
|
|
|
|
|
if (positionId > 0 && lon > 0 && lat > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var key = RedisKeyList.PositioinRegion(positionId);
|
|
|
|
|
|
var geodata = await _redisService.GetAsync<string>(key);
|
2025-03-26 02:54:22 +00:00
|
|
|
|
if (geodata == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
geodata = await _db.CopyNew().Queryable<PositionInfo>()
|
|
|
|
|
|
.Where(s => s.Id == positionId)
|
|
|
|
|
|
.Select(s => s.Region)
|
|
|
|
|
|
.FirstAsync();
|
2025-03-26 07:47:27 +00:00
|
|
|
|
await _redisService.SetAsync<string>(key, geodata);
|
2025-03-26 02:54:22 +00:00
|
|
|
|
}
|
2025-03-26 02:47:56 +00:00
|
|
|
|
WKTReader reader = new WKTReader();
|
|
|
|
|
|
Geometry point = reader.Read($"POINT ({lon} {lat})");
|
2025-03-26 02:54:22 +00:00
|
|
|
|
Geometry multipolygon = reader.Read(geodata);
|
|
|
|
|
|
if (multipolygon.Contains(point))
|
2025-03-26 02:47:56 +00:00
|
|
|
|
{
|
2025-03-26 02:54:22 +00:00
|
|
|
|
return 1;
|
2025-03-26 02:47:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 推送消息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="message"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task PushMessage(object message)
|
|
|
|
|
|
{
|
|
|
|
|
|
//推送前端无人机数据
|
|
|
|
|
|
await _pushService.SendMessageToAll(message);
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置设备在线状态,并更新数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private async Task SetDeviceStataus(RevData input)
|
|
|
|
|
|
{
|
|
|
|
|
|
await _redisService.SetAsync(RedisKeyList.DeviceStatus(input.product_ad_id), true, TimeSpan.FromSeconds(5));
|
|
|
|
|
|
//更新 设备缓存
|
|
|
|
|
|
var key = RedisKeyList.DeviceInfo(input.product_ad_id);
|
|
|
|
|
|
var deviceinfo = await _redisService.GetAsync<DeviceEntity>(key);
|
2025-04-12 09:46:40 +00:00
|
|
|
|
if (deviceinfo != null && deviceinfo.isMove)
|
2025-03-22 12:16:22 +00:00
|
|
|
|
{
|
|
|
|
|
|
deviceinfo.Lat = input.product_lat;
|
|
|
|
|
|
deviceinfo.Lon = input.product_lon;
|
|
|
|
|
|
await _redisService.SetAsync(key, deviceinfo);
|
2025-04-05 10:34:21 +00:00
|
|
|
|
//更新位置
|
|
|
|
|
|
// await _db.Updateable(deviceinfo).ExecuteCommandAsync();
|
2025-04-07 14:38:22 +00:00
|
|
|
|
await _db.CopyNew().Updateable<DeviceEntity>(deviceinfo).UpdateColumns(it => new { it.Lat, it.Lon }).ExecuteCommandAsync();
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private async Task<long> GetBatId(string droneId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var timeSpan = Convert.ToDouble(_config["BatchId"]);
|
|
|
|
|
|
var key = RedisKeyList.BatchIdBysn(droneId);
|
|
|
|
|
|
//从redis取出batchid,如果没有,就新加一个,每次访问都重置一下过期时间来模拟滑动过期
|
|
|
|
|
|
var batchId = await _redisService.GetAsync<long>(key);
|
|
|
|
|
|
if (batchId == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
batchId = SnowFlakeSingle.Instance.NextId();
|
2025-04-04 11:49:50 +00:00
|
|
|
|
await _redisService.DeleteAsync(RedisKeyList.index_data());
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
await _redisService.SetAsync(key, batchId, TimeSpan.FromSeconds(timeSpan));
|
|
|
|
|
|
return batchId;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// //根据batchId获取报警信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="batchId"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<ApiResult> GetByBatchId(long batchId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var items = await _db.Queryable<Alarm>().SplitTable()
|
|
|
|
|
|
.Where(s => s.BatchId == batchId)
|
|
|
|
|
|
.OrderBy(s => s.Id).Select(s => new
|
|
|
|
|
|
{
|
|
|
|
|
|
Lon = s.drone_lon,
|
|
|
|
|
|
Lat = s.drone_lat,
|
|
|
|
|
|
Alt = s.height,
|
2025-03-31 13:44:50 +00:00
|
|
|
|
s.app_lat,
|
|
|
|
|
|
s.app_lon,
|
2025-03-22 12:16:22 +00:00
|
|
|
|
s.CreateTime,
|
|
|
|
|
|
AlarmLevel = s.alarmLevel,
|
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
return new ApiResult() { data = items };
|
|
|
|
|
|
}
|
2025-03-27 16:34:20 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 首页统计
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<Dictionary<string, int>> IndexCount()
|
|
|
|
|
|
{
|
|
|
|
|
|
Dictionary<string, int> result = new Dictionary<string, int>();
|
|
|
|
|
|
// 获取当前日期和时间
|
|
|
|
|
|
DateTime currentDate = DateTime.Now;
|
|
|
|
|
|
// 获取当天的开始时间
|
|
|
|
|
|
DateTime startDate = currentDate.Date;
|
|
|
|
|
|
// 获取当天的结束时间(23:59:59)
|
|
|
|
|
|
DateTime endDate = currentDate.Date.AddDays(1).AddTicks(-1);
|
|
|
|
|
|
//计算当天
|
|
|
|
|
|
var todaywaring = await _db.Queryable<Alarm>().SplitTable()
|
2025-04-12 09:46:40 +00:00
|
|
|
|
.Where(s => s.alarmLevel > 0 && s.IsWhitelist == false)
|
2025-03-27 16:34:20 +00:00
|
|
|
|
.Where(s => s.CreateTime >= startDate && s.CreateTime <= endDate)
|
|
|
|
|
|
.GroupBy(s => s.BatchId)
|
|
|
|
|
|
.Select(s => s.BatchId).CountAsync();
|
|
|
|
|
|
//计算当天处理次数
|
|
|
|
|
|
//var todayhandle = _db.Queryable<AttackEntity>()
|
|
|
|
|
|
// .Where(s => s.BatchId > 0)
|
|
|
|
|
|
// .Where(s => s.CreateTime >= startDate && s.CreateTime <= endDate);
|
|
|
|
|
|
//计算总数
|
|
|
|
|
|
var totalcount = _db.Queryable<Alarm>().SplitTable()
|
2025-04-12 09:46:40 +00:00
|
|
|
|
.Where(s => s.alarmLevel > 0 && s.IsWhitelist == false)
|
2025-03-27 16:34:20 +00:00
|
|
|
|
.GroupBy(s => s.BatchId)
|
|
|
|
|
|
.Select(s => s.BatchId);
|
|
|
|
|
|
//计算处理总数
|
|
|
|
|
|
//var totalhandle = _db.Queryable<AttackEntity>()
|
|
|
|
|
|
// .Where(x => x.BatchId > 0);
|
|
|
|
|
|
//组合查询结果
|
|
|
|
|
|
//return new
|
|
|
|
|
|
//{
|
|
|
|
|
|
// todaywaring = await todaywaring.CountAsync(),
|
|
|
|
|
|
// todayhandle =0,
|
|
|
|
|
|
// totalcount = await totalcount.CountAsync(),
|
|
|
|
|
|
// totalhandle = 0
|
|
|
|
|
|
//};
|
|
|
|
|
|
result.Add("todaywaring", todaywaring);
|
|
|
|
|
|
result.Add("todayhandle", 0);
|
|
|
|
|
|
result.Add("totalcount", await totalcount.CountAsync());
|
|
|
|
|
|
result.Add("totalhandle", 0);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2025-03-22 12:16:22 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 分页
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<ApiResult> GetPage(AlarmReq input)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = await CreatePage(input);
|
|
|
|
|
|
return new ApiResult()
|
|
|
|
|
|
{
|
|
|
|
|
|
code = 0,
|
|
|
|
|
|
data = new
|
|
|
|
|
|
{
|
|
|
|
|
|
total = result.Item1,
|
|
|
|
|
|
items = result.Item2
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 热力图
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<ApiResult> hotmap()
|
|
|
|
|
|
{
|
|
|
|
|
|
var query = await _db.Queryable<Alarm>().SplitTable()
|
|
|
|
|
|
.GroupBy(x => new { Lon = SqlFunc.Round(x.drone_lon, 4), Lat = SqlFunc.Round(x.drone_lat, 4) }) // 按经纬度分组
|
|
|
|
|
|
.Select(x => new
|
|
|
|
|
|
{
|
|
|
|
|
|
Lon = SqlFunc.Round(x.drone_lon, 4),
|
|
|
|
|
|
Lat = SqlFunc.Round(x.drone_lat, 4),
|
|
|
|
|
|
Count = SqlFunc.AggregateCount(x.BatchId), // 统计去重后的BatchId
|
|
|
|
|
|
})
|
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
return new ApiResult() { data = query };
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<Tuple<int, List<AlarmRepDto>>> CreatePage(AlarmReq input)
|
|
|
|
|
|
{
|
|
|
|
|
|
RefAsync<int> total = 0;
|
|
|
|
|
|
var items = await _db.Queryable<Alarm>().SplitTable()
|
|
|
|
|
|
.WhereIF(input.Frequency.HasValue, st => st.freq == input.Frequency.Value)
|
|
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.sn), s => s.serial_number.Contains(input.sn))
|
|
|
|
|
|
.WhereIF(!string.IsNullOrEmpty(input.model), st => st.device_type == input.model)
|
|
|
|
|
|
.WhereIF(input.strartDate.HasValue, st => st.CreateTime >= input.strartDate.Value)
|
|
|
|
|
|
.WhereIF(input.endDate.HasValue, st => st.CreateTime <= input.endDate.Value.AddDays(1))
|
|
|
|
|
|
.OrderBy(s => s.BatchId, OrderByType.Desc)
|
2025-03-31 13:44:50 +00:00
|
|
|
|
.GroupBy(s => new { s.BatchId, s.serial_number, s.device_type, s.positionId, s.PostionName, s.freq })
|
2025-03-22 12:16:22 +00:00
|
|
|
|
.Select(st => new AlarmRepDto
|
|
|
|
|
|
{
|
|
|
|
|
|
batchId = st.BatchId.ToString(),
|
|
|
|
|
|
startTime = SqlFunc.AggregateMin(st.CreateTime),
|
|
|
|
|
|
endTime = SqlFunc.AggregateMax(st.CreateTime),
|
|
|
|
|
|
sn = st.serial_number,
|
2025-03-29 02:10:01 +00:00
|
|
|
|
Frequency = st.freq,
|
2025-03-22 12:16:22 +00:00
|
|
|
|
duration = (SqlFunc.AggregateMax(st.CreateTime) - SqlFunc.AggregateMin(st.CreateTime)).TotalSeconds,
|
|
|
|
|
|
model = st.device_type,
|
|
|
|
|
|
positionId = st.positionId,
|
|
|
|
|
|
positionName = st.PostionName
|
|
|
|
|
|
}).MergeTable()//合并查询
|
|
|
|
|
|
.ToPageListAsync(input.pageNum, input.pageSize, total);
|
|
|
|
|
|
return Tuple.Create(total.Value, items);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-13 05:55:26 +00:00
|
|
|
|
|
2025-03-22 12:16:22 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 报表统计
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<ApiResult> GetReport(DateTime? start, DateTime? end)
|
|
|
|
|
|
{
|
|
|
|
|
|
start = start.HasValue ? start.Value : DateTime.Now.AddMonths(-1);
|
|
|
|
|
|
end = end.HasValue ? end.Value.AddDays(1) : DateTime.Now.Date.AddDays(1);
|
|
|
|
|
|
var query = await _db.Queryable<Alarm>().SplitTable()
|
2025-03-30 23:38:50 +00:00
|
|
|
|
.Where(s => s.alarmLevel > 0)
|
2025-03-22 12:16:22 +00:00
|
|
|
|
.WhereIF(start.HasValue, st => st.CreateTime >= start.Value)
|
|
|
|
|
|
.WhereIF(end.HasValue, st => st.CreateTime <= end.Value.AddDays(1))
|
|
|
|
|
|
.GroupBy(s => new { s.BatchId, s.serial_number, s.device_type, s.positionId, s.PostionName, s.DeviceId, s.DeviceName })
|
|
|
|
|
|
.Select(st => new
|
|
|
|
|
|
{
|
|
|
|
|
|
batchId = st.BatchId,
|
|
|
|
|
|
startTime = SqlFunc.AggregateMin(st.CreateTime),
|
|
|
|
|
|
endTime = SqlFunc.AggregateMax(st.CreateTime),
|
|
|
|
|
|
sn = st.serial_number,
|
|
|
|
|
|
Frequency = SqlFunc.AggregateMax(st.freq),
|
|
|
|
|
|
duration = (SqlFunc.AggregateMax(st.CreateTime) - SqlFunc.AggregateMin(st.CreateTime)).TotalSeconds,
|
|
|
|
|
|
model = st.device_type,
|
|
|
|
|
|
positionName = st.PostionName,
|
|
|
|
|
|
deviceId = st.DeviceId,
|
|
|
|
|
|
deviceName = st.DeviceName
|
|
|
|
|
|
}).MergeTable()//合并查询
|
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
return new ApiResult()
|
|
|
|
|
|
{
|
|
|
|
|
|
data = new
|
|
|
|
|
|
{
|
|
|
|
|
|
freq = query.GroupBy(s => new { freq = FreqConvert.CoverFreq(s.Frequency) })
|
|
|
|
|
|
.Select(b => new
|
|
|
|
|
|
{
|
|
|
|
|
|
b.Key.freq,
|
|
|
|
|
|
count = b.Count()
|
|
|
|
|
|
}),
|
|
|
|
|
|
model = query.GroupBy(s => new { s.model })
|
|
|
|
|
|
.Select(b => new
|
|
|
|
|
|
{
|
|
|
|
|
|
b.Key.model,
|
|
|
|
|
|
count = b.Count()
|
|
|
|
|
|
}),
|
|
|
|
|
|
position = query.GroupBy(s => new { s.positionName })
|
|
|
|
|
|
.Select(s => new
|
|
|
|
|
|
{
|
|
|
|
|
|
s.Key.positionName,
|
|
|
|
|
|
count = s.Count()
|
|
|
|
|
|
}),
|
2025-03-30 23:38:50 +00:00
|
|
|
|
time = query.GroupBy(s => s.startTime.ToString("HH"))
|
|
|
|
|
|
.Select(it => new
|
|
|
|
|
|
{
|
|
|
|
|
|
it.Key,
|
|
|
|
|
|
count = it.Count()
|
|
|
|
|
|
}),
|
|
|
|
|
|
date = query.GroupBy(s => s.startTime.ToString("yyyy-MM-dd"))
|
|
|
|
|
|
.Select(it => new
|
|
|
|
|
|
{
|
|
|
|
|
|
it.Key,
|
|
|
|
|
|
count = it.Count()
|
|
|
|
|
|
}),
|
2025-03-22 12:16:22 +00:00
|
|
|
|
device = query.GroupBy(s => new { s.deviceName })
|
2025-03-30 23:38:50 +00:00
|
|
|
|
.Select(b => new
|
2025-03-22 12:16:22 +00:00
|
|
|
|
{
|
2025-03-30 23:38:50 +00:00
|
|
|
|
b.Key.deviceName,
|
|
|
|
|
|
count = b.Count()
|
|
|
|
|
|
})
|
2025-03-22 12:16:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 热力图,取经纬度4位数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="batchIds"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private async Task<object> GenerateHotMap(List<long> batchIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
return await _db.Queryable<Alarm>().SplitTable()
|
|
|
|
|
|
.Where(s => s.drone_lat > 0 && s.drone_lon > 0 && batchIds.Contains(s.BatchId))
|
|
|
|
|
|
.Select(s => new
|
|
|
|
|
|
{
|
|
|
|
|
|
drone_lon = SqlFunc.Round(s.drone_lon, 4),
|
|
|
|
|
|
drone_lat = SqlFunc.Round(s.drone_lat, 4),
|
|
|
|
|
|
})
|
|
|
|
|
|
.GroupBy(s => new { s.drone_lat, s.drone_lon })
|
|
|
|
|
|
.Select(s => new
|
|
|
|
|
|
{
|
|
|
|
|
|
Key = new { Lon = SqlFunc.Round(s.drone_lat, 4), Lat = SqlFunc.Round(s.drone_lon, 4) },
|
|
|
|
|
|
val = SqlFunc.AggregateCount(s)
|
|
|
|
|
|
})
|
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|