using HslCommunication.Core; using HslCommunication.Serial; using System; using System.Collections.Generic; using System.Linq; using System.Text; using HslCommunication.BasicFramework; namespace HslCommunication.Profinet.LSIS { /// /// XGB Cnet I/F module supports Serial Port. /// public class XGBCnet : SerialDeviceBase { #region Constructor /// /// Instantiate a Default object /// public XGBCnet() { WordLength = 2; ByteTransform = new RegularByteTransform(); } #endregion #region Public Member /// /// PLC Station No. /// public byte Station { get; set; } = 0x05; #endregion #region Read Write Byte /// /// Read single byte value from plc /// /// Start address /// result public OperateResult ReadByte(string address) { var read = Read(address, 2); if (!read.IsSuccess) return OperateResult.CreateFailedResult(read); return OperateResult.CreateSuccessResult(read.Content[0]); } /// /// Write single byte value to plc /// /// Start address /// value /// Whether to write the successful public OperateResult Write(string address, byte value) { return Write(address, new byte[] { value }); } /// /// WriteCoil /// /// /// /// public OperateResult WriteCoil(string address, bool value) { return Write(address, new byte[] { (byte)(value ? 0x01 : 0x00), 0x00 }); } #endregion #region Read Write Support /// /// Read Bytes From PLC, you should specify the length /// /// the address of the data /// the length of the data, in byte unit /// result contains whether success. public override OperateResult Read(string address, ushort length) { OperateResult command = BuildReadByteCommand(Station, address, length); if (!command.IsSuccess) return command; OperateResult read = ReadBase(command.Content); if (!read.IsSuccess) return read; return ExtractActualData(read.Content, true); } /// /// Write Data into plc, , you should specify the address /// /// the address of the data /// source data /// result contains whether success. public override OperateResult Write(string address, byte[] value) { OperateResult command = BuildWriteByteCommand(Station, address, value); if (!command.IsSuccess) return command; OperateResult read = ReadBase(command.Content); if (!read.IsSuccess) return read; return ExtractActualData(read.Content, false); } #endregion #region Object Override /// /// Returns a string representing the current object /// /// ×Ö·û´®ÐÅÏ¢ public override string ToString() { return $"XGBCnet[{PortName}:{BaudRate}]"; } #endregion #region Static Helper /// /// reading address Type of ReadByte /// /// plc station /// address, for example: M100, D100, DW100 /// read length /// command bytes private static OperateResult BuildReadByteCommand(byte station, string address, ushort length) { var analysisResult = XGBFastEnet.AnalysisAddress(address, true); if (!analysisResult.IsSuccess) return OperateResult.CreateFailedResult(analysisResult); List command = new List(); command.Add(0x05); // ENQ command.AddRange(SoftBasic.BuildAsciiBytesFrom(station)); command.Add(0x72); // command r command.Add(0x53); // command type: SB command.Add(0x42); command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)analysisResult.Content.Length)); command.AddRange(Encoding.ASCII.GetBytes(analysisResult.Content)); command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)length)); command.Add(0x04); // EOT int sum = 0; for (int i = 0; i < command.Count; i++) { sum += command[i]; } command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)sum)); return OperateResult.CreateSuccessResult(command.ToArray()); } /// /// One reading address Type of ReadByte /// /// plc station /// address, for example: MX100, DW100, TW100 /// read length /// private static OperateResult BuildReadOneCommand(byte station, string address, ushort length) { var analysisResult = XGBFastEnet.AnalysisAddress(address, true); if (!analysisResult.IsSuccess) return OperateResult.CreateFailedResult(analysisResult); List command = new List(); command.Add(0x05); // ENQ command.AddRange(SoftBasic.BuildAsciiBytesFrom(station)); command.Add(0x72); // command r command.Add(0x53); // command type: SS command.Add(0x53); command.Add(0x01); // Number of blocks command.Add(0x00); command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)analysisResult.Content.Length)); command.AddRange(Encoding.ASCII.GetBytes(analysisResult.Content)); command.Add(0x04); // EOT int sum = 0; for (int i = 0; i < command.Count; i++) { sum += command[i]; } command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)sum)); return OperateResult.CreateSuccessResult(command.ToArray()); } /// /// write data to address Type of ReadByte /// /// plc station /// address, for example: M100, D100, DW100 /// source value /// command bytes private static OperateResult BuildWriteByteCommand(byte station, string address, byte[] value) { var analysisResult = XGBFastEnet.AnalysisAddress(address, false); if (!analysisResult.IsSuccess) return OperateResult.CreateFailedResult(analysisResult); var DataTypeResult = XGBFastEnet.GetDataTypeToAddress(address); if (!DataTypeResult.IsSuccess) return OperateResult.CreateFailedResult(DataTypeResult); List command = new List(); command.Add(0x05); // ENQ command.AddRange(SoftBasic.BuildAsciiBytesFrom(station)); command.Add(0x77); // command w command.Add(0x53); // command type: S switch (DataTypeResult.Content) { case "Bit": case "Byte": command.Add(0x53); // command type: SS command.Add(0x30); // Number of blocks command.Add(0x31); command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)analysisResult.Content.Length)); command.AddRange(Encoding.ASCII.GetBytes(analysisResult.Content)); break; case "Word": case "DWord": case "LWord": case "Continuous": command.Add(0x42); // command type: SB command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)analysisResult.Content.Length)); command.AddRange(Encoding.ASCII.GetBytes(analysisResult.Content)); command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)value.Length)); break; default: break; } command.AddRange(SoftBasic.BytesToAsciiBytes(value)); command.Add(0x04); // EOT int sum = 0; for (int i = 0; i < command.Count; i++) { sum += command[i]; } command.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)sum)); return OperateResult.CreateSuccessResult(command.ToArray()); } /// /// Extract actual data form plc response /// /// response data /// read /// result public static OperateResult ExtractActualData(byte[] response, bool isRead) { try { if (isRead) { if (response[0] == 0x06) { byte[] buffer = new byte[response.Length - 13]; Array.Copy(response, 10, buffer, 0, buffer.Length); return OperateResult.CreateSuccessResult(SoftBasic.AsciiBytesToBytes(buffer)); } else { byte[] buffer = new byte[response.Length - 9]; Array.Copy(response, 6, buffer, 0, buffer.Length); return new OperateResult(BitConverter.ToUInt16(SoftBasic.AsciiBytesToBytes(buffer), 0), "Data:" + SoftBasic.ByteToHexString(response)); } } else { if (response[0] == 0x06) { return OperateResult.CreateSuccessResult(new byte[0]); } else { byte[] buffer = new byte[response.Length - 9]; Array.Copy(response, 6, buffer, 0, buffer.Length); return new OperateResult(BitConverter.ToUInt16(SoftBasic.AsciiBytesToBytes(buffer), 0), "Data:" + SoftBasic.ByteToHexString(response)); } } } catch (Exception ex) { return new OperateResult(ex.Message); } } #endregion } }