You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iot/projects/Platform/EventHandlers/UpateStatisticEventHandler.cs

302 lines
12 KiB

using Application.Domain.Entities;
using Infrastructure.Data;
using Infrastructure.Events;
using Infrastructure.Extensions;
using IoT.Shared.Application.Models;
using Polly;
using System;
using System.Linq;
namespace Platform.EventHandlers
{
public class UpateStatisticEventHandler :
IEventHander<EntityDeleted<Organ>>,
IEventHander<EntityDeleted<Building>>,
IEventHander<EntityUpdated<IoTGateway>>,
IEventHander<EntityDeleted<IoTGateway>>,
IEventHander<EntityInserted<IoTData>>,
IEventHander<EntityUpdated<IoTData>>,
IEventHander<EntityDeleted<IoTData>>,
IEventHander<EntityInserted<IoTDevice>>,
IEventHander<EntityDeleted<IoTDevice>>
{
private readonly IRepository<Statistic> _statisticRepo;
private readonly IRepository<Building> _buildingRepo;
private readonly IRepository<IoTGateway> _gatewayRepo;
private readonly IRepository<IoTDevice> _deviceRepo;
private readonly IRepository<IoTData> _dataRepo;
public UpateStatisticEventHandler(IRepository<Statistic> statisticRepo,
IRepository<Building> buildingRepo,
IRepository<IoTDevice> deviceRepo,
IRepository<IoTGateway> gatewayRepo,
IRepository<IoTData> dataRepo)
{
this._statisticRepo = statisticRepo;
this._buildingRepo = buildingRepo;
this._gatewayRepo = gatewayRepo;
this._deviceRepo = deviceRepo;
this._dataRepo = dataRepo;
}
public void Handle(EntityDeleted<Organ> message)
{
//删除统计表中该机构相关的数据
var prefix = $"[{message.Data.Id}]";
var list = this._statisticRepo.Table()
.Where(o => o.Key.StartsWith(prefix))
.ToList();
foreach (var entity in list)
{
this._statisticRepo.Delete(entity);
}
this._statisticRepo.SaveChanges();
}
public void Handle(EntityDeleted<Building> message)
{
//删除统计表中该建筑相关内容
var prefix = $"[{message.Data.OrganId}][{message.Data.Id}]";
var list = this._statisticRepo.Table().Where(o => o.Key.StartsWith(prefix)).ToList();
foreach (var item in list)
{
this._statisticRepo.Delete(item);
}
this._statisticRepo.SaveChanges();
//更新机构信息
var organId = message.Data.OrganId;
this.UpdateOrganData(organId);
}
public void Handle(EntityUpdated<IoTGateway> message)
{
var buildingId1 = message.Data.BuildingId;
var buildingId2 = message.OriginalEntity.BuildingId;
if (buildingId1.HasValue)
{
if (buildingId2.HasValue)
{
if (buildingId1.Value != buildingId2.Value)
{
this.UpdateByBuilding(buildingId1.Value);
this.UpdateByBuilding(buildingId2.Value);
}
}
else
{
this.UpdateByBuilding(buildingId1.Value);
}
}
else
{
if (buildingId2.HasValue)
{
this.UpdateByBuilding(buildingId2.Value);
}
}
}
public void Handle(EntityDeleted<IoTGateway> message)
{
if (message.Data.BuildingId.HasValue)
{
this.UpdateByBuilding(message.Data.BuildingId.Value);
}
}
private void UpdateByBuilding(Guid buildingId)
{
var organId = this.GetOrganId(buildingId);
this.UpdateOrganData(organId);
this.UpdateBuildingData(organId, buildingId);
}
private void UpdateOrganData(Guid organId)
{
//设备数量
var deviceCount = this._deviceRepo.ReadOnlyTable()
.Where(o => o.IoTGateway.BuildingId.HasValue)
.Where(o => o.IoTGateway.Building.OrganId == organId).Count();
UpdateValue($"[{organId}]", "DeviceCount", deviceCount, StatisticType.Int);
//最大最小值
UpdateOrganDataValue(organId, DataKeys.Light.GetName(), StatisticType.Int);
UpdateOrganDataValue(organId, DataKeys.Temperature.GetName(), StatisticType.Double);
UpdateOrganDataValue(organId, DataKeys.Humidity.GetName(), StatisticType.Double);
//用电器
UpdateOrganPowerState(organId);
}
private void UpdateOrganPowerState(Guid organId)
{
var key = DataKeys.PowerState.GetName();
var query = this._dataRepo.ReadOnlyTable()
.Where(o => o.IoTDevice.IoTGateway.BuildingId.HasValue)
.Where(o => o.IoTDevice.IoTGateway.Building.OrganId == organId)
.Where(o => o.Key == key);
var total = query.Count();
var close = query.Count(o => o.IntValue == 0);
var open = total - close;
UpdateValue($"[{organId}]", "DeviceOpenCount", open, StatisticType.Int);
UpdateValue($"[{organId}]", "DeviceCloseCount", close, StatisticType.Int);
}
public void UpdateBuildingData(Guid organId, Guid buildingId)
{
//设备数量
var prefix = $"[{organId}][{buildingId}]";
var intValue = this._deviceRepo.ReadOnlyTable().Where(o => o.IoTGateway.BuildingId == buildingId).Count();
UpdateValue(prefix, "DeviceCount", intValue, StatisticType.Int);
//最大最小值
UpdateBuildingDataValue(organId, buildingId, DataKeys.Light.GetName(), StatisticType.Int);
UpdateBuildingDataValue(organId, buildingId, DataKeys.Temperature.GetName(), StatisticType.Double);
UpdateBuildingDataValue(organId, buildingId, DataKeys.Humidity.GetName(), StatisticType.Double);
//用电器
UpdateBuildingPowerState(organId, buildingId);
}
private void UpdateBuildingPowerState(Guid organId, Guid buildingId)
{
var key = DataKeys.PowerState.GetName();
var query = this._dataRepo.ReadOnlyTable()
.Where(o => o.IoTDevice.IoTGateway.BuildingId == buildingId)
.Where(o => o.Key == key);
var total = query.Count();
var close = query.Count(o => o.IntValue == 0);
var open = total - close;
UpdateValue($"[{organId}][{buildingId}]", "DeviceOpenCount", open, StatisticType.Int);
UpdateValue($"[{organId}][{buildingId}]", "DeviceCloseCount", close, StatisticType.Int);
}
private void UpdateOrganDataValue(Guid organId, string key, StatisticType type)
{
var query = this._dataRepo.ReadOnlyTable()
.Where(o => o.IoTDevice.IoTGateway.BuildingId.HasValue)
.Where(o => o.IoTDevice.IoTGateway.Building.OrganId == organId)
.Where(o => o.Key == key);
UpdateValue($"[{organId}]", $"Max{key}", type == StatisticType.Int ? query.Max(o => o.IntValue) : query.Max(o => o.DoubleValue), type);
UpdateValue($"[{organId}]", $"Min{key}", type == StatisticType.Int ? query.Min(o => o.IntValue) : query.Min(o => o.DoubleValue), type);
}
private void UpdateBuildingDataValue(Guid organId, Guid buildingId, string key, StatisticType type)
{
var query = this._dataRepo.ReadOnlyTable()
.Where(o => o.IoTDevice.IoTGateway.BuildingId == buildingId)
.Where(o => o.Key == key);
UpdateValue($"[{organId}][{buildingId}]", $"Max{key}", type == StatisticType.Int ? query.Max(o => o.IntValue) : query.Max(o => o.DoubleValue), type);
UpdateValue($"[{organId}][{buildingId}]", $"Min{key}", type == StatisticType.Int ? query.Min(o => o.IntValue) : query.Min(o => o.DoubleValue), type);
}
public void Handle(EntityInserted<IoTData> message)
{
IoTDataEventHandle(message);
}
public void Handle(EntityUpdated<IoTData> message)
{
IoTDataEventHandle(message);
}
public void Handle(EntityDeleted<IoTData> message)
{
IoTDataEventHandle(message);
}
public void Handle(EntityInserted<IoTDevice> message)
{
this.Update(message);
}
public void Handle(EntityDeleted<IoTDevice> message)
{
this.Update(message);
}
private void Update(BaseEvent<IoTDevice> message)
{
var gatewayId = message.Data.IoTGatewayId;
var buildingId = this._gatewayRepo.ReadOnlyTable()
.Where(o => o.Id == gatewayId)
.Select(o => o.BuildingId)
.FirstOrDefault();
if (buildingId.HasValue)
{
UpdateByBuilding(buildingId.Value);
}
}
private void IoTDataEventHandle(BaseEvent<IoTData> message)
{
if (message.Data.Key == DataKeys.Light.GetName() ||
message.Data.Key == DataKeys.Temperature.GetName() ||
message.Data.Key == DataKeys.Humidity.GetName() ||
message.Data.Key == DataKeys.PowerState.GetName())
{
var deviceId = message.Data.IoTDeviceId;
var buildingId = this._deviceRepo.ReadOnlyTable()
.Where(o => o.Id == deviceId)
.Where(o => o.IoTGateway.BuildingId.HasValue)
.Select(o => o.IoTGateway.BuildingId)
.FirstOrDefault();
if (buildingId != null)
{
var organId = this.GetOrganId(buildingId.Value);
if (message.Data.Key == DataKeys.Light.GetName())
{
UpdateOrganDataValue(organId, DataKeys.Light.GetName(), StatisticType.Int);
UpdateBuildingDataValue(organId, buildingId.Value, DataKeys.Light.GetName(), StatisticType.Int);
}
else if(message.Data.Key == DataKeys.Temperature.GetName())
{
UpdateOrganDataValue(organId, DataKeys.Temperature.GetName(), StatisticType.Double);
UpdateBuildingDataValue(organId, buildingId.Value, DataKeys.Temperature.GetName(), StatisticType.Double);
}
else if(message.Data.Key == DataKeys.Humidity.GetName())
{
UpdateOrganDataValue(organId, DataKeys.Humidity.GetName(), StatisticType.Double);
UpdateBuildingDataValue(organId, buildingId.Value, DataKeys.Humidity.GetName(), StatisticType.Double);
}
else if(message.Data.Key == DataKeys.PowerState.GetName())
{
UpdateOrganPowerState(organId);
UpdateBuildingPowerState(organId, buildingId.Value);
}
}
}
}
private void UpdateValue(string prefix, string name, object value, StatisticType type)
{
void Exec()
{
var key = $"{prefix}{name}";
var entity = this._statisticRepo.Table().FirstOrDefault(o => o.Key == key);
if (entity == null)
{
entity = new Statistic
{
Type = type,
Key = key
};
this._statisticRepo.Add(entity);
}
entity.SetValue(value);
this._statisticRepo.SaveChanges();
}
Policy.Handle<Exception>()
.Retry(3,(e,i)=> {
e.PrintStack($"retry {i}:{e.Message??e.InnerException?.Message}");
})
.Execute(() => Exec());
}
private Guid GetOrganId(Guid buildingId)
{
return this._buildingRepo.ReadOnlyTable()
.Where(o => o.Id == buildingId)
.Select(o => o.OrganId)
.FirstOrDefault();
}
}
}