|
@@ -1,23 +1,23 @@
|
|
|
-using Aitex.Common.Util;
|
|
|
-using Aitex.Core.RT.Device;
|
|
|
-using Aitex.Core.RT.Log;
|
|
|
-using Aitex.Core.UI.Control;
|
|
|
-using Aitex.Core.Util;
|
|
|
-using MECF.Framework.Common.Device.Festo;
|
|
|
-using MECF.Framework.Common.Device.Wago;
|
|
|
-using MECF.Framework.Common.Net;
|
|
|
-using MECF.Framework.Common.Simulator;
|
|
|
-using MECF.Framework.Simulator.Core.Driver;
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.IO;
|
|
|
-using static MECF.Framework.Common.Simulator.MotorSimulator;
|
|
|
-
|
|
|
-namespace CyberX8_Simulator.Devices
|
|
|
-{
|
|
|
- public class WagoSocketSimulator : SocketDeviceSimulator
|
|
|
- {
|
|
|
- private const short WRITE_DO_STARTADDRESS = 0x0200;
|
|
|
+using Aitex.Common.Util;
|
|
|
+using Aitex.Core.RT.Device;
|
|
|
+using Aitex.Core.RT.Log;
|
|
|
+using Aitex.Core.UI.Control;
|
|
|
+using Aitex.Core.Util;
|
|
|
+using MECF.Framework.Common.Device.Festo;
|
|
|
+using MECF.Framework.Common.Device.Wago;
|
|
|
+using MECF.Framework.Common.Net;
|
|
|
+using MECF.Framework.Common.Simulator;
|
|
|
+using MECF.Framework.Simulator.Core.Driver;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using static MECF.Framework.Common.Simulator.MotorSimulator;
|
|
|
+
|
|
|
+namespace CyberX8_Simulator.Devices
|
|
|
+{
|
|
|
+ public class WagoSocketSimulator : SocketDeviceSimulator
|
|
|
+ {
|
|
|
+ private const short WRITE_DO_STARTADDRESS = 0x0200;
|
|
|
private const short WRITE_AO_STARTADDRESS = 0x0200;
|
|
|
|
|
|
//键是名字,值是对应数据所在的位置 注意:要和WagoControlCfg里面的地址顺序对上
|
|
@@ -27,41 +27,41 @@ namespace CyberX8_Simulator.Devices
|
|
|
|
|
|
public Dictionary<string, int> AINameIndexDic;
|
|
|
|
|
|
- public Dictionary<string, int> AONameIndexDic;
|
|
|
-
|
|
|
- private IByteTransform byteTransform = new BigEndianByteTransformBase();
|
|
|
- //存储模拟器数据的数组
|
|
|
- public byte[] DOBytes = new byte[200];
|
|
|
-
|
|
|
- public short[] AOShorts = new short[200];
|
|
|
-
|
|
|
- public byte[] DIBytes = new byte[200];
|
|
|
-
|
|
|
- public short[] AIShorts = new short[200];
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 写DO锁
|
|
|
- /// </summary>
|
|
|
- private object _writeDOLocker = new object();
|
|
|
- /// <summary>
|
|
|
- /// 写AO锁
|
|
|
- /// </summary>
|
|
|
- private object _writeAOLocker = new object();
|
|
|
+ public Dictionary<string, int> AONameIndexDic;
|
|
|
+
|
|
|
+ private IByteTransform byteTransform = new BigEndianByteTransformBase();
|
|
|
+ //存储模拟器数据的数组
|
|
|
+ public byte[] DOBytes = new byte[200];
|
|
|
+
|
|
|
+ public short[] AOShorts = new short[200];
|
|
|
+
|
|
|
+ public byte[] DIBytes = new byte[200];
|
|
|
+
|
|
|
+ public short[] AIShorts = new short[200];
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 写DO锁
|
|
|
+ /// </summary>
|
|
|
+ private object _writeDOLocker = new object();
|
|
|
+ /// <summary>
|
|
|
+ /// 写AO锁
|
|
|
+ /// </summary>
|
|
|
+ private object _writeAOLocker = new object();
|
|
|
/// <summary>
|
|
|
/// Festo Data Buffer
|
|
|
- /// </summary>
|
|
|
- private Dictionary<string, bool> _festoDataBuffer = new Dictionary<string, bool>();
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<string, bool> _festoDataBuffer = new Dictionary<string, bool>();
|
|
|
/// <summary>
|
|
|
/// Name-WagoDO dictionary
|
|
|
- /// </summary>
|
|
|
- private Dictionary<string, WagoDO> _doNameWagoDODic = new Dictionary<string, WagoDO>();
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<string, WagoDO> _doNameWagoDODic = new Dictionary<string, WagoDO>();
|
|
|
/// <summary>
|
|
|
/// Name-WagoDI dictionary
|
|
|
- /// </summary>
|
|
|
- private Dictionary<string, WagoDI> _diNameWagoDIDic = new Dictionary<string, WagoDI>();
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<string, WagoDI> _diNameWagoDIDic = new Dictionary<string, WagoDI>();
|
|
|
/// <summary>
|
|
|
/// 定时器
|
|
|
- /// </summary>
|
|
|
+ /// </summary>
|
|
|
private PeriodicJob _LoaderPeriodicJob;
|
|
|
private PeriodicJob _Wago2PeriodicJob;
|
|
|
private PeriodicJob _Wago4PeriodicJob;
|
|
@@ -92,14 +92,14 @@ namespace CyberX8_Simulator.Devices
|
|
|
public event VariableValueChanged OnAIVariableValueChanged;
|
|
|
public event VariableValueChanged OnDOVariableValueChanged;
|
|
|
public event VariableValueChanged OnAOVariableValueChanged;
|
|
|
- #endregion
|
|
|
-
|
|
|
- public WagoSocketSimulator(int port):base(port)
|
|
|
- {
|
|
|
- SimulatorCommManager.Instance.OnUpdateVariableValueChanged += UpdataDataCausedByOtherModule;
|
|
|
- MotorSimulator.Instance.OnUpdateWagoDatasChanged += UpdataDataCausedByOtherModule;
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ public WagoSocketSimulator(int port):base(port)
|
|
|
+ {
|
|
|
+ SimulatorCommManager.Instance.OnUpdateVariableValueChanged += UpdataDataCausedByOtherModule;
|
|
|
+ MotorSimulator.Instance.OnUpdateWagoDatasChanged += UpdataDataCausedByOtherModule;
|
|
|
InitializeData(port);
|
|
|
- _port = port;
|
|
|
+ _port = port;
|
|
|
}
|
|
|
private void UpdataDataCausedByOtherModule(string sourceName,string name, bool value, bool invert)
|
|
|
{
|
|
@@ -298,11 +298,11 @@ namespace CyberX8_Simulator.Devices
|
|
|
UpdataDIBytes("r_METAL4_PUMP_ON", value ? 1 : 0);
|
|
|
}
|
|
|
}
|
|
|
- /// <summary>
|
|
|
- /// 初始化字典
|
|
|
- /// </summary>
|
|
|
- private void InitializeData(int port) //端口用于初始化不同Wago设备的字典
|
|
|
- {
|
|
|
+ /// <summary>
|
|
|
+ /// 初始化字典
|
|
|
+ /// </summary>
|
|
|
+ private void InitializeData(int port) //端口用于初始化不同Wago设备的字典
|
|
|
+ {
|
|
|
//加载对应配置文件 WagoControllerCfg-Simulator.xml
|
|
|
try
|
|
|
{
|
|
@@ -459,7 +459,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
if (AINameIndexDic.ContainsKey("r_MBS2_FLOW")) AIShorts[AINameIndexDic["r_MBS2_FLOW"]] = 16000;
|
|
|
|
|
|
}
|
|
|
- #region 公共方法
|
|
|
+ #region 公共方法
|
|
|
public void UpdataDOBytes(string name,int value)
|
|
|
{
|
|
|
if (OnDOVariableValueChanged != null)
|
|
@@ -535,237 +535,237 @@ namespace CyberX8_Simulator.Devices
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 功能方法
|
|
|
+ /// <summary>
|
|
|
+ /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="byteArray"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public byte ConvertByteArrayToHex(byte[] byteArray)
|
|
|
+ {
|
|
|
+ byte result = 0;
|
|
|
+ // 先将 byte 数组转换为二进制数
|
|
|
+ int binaryValue = 0;
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ binaryValue |= (byteArray[i] << (7 - i));
|
|
|
+ }
|
|
|
|
|
|
- #region 功能方法
|
|
|
- /// <summary>
|
|
|
- /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式)
|
|
|
- /// </summary>
|
|
|
- /// <param name="byteArray"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public byte ConvertByteArrayToHex(byte[] byteArray)
|
|
|
- {
|
|
|
- byte result = 0;
|
|
|
- // 先将 byte 数组转换为二进制数
|
|
|
- int binaryValue = 0;
|
|
|
- for (int i = 0; i < 8; i++)
|
|
|
- {
|
|
|
- binaryValue |= (byteArray[i] << (7 - i));
|
|
|
- }
|
|
|
-
|
|
|
- // 逆转二进制数
|
|
|
- int reversedValue = 0;
|
|
|
- for (int i = 0; i < 8; i++)
|
|
|
- {
|
|
|
- reversedValue |= ((binaryValue >> i) & 1) << (7 - i);
|
|
|
- }
|
|
|
- // 转换为十六进制byte
|
|
|
- if (byte.TryParse(reversedValue.ToString("X2"), System.Globalization.NumberStyles.HexNumber, null, out result))
|
|
|
- {
|
|
|
- return result;
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 将short数组转成长度两倍的byte数组
|
|
|
- /// </summary>
|
|
|
- /// <param name="shortArray"></param>
|
|
|
- /// <returns></returns>
|
|
|
- private byte[] ConvertShortArrayToByteArray(short[] shortArray)
|
|
|
- {
|
|
|
- byte[] byteArray = new byte[shortArray.Length * 2];
|
|
|
- for (int i = 0; i < shortArray.Length; i++)
|
|
|
- {
|
|
|
- byte[] tempBytes = BitConverter.GetBytes(shortArray[i]);
|
|
|
- Array.Reverse(tempBytes);
|
|
|
- Array.Copy(tempBytes, 0, byteArray, i * 2, 2);
|
|
|
- }
|
|
|
- return byteArray;
|
|
|
- }
|
|
|
- #endregion
|
|
|
-
|
|
|
- protected override void ProcessUnsplitMessage(byte[] data)
|
|
|
- {
|
|
|
- byte command = data[7];
|
|
|
- if (command == 0x01) //读DO
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- short bitCount = byteTransform.TransInt16(data, 10);
|
|
|
- byte byteCount = (byte)(bitCount / 8 + 1);
|
|
|
- byte[] bytes = new byte[byteCount];
|
|
|
- for(int i = 0; i < byteCount;i++)
|
|
|
- {
|
|
|
- byte[] tempbytes = new byte[8];
|
|
|
- Array.Copy(DOBytes,8 * i, tempbytes, 0, 8);
|
|
|
- bytes[i] = ConvertByteArrayToHex(tempbytes);
|
|
|
- }
|
|
|
- OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
|
|
|
- return;
|
|
|
- }
|
|
|
- else if(command == 0x03)//读AO
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- short registerCount = byteTransform.TransInt16(data, 10);
|
|
|
- short[] shorts = new short[registerCount];//获取指定寄存器里的内容
|
|
|
- Array.Copy(AOShorts, 0, shorts, 0, registerCount);
|
|
|
- byte[] bytes = new byte[registerCount * 2];
|
|
|
- bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组长度两倍的bytes数组中
|
|
|
- OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (command == 0x02)//读DI
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- short bitCount = byteTransform.TransInt16(data, 10);
|
|
|
- byte byteCount = (byte)(bitCount / 8 + 1);
|
|
|
- byte[] bytes = new byte[byteCount];
|
|
|
- for (int i = 0; i < byteCount; i++)
|
|
|
- {
|
|
|
- byte[] tempbytes = new byte[8];
|
|
|
- Array.Copy(DIBytes, 8 * i, tempbytes, 0, 8);
|
|
|
- bytes[i] = ConvertByteArrayToHex(tempbytes);
|
|
|
- }
|
|
|
- OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (command == 0x04)//读AI
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- short registerCount = byteTransform.TransInt16(data, 10);
|
|
|
- short[] shorts = new short[registerCount];//获取指定寄存器里的内容
|
|
|
- Array.Copy(AIShorts, 0, shorts, 0, registerCount);
|
|
|
- byte[] bytes = new byte[registerCount * 2];
|
|
|
- bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组两倍的bytes数组中
|
|
|
- OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (command == 0x05)//写DO
|
|
|
- {
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- if (startAddress > 0x03FF || startAddress < WRITE_DO_STARTADDRESS)
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
|
|
|
- return;
|
|
|
- }
|
|
|
- int position = startAddress - WRITE_DO_STARTADDRESS;
|
|
|
- bool status = data[10] == 0xFF ? true : false;
|
|
|
- lock (_writeDOLocker)
|
|
|
- {
|
|
|
- DOBytes[position] = status ? (byte)1 : (byte)0;
|
|
|
- }
|
|
|
- OnWriteMessage(data); //原消息返回
|
|
|
- //触发Wago对应数据更新
|
|
|
+ // 逆转二进制数
|
|
|
+ int reversedValue = 0;
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ reversedValue |= ((binaryValue >> i) & 1) << (7 - i);
|
|
|
+ }
|
|
|
+ // 转换为十六进制byte
|
|
|
+ if (byte.TryParse(reversedValue.ToString("X2"), System.Globalization.NumberStyles.HexNumber, null, out result))
|
|
|
+ {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 将short数组转成长度两倍的byte数组
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="shortArray"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] ConvertShortArrayToByteArray(short[] shortArray)
|
|
|
+ {
|
|
|
+ byte[] byteArray = new byte[shortArray.Length * 2];
|
|
|
+ for (int i = 0; i < shortArray.Length; i++)
|
|
|
+ {
|
|
|
+ byte[] tempBytes = BitConverter.GetBytes(shortArray[i]);
|
|
|
+ Array.Reverse(tempBytes);
|
|
|
+ Array.Copy(tempBytes, 0, byteArray, i * 2, 2);
|
|
|
+ }
|
|
|
+ return byteArray;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ protected override void ProcessUnsplitMessage(byte[] data)
|
|
|
+ {
|
|
|
+ byte command = data[7];
|
|
|
+ if (command == 0x01) //读DO
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ short bitCount = byteTransform.TransInt16(data, 10);
|
|
|
+ byte byteCount = (byte)(bitCount / 8 + 1);
|
|
|
+ byte[] bytes = new byte[byteCount];
|
|
|
+ for(int i = 0; i < byteCount;i++)
|
|
|
+ {
|
|
|
+ byte[] tempbytes = new byte[8];
|
|
|
+ Array.Copy(DOBytes,8 * i, tempbytes, 0, 8);
|
|
|
+ bytes[i] = ConvertByteArrayToHex(tempbytes);
|
|
|
+ }
|
|
|
+ OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if(command == 0x03)//读AO
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ short registerCount = byteTransform.TransInt16(data, 10);
|
|
|
+ short[] shorts = new short[registerCount];//获取指定寄存器里的内容
|
|
|
+ Array.Copy(AOShorts, 0, shorts, 0, registerCount);
|
|
|
+ byte[] bytes = new byte[registerCount * 2];
|
|
|
+ bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组长度两倍的bytes数组中
|
|
|
+ OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (command == 0x02)//读DI
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ short bitCount = byteTransform.TransInt16(data, 10);
|
|
|
+ byte byteCount = (byte)(bitCount / 8 + 1);
|
|
|
+ byte[] bytes = new byte[byteCount];
|
|
|
+ for (int i = 0; i < byteCount; i++)
|
|
|
+ {
|
|
|
+ byte[] tempbytes = new byte[8];
|
|
|
+ Array.Copy(DIBytes, 8 * i, tempbytes, 0, 8);
|
|
|
+ bytes[i] = ConvertByteArrayToHex(tempbytes);
|
|
|
+ }
|
|
|
+ OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (command == 0x04)//读AI
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ short registerCount = byteTransform.TransInt16(data, 10);
|
|
|
+ short[] shorts = new short[registerCount];//获取指定寄存器里的内容
|
|
|
+ Array.Copy(AIShorts, 0, shorts, 0, registerCount);
|
|
|
+ byte[] bytes = new byte[registerCount * 2];
|
|
|
+ bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组两倍的bytes数组中
|
|
|
+ OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (command == 0x05)//写DO
|
|
|
+ {
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ if (startAddress > 0x03FF || startAddress < WRITE_DO_STARTADDRESS)
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int position = startAddress - WRITE_DO_STARTADDRESS;
|
|
|
+ bool status = data[10] == 0xFF ? true : false;
|
|
|
+ lock (_writeDOLocker)
|
|
|
+ {
|
|
|
+ DOBytes[position] = status ? (byte)1 : (byte)0;
|
|
|
+ }
|
|
|
+ OnWriteMessage(data); //原消息返回
|
|
|
+ //触发Wago对应数据更新
|
|
|
UpdateDataCausedByWago(position, status);
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (command == 0x06)//写AO
|
|
|
- {
|
|
|
- short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
- if(startAddress > 0x02FF || startAddress < WRITE_AO_STARTADDRESS)
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
|
|
|
- return;
|
|
|
- }
|
|
|
- int position = startAddress - WRITE_AO_STARTADDRESS;
|
|
|
- short value = byteTransform.TransInt16(data, 10);
|
|
|
- lock (_writeAOLocker)
|
|
|
- {
|
|
|
- AOShorts[position] = value;
|
|
|
- }
|
|
|
- OnWriteMessage(data); //原消息返回
|
|
|
- return;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- short flag = byteTransform.TransInt16(data, 0);
|
|
|
- byte channel = data[6];
|
|
|
- OnWriteMessage(CreateError(flag, channel, command, 0x01)); //指令错误
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 回复读数字量
|
|
|
- /// </summary>
|
|
|
- /// <param name="flag"></param>
|
|
|
- /// <param name="channel"></param>
|
|
|
- /// <param name="command"></param>
|
|
|
- /// <param name="byteCount"></param>
|
|
|
- /// <param name="values"></param>
|
|
|
- /// <returns></returns>
|
|
|
- private byte[] CreateReadDigitalResponse(short flag, byte channel, byte command, byte byteCount, byte[] values)
|
|
|
- {
|
|
|
- byte[] bytes = new byte[7 + 2 + values.Length]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+values.length个字节
|
|
|
- Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
- bytes[2] = 0x00;
|
|
|
- bytes[3] = 0x00;
|
|
|
- short dataLength = (short)(3 + values.Length);
|
|
|
- Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
|
|
|
- bytes[6] = channel;
|
|
|
- bytes[7] = command;
|
|
|
- bytes[8] = byteCount;
|
|
|
- Array.Copy(values, 0, bytes, 9, values.Length);
|
|
|
- return bytes;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 回复读模拟量
|
|
|
- /// </summary>
|
|
|
- /// <param name="flag"></param>
|
|
|
- /// <param name="channel"></param>
|
|
|
- /// <param name="command"></param>
|
|
|
- /// <param name="registerCount"></param>
|
|
|
- /// <param name="values"></param>
|
|
|
- /// <returns></returns>
|
|
|
- private byte[] CreateReadAnalogyResponse(short flag, byte channel, byte command, byte registerCount, byte[] values)
|
|
|
- {
|
|
|
- byte[] bytes = new byte[7 + 2 + 2 * registerCount]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+registerCount*2个字节(一个寄存器占两个字节)
|
|
|
- Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
- bytes[2] = 0x00;
|
|
|
- bytes[3] = 0x00;
|
|
|
- short dataLength = (short)(3 + 2 * registerCount);
|
|
|
- Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
|
|
|
- bytes[6] = channel;
|
|
|
- bytes[7] = command;
|
|
|
- bytes[8] = (byte)(2 * registerCount);
|
|
|
- Array.Copy(values, 0, bytes, 9, values.Length);
|
|
|
- return bytes;
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 错误回复
|
|
|
- /// </summary>
|
|
|
- /// <param name="flag"></param>
|
|
|
- /// <param name="channel"></param>
|
|
|
- /// <param name="command"></param>
|
|
|
- /// <param name="error"></param>
|
|
|
- /// <returns></returns>
|
|
|
- private byte[] CreateError(short flag, byte channel, byte command, byte error)
|
|
|
- {
|
|
|
- byte[] bytes = new byte[9];
|
|
|
- Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
- bytes[2] = 0x00;
|
|
|
- bytes[3] = 0x00;
|
|
|
- bytes[4] = 0x00;
|
|
|
- bytes[5] = 0x03;
|
|
|
- bytes[6] = channel;
|
|
|
- bytes[7] = (byte)(command | 0x80);
|
|
|
- bytes[8] = error;
|
|
|
- return bytes;
|
|
|
- }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (command == 0x06)//写AO
|
|
|
+ {
|
|
|
+ short startAddress = byteTransform.TransInt16(data, 8);
|
|
|
+ if(startAddress > 0x02FF || startAddress < WRITE_AO_STARTADDRESS)
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int position = startAddress - WRITE_AO_STARTADDRESS;
|
|
|
+ short value = byteTransform.TransInt16(data, 10);
|
|
|
+ lock (_writeAOLocker)
|
|
|
+ {
|
|
|
+ AOShorts[position] = value;
|
|
|
+ }
|
|
|
+ OnWriteMessage(data); //原消息返回
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ short flag = byteTransform.TransInt16(data, 0);
|
|
|
+ byte channel = data[6];
|
|
|
+ OnWriteMessage(CreateError(flag, channel, command, 0x01)); //指令错误
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 回复读数字量
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="flag"></param>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <param name="byteCount"></param>
|
|
|
+ /// <param name="values"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] CreateReadDigitalResponse(short flag, byte channel, byte command, byte byteCount, byte[] values)
|
|
|
+ {
|
|
|
+ byte[] bytes = new byte[7 + 2 + values.Length]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+values.length个字节
|
|
|
+ Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
+ bytes[2] = 0x00;
|
|
|
+ bytes[3] = 0x00;
|
|
|
+ short dataLength = (short)(3 + values.Length);
|
|
|
+ Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
|
|
|
+ bytes[6] = channel;
|
|
|
+ bytes[7] = command;
|
|
|
+ bytes[8] = byteCount;
|
|
|
+ Array.Copy(values, 0, bytes, 9, values.Length);
|
|
|
+ return bytes;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 回复读模拟量
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="flag"></param>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <param name="registerCount"></param>
|
|
|
+ /// <param name="values"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] CreateReadAnalogyResponse(short flag, byte channel, byte command, byte registerCount, byte[] values)
|
|
|
+ {
|
|
|
+ byte[] bytes = new byte[7 + 2 + 2 * registerCount]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+registerCount*2个字节(一个寄存器占两个字节)
|
|
|
+ Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
+ bytes[2] = 0x00;
|
|
|
+ bytes[3] = 0x00;
|
|
|
+ short dataLength = (short)(3 + 2 * registerCount);
|
|
|
+ Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
|
|
|
+ bytes[6] = channel;
|
|
|
+ bytes[7] = command;
|
|
|
+ bytes[8] = (byte)(2 * registerCount);
|
|
|
+ Array.Copy(values, 0, bytes, 9, values.Length);
|
|
|
+ return bytes;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 错误回复
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="flag"></param>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <param name="error"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] CreateError(short flag, byte channel, byte command, byte error)
|
|
|
+ {
|
|
|
+ byte[] bytes = new byte[9];
|
|
|
+ Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
|
|
|
+ bytes[2] = 0x00;
|
|
|
+ bytes[3] = 0x00;
|
|
|
+ bytes[4] = 0x00;
|
|
|
+ bytes[5] = 0x03;
|
|
|
+ bytes[6] = channel;
|
|
|
+ bytes[7] = (byte)(command | 0x80);
|
|
|
+ bytes[8] = error;
|
|
|
+ return bytes;
|
|
|
+ }
|
|
|
/// <summary>
|
|
|
/// loader 定时器
|
|
|
/// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <returns></returns>
|
|
|
private bool OnTimer()
|
|
|
{
|
|
|
LeakTestSimulator();
|
|
@@ -774,7 +774,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
/// <summary>
|
|
|
/// Wago2定时器
|
|
|
/// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <returns></returns>
|
|
|
private bool OnTimer1()
|
|
|
{
|
|
|
RinseWaterLevelSimulator();
|
|
@@ -784,16 +784,16 @@ namespace CyberX8_Simulator.Devices
|
|
|
/// <summary>
|
|
|
/// Wago4定时器
|
|
|
/// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <returns></returns>
|
|
|
private bool OnTimer3()
|
|
|
{
|
|
|
Pump4FlowSimulator();
|
|
|
return true;
|
|
|
}
|
|
|
- #region 模拟方法
|
|
|
+ #region 模拟方法
|
|
|
/// <summary>
|
|
|
/// Loader LeakTest模拟
|
|
|
- /// </summary>
|
|
|
+ /// </summary>
|
|
|
private void LeakTestSimulator()
|
|
|
{
|
|
|
if (DOBytes[DONameIndexDic["c_VACUUM_TEST"]] == 1 && _festoDataBuffer["FlowTestClamp"] && AIShorts[AINameIndexDic["r_LOADER_GasFlowSensor_FLOW"]] == 0)
|
|
@@ -816,7 +816,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
|
|
|
/// <summary>
|
|
|
/// QDR水位模拟
|
|
|
- /// </summary>
|
|
|
+ /// </summary>
|
|
|
private void RinseWaterLevelSimulator()
|
|
|
{
|
|
|
//QDR1
|
|
@@ -881,7 +881,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// metal1/2/3 pump流量模拟
|
|
|
- /// </summary>
|
|
|
+ /// </summary>
|
|
|
private void PumpFlowSimulator()
|
|
|
{
|
|
|
if (DOBytes[DONameIndexDic["c_METAL3_PUMP_ON"]] == 1)
|
|
@@ -913,7 +913,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// metal4 pump流量模拟
|
|
|
- /// </summary>
|
|
|
+ /// </summary>
|
|
|
private void Pump4FlowSimulator()
|
|
|
{
|
|
|
if (DONameIndexDic.ContainsKey("c_METAL4_PUMP_ON") && DOBytes[DONameIndexDic["c_METAL4_PUMP_ON"]] == 1)
|
|
@@ -924,7 +924,7 @@ namespace CyberX8_Simulator.Devices
|
|
|
{
|
|
|
SimulatorCommManager.Instance.CheckDataChanged("c_METAL4_PUMP_ON", false, false);
|
|
|
}
|
|
|
- }
|
|
|
- #endregion
|
|
|
- }
|
|
|
-}
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|