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>, IEventHander>, IEventHander>, IEventHander>, IEventHander>, IEventHander>, IEventHander>, IEventHander>, IEventHander> { private readonly IRepository _statisticRepo; private readonly IRepository _buildingRepo; private readonly IRepository _gatewayRepo; private readonly IRepository _deviceRepo; private readonly IRepository _dataRepo; public UpateStatisticEventHandler(IRepository statisticRepo, IRepository buildingRepo, IRepository deviceRepo, IRepository gatewayRepo, IRepository dataRepo) { this._statisticRepo = statisticRepo; this._buildingRepo = buildingRepo; this._gatewayRepo = gatewayRepo; this._deviceRepo = deviceRepo; this._dataRepo = dataRepo; } public void Handle(EntityDeleted 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 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 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 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 message) { IoTDataEventHandle(message); } public void Handle(EntityUpdated message) { IoTDataEventHandle(message); } public void Handle(EntityDeleted message) { IoTDataEventHandle(message); } public void Handle(EntityInserted message) { this.Update(message); } public void Handle(EntityDeleted message) { this.Update(message); } private void Update(BaseEvent 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 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() .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(); } } }