123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- using Aitex.Common.Util;
- using Aitex.Core.RT.Device;
- using Aitex.Core.RT.IOCore;
- using Aitex.Core.Util;
- using MECF.Framework.Common.Device.Festo;
- using MECF.Framework.Common.Net;
- using MECF.Framework.Simulator.Core.Driver;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net;
- using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
- namespace CyberX8_Simulator.Devices
- {
- public class FestoSocketSimulator : SocketDeviceSimulator
- {
- //Write Address
- private const ushort FESTO_DO_START_ADDRESS = 0x9C43;//FestoDO起始地址(40003)
- //Read Address
- private const ushort FESTO_DI_START_ADDRESS = 0xB153;//FestoDI起始地址(45395)
- //Register Count
- private const int FESTO_REGISTER_COUNT = 100;
- private IByteTransform byteTransform = new BigEndianByteTransformBase();
- /// <summary>
- /// 数据(index - data)
- /// </summary>
- private short[] _festoOutputDataDic = new short[FESTO_REGISTER_COUNT];
- /// <summary>
- /// 数据(DOName - index)
- /// </summary>
- private Dictionary<string, FestoDO> _festoNameIndexDic = new Dictionary<string, FestoDO>();
- /// <summary>
- /// do 索引对象字典(key-地址索引-bit,value--do名称)
- /// </summary>
- private Dictionary<string, string> _doNameDictionary = new Dictionary<string, string>();
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="port"></param>
- public FestoSocketSimulator(int port) : base(port)
- {
- for(int i = 0; i < FESTO_REGISTER_COUNT; i++)
- {
- _festoOutputDataDic[i] = 0x00;
- }
- string oldXmlPath = PathManager.GetCfgDir();
- string newXmlPath = oldXmlPath.Replace("CyberX8_Simulator", "CyberX8_RT") + "Devices\\FestoControllerCfg-Simulator.xml";
- FestoControllerCfg cfg = CustomXmlSerializer.Deserialize<FestoControllerCfg>(new FileInfo(newXmlPath));
- foreach (FestoDeviceConfig config in cfg.FestoDeviceConfigs)
- {
- if(port == config.Port)
- {
- foreach (FestoDO item in config.FestoDoes)
- {
- _festoNameIndexDic[item.Name] = item;
- string str = $"{item.Address}-{item.Bit}";
- _doNameDictionary[str] = item.Name;
- }
- }
- }
- }
- /// <summary>
- /// 解析信息
- /// </summary>
- /// <param name="data"></param>
- protected override void ProcessUnsplitMessage(byte[] data)
- {
- short flag = byteTransform.TransInt16(data, 0);//事务标识符
- byte channel = data[6];//单元标识符
- byte command = data[7];//功能码
- if (command == 0x03)//读取
- {
- ushort startAddress = byteTransform.TransUInt16(data, 8);//起始寄存器地址
- short registerCount = byteTransform.TransInt16(data, 10);//寄存器数量
- byte[] bytes = new byte[2 * registerCount];//读取2*registerCount Byte数据
- if (startAddress >= FESTO_DI_START_ADDRESS)
- {
- for (int i = 0; i < registerCount; i++)
- {
- Array.Copy(byteTransform.GetBytes(_festoOutputDataDic[startAddress - FESTO_DI_START_ADDRESS + i]), 0, bytes, i * 2, 2);
- }
- OnWriteMessage(CreateReadResponse(flag, channel, command, registerCount, bytes));
- }
- else
- {
- OnWriteMessage(CreateError(flag, channel, command, 0x8A));
- }
- }
- else if(command == 0x06)//写入
- {
- ushort startAddress = byteTransform.TransUInt16(data, 8);//起始寄存器地址
- short value = byteTransform.TransInt16(data, 10);//写入的值(2 Byte)
- if(startAddress >= FESTO_DO_START_ADDRESS)
- {
- //通知相关数据变化
- var result = DecodeDOData(startAddress, value);
- SimulatorCommManager.Instance.CheckDataChanged(result.Item1, result.Item2);
- //modbus起始地址n为数据,n+1为诊断数据,取地址n下的数据
- _festoOutputDataDic[(startAddress - FESTO_DO_START_ADDRESS) * 2] = value;
-
- OnWriteMessage(CreateWriteResponse(flag, channel, command, startAddress, value));
- }
- else
- {
- OnWriteMessage(CreateError(flag, channel, command, 0x8A));
- }
- }
- else
- {
- OnWriteMessage(CreateError(flag, channel, command, 0x84));
- }
- }
- /// <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[] CreateReadResponse(short flag, byte channel, byte command, short registerCount, byte[] values)
- {
-
- byte[] bytes = new byte[6 + 3 + 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] = (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="startAddress"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- private byte[] CreateWriteResponse(short flag, byte channel, byte command, ushort startAddress, short value)
- {
- byte[] bytes = new byte[12];
- Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
- bytes[2] = 0x00;
- bytes[3] = 0x00;
- bytes[4] = 0x00;
- bytes[5] = 0x06;
- bytes[6] = channel;
- bytes[7] = command;
- byte[] addressByt = byteTransform.GetBytes(startAddress);
- Array.Copy(addressByt, 0, bytes, 8, 2);
- byte[] valueByt = byteTransform.GetBytes(value);
- Array.Copy(valueByt, 0, bytes, 10, 2);
- 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>
- /// 更新DI数据
- /// </summary>
- /// <param name="name"></param>
- /// <param name="value"></param>
- public void UpdataDOBytes(string name, int value)
- {
- if (_festoNameIndexDic.ContainsKey(name))
- {
- FestoDO festoDO = _festoNameIndexDic[name];
- short byteValue = (short) (_festoOutputDataDic[(festoDO.Address - FESTO_DO_START_ADDRESS) * 2] & ~(1 << festoDO.Bit));
- short tmp = (short)(value << festoDO.Bit);
- _festoOutputDataDic[(festoDO.Address - FESTO_DO_START_ADDRESS) * 2] = (short)(byteValue | tmp);
- }
- }
- /// <summary>
- /// 解析数据
- /// </summary>
- /// <param name="address"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- private (string, bool) DecodeDOData(ushort address, short value)
- {
- int index = (address - FESTO_DO_START_ADDRESS) * 2;
- int bitNum = (int)Math.Log(_festoOutputDataDic[index] ^ value, 2);
- bool valueBool = (value & (1 << bitNum)) != 0 ? true : false;
- string str = $"{address}-{bitNum}";
- return (_doNameDictionary[str], valueBool);
- }
- }
- }
|