using Aitex.Core.RT.Log; using Aitex.Core.Util; using DocumentFormat.OpenXml.Wordprocessing; using MECF.Framework.Common.Device.PowerSupplier; using MECF.Framework.Common.Net; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MECF.Framework.Common.Device.Wago { public class WagoModbusDevice : JetMessageTcpClient { #region 常量 private const int DO_READ_CMD = 1; private const int DI_READ_CMD = 2; private const int AO_READ_CMD = 3; private const int AI_READ_CMD = 4; private const int DO_WRITE_CMD= 5; private const int AO_WRITE_CMD = 6; #endregion #region 内部变量 /// /// 名称 /// private string _name; /// /// 上一次错误信息 /// private string _lastErrorMsg = ""; /// /// 通道 /// private byte _channel = 1; /// /// IP地址 /// private string _ip = ""; /// /// 端口号 /// private int _port = 502; /// /// 定时器 /// private PeriodicJob _periodicJob; /// /// 共享锁 /// private object _locker = new object(); /// /// 共享锁时长 /// private int _lockerTime = 2000; /// /// AI总数 /// private ushort _aiCount = 0; /// /// AI起始地址 /// private ushort _aiStartAddress = 0; /// /// AO总数 /// private ushort _aoCount = 0; /// /// AO起始地址 /// private ushort _aoStartAddress = 0; /// /// DI总数 /// private ushort _diCount = 0; /// /// DI起始地址 /// private ushort _diStartAddress = 0; /// /// DO总数 /// private ushort _doCount = 0; /// /// DO起始地址 /// private ushort _doStartAddress = 0; /// /// 读取索引 /// private int _readIndex = 0; #endregion /// /// 构造函数 /// /// /// public WagoModbusDevice(string name, string ip, int port,byte channel) : base(ip, port) { ReceiveTimeout = 1000; SendTimeout = 1000; ConnectTimeout = 1000; _name = name; _ip = ip; _port = port; _channel = channel; _periodicJob = new PeriodicJob(50, OnTimer, $"Wago {name} timer", false,true); } /// /// 定时器执行 /// /// private bool OnTimer() { if(Monitor.TryEnter(_locker, _lockerTime)) { if (_readIndex == 0) { ApplyAllDIDatas(); _readIndex++; } else if(_readIndex==1) { ApplyAllDODatas(); _readIndex++; } else if (_readIndex == 2) { ApplyAllAIDatas(); _readIndex++; } else { ApplyAllAODatas(); _readIndex = 0; } Monitor.Exit(_locker); } return true; } /// /// 更新地址数量 /// public void Initialize(ushort diCount,ushort diStartAdress,ushort doCount,ushort doStartAdress,ushort aiCount,ushort aiStartAddress, ushort aoCount,ushort aoStartAddress) { _diCount = diCount; _diStartAddress = diStartAdress; _doCount = doCount; _doStartAddress=doStartAdress; _aiCount = aiCount; _aiStartAddress = aiStartAddress; _aoCount = aoCount; _aoStartAddress = aoStartAddress; NetResult result = Connect(); if (result.IsSuccess) { LOG.WriteLog(eEvent.INFO_WAGO, _name, $"connect {_ip}:{_port} success"); } else { LOG.WriteLog(eEvent.INFO_WAGO, _name, $"connect {_ip}:{_port} failed"); } _periodicJob.Start(); } /// /// 写入DO数值 /// /// /// /// public bool WriteDOValue(ushort address, byte value) { WagoCommand command = new WagoCommand(); command.Address = address; command.CommandCode = DO_WRITE_CMD; command.WriteValue = value; command.Channel = _channel; if (Monitor.TryEnter(_locker, _lockerTime)) { bool result = SetOperation(command); Monitor.Exit(_locker); return result; } else { LOG.WriteLog(eEvent.ERR_WAGO, "Wago", $"Write apply locker over {_lockerTime}"); return false; } } /// /// 写入AO数值 /// /// /// /// public bool WriteAOValue(ushort address, byte[] value) { WagoCommand command = new WagoCommand(); command.Address = address; command.CommandCode = AO_WRITE_CMD; command.WriteValue = value; command.Channel = _channel; if (Monitor.TryEnter(_locker, _lockerTime)) { bool result = SetOperation(command); Monitor.Exit(_locker); return result; } else { LOG.WriteLog(eEvent.ERR_WAGO, "Wago", $"Write apply locker over {_lockerTime}"); return false; } } /// /// 设置操作 /// /// /// private bool SetOperation(WagoCommand command) { if (Connected) { return SetOperationCommand(command); } else { NetResult netResult = Connect(); if (netResult.IsSuccess) { return SetOperationCommand(command); } else { WriteErrMsg("connect failed"); return false; } } } /// /// 设置操作指令 /// /// /// private bool SetOperationCommand(WagoCommand command) { NetResult netResult = SetData(command); if (!netResult.IsSuccess) { WriteErrMsg($"write write {command.Address.ToString("X2")} value {command.WriteValue} failed,{netResult.Message}"); return false; } return true; } #region 申请数据 /// /// 申请所有DI数据 /// public void ApplyAllDIDatas() { ApplyAllDataTypeDatas(DI_READ_CMD, _diCount, _diStartAddress); } /// /// 申请所有DO数据 /// public void ApplyAllDODatas() { ApplyAllDataTypeDatas(DO_READ_CMD, _doCount, _doStartAddress); } /// /// 申请所有AI数据 /// public void ApplyAllAIDatas() { ApplyAllDataTypeDatas(AI_READ_CMD, _aiCount, _aiStartAddress); } /// /// 申请所有AO数据 /// public void ApplyAllAODatas() { ApplyAllDataTypeDatas(AO_READ_CMD, _aoCount, _aoStartAddress); } /// /// 申请所有数据类型数据 /// /// /// /// private void ApplyAllDataTypeDatas(byte dataType,ushort dataCount,ushort startAddress) { WagoCommand command = new WagoCommand(); command.Address = startAddress; command.RegisterCount = dataCount; command.CommandCode = dataType; command.Channel = _channel; ApplyDataOperation(command); } /// /// 申请数据操作 /// /// private void ApplyDataOperation(WagoCommand command) { if (!Connected) { NetResult connectResult = Connect(); if (!connectResult.IsSuccess) { WriteErrMsg("connect failed"); return; } } NetResult netResult = ApplyData(command); if (!netResult.IsSuccess) { WriteErrMsg($"apply {command.Address.ToString("X2")} failed,{netResult.Message}"); return; } if (netResult.Data.Datas != null) { if (command.CommandCode == DO_READ_CMD||command.CommandCode==DI_READ_CMD) { bool[] digDatas = (bool[])netResult.Data.Datas; bool[] digs = new bool[command.RegisterCount]; int count=command.RegisterCount>=digDatas.Length?digDatas.Length:command.RegisterCount; Array.Copy(digDatas,0,digs,0,count); if (command.CommandCode == DO_READ_CMD) { WagoControllerCfgManager.Instance.UpdateWagoDOData(_name, digs); } else { WagoControllerCfgManager.Instance.UpdateWagoDIData(_name, digs); } } else { byte[] datas = (byte[])netResult.Data.Datas; if (command.CommandCode == AI_READ_CMD) { WagoControllerCfgManager.Instance.UpdateWagoAIData(_name, datas); //LOG.WriteBackgroundLog(eEvent.INFO_WAGO, "Wago", string.Join(" ", Array.ConvertAll(datas,O=>O.ToString("X2")))); } else { WagoControllerCfgManager.Instance.UpdateWagoAOData(_name, datas); } } } } #endregion /// /// 写错误日志 /// /// private void WriteErrMsg(string msg) { if (msg != _lastErrorMsg) { _lastErrorMsg = msg; LOG.WriteLog(eEvent.ERR_WAGO, _name, msg); } } } }