Modbus ASCII and Siemens PPI support (not test), ComConnector Remaintainence.
This commit is contained in:
@@ -43,6 +43,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AddressFormaterModbus.cs" />
|
||||
<Compile Include="AddressTranslatorModbus.cs" />
|
||||
<Compile Include="ModbusAsciiProtocal.cs" />
|
||||
<Compile Include="ModbusAsciiProtocalLinker.cs" />
|
||||
<Compile Include="ModbusMachine.cs" />
|
||||
<Compile Include="ModbusProtocal.cs" />
|
||||
<Compile Include="ModbusProtocalLinkerBytesExtend.cs" />
|
||||
|
||||
23
Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs
Normal file
23
Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocal.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
/// <summary>
|
||||
/// Modbus/Rtu协议
|
||||
/// </summary>
|
||||
public class ModbusAsciiProtocal : ModbusProtocal
|
||||
{
|
||||
public ModbusAsciiProtocal() : this(ConfigurationManager.COM)
|
||||
{
|
||||
}
|
||||
|
||||
public ModbusAsciiProtocal(string com)
|
||||
{
|
||||
ProtocalLinker = new ModbusAsciiProtocalLinker(com);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs
Normal file
33
Modbus.Net/Modbus.Net.Modbus/ModbusAsciiProtocalLinker.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
public class ModbusAsciiProtocalLinker : ComProtocalLinker
|
||||
{
|
||||
public override bool? CheckRight(byte[] content)
|
||||
{
|
||||
if (!base.CheckRight(content).Value) return false;
|
||||
//CRC校验失败
|
||||
string contentString = Encoding.ASCII.GetString(content);
|
||||
if (!Crc16.GetInstance().LrcEfficacy(contentString))
|
||||
{
|
||||
throw new ModbusProtocalErrorException(501);
|
||||
}
|
||||
//Modbus协议错误
|
||||
if (byte.Parse(contentString.Substring(3, 2)) > 127)
|
||||
{
|
||||
throw new ModbusProtocalErrorException(byte.Parse(contentString.Substring(5, 2)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ModbusAsciiProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,9 +124,10 @@ namespace Modbus.Net.Modbus
|
||||
var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
|
||||
FunctionCode = (byte)translateAddress.Area;
|
||||
StartAddress = (ushort)translateAddress.Address;
|
||||
WriteCount = (ushort)Math.Ceiling(writeValue.Length / 2.0);
|
||||
WriteByteCount = 0;
|
||||
WriteValue = writeValue;
|
||||
var writeByteValue = BigEndianValueHelper.Instance.ObjectArrayToByteArray(writeValue);
|
||||
WriteCount = (ushort)(writeByteValue.Length / 2);
|
||||
WriteByteCount = (byte)writeByteValue.Length;
|
||||
WriteValue = writeByteValue;
|
||||
}
|
||||
|
||||
public byte BelongAddress { get; private set; }
|
||||
@@ -139,7 +140,7 @@ namespace Modbus.Net.Modbus
|
||||
|
||||
public byte WriteByteCount { get; private set; }
|
||||
|
||||
public object[] WriteValue { get; private set; }
|
||||
public byte[] WriteValue { get; private set; }
|
||||
}
|
||||
|
||||
public class WriteDataModbusOutputStruct : OutputStruct
|
||||
@@ -172,7 +173,6 @@ namespace Modbus.Net.Modbus
|
||||
var r_message = (WriteDataModbusInputStruct)message;
|
||||
byte[] formattingBytes = Format(r_message.BelongAddress, r_message.FunctionCode,
|
||||
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.WriteValue);
|
||||
formattingBytes[6] = (byte)(formattingBytes.Length - 7);
|
||||
return formattingBytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
@@ -43,10 +45,42 @@ namespace Modbus.Net.Modbus
|
||||
|
||||
public override byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
//Modbus/Rtu协议收缩,抛弃后面1个字节的内容
|
||||
//Modbus/Rtu协议收缩,抛弃后面2个字节的内容
|
||||
byte[] newContent = new byte[content.Length - 2];
|
||||
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
|
||||
public class ModbusAsciiProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
|
||||
{
|
||||
public override byte[] BytesExtend(byte[] content)
|
||||
{
|
||||
List<byte> newContent = new List<byte>();
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(":"));
|
||||
foreach (var number in content)
|
||||
{
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(number.ToString()));
|
||||
}
|
||||
newContent.AddRange(Encoding.ASCII.GetBytes(Crc16.GetInstance().GetLRC(content)));
|
||||
newContent.Add(0x0d);
|
||||
newContent.Add(0x0a);
|
||||
return newContent.ToArray();
|
||||
}
|
||||
|
||||
public override byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
List<byte> newContent = new List<byte>();
|
||||
string ans = Encoding.ASCII.GetString(content);
|
||||
var index = ans.IndexOf(Environment.NewLine);
|
||||
ans = ans.Substring(1, index - 1);
|
||||
for (int i = 0; i < ans.Length; i += 2)
|
||||
{
|
||||
var number = byte.Parse(ans.Substring(i, 2));
|
||||
newContent.Add(number);
|
||||
}
|
||||
newContent.RemoveAt(newContent.Count-1);
|
||||
return newContent.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Modbus.Net.Modbus
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace Modbus.Net.Modbus
|
||||
{
|
||||
class ModbusRtuProtocalLinker : ComProtocalLinker
|
||||
{
|
||||
@@ -18,7 +20,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
public ModbusRtuProtocalLinker(string com) : base(com)
|
||||
public ModbusRtuProtocalLinker(string com) : base(com, 9600, Parity.None, StopBits.One, 8)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace Modbus.Net.Modbus
|
||||
/// Tcp连接
|
||||
/// </summary>
|
||||
Tcp = 1,
|
||||
/// <summary>
|
||||
/// Ascii连接
|
||||
/// </summary>
|
||||
Ascii = 2,
|
||||
}
|
||||
|
||||
public class ModbusUtility : BaseUtility
|
||||
@@ -74,6 +78,11 @@ namespace Modbus.Net.Modbus
|
||||
Wrapper = ConnectionString == null ? new ModbusTcpProtocal() : (ConnectionStringPort == null ? new ModbusTcpProtocal(ConnectionString) : new ModbusTcpProtocal(ConnectionStringIp,ConnectionStringPort.Value));
|
||||
break;
|
||||
}
|
||||
case ModbusType.Ascii:
|
||||
{
|
||||
Wrapper = ConnectionString == null ? new ModbusAsciiProtocal() : new ModbusAsciiProtocal(ConnectionString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
<Compile Include="AddressFormaterSiemens.cs" />
|
||||
<Compile Include="AddressTranslatorSiemens.cs" />
|
||||
<Compile Include="SiemensMachine.cs" />
|
||||
<Compile Include="SiemensPpiProtocal.cs" />
|
||||
<Compile Include="SiemensPpiProtocalLinker.cs" />
|
||||
<Compile Include="SiemensProtocal.cs" />
|
||||
<Compile Include="SiemensProtocalLinkerBytesExtend.cs" />
|
||||
<Compile Include="SiemensStructDefinition.cs" />
|
||||
|
||||
70
Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs
Normal file
70
Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocal.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Modbus.Net.Siemens
|
||||
{
|
||||
public class SiemensPpiProtocal : SiemensProtocal
|
||||
{
|
||||
private readonly string _com;
|
||||
private int _connectTryCount;
|
||||
|
||||
public SiemensPpiProtocal() : this( ConfigurationManager.COM)
|
||||
{
|
||||
}
|
||||
|
||||
public SiemensPpiProtocal(string com)
|
||||
{
|
||||
_com = com;
|
||||
_connectTryCount = 0;
|
||||
}
|
||||
|
||||
public override byte[] SendReceive(bool isLittleEndian, params object[] content)
|
||||
{
|
||||
return AsyncHelper.RunSync(() => SendReceiveAsync(isLittleEndian, content));
|
||||
}
|
||||
|
||||
public override async Task<byte[]> SendReceiveAsync(bool isLittleEndian, params object[] content)
|
||||
{
|
||||
if (ProtocalLinker == null || !ProtocalLinker.IsConnected)
|
||||
{
|
||||
await ConnectAsync();
|
||||
}
|
||||
return await base.SendReceiveAsync(isLittleEndian, content);
|
||||
}
|
||||
|
||||
private async Task<OutputStruct> ForceSendReceiveAsync(ProtocalUnit unit, InputStruct content)
|
||||
{
|
||||
return await base.SendReceiveAsync(unit, content);
|
||||
}
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
return AsyncHelper.RunSync(ConnectAsync);
|
||||
}
|
||||
|
||||
public override async Task<bool> ConnectAsync()
|
||||
{
|
||||
ProtocalLinker = new SiemensPpiProtocalLinker(_com);
|
||||
var inputStruct = new ComCreateReferenceSiemensInputStruct();
|
||||
var outputStruct =
|
||||
await await
|
||||
ForceSendReceiveAsync(this[typeof (ComCreateReferenceSiemensProtocal)],
|
||||
inputStruct).
|
||||
ContinueWith(async answer =>
|
||||
{
|
||||
if (!ProtocalLinker.IsConnected) return false;
|
||||
var inputStruct2 = new ComEstablishAssociationSiemensInputStruct();
|
||||
var outputStruct2 =
|
||||
(ComConfirmSiemensOutputStruct)
|
||||
await
|
||||
ForceSendReceiveAsync(this[typeof(ComEstablishAssociationSiemensProtocal)],
|
||||
inputStruct2);
|
||||
return outputStruct2 != null;
|
||||
});
|
||||
return outputStruct != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs
Normal file
69
Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocalLinker.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Modbus.Net.Siemens
|
||||
{
|
||||
public class SiemensPpiProtocalLinker : ComProtocalLinker
|
||||
{
|
||||
public override async Task<byte[]> SendReceiveAsync(byte[] content)
|
||||
{
|
||||
byte[] extBytes = BytesExtend(content);
|
||||
if (extBytes[6] == 0x7c)
|
||||
{
|
||||
var inputStruct2 = new ComEstablishAssociationSiemensInputStruct();
|
||||
var receiveBytes2 =
|
||||
await SendReceiveWithoutExtAndDecAsync(
|
||||
new ComEstablishAssociationSiemensProtocal().Format(inputStruct2));
|
||||
}
|
||||
var receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
|
||||
while (receiveBytes.Length == 1 && receiveBytes[0] == 0xf9)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
var inputStruct2 = new ComEstablishAssociationSiemensInputStruct();
|
||||
receiveBytes =
|
||||
await SendReceiveWithoutExtAndDecAsync(
|
||||
new ComEstablishAssociationSiemensProtocal().Format(inputStruct2));
|
||||
}
|
||||
if (content.Length > 6 && receiveBytes.Length == 1 && receiveBytes[0] == 0xe5)
|
||||
{
|
||||
var inputStruct2 = new ComEstablishAssociationSiemensInputStruct();
|
||||
var receiveBytes2 =
|
||||
await SendReceiveWithoutExtAndDecAsync(
|
||||
new ComEstablishAssociationSiemensProtocal().Format(inputStruct2));
|
||||
return BytesDecact(receiveBytes2);
|
||||
}
|
||||
return BytesDecact(receiveBytes);
|
||||
}
|
||||
|
||||
public override bool? CheckRight(byte[] content)
|
||||
{
|
||||
if (!base.CheckRight(content).Value) return false;
|
||||
int fcsCheck = 0;
|
||||
if (content.Length == 1 && content[0] == 0xe5)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (content.Length == 6 && content[3] == 0) return true;
|
||||
for (int i = 4; i < content.Length - 2; i++)
|
||||
{
|
||||
fcsCheck += content[i];
|
||||
}
|
||||
fcsCheck = fcsCheck%256;
|
||||
if (fcsCheck != content[content.Length - 2]) return false;
|
||||
if (content[content.Length - 1] != 0x16) return false;
|
||||
if (content[1] != content.Length - 6) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public SiemensPpiProtocalLinker(string com)
|
||||
: base(com, 9600, Parity.Even, StopBits.One, 8)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,30 @@ namespace Modbus.Net.Siemens
|
||||
|
||||
}
|
||||
|
||||
internal class ComCreateReferenceSiemensInputStruct : InputStruct
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class ComCreateReferenceSiemensOutputStruct : OutputStruct
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class ComCreateReferenceSiemensProtocal : SpecialProtocalUnit
|
||||
{
|
||||
public override byte[] Format(InputStruct message)
|
||||
{
|
||||
var r_message = (ComCreateReferenceSiemensInputStruct) message;
|
||||
return Format((byte)0x10, (byte)0x02, (byte)0x00, (byte)0x49, (byte)0x4B, (byte)0x16);
|
||||
}
|
||||
|
||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||
{
|
||||
return new ComCreateReferenceSiemensOutputStruct();
|
||||
}
|
||||
}
|
||||
|
||||
internal class CreateReferenceSiemensInputStruct : InputStruct
|
||||
{
|
||||
public CreateReferenceSiemensInputStruct(byte tdpuSize, ushort srcTsap, ushort dstTsap)
|
||||
@@ -119,6 +143,38 @@ namespace Modbus.Net.Siemens
|
||||
}
|
||||
}
|
||||
|
||||
internal class ComEstablishAssociationSiemensInputStruct : InputStruct
|
||||
{
|
||||
}
|
||||
|
||||
internal class ComConfirmSiemensOutputStruct : OutputStruct
|
||||
{
|
||||
public ComConfirmSiemensOutputStruct(byte confirmByte)
|
||||
{
|
||||
ConfirmByte = confirmByte;
|
||||
}
|
||||
|
||||
public byte ConfirmByte { get; set; }
|
||||
}
|
||||
|
||||
internal class ComEstablishAssociationSiemensProtocal : SpecialProtocalUnit
|
||||
{
|
||||
public override byte[] Format(InputStruct message)
|
||||
{
|
||||
var r_message = (ComEstablishAssociationSiemensInputStruct)message;
|
||||
return Format((byte)0x10, (byte)0x02, (byte)0x00, (byte)0x5c, (byte)0x5e, (byte)0x16);
|
||||
}
|
||||
|
||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||
{
|
||||
//if (messageBytes.Length == 1)
|
||||
//{
|
||||
var confirmByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||
return new ComConfirmSiemensOutputStruct(confirmByte);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
internal class EstablishAssociationSiemensInputStruct : InputStruct
|
||||
{
|
||||
public EstablishAssociationSiemensInputStruct(ushort pduRef, ushort maxCalling, ushort maxCalled, ushort maxPdu)
|
||||
@@ -245,7 +301,7 @@ namespace Modbus.Net.Siemens
|
||||
byte area = r_message.Area;
|
||||
int offsetBit = r_message.Offset*8;
|
||||
byte[] offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
|
||||
return Format(new byte[7], protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
||||
return Format(new byte[6], (byte)0x6c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
||||
, variableSpec, vAddrLg, syntaxId, type, numberOfElements, dbBlock, area,
|
||||
offsetBitBytes.Skip(1).ToArray());
|
||||
}
|
||||
@@ -325,12 +381,19 @@ namespace Modbus.Net.Siemens
|
||||
const byte reserved = 0x00;
|
||||
const byte type = (byte)SiemensDataType.OtherAccess;
|
||||
ushort numberOfWriteBits = (ushort)(valueBytes.Length*8);
|
||||
return Format(new byte[7], protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
||||
return Format(new byte[6], (byte)0x7c, protoId, rosctr, redId, pduRef, parLg, datLg, serviceId, numberOfVariables
|
||||
, variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area,
|
||||
offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes);
|
||||
}
|
||||
|
||||
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
|
||||
{
|
||||
if (messageBytes.Length == 1)
|
||||
{
|
||||
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
|
||||
return new WriteRequestSiemensOutputStruct(0, accessResult == 0xe5 ? SiemensAccessResult.NoError : SiemensAccessResult.InvalidAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = 4;
|
||||
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
|
||||
@@ -339,6 +402,7 @@ namespace Modbus.Net.Siemens
|
||||
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public class ReadTimeSiemensInputStruct : InputStruct
|
||||
|
||||
@@ -18,4 +18,30 @@ namespace Modbus.Net.Siemens
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
|
||||
public class SiemensPpiProtocalLinkerBytesExtend : ProtocalLinkerBytesExtend
|
||||
{
|
||||
public override byte[] BytesExtend(byte[] content)
|
||||
{
|
||||
byte[] newContent = new byte[content.Length + 2];
|
||||
Array.Copy(content, 0, newContent, 0, content.Length);
|
||||
Array.Copy(new byte[] { 0x68, (byte)(content.Length - 4), (byte)(content.Length - 4), 0x68, 0x02, 0x00 }, 0, newContent, 0, 6);
|
||||
int check = 0;
|
||||
for (int i = 4; i < newContent.Length - 2; i++)
|
||||
{
|
||||
check += newContent[i];
|
||||
}
|
||||
check = check%256;
|
||||
newContent[newContent.Length - 2] = (byte) check;
|
||||
newContent[newContent.Length - 1] = 0x16;
|
||||
return newContent;
|
||||
}
|
||||
|
||||
public override byte[] BytesDecact(byte[] content)
|
||||
{
|
||||
byte[] newContent = new byte[content.Length - 9];
|
||||
Array.Copy(content, 7, newContent, 0, newContent.Length);
|
||||
return newContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,11 @@ namespace Modbus.Net.Siemens
|
||||
_siemensType = value;
|
||||
switch (_siemensType)
|
||||
{
|
||||
//case SiemensType.Ppi:
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
case SiemensType.Ppi:
|
||||
{
|
||||
Wrapper = ConnectionString == null ? new SiemensPpiProtocal() : new SiemensPpiProtocal(ConnectionString);
|
||||
break;
|
||||
}
|
||||
//case SiemensType.Mpi:
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
|
||||
@@ -38,8 +38,6 @@ namespace Modbus.Net
|
||||
double initNum = -1;
|
||||
double preNum = -1;
|
||||
Type preType = null;
|
||||
double getCount = 0;
|
||||
double byteCount = 0;
|
||||
List<AddressUnit> originalAddresses = new List<AddressUnit>();
|
||||
var orderedAddresses =
|
||||
groupedAddress.OrderBy(
|
||||
@@ -51,8 +49,6 @@ namespace Modbus.Net
|
||||
if (initNum < 0)
|
||||
{
|
||||
initNum = address.Address + address.SubAddress * (0.125 / AddressTranslator.GetAreaByteLength(address.Area));
|
||||
getCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName] / AddressTranslator.GetAreaByteLength(address.Area);
|
||||
byteCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName];
|
||||
originalAddresses.Add(address);
|
||||
}
|
||||
else
|
||||
@@ -62,9 +58,19 @@ namespace Modbus.Net
|
||||
preNum +
|
||||
BigEndianValueHelper.Instance.ByteLength[preType.FullName]/
|
||||
AddressTranslator.GetAreaByteLength(address.Area))
|
||||
{
|
||||
originalAddresses.Add(address);
|
||||
if (address.Address +
|
||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)) +
|
||||
BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]/
|
||||
AddressTranslator.GetAreaByteLength(address.Area) <=
|
||||
preNum +
|
||||
BigEndianValueHelper.Instance.ByteLength[preType.FullName]/
|
||||
AddressTranslator.GetAreaByteLength(address.Area))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (address.Address +
|
||||
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)) >
|
||||
preNum +
|
||||
@@ -75,22 +81,16 @@ namespace Modbus.Net
|
||||
{
|
||||
Area = area,
|
||||
Address = (int) Math.Floor(initNum),
|
||||
GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum) + 1) * AddressTranslator.GetAreaByteLength(address.Area)),
|
||||
GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum)) * AddressTranslator.GetAreaByteLength(address.Area) + BigEndianValueHelper.Instance.ByteLength[preType.FullName]),
|
||||
DataType = typeof (byte),
|
||||
OriginalAddresses = originalAddresses.ToList(),
|
||||
});
|
||||
initNum = address.Address;
|
||||
getCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]/
|
||||
AddressTranslator.GetAreaByteLength(address.Area);
|
||||
byteCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName];
|
||||
originalAddresses.Clear();
|
||||
originalAddresses.Add(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
getCount += BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]/
|
||||
AddressTranslator.GetAreaByteLength(address.Area);
|
||||
byteCount += BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName];
|
||||
originalAddresses.Add(address);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace Modbus.Net
|
||||
{
|
||||
Area = area,
|
||||
Address = (int)Math.Floor(initNum),
|
||||
GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum) + 1) * AddressTranslator.GetAreaByteLength(area)),
|
||||
GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum)) * AddressTranslator.GetAreaByteLength(area) + BigEndianValueHelper.Instance.ByteLength[preType.FullName]),
|
||||
DataType = typeof (byte),
|
||||
OriginalAddresses = originalAddresses.ToList()
|
||||
});
|
||||
|
||||
@@ -405,6 +405,11 @@ namespace Modbus.Net
|
||||
valueHelper.ByteArrayToObjectArray(datas,
|
||||
new KeyValuePair<Type, int>(typeof (byte), datas.Length)));
|
||||
}
|
||||
//如果不保持连接,断开连接
|
||||
if (!KeepConnect)
|
||||
{
|
||||
BaseUtility.Disconnect();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Modbus.Net
|
||||
/// 生成CRC码
|
||||
/// </summary>
|
||||
/// <param name="message">发送或返回的命令,CRC码除外</param>
|
||||
/// <param name="Rcvbuf">存储CRC码的字节的数组</param>
|
||||
/// <param name="CRC">生成的CRC码</param>
|
||||
public short GetCRC(byte[] message, ref byte[] Rcvbuf)
|
||||
{
|
||||
@@ -84,5 +85,106 @@ namespace Modbus.Net
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 取模FF(255)
|
||||
/// 取反+1
|
||||
/// </summary>
|
||||
/// <param name="writeUncheck"></param>
|
||||
/// <returns></returns>
|
||||
public bool LrcEfficacy(string message)
|
||||
{
|
||||
var index = message.IndexOf(Environment.NewLine, StringComparison.InvariantCulture);
|
||||
var writeUncheck = message.Substring(1, index - 3);
|
||||
var checkString = message.Substring(index - 3, 2);
|
||||
char[] hexArray = new char[writeUncheck.Length];
|
||||
hexArray = writeUncheck.ToCharArray();
|
||||
int decNum = 0, decNumMSB = 0, decNumLSB = 0;
|
||||
int decByte, decByteTotal = 0;
|
||||
|
||||
bool msb = true;
|
||||
|
||||
for (int t = 0; t <= hexArray.GetUpperBound(0); t++)
|
||||
{
|
||||
if ((hexArray[t] >= 48) && (hexArray[t] <= 57))
|
||||
|
||||
decNum = (hexArray[t] - 48);
|
||||
|
||||
else if ((hexArray[t] >= 65) & (hexArray[t] <= 70))
|
||||
decNum = 10 + (hexArray[t] - 65);
|
||||
|
||||
if (msb)
|
||||
{
|
||||
decNumMSB = decNum * 16;
|
||||
msb = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decNumLSB = decNum;
|
||||
msb = true;
|
||||
}
|
||||
if (msb)
|
||||
{
|
||||
decByte = decNumMSB + decNumLSB;
|
||||
decByteTotal += decByte;
|
||||
}
|
||||
}
|
||||
|
||||
decByteTotal = (255 - decByteTotal) + 1;
|
||||
decByteTotal = decByteTotal & 255;
|
||||
|
||||
int a, b = 0;
|
||||
|
||||
string hexByte = "", hexTotal = "";
|
||||
double i;
|
||||
|
||||
for (i = 0; decByteTotal > 0; i++)
|
||||
{
|
||||
//b = Convert.ToInt32(System.Math.Pow(16.0, i));
|
||||
a = decByteTotal % 16;
|
||||
decByteTotal /= 16;
|
||||
if (a <= 9)
|
||||
hexByte = a.ToString();
|
||||
else
|
||||
{
|
||||
switch (a)
|
||||
{
|
||||
case 10:
|
||||
hexByte = "A";
|
||||
break;
|
||||
case 11:
|
||||
hexByte = "B";
|
||||
break;
|
||||
case 12:
|
||||
hexByte = "C";
|
||||
break;
|
||||
case 13:
|
||||
hexByte = "D";
|
||||
break;
|
||||
case 14:
|
||||
hexByte = "E";
|
||||
break;
|
||||
case 15:
|
||||
hexByte = "F";
|
||||
break;
|
||||
}
|
||||
}
|
||||
hexTotal = String.Concat(hexByte, hexTotal);
|
||||
}
|
||||
return hexTotal == checkString;
|
||||
}
|
||||
|
||||
public string GetLRC(byte[] code)
|
||||
{
|
||||
int sum = 0;
|
||||
foreach (byte b in code)
|
||||
{
|
||||
sum += b;
|
||||
}
|
||||
sum = sum % 255;//取模FF(255)
|
||||
sum = ~sum + 1;//取反+1
|
||||
string lrc = Convert.ToString(sum, 16);
|
||||
return lrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,28 +8,50 @@ namespace Modbus.Net
|
||||
{
|
||||
public class ComConnector : BaseConnector, IDisposable
|
||||
{
|
||||
public override string ConnectionToken { get { return _com; }
|
||||
}
|
||||
public override string ConnectionToken => _com;
|
||||
|
||||
private SerialPort _serialPort1;
|
||||
|
||||
private SerialPort SerialPort1
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_serialPort1 == null)
|
||||
{
|
||||
_serialPort1 = new SerialPort
|
||||
{
|
||||
PortName = _com,
|
||||
BaudRate = _baudRate,
|
||||
Parity = _parity,
|
||||
StopBits = _stopBits,
|
||||
DataBits = _dataBits,
|
||||
ReadTimeout = _timeoutTime,
|
||||
};
|
||||
}
|
||||
return _serialPort1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public delegate byte[] GetDate(byte[] bts);
|
||||
|
||||
//private GetDate mygetDate;
|
||||
private readonly string _com;
|
||||
private readonly int _timeoutTime;
|
||||
private readonly int _baudRate;
|
||||
private readonly Parity _parity;
|
||||
private readonly StopBits _stopBits;
|
||||
private readonly int _dataBits;
|
||||
|
||||
public ComConnector(string com, int timeoutTime)
|
||||
public ComConnector(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits, int timeoutTime)
|
||||
{
|
||||
this._com = com;
|
||||
_serialPort1 = new SerialPort
|
||||
{
|
||||
PortName = com,
|
||||
BaudRate = 9600,
|
||||
Parity = Parity.None,
|
||||
StopBits = StopBits.One,
|
||||
DataBits = 8,
|
||||
ReadTimeout = timeoutTime,
|
||||
};
|
||||
_com = com;
|
||||
_timeoutTime = timeoutTime;
|
||||
_baudRate = baudRate;
|
||||
_parity = parity;
|
||||
_stopBits = stopBits;
|
||||
_dataBits = dataBits;
|
||||
|
||||
//端口号
|
||||
//比特率
|
||||
//奇偶校验
|
||||
@@ -41,16 +63,14 @@ namespace Modbus.Net
|
||||
|
||||
public override bool IsConnected
|
||||
{
|
||||
get { return _serialPort1 != null && _serialPort1.IsOpen; }
|
||||
get { return SerialPort1 != null && SerialPort1.IsOpen; }
|
||||
}
|
||||
|
||||
public override bool Connect()
|
||||
{
|
||||
if (_serialPort1 != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort1.Open();
|
||||
SerialPort1.Open();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
@@ -58,8 +78,6 @@ namespace Modbus.Net
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override Task<bool> ConnectAsync()
|
||||
{
|
||||
@@ -68,11 +86,11 @@ namespace Modbus.Net
|
||||
|
||||
public override bool Disconnect()
|
||||
{
|
||||
if (_serialPort1 != null)
|
||||
if (SerialPort1 != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort1.Close();
|
||||
Dispose();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
@@ -100,16 +118,24 @@ namespace Modbus.Net
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_serialPort1.IsOpen)
|
||||
if (!SerialPort1.IsOpen)
|
||||
{
|
||||
_serialPort1.Open();
|
||||
try
|
||||
{
|
||||
SerialPort1.Open();
|
||||
}
|
||||
_serialPort1.Write(sendbytes, 0, sendbytes.Length);
|
||||
catch (Exception)
|
||||
{
|
||||
Dispose();
|
||||
SerialPort1.Open();
|
||||
}
|
||||
}
|
||||
SerialPort1.Write(sendbytes, 0, sendbytes.Length);
|
||||
return ReadMsg();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_serialPort1.Close();
|
||||
Dispose();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +149,7 @@ namespace Modbus.Net
|
||||
{
|
||||
try
|
||||
{
|
||||
_serialPort1.Write(sendbytes, 0, sendbytes.Length);
|
||||
SerialPort1.Write(sendbytes, 0, sendbytes.Length);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -148,22 +174,21 @@ namespace Modbus.Net
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_serialPort1.IsOpen)
|
||||
if (!SerialPort1.IsOpen)
|
||||
{
|
||||
_serialPort1.Open();
|
||||
SerialPort1.Open();
|
||||
}
|
||||
|
||||
byte[] data = new byte[200];
|
||||
byte[] data;
|
||||
Thread.Sleep(100);
|
||||
int i = _serialPort1.Read(data, 0, _serialPort1.BytesToRead);
|
||||
int i = ReadComm(out data, 10, 5000, 1000);
|
||||
byte[] returndata = new byte[i];
|
||||
Array.Copy(data, 0, returndata, 0, i);
|
||||
_serialPort1.Close();
|
||||
return returndata;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_serialPort1.Close();
|
||||
Dispose();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -181,33 +206,35 @@ namespace Modbus.Net
|
||||
public int ReadComm(out Byte[] readBuf, int bufRoom, int HowTime, int ByteTime)
|
||||
{
|
||||
//throw new System.NotImplementedException();
|
||||
readBuf = new Byte[64];
|
||||
readBuf = new Byte[1023];
|
||||
Array.Clear(readBuf, 0, readBuf.Length);
|
||||
|
||||
int nReadLen, nBytelen;
|
||||
if (_serialPort1.IsOpen == false)
|
||||
if (SerialPort1.IsOpen == false)
|
||||
return -1;
|
||||
nBytelen = 0;
|
||||
_serialPort1.ReadTimeout = HowTime;
|
||||
SerialPort1.ReadTimeout = HowTime;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
readBuf[nBytelen] = (byte) _serialPort1.ReadByte();
|
||||
byte[] bTmp = new byte[1023];
|
||||
while (SerialPort1.BytesToRead > 0)
|
||||
{
|
||||
readBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
||||
byte[] bTmp = new byte[bufRoom];
|
||||
Array.Clear(bTmp, 0, bTmp.Length);
|
||||
|
||||
nReadLen = ReadBlock(out bTmp, bufRoom - 1, ByteTime);
|
||||
nReadLen = ReadBlock(bTmp, bufRoom, ByteTime);
|
||||
|
||||
if (nReadLen > 0)
|
||||
{
|
||||
Array.Copy(bTmp, 0, readBuf, 1, nReadLen);
|
||||
nBytelen = 1 + nReadLen;
|
||||
|
||||
Array.Copy(bTmp, 0, readBuf, nBytelen + 1, nReadLen);
|
||||
nBytelen += 1 + nReadLen;
|
||||
}
|
||||
|
||||
else if (nReadLen == 0)
|
||||
nBytelen = 1;
|
||||
nBytelen += 1;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -225,25 +252,21 @@ namespace Modbus.Net
|
||||
/// <param name="ReadRoom">串口数据缓冲空间大小 </param>
|
||||
/// <param name="ByteTime">字节间隔最大时间 </param>
|
||||
/// <returns>从串口实际读入的字节个数 </returns>
|
||||
public int ReadBlock(out byte[] ReadBuf, int ReadRoom, int ByteTime)
|
||||
public int ReadBlock(byte[] ReadBuf, int ReadRoom, int ByteTime)
|
||||
{
|
||||
//throw new System.NotImplementedException();
|
||||
ReadBuf = new byte[1024];
|
||||
Array.Clear(ReadBuf, 0, ReadBuf.Length);
|
||||
|
||||
sbyte nBytelen;
|
||||
//long nByteRead;
|
||||
|
||||
if (_serialPort1.IsOpen == false)
|
||||
if (SerialPort1.IsOpen == false)
|
||||
return 0;
|
||||
nBytelen = 0;
|
||||
_serialPort1.ReadTimeout = ByteTime;
|
||||
SerialPort1.ReadTimeout = ByteTime;
|
||||
|
||||
while (nBytelen < (ReadRoom - 1))
|
||||
while (nBytelen < ReadRoom - 1 && SerialPort1.BytesToRead > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
ReadBuf[nBytelen] = (byte) _serialPort1.ReadByte();
|
||||
ReadBuf[nBytelen] = (byte) SerialPort1.ReadByte();
|
||||
nBytelen++; // add one
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -253,7 +276,6 @@ namespace Modbus.Net
|
||||
}
|
||||
ReadBuf[nBytelen] = 0x00;
|
||||
return nBytelen;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -342,6 +364,7 @@ namespace Modbus.Net
|
||||
{
|
||||
_serialPort1.Close();
|
||||
_serialPort1.Dispose();
|
||||
_serialPort1 = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace Modbus.Net
|
||||
{
|
||||
public abstract class ComProtocalLinker : ProtocalLinker
|
||||
{
|
||||
protected ComProtocalLinker() : this(ConfigurationManager.COM)
|
||||
protected ComProtocalLinker(int baudRate, Parity parity, StopBits stopBits, int dataBits) : this(ConfigurationManager.COM, baudRate, parity, stopBits, dataBits)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected ComProtocalLinker(string com)
|
||||
protected ComProtocalLinker(string com, int baudRate, Parity parity, StopBits stopBits, int dataBits)
|
||||
{
|
||||
//初始化连对象
|
||||
_baseConnector = new ComConnector(com, 30000);
|
||||
_baseConnector = new ComConnector(com, baudRate, parity, stopBits, dataBits, 30000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,12 +416,12 @@ namespace Modbus.Net
|
||||
{
|
||||
if (subPos < 0 && subPos >= 8) throw new IndexOutOfRangeException();
|
||||
int ans = number % 2;
|
||||
int i = 7;
|
||||
while (i >= subPos)
|
||||
int i = 0;
|
||||
while (i <= subPos)
|
||||
{
|
||||
ans = number % 2;
|
||||
number /= 2;
|
||||
i--;
|
||||
i++;
|
||||
}
|
||||
subPos += 1;
|
||||
if (subPos > 7)
|
||||
|
||||
@@ -41,25 +41,26 @@ namespace NA200H.UI.WPF
|
||||
|
||||
private void GetMachineEnter()
|
||||
{
|
||||
machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List<AddressUnit>()
|
||||
//machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List<AddressUnit>()
|
||||
//{
|
||||
//new AddressUnit() {Id = "1", Area = "MW", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "2", Area = "MW", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "3", Area = "MW", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "4", Area = "MW", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//});
|
||||
//machine.AddressFormater = new AddressFormaterNA200H();
|
||||
//machine.AddressTranslator = new AddressTranslatorNA200H();
|
||||
//machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator);
|
||||
//machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator);
|
||||
machine = new SiemensMachine(SiemensType.Ppi, "COM4", SiemensMachineModel.S7_300, new List<AddressUnit>()
|
||||
{
|
||||
new AddressUnit() {Id = "1", Area = "MW", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "2", Area = "MW", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "3", Area = "MW", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "4", Area = "MW", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "1", Area = "V", Address = 0, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "2", Area = "V", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "3", Area = "V", Address = 4, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
new AddressUnit() {Id = "4", Area = "V", Address = 6, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}
|
||||
});
|
||||
machine.AddressFormater = new AddressFormaterNA200H();
|
||||
machine.AddressTranslator = new AddressTranslatorNA200H();
|
||||
machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator);
|
||||
machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator);
|
||||
//machine = new SiemensMachine(SiemensType.Tcp, "192.168.3.11:102", SiemensMachineModel.S7_300, new List<AddressUnit>()
|
||||
//{
|
||||
//new AddressUnit() {Id = "1", Area = "V", Address = 0, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "2", Area = "V", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "3", Area = "V", Address = 4, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0},
|
||||
//new AddressUnit() {Id = "4", Area = "V", Address = 6, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}
|
||||
//});
|
||||
//machine.AddressCombiner = new AddressCombinerContinus();
|
||||
var result = machine.GetDatas(MachineGetDataType.CommunicationTag);
|
||||
var resultFormat = BaseMachine.MapGetValuesToSetValues(result);
|
||||
SetValue(new ushort[4] {(ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"]});
|
||||
@@ -85,8 +86,8 @@ namespace NA200H.UI.WPF
|
||||
ushort.TryParse(Add1.Text, out add1);
|
||||
ushort.TryParse(Add2.Text, out add2);
|
||||
ushort.TryParse(Add3.Text, out add3);
|
||||
utility.SetDatas(0x02, 0x00, "NW 1", new object[] { add1, add2, add3 });
|
||||
//utility.SetDatas(0x02, 0x00, "V 1", new object[] { add1, add2, add3 });
|
||||
//utility.SetDatas(0x02, 0x00, "NW 1", new object[] { add1, add2, add3 });
|
||||
utility.SetDatas(0x02, 0x00, "V 1", new object[] { add1, add2, add3 });
|
||||
Thread.Sleep(100);
|
||||
GetUtilityEnter();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user