wanshenmean
2025-04-11 0abd867230198628a88f54370104bee0306f1f7c
添加提升机调度
已修改5个文件
已添加3个文件
655 ■■■■■ 文件已修改
代码管理/NEWCode/WIDESEAWCS_PDA/pages/叫料/正极叫料.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_PDA/pages/叫料/负极叫料.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Elevator/CommonElevator.cs 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Elevator/IElevator.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Roast/CommonRoast.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Roast/IRoast.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ElevatorJob/ElevatorJob.cs 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_PDA/pages/½ÐÁÏ/Õý¼«½ÐÁÏ.vue
@@ -152,14 +152,15 @@
                    this.$t.message.toast('可叫数量为0,无法叫任务');
                    return;
                }
                let guid = this.generateUUID()
                let formDataParam = {
                dTaskId: this.generateUUID(),
                    dTaskId: guid,
                productCode: productCode,
                orderNo: orderNo,
                taskNo:2,
                number: availableQuantity > 4 ? 4 : availableQuantity,
                inputValue: inputValue,
                DTaskId: this.generateUUID(),
                    DTaskId: guid,
                ProductCode: productCode,
                OrderNo: orderNo,
                Number: availableQuantity > 4 ? 4 : availableQuantity,
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_PDA/pages/½ÐÁÏ/¸º¼«½ÐÁÏ.vue
@@ -158,14 +158,15 @@
                    this.$t.message.toast('可叫数量为0,无法叫任务');
                    return;
                }
                let guid = this.generateUUID()
                let formDataParam = {
                    dTaskId: this.generateUUID(),
                    dTaskId: guid,
                    productCode: productCode,
                    orderNo: orderNo,
                    taskNo:2,
                    number: availableQuantity > 4 ? 4 : availableQuantity,
                    inputValue: inputValue,
                    DTaskId: this.generateUUID(),
                    DTaskId: guid,
                    ProductCode: productCode,
                    OrderNo: orderNo,
                    Number: availableQuantity > 4 ? 4 : availableQuantity,
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Elevator/CommonElevator.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,276 @@
using HslCommunication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_QuartzJob.ConveyorLine.Enum;
using WIDESEAWCS_QuartzJob.DeviceBase;
using WIDESEAWCS_QuartzJob.DTO;
namespace WIDESEAWCS_QuartzJob.Elevator
{
    public class CommonElevator: IElevator
    {
        #region Private Member
        /// <summary>
        /// çƒ˜çƒ¤é€šè®¯å¯¹è±¡
        /// </summary>
        private readonly BaseCommunicator _communicator;
        /// <summary>
        /// çƒ˜çƒ¤åè®®ä¿¡æ¯
        /// </summary>
        private readonly List<DeviceProDTO> _deviceProDTOs;
        /// <summary>
        /// çƒ˜çƒ¤åè®®æ˜Žç»†ä¿¡æ¯
        /// </summary>
        private readonly List<DeviceProtocolDetailDTO> _deviceProtocolDetailDTOs;
        /// <summary>
        /// è®¾å¤‡ç¼–号
        /// </summary>
        public readonly string _deviceCode;
        /// <summary>
        /// è®¾å¤‡åç§°
        /// </summary>
        public readonly string _deviceName;
        private bool _heartStatr = true;
        private bool _isConnected = true;
        #endregion
        #region Public Member
        /// <summary>
        /// çƒ˜çƒ¤é€šè®¯å¯¹è±¡
        /// </summary>
        public BaseCommunicator Communicator => _communicator;
        /// <summary>
        /// çƒ˜çƒ¤åè®®ä¿¡æ¯
        /// </summary>
        public List<DeviceProDTO> DeviceProDTOs => _deviceProDTOs;
        /// <summary>
        /// çƒ˜çƒ¤åè®®æ˜Žç»†ä¿¡æ¯
        /// </summary>
        public List<DeviceProtocolDetailDTO> DeviceProtocolDetailDTOs => _deviceProtocolDetailDTOs;
        /// <summary>
        /// è®¾å¤‡ç¼–号
        /// </summary>
        public string DeviceCode => _deviceCode;
        /// <summary>
        /// è®¾å¤‡åç§°
        /// </summary>
        public string DeviceName => _deviceName;
        /// <summary>
        /// é€šè®¯æ˜¯å¦å·²è¿žæŽ¥
        /// </summary>
        public bool IsConnected => Communicator.IsConnected && _isConnected;
        #endregion
        #region Constructor Function
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="communicator">烘烤通讯对象</param>
        /// <param name="deviceProDTOs">烘烤协议信息</param>
        /// <param name="deviceProtocolDetailDTOs">烘烤协议明细信息</param>
        /// <param name="deviceCode">设备编号</param>
        /// <param name="deviceName">设备名称</param>
        public CommonElevator(BaseCommunicator communicator, List<DeviceProDTO> deviceProDTOs, List<DeviceProtocolDetailDTO> deviceProtocolDetailDTOs, string deviceCode, string deviceName)
        {
            _communicator = communicator;
            _deviceProDTOs = deviceProDTOs;
            _deviceProtocolDetailDTOs = deviceProtocolDetailDTOs;
            _deviceCode = deviceCode;
            _deviceName = deviceName;
            CheckConnect();
        }
        #endregion
        #region Private Method
        private void CheckConnect()
        {
            Task.Run(() =>
            {
                while (_heartStatr)
                {
                    try
                    {
                        DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault();
                        if (devicePro == null)
                            _isConnected = false;
                        else
                            Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType);
                        _isConnected = true;
                    }
                    catch (Exception ex)
                    {
                        _isConnected = false;
                    }
                    Thread.Sleep(500);
                }
            });
        }
        #endregion
        #region Public Method
        /// <summary>
        /// è¯»å–PLC协议地址的数据
        /// </summary>
        /// <typeparam name="TEnum">协议信息的枚举对象信息。</typeparam>
        /// <typeparam name="TResult">读取数据的类型对象信息。</typeparam>
        /// <param name="value">枚举值</param>
        /// <param name="deviceChildCode">设备子编号</param>
        /// <returns>读取到的数据</returns>
        public TResult GetValue<TEnum, TResult>(TEnum value, string deviceChildCode) where TEnum : Enum
        {
            if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络");
            DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == value.ToString() && x.DeviceChildCode == deviceChildCode);
            return devicePro == null ? throw new Exception($"读取数据错误,未在协议信息里面找到参数{value.ToString()}") : (TResult)Communicator.ReadAsObj(devicePro.DeviceProAddress, devicePro.DeviceDataType);
        }
        /// <summary>
        /// ä¸Žè®¾å¤‡çš„心跳
        /// </summary>
        public void Heartbeat()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="command"></param>
        /// <param name="deviceChildCode"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool SendCommand<T>(T command, string deviceChildCode) where T : IDataTransfer, new()
        {
            if (Communicator is SiemensS7)
            {
                if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络");
                DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceChildCode == deviceChildCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault();
                if (devicePro == null)
                {
                    return false;
                }
                if (Communicator.WriteCustomer(devicePro.DeviceProAddress, command))
                {
                    return true;
                }
                return false;
            }
            else
            {
                throw new Exception("暂不支持除西门子之外的PLC");
            }
        }
        /// <summary>
        /// è¯»å–PLC数据,返回自定义对象
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="deviceChildCode">子设备编号</param>
        /// <returns>返回自定义对象或抛出异常</returns>
        /// <exception cref="Exception"></exception>
        public T ReadCustomer<T>(string deviceChildCode) where T : IDataTransfer, new()
        {
            if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络");
            DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == "ReadDeviceCommand" && x.DeviceChildCode == deviceChildCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault();
            if (devicePro == null)
            {
                throw new Exception("未找到协议信息");
            }
            else
            {
                return Communicator.ReadCustomer<T>(devicePro.DeviceProAddress);
            }
        }
        /// <summary>
        /// æ ¹æ®å‚数名称、设备子编号写入对应的数据。
        /// </summary>
        /// <typeparam name="TEnum">参数名称枚举类型。</typeparam>
        /// <typeparam name="TValue">要写入的数据类型。</typeparam>
        /// <param name="enum">参数名称。</param>
        /// <param name="value">要写入的数据。</param>
        /// <param name="deviceChildCode">设备子编号写</param>
        /// <returns>返回写入成功或失败</returns>
        public bool SetValue<TEnum, TValue>(TEnum @enum, TValue value, string deviceChildCode)
            where TEnum : Enum
            where TValue : notnull
        {
            if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络");
            DeviceProDTO? devicePro = _deviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == @enum.ToString() && x.DeviceChildCode == deviceChildCode);
            return devicePro == null ? throw new Exception($"写入数据错误,未在协议信息里面找到参数{value.ToString()}") : Communicator.WriteObj(devicePro.DeviceProAddress, devicePro.DeviceDataType, value);
        }
        /// <summary>
        /// æ˜¯å¦å ä½
        /// </summary>
        /// <param name="deviceChildCode">设备子编号</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool IsOccupied(string deviceChildCode)
        {
            if (Communicator.IsConnected)
            {
                List<DeviceProDTO> devicePros = _deviceProDTOs.Where(x => x.DeviceProParamType == ConveyorLineStatus.IsOccupied.ToString()).ToList();
                if (devicePros.Count == 0)
                {
                    //todo åè®®ä¿¡æ¯æœªèŽ·å–åˆ°æ—¶æŠ›å‡ºå¼‚å¸¸
                    throw new Exception();
                }
                for (int i = 0; i < devicePros.Count; i++)
                {
                    object readStatus = Communicator.ReadAsObj(devicePros[i].DeviceProAddress, devicePros[i].DeviceDataType);
                    //todo åè®®æ˜Žç»†ä¿¡æ¯æœªèŽ·å–åˆ°æ—¶æŠ›å‡ºå¼‚å¸¸
                    DeviceProtocolDetailDTO? deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePros[i].DeviceProParamName) ?? throw new Exception();
                    deviceProtocolDetail = _deviceProtocolDetailDTOs.FirstOrDefault(x => x.DeviceProParamName == devicePros[i].DeviceProParamType && x.ProtocalDetailValue.Equals(readStatus.ToString()));
                    if (deviceProtocolDetail != null)
                    {
                        return true;
                    }
                    return false;
                }
            }
            //todo é€šè®¯æœªè¿žæŽ¥æ—¶æŠ›å‡ºå¼‚常
            return false;
        }
        /// <summary>
        /// é‡Šæ”¾å¯¹è±¡
        /// </summary>
        public void Dispose()
        {
            // è®¾ç½®å¿ƒè·³çŠ¶æ€ä¸ºfalse
            _heartStatr = false;
            // é‡Šæ”¾é€šä¿¡å™¨èµ„源
            _communicator.Dispose();
            // å‘Šè¯‰åžƒåœ¾å›žæ”¶å™¨ä¸å†è°ƒç”¨ç»ˆç»“器
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Elevator/IElevator.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
using HslCommunication;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_QuartzJob.DTO;
namespace WIDESEAWCS_QuartzJob
{
    public interface IElevator : IDevice
    {
        /// <summary>
        /// é€šè®¯å¯¹è±¡
        /// </summary>
        BaseCommunicator Communicator { get; }
        /// <summary>
        /// é€šè®¯åè®®ä¿¡æ¯
        /// </summary>
        List<DeviceProDTO> DeviceProDTOs { get; }
        /// <summary>
        /// é€šè®¯åè®®æ˜Žç»†ä¿¡æ¯
        /// </summary>
        List<DeviceProtocolDetailDTO> DeviceProtocolDetailDTOs { get; }
        /// <summary>
        /// è®¾å¤‡æ˜¯å¦å·²è¿žæŽ¥
        /// </summary>
        bool IsConnected { get; }
        /// <summary>
        /// ä¸Žè®¾å¤‡çš„心跳
        /// </summary>
        void Heartbeat();
        /// <summary>
        /// è¯»å–PLC协议地址的数据
        /// </summary>
        /// <typeparam name="TEnum">协议信息的枚举对象信息。</typeparam>
        /// <typeparam name="TResult">读取数据的类型对象信息。</typeparam>
        /// <param name="value">枚举值</param>
        /// <param name="deviceChildCode">设备子编号</param>
        /// <returns>读取到的数据</returns>
        TResult GetValue<TEnum, TResult>(TEnum value, string deviceChildCode) where TEnum : Enum;
        /// <summary>
        /// æ ¹æ®å‚数名称、设备子编号写入对应的数据。
        /// </summary>
        /// <typeparam name="TEnum">参数名称枚举类型。</typeparam>
        /// <typeparam name="TValue">要写入的数据类型。</typeparam>
        /// <param name="enum">参数名称。</param>
        /// <param name="value">要写入的数据。</param>
        /// <param name="deviceChildCode">设备子编号写</param>
        /// <returns>返回写入成功或失败</returns>
        bool SetValue<TEnum, TValue>(TEnum @enum, TValue value, string deviceChildCode) where TEnum : Enum where TValue : notnull;
        /// <summary>
        /// è¯»å–站台是否被占用
        /// </summary>
        /// <param name="deviceChildCode">设备子编号</param>
        /// <returns></returns>
        bool IsOccupied(string deviceChildCode);
        /// <summary>
        /// å‘送任务命令
        /// </summary>
        /// <typeparam name="T">任务命令对象的类型泛型</typeparam>
        /// <param name="command">任务命令</param>
        /// <param name="deviceChildCode">设备子编号</param>
        /// <returns></returns>
        bool SendCommand<T>(T command, string deviceChildCode) where T : IDataTransfer, new();
    }
}
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Roast/CommonRoast.cs
@@ -1,4 +1,5 @@
#region << ç‰ˆ æœ¬ æ³¨ é‡Š >>
/*----------------------------------------------------------------
 * å‘½åç©ºé—´ï¼šWIDESEAWCS_QuartzJob
 * åˆ›å»ºè€…:胡童庆
@@ -13,20 +14,15 @@
 * ä¿®æ”¹è¯´æ˜Žï¼š
 * 
 *----------------------------------------------------------------*/
#endregion << ç‰ˆ æœ¬ æ³¨ é‡Š >>
using HslCommunication;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_QuartzJob.ConveyorLine.Enum;
using WIDESEAWCS_QuartzJob.DeviceBase;
using WIDESEAWCS_QuartzJob.DTO;
using WIDESEAWCS_QuartzJob.StackerCrane.Enum;
namespace WIDESEAWCS_QuartzJob
{
@@ -37,6 +33,7 @@
    public class CommonRoast : IRoast
    {
        #region Private Member
        /// <summary>
        /// çƒ˜çƒ¤é€šè®¯å¯¹è±¡
        /// </summary>
@@ -65,9 +62,11 @@
        private bool _heartStatr = true;
        private bool _isConnected = true;
        #endregion
        #region Public Member
        /// <summary>
        /// çƒ˜çƒ¤é€šè®¯å¯¹è±¡
        /// </summary>
@@ -101,6 +100,7 @@
        #endregion
        #region Constructor Function
        /// <summary>
        /// æž„造函数
        /// </summary>
@@ -118,9 +118,11 @@
            _deviceName = deviceName;
            CheckConnect();
        }
        #endregion
        #region Private Method
        private void CheckConnect()
        {
            Task.Run(() =>
@@ -144,9 +146,11 @@
                }
            });
        }
        #endregion
        #region Public Method
        /// <summary>
        /// è¯»å–PLC协议地址的数据
        /// </summary>
@@ -180,7 +184,7 @@
        /// <exception cref="Exception"></exception>
        public bool SendCommand<T>(T command, string deviceChildCode) where T : IDataTransfer, new()
        {
            if(Communicator is SiemensS7)
            if (Communicator is MelsecA1ENetCommunicator)
            {
                if (!IsConnected) throw new Exception($"通讯连接错误,请检查网络");
                DeviceProDTO? devicePro = _deviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceChildCode == deviceChildCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault();
@@ -285,6 +289,7 @@
            // å‘Šè¯‰åžƒåœ¾å›žæ”¶å™¨ä¸å†è°ƒç”¨ç»ˆç»“器
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Roast/IRoast.cs
@@ -1,4 +1,5 @@
#region << ç‰ˆ æœ¬ æ³¨ é‡Š >>
/*----------------------------------------------------------------
 * å‘½åç©ºé—´ï¼šWIDESEAWCS_QuartzJob
 * åˆ›å»ºè€…:胡童庆
@@ -13,6 +14,7 @@
 * ä¿®æ”¹è¯´æ˜Žï¼š
 * 
 *----------------------------------------------------------------*/
#endregion << ç‰ˆ æœ¬ æ³¨ é‡Š >>
using HslCommunication;
@@ -32,7 +34,6 @@
    /// </summary>
    public interface IRoast : IDevice
    {
        /// <summary>
        /// é€šè®¯å¯¹è±¡
        /// </summary>
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -18,7 +18,7 @@
    "DBType": "SqlServer",
    //连接字符串
    //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=",
    "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_GanFengLiYeNew;User ID=sa;Password=sa123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
    "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_GanFengLiYeNew;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
    //跨域
    "Cors": {
´úÂë¹ÜÀí/NEWCode/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ElevatorJob/ElevatorJob.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
using Quartz;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Elevator;
namespace WIDESEAWCS_Tasks
{
    public class ElevatorJob : JobBase, IJob, IDisposable
    {
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
        public Task Execute(IJobExecutionContext context)
        {
            // ä»Žä¸Šä¸‹æ–‡ä¸­èŽ·å– JobParams å¹¶è½¬æ¢ä¸º Roast ç±»åž‹
            CommonElevator elevator = (CommonElevator)context.JobDetail.JobDataMap.Get("JobParams");
            // åˆå§‹åŒ– AGV å˜é‡
            AGV agv = null;
            if (elevator == null)
            {
                throw new Exception("未找到提升机设备参数。");
            }
            // è¿žæŽ¥ AGV
            // æ ¹æ®è®¾å¤‡åç§°å†³å®šæ˜¯æ­£æžè¿˜æ˜¯è´Ÿæž AGV
            List<string> agvNames = new List<string>() { "正极AGV", "负极AGV" };
            foreach (var agvName in agvNames)
            {
                // ä»Žå­˜å‚¨ä¸­æŸ¥æ‰¾æŒ‡å®šåç§°çš„设备
                IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceName == agvName);
                if (device != null)
                {
                    agv = (AGV)device;
                }
                else
                {
                    ConsoleHelper.WriteErrorLine($"未找到{agvName}设备参数。");
                    continue;
                }
                var elevatorNamesValues = GetDBElevatorNamesValues(agvName);
                var agvNamesValues = GetDBAGVNamesValues(agvName);
                DeviceInteraction(elevator, agv, elevatorNamesValues, agvNamesValues);
            }
            return Task.CompletedTask;
        }
        public static void DeviceInteraction(CommonElevator elevator, AGV agv, List<string> elevatorNames, List<string> agvNames)
        {
            if (agv.DeviceName == "正极AGV")
            {
                HandlePositiveAGV(elevator, agv, elevatorNames, agvNames);
            }
            else
            {
                HandleNegativeAGV(elevator, agv, elevatorNames, agvNames);
            }
        }
        private static void HandlePositiveAGV(CommonElevator elevator, AGV agv, List<string> elevatorNames, List<string> agvNames)
        {
            // æ­£æžAGV只需要处理前两个信号
            var elevatorSignal = elevator.Communicator.Read<byte>(elevatorNames[0], 100);
            var agvSignal = agv.Communicator.Read<byte>(agvNames[1], 100);
            agv.Communicator.Write(agvNames[0], elevatorSignal);
            elevator.Communicator.Write(agvNames[1], agvSignal);
            ConsoleHelper.WriteInfoLine($"正极AGV交互: å†™å…¥ç”µæ¢¯ä¿¡å·[{elevatorSignal}]到{agvNames[0]}," +
                                       $"写入AGV信号[{agvSignal}]到{agvNames[1]}");
        }
        private static void HandleNegativeAGV(CommonElevator elevator, AGV agv, List<string> elevatorNames, List<string> agvNames)
        {
            // å®šä¹‰ä¿¡å·ç»„处理(起始索引,操作类型,日志描述)
            var operations = new List<(int startIdx, string type, string desc)>
            {
                (0,  "E→A", "基础信号交互"),
                (2,  "A→E", "状态反馈"),
                (4,  "E→A", "设备状态同步"),
                (6,  "A→E", "任务指令"),
                (8,  "E→A", "位置信息同步"),
                (10, "A→E", "单信号反馈"),
                (11, "A→E", "双信号反馈"),
                (13, "A→E", "单信号反馈"),
                (14, "E→A", "设备状态同步"),
                (16, "A→E", "运行指令"),
                (18, "E→A", "多信号同步"),
                (22, "A→E", "结束信号反馈")
            };
            foreach (var op in operations)
            {
                ProcessSignalGroup(
                    elevator, agv,
                    elevatorNames, agvNames,
                    op.startIdx,
                    op.type,
                    op.desc
                );
            }
        }
        private static void ProcessSignalGroup(CommonElevator elevator, AGV agv, List<string> elevatorNames, List<string> agvNames, int startIdx, string operationType, string description)
        {
            const int GROUP_SIZE = 2; // æ¯ç»„处理2个信号
            // ç‰¹æ®Šå¤„理最后几个信号组
            if (startIdx >= 18)
            {
                HandleSpecialSignals(elevator, agv, elevatorNames, agvNames, startIdx);
                return;
            }
            var values = new List<byte[]>();
            var targets = new List<string>();
            // æ ¹æ®æ“ä½œç±»åž‹å¤„理信号
            if (operationType == "E→A")
            {
                for (int i = 0; i < GROUP_SIZE; i++)
                {
                    int idx = startIdx + i;
                    if (idx >= elevatorNames.Count) break;
                    var value = elevator.Communicator.Read<byte>(elevatorNames[idx], 100);
                    agv.Communicator.Write(agvNames[idx], value);
                    values.Add(value);
                    targets.Add(agvNames[idx]);
                    if (description == "单信号反馈") break;
                }
            }
            else if (operationType == "A→E")
            {
                for (int i = 0; i < GROUP_SIZE; i++)
                {
                    int idx = startIdx + i;
                    if (idx >= agvNames.Count) break;
                    var value = agv.Communicator.Read<byte>(agvNames[idx], 100);
                    elevator.Communicator.Write(elevatorNames[idx], value);
                    values.Add(value);
                    targets.Add(elevatorNames[idx]);
                    if (description == "单信号反馈") break;
                }
            }
            // ç”ŸæˆåŠ¨æ€æ—¥å¿—æè¿°
            var logValues = string.Join("], [", values);
            var logTargets = string.Join(",", targets);
            ConsoleHelper.WriteInfoLine($"负极AGV交互({description}): ä¼ è¾“信号组[{logValues}]到目标地址[{logTargets}]");
        }
        private static void HandleSpecialSignals(CommonElevator elevator, AGV agv,
                                                List<string> elevatorNames, List<string> agvNames,
                                                int startIdx)
        {
            // å¤„理18-21号电梯信号(4个信号)
            var elevatorSignals = Enumerable.Range(18, 4)
                .Select(i => elevator.Communicator.Read<byte>(elevatorNames[i], 100))
                .ToList();
            for (int i = 0; i < 4; i++)
            {
                agv.Communicator.Write(agvNames[18 + i], elevatorSignals[i]);
            }
            // å¤„理22-23号AGV信号
            var agvSignals = Enumerable.Range(22, 2)
                .Select(i => agv.Communicator.Read<byte>(agvNames[i], 100))
                .ToList();
            for (int i = 0; i < 2; i++)
            {
                elevator.Communicator.Write(elevatorNames[22 + i], agvSignals[i]);
            }
            ConsoleHelper.WriteInfoLine($"负极AGV交互(特殊信号组): " +
                                       $"写入电梯信号[{string.Join(",", elevatorSignals)}]到AGV," +
                                       $"读取AGV信号[{string.Join(",", agvSignals)}]到电梯");
        }
        private List<string> GetDBElevatorNamesValues(string deviceName)
        {
            List<string> dbNamesValues = null;
            if (deviceName == "正极AGV")
            {
                dbNamesValues = new List<string>()
                {
                    "DB1002.1600",
                    "DB1002.1700"
                };
            }
            else
            {
                dbNamesValues = new List<string>()
                {
                    "DB1002.0",
                    "DB1002.600",
                    "DB1002.100",
                    "DB1002.700",
                    "DB1002.1000",
                    "DB1002.1200",
                    "DB1002.1100",
                    "DB1002.1300",
                    "DB1002.1800",
                    "DB1002.1200",
                    "DB1002.11400",
                    "DB1002.1900",
                    "DB1002.2100",
                    "DB1002.2300",
                    "DB1002.2400",
                    "DB1002.2600",
                    "DB1002.2500",
                    "DB1002.2700",
                    "DB1002.2000",
                    "DB1002.2800",
                    "DB1002.3000",
                    "DB1002.2200",
                    "DB1002.2900",
                    "DB1002.3100"
                };
            }
            return dbNamesValues;
        }
        private List<string> GetDBAGVNamesValues(string deviceName)
        {
            List<string> dbNamesValues = null;
            if (deviceName == "正极AGV")
            {
                dbNamesValues = new List<string>()
                {
                    "DB1002.4000",
                    "DB1002.4100"
                };
            }
            else
            {
                dbNamesValues = new List<string>()
                {
                    "DB1002.200",
                    "DB1002.600",
                    "DB1002.300",
                    "DB1002.700",
                    "DB1002.1000",
                    "DB1002.1400",
                    "DB1002.1100",
                    "DB1002.1500",
                    "DB1002.17800",
                    "DB1002.1400",
                    "DB1002.2200",
                    "DB1002.17900",
                    "DB1002.18100",
                    "DB1002.18300",
                    "DB1002.18400",
                    "DB1002.18600",
                    "DB1002.18500",
                    "DB1002.18700",
                    "DB1002.18800",
                    "DB1002.19000",
                    "DB1002.18200",
                    "DB1002.18000",
                    "DB1002.18900",
                    "DB1002.19100"
                };
            }
            return dbNamesValues;
        }
    }
}