ly/Service/AlarmService.cs

278 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
using SqlSugar;
using StackExchange.Redis;
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);
if (input.data.Any())
{
var key = RedisKeyList.DeviceInfo(input.product_ad_id);
var deviceinfo = await _redisService.GetAsync<DeviceEntity>(key);
if (deviceinfo == null)
{
deviceinfo = await _db.CopyNew().Queryable<DeviceEntity>().Where(s => s.DeviceSN == input.product_ad_id).FirstAsync();
if (deviceinfo == null)
{
return new ApiResult() { code = 1, msg = "设备不存在" };
}
await _redisService.SetAsync(key, deviceinfo, TimeSpan.FromDays(1));
}
var entity = input.data.Adapt<List<Alarm>>();
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;
}
await _db.CopyNew().Insertable(entity).SplitTable().ExecuteReturnSnowflakeIdListAsync();
//推送报警信息
await _pushService.SendMessageToAll(new { msgType = "event", data = entity });
}
return new ApiResult();
}
/// <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);
if (deviceinfo == null)
{
deviceinfo.Lat = input.product_lat;
deviceinfo.Lon = input.product_lon;
await _redisService.SetAsync(key, deviceinfo);
}
}
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();
}
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,
s.CreateTime,
AlarmLevel = s.alarmLevel,
}).ToListAsync();
return new ApiResult() { data = items };
}
/// <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)
.GroupBy(s => new { s.BatchId, s.serial_number, s.device_type, s.positionId, s.PostionName })
.Select(st => new AlarmRepDto
{
batchId = st.BatchId.ToString(),
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,
positionId = st.positionId,
positionName = st.PostionName
}).MergeTable()//合并查询
.ToPageListAsync(input.pageNum, input.pageSize, total);
return Tuple.Create(total.Value, items);
}
/// <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()
.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()
}),
hotmap = await GenerateHotMap(query.Select(s => s.batchId).ToList()),
device = query.GroupBy(s => new { s.deviceName })
.Select(s => new
{
s.Key.deviceName,
count = s.Count()
}),
date = query.GroupBy(s => s.startTime.ToString("yyyy-MM-dd"))
.Select(it => new { it.Key, count = it.Count() })
}
};
}
/// <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();
}
}
}