EquipmentStatusService.cs 6.68 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CNCFanucDataReading
{
    public class EquipmentStatusService : IDisposable
    {
        private readonly IFreeSql _fsql;
        private bool _disposed = false;

        public EquipmentStatusService(string connectionString)
        {
            if (string.IsNullOrEmpty(connectionString))
                throw new ArgumentException("数据库连接字符串不能为空", nameof(connectionString));

            _fsql = new FreeSql.FreeSqlBuilder()
                .UseConnectionString(FreeSql.DataType.SqlServer, connectionString)
                .UseAutoSyncStructure(false) // 自动同步实体结构到数据库
                .Build();

        }

        /// <summary>
        /// 更新或创建设备状态
        /// 1. 如果表内没有该设备的数据则创建
        /// 2. 如果设备状态没有变更则修改UpdateTime和StatusDuration
        /// 3. 如果设备状态发生变更,则往历史表插入一条数据
        /// </summary>
        public async Task<bool> UpsertEquipmentStatusAsync(BaseEquipment equipment,string status)
        {
            using (var uow = _fsql.CreateUnitOfWork())
            {
                try
                {
                    var now = DateTime.Now;

                    // 1. 查找当前设备状态
                    var currentStatus = await uow.Orm.Select<DaqEquipmentStatusRecord>()
                        .Where(r => r.EquipmentCode == equipment.EquipmentCode)
                        .FirstAsync();

                    if (currentStatus == null)
                    {
                        // 情况1:没有数据则创建
                        await CreateNewStatusAsync(uow.Orm, equipment, status, now);
                    }
                    else
                    {
                        if (currentStatus.Status == status)
                        {
                            // 情况2:状态没有变更,更新UpdateTime和StatusDuration
                            await UpdateStatusDurationAsync(uow.Orm, currentStatus, now);
                        }
                        else
                        {
                            // 情况3:状态变更,记录历史并更新当前状态
                            await HandleStatusChangeAsync(uow.Orm, currentStatus, equipment, status, now);
                        }
                    }

                    uow.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    uow.Rollback();
                    // 记录日志
                    Console.WriteLine($"更新设备状态失败: {ex.Message}");
                    return false;
                }
            }
        }

        /// <summary>
        /// 创建设备新状态
        /// </summary>
        private async Task CreateNewStatusAsync(IFreeSql fsql, BaseEquipment equipment, string status, DateTime now)
        {
            var newStatus = new DaqEquipmentStatusRecord
            {
                Id = Guid.NewGuid(),
                EquipmentCode = equipment.EquipmentCode,
                EquipmentName = equipment.EquipmentName,
                EquipmentTypeCode = equipment.EquipmentTypeCode,
                Status = status,
                IsEnd = false,
               // ProjectCode = equipment.ProjectKeys,
                FactoryCode = equipment.FactoryCode,
                CreateTime = now,
                UpdateTime = now,
                HandleTime = now,
                StatusDuration = 0
            };

            await fsql.Insert(newStatus).ExecuteAffrowsAsync();

            Console.WriteLine($"[{now:HH:mm:ss}] 创建设备状态: {equipment.EquipmentName} -> {status}");
        }

        /// <summary>
        /// 更新状态持续时间
        /// </summary>
        private async Task UpdateStatusDurationAsync(IFreeSql fsql, DaqEquipmentStatusRecord currentStatus, DateTime now)
        {
            var duration = (int)((now - currentStatus.UpdateTime).TotalSeconds + currentStatus.StatusDuration);

            await fsql.Update<DaqEquipmentStatusRecord>()
                .Set(r => r.UpdateTime, now)
                .Set(r => r.HandleTime, now)
                .Set(r => r.StatusDuration, duration)
                .Where(r => r.Id == currentStatus.Id)
                .ExecuteAffrowsAsync();
        }

        /// <summary>
        /// 处理状态变更
        /// </summary>
        private async Task HandleStatusChangeAsync(IFreeSql fsql, DaqEquipmentStatusRecord currentStatus,
            BaseEquipment equipment, string status, DateTime now)
        {
            // 1. 计算上一个状态的持续时间
            var lastDuration = (int)((now - currentStatus.UpdateTime).TotalSeconds + currentStatus.StatusDuration);

            // 2. 插入新的历史记录
            var historyRecord = new DaqEquipmentStatusRecordHistory
            {
                Id = Guid.NewGuid(),
                EquipmentCode = currentStatus.EquipmentCode,
                EquipmentName = currentStatus.EquipmentName,
                EquipmentTypeCode = currentStatus.EquipmentTypeCode,
                Status = currentStatus.Status, // 旧状态
                IsEnd = true,
                ProjectCode = currentStatus.ProjectCode,
                FactoryCode = currentStatus.FactoryCode,
                CreateTime = currentStatus.CreateTime,
                UpdateTime = now, // 状态结束时间
                HandleTime = now,
                Remark = $"状态变更为: {status}",
                StatusDuration = lastDuration
            };

            await fsql.Insert(historyRecord).ExecuteAffrowsAsync();

            // 3. 更新当前状态为新状态
            await fsql.Update<DaqEquipmentStatusRecord>()
                .Set(r => r.Status, status)
                .Set(r => r.IsEnd, false)
                .Set(r => r.UpdateTime, now)
                .Set(r => r.HandleTime, now)
                .Set(r => r.StatusDuration, 1) // 新状态持续时间从1开始
                .Where(r => r.Id == currentStatus.Id)
                .ExecuteAffrowsAsync();

            Console.WriteLine($"[{now:HH:mm:ss}] 设备状态变更: {equipment.EquipmentCode} {currentStatus.Status} -> {status} (持续: {lastDuration}秒)");
        }


        public void Dispose()
        {
            if (!_disposed)
            {
                _fsql?.Dispose();
                _disposed = true;
            }
        }
    }

    public static class EquipmentStatus
    {
        public const string Free = "Free";
        public const string Running = "Running";
        public const string Failure = "Failure";
    }
}