DigitalTwinController.cs 4.39 KB
using HHECS.BllModel;
using HHECS.DAQServer.DataAccess;
using HHECS.DAQServer.Dto.DigitalTwin;
using HHECS.DAQServer.Dto.Equipment;
using HHECS.EquipmentModel;
using LinqKit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using System.Text;
using System.Text.Json;

namespace HHECS.DAQServer.Controllers
{
    /// <summary>
    /// 数字孪生接口
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class DigitalTwinController : ControllerBase
    {
        private readonly DataContext _context;
        private readonly IDistributedCache _cache;

        public DigitalTwinController(DataContext dataContext, IDistributedCache cache)
        {
            _context = dataContext;
            _cache = cache;
        }

        /// <summary>
        /// 获取设备实时数据
        /// </summary>
        /// <param name="projectCode">项目编号</param>
        /// <param name="area">区域</param>
        /// <param name="equipmentTypeCode">设备类型</param>
        /// <returns></returns>
        [HttpGet("{projectCode}")]
        public async Task<BllResult<List<EquipmentInfoResponseDto>>> GetEquipmentInfo(string projectCode, string area = null, string equipmentTypeCode = null)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(projectCode))
                {
                    return BllResultFactory.Error<List<EquipmentInfoResponseDto>>($"{nameof(projectCode)}不能为空!");
                }

                var filter = PredicateBuilder.New<Equipment>(true);
                if (!string.IsNullOrWhiteSpace(projectCode))
                {
                    if (string.IsNullOrWhiteSpace(area))
                    {
                        filter = filter.And(x => x.Code.StartsWith($"{projectCode}-"));
                    }
                    else
                    {
                        filter = filter.And(x => x.Code.StartsWith($"{projectCode}-{area}-"));
                    }
                }

                if (!string.IsNullOrWhiteSpace(equipmentTypeCode))
                {
                    filter = filter.And(x => x.EquipmentType.Code == equipmentTypeCode);
                }

                var equipmentData = _context.Equipment.Where(filter).WithLock(SqlServerLock.NoLock).Include(x => x.EquipmentType).ToList(x => new EquipmentInfoResponseDto
                {
                    EquipmentCode = x.Code,
                    EquipmentName = x.Name,
                    Remark = x.ConnectName,
                    EquipmentTypeCode = x.EquipmentType.Code,
                    EquipmentTypeName = x.EquipmentType.Name,
                    EquipmentProps = _context.EquipmentProp.Where(p => p.EquipmentId == x.Id).ToList(p => new EquipmentPropDto
                    {
                        EquipmentPropCode = p.EquipmentTypePropTemplateCode,
                        EquipmentPropName = p.Remark,
                        DataAddress = p.Address,
                        Value = p.Value,
                        DataSourceTime = p.Updated,
                    })
                });

                //从缓存取值
                foreach (var item in equipmentData)
                {
                    var cacheDataBytes = await _cache.GetAsync(item.EquipmentCode);
                    if (cacheDataBytes == null)
                    {
                        continue;
                    }
                    var cacheData = JsonSerializer.Deserialize<EquipmentDataDto>(Encoding.Default.GetString(cacheDataBytes));
                    var cacheDataSourceTime = DateTimeOffset.FromUnixTimeSeconds(cacheData.Timestamp).LocalDateTime;
                    foreach (var tagItem in cacheData.Reported)
                    {
                        var propItem = item.EquipmentProps.Where(x => x.DataAddress == tagItem.Tag).FirstOrDefault();
                        if (propItem != null && cacheDataSourceTime >= propItem.DataSourceTime)
                        {
                            propItem.Value = tagItem.Value;
                            propItem.DataSourceTime = cacheDataSourceTime;
                        }
                    }
                }

                return BllResultFactory.Success(equipmentData);
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error<List<EquipmentInfoResponseDto>>(ex.Message);
            }
        }
    }
}