ChangShaBoardController.cs 8.18 KB
using HHECS.BllModel;
using HHECS.DAQServer.DataFlag;
using HHECS.DAQServer.Dto.ChangShaBoard;
using HHECS.DAQShared.Common.Enums;
using HHECS.DAQShared.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;

namespace HHECS.DAQServer.Controllers
{
    /// <summary>
    /// 长沙仓库看板接口
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class ChangShaBoardController : ControllerBase
    {
        private readonly IFreeSql<IOTCloundFlag> _iotCloundFreeSql;
        private readonly IDistributedCache _cache;

        public ChangShaBoardController(IFreeSql<IOTCloundFlag> iotCloundFreeSql, IDistributedCache cache)
        {
            _iotCloundFreeSql = iotCloundFreeSql;
            _cache = cache;
        }

        /// <summary>
        /// 获取堆垛机设备看板信息
        /// </summary>
        /// <param name="projectCode"></param>
        /// <param name="factoryCode"></param>
        /// <returns></returns>
        [HttpGet]
        public BllResult<SRMInfoBoardDto> GetSRMInfo(string projectCode, string factoryCode)
        {
            try
            {
                var cacheKey = $"{nameof(ChangShaBoardController)}_{nameof(GetSRMInfo)}_{projectCode}_{factoryCode}";
                var cacheValue = _cache.Get(cacheKey);
                if (cacheValue != null)
                {
                    var cacheData = JsonSerializer.Deserialize<SRMInfoBoardDto>(cacheValue);
                    return BllResultFactory.Success(cacheData);
                }

                using var equipmentRepository = _iotCloundFreeSql.GetRepository<Equipment>();
                using var equipmentTypeRepository = _iotCloundFreeSql.GetRepository<EquipmentType>();
                using var equipmentAlarmRecordRepository = _iotCloundFreeSql.GetRepository<EquipmentAlarmRecord>();
                using var equipmentStatusRecordRepository = _iotCloundFreeSql.GetRepository<EquipmentStatusRecord>();
                using var equipmentStatusRecordHistoryRepository = _iotCloundFreeSql.GetRepository<EquipmentStatusRecordHistory>();
                var srmTypes = new List<EquipmentTypeConst>
                {
                    EquipmentTypeConst.SingleForkSRM,
                    EquipmentTypeConst.SingleForkSRMV2,
                    EquipmentTypeConst.DoubleForkSRM,
                    EquipmentTypeConst.DoubleForkSRMV2,
                }.Select(x => x.ToString()).ToList();
                var equipmetTypeIds = equipmentTypeRepository.Where(x => srmTypes.Contains(x.Code)).ToList(x => x.Id);
                var equipments = equipmentRepository.Where(x => equipmetTypeIds.Contains(x.EquipmentTypeId) && x.ProjectCode == projectCode && x.FactoryCode == factoryCode).ToList();
                var equipmentCodes = equipments.Select(x => x.Code).ToList();

                //近7天的设备统计数据
                var efficiency = equipments.Select(equipment =>
                {
                    var startTime = DateTime.Today.AddDays(-7);
                    var records = equipmentStatusRecordHistoryRepository.Where(x => x.EquipmentCode == equipment.Code && x.CreateTime >= startTime).ToList();
                    var runTicks = records.Where(x => x.Status == EquipmentStatus.Running.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var freeTicks = records.Where(x => x.Status == EquipmentStatus.Free.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var failureTicks = records.Where(x => x.Status == EquipmentStatus.Failure.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var offLineTicks = DateTime.Now.Ticks - records.Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var totalTicks = runTicks + freeTicks + failureTicks + offLineTicks;
                    var failureCount = records.Where(x => x.Status == EquipmentStatus.Failure.ToString()).Count();

                    var workTicks = TimeSpan.FromHours(8).Ticks;
                    var availability = (runTicks + freeTicks) / (double)workTicks;
                    if (availability >= 1)
                    {
                        workTicks = runTicks + freeTicks + failureTicks;
                        availability = (runTicks + freeTicks) / (double)workTicks;
                    }

                    var work2Ticks = runTicks + freeTicks + failureTicks;
                    return new SRMEfficiencyDto
                    {
                        SRMCode = equipment.Code,
                        SRMName = equipment.Name,
                        OEE = work2Ticks == 0 ? 0 : Math.Round((double)runTicks / work2Ticks, 3),
                        MTBF = failureCount == 0 ? 0 : Math.Round(TimeSpan.FromTicks(runTicks + freeTicks).TotalHours / failureCount, 1),
                        MTTR = failureCount == 0 ? 0 : Math.Round(TimeSpan.FromTicks(failureTicks).TotalHours / failureCount, 3),
                        Availability = Math.Round((double)availability, 3),
                    };
                }).ToList();

                //今日设备状态
                var status = equipments.Select(equipment =>
                {
                    var statusRecord = equipmentStatusRecordRepository.Where(x => x.EquipmentCode == equipment.Code && x.CreateTime >= DateTime.Today).OrderByDescending(y => y.CreateTime).First(x => x.Status);
                    var currentStatus = EquipmentStatus.Offline;
                    if (Enum.TryParse<EquipmentStatus>(statusRecord, true, out var statusEnum))
                    {
                        currentStatus = statusEnum;
                    }
                    var records = equipmentStatusRecordHistoryRepository.Where(x => x.EquipmentCode == equipment.Code && x.CreateTime >= DateTime.Today).ToList();
                    var runTicks = records.Where(x => x.Status == EquipmentStatus.Running.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var freeTicks = records.Where(x => x.Status == EquipmentStatus.Free.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var failureTicks = records.Where(x => x.Status == EquipmentStatus.Failure.ToString()).Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    var offLineTicks = (DateTime.Now.Ticks - DateTime.Today.Ticks) - records.Sum(x => (x.UpdateTime - x.CreateTime).Ticks);
                    double totalTicks = runTicks + freeTicks + failureTicks + offLineTicks;
                    return new SRMStatusDto
                    {
                        Code = equipment.Code,
                        Name = equipment.Name,
                        CurrentStatus = EquipmentStatus.Offline.ToString(),
                        Run = Math.Round(runTicks / totalTicks, 3),
                        Free = Math.Round(freeTicks / totalTicks, 3),
                        Alarm = Math.Round(failureTicks / totalTicks, 3),
                        Offline = Math.Round(offLineTicks / totalTicks, 3),
                    };
                }).ToList();

                //实时报警
                var alarms = equipmentAlarmRecordRepository.Where(x => equipmentCodes.Contains(x.EquipmentCode) && x.CreateTime >= DateTime.Today && !x.IsEnd).OrderByDescending(x => x.CreateTime).Take(50).ToList(x => new SRMAlarmDto
                {
                    SRMCode = x.EquipmentCode,
                    SRMName = x.EquipmentName,
                    Alarm = x.AlarmMessage,
                    CreateTime = x.CreateTime.ToString(),
                    UpdateTime = x.UpdateTime.ToString(),
                }).ToList();

                var data = new SRMInfoBoardDto
                {
                    Efficiency = efficiency,
                    Status = status,
                    Alarms = alarms
                };
                _cache.Set(cacheKey, JsonSerializer.SerializeToUtf8Bytes(data), new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(5)
                });
                return BllResultFactory.Success(data);
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error<SRMInfoBoardDto>(ex.Message);
            }
        }
    }
}