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
}
}