SetBit Support (not test)

This commit is contained in:
罗圣
2016-08-30 17:34:20 +08:00
parent 0ad78c06b9
commit e09eeadd80
15 changed files with 343 additions and 194 deletions

View File

@@ -124,7 +124,7 @@ namespace Modbus.Net.Modbus
var translateAddress = addressTranslator.AddressTranslate(startAddress, false); var translateAddress = addressTranslator.AddressTranslate(startAddress, false);
FunctionCode = (byte)translateAddress.Area; FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort)translateAddress.Address; StartAddress = (ushort)translateAddress.Address;
WriteCount = (ushort)writeValue.Length; WriteCount = (ushort)Math.Ceiling(writeValue.Length / 2.0);
WriteByteCount = 0; WriteByteCount = 0;
WriteValue = writeValue; WriteValue = writeValue;
} }

View File

@@ -2,9 +2,9 @@
{ {
class ModbusRtuProtocalLinker : ComProtocalLinker class ModbusRtuProtocalLinker : ComProtocalLinker
{ {
public override bool CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (!base.CheckRight(content)) return false; if (!base.CheckRight(content).Value) return false;
//CRC校验失败 //CRC校验失败
if (!Crc16.GetInstance().CrcEfficacy(content)) if (!Crc16.GetInstance().CrcEfficacy(content))
{ {

View File

@@ -2,9 +2,9 @@
{ {
public class ModbusTcpProtocalLinker : TcpProtocalLinker public class ModbusTcpProtocalLinker : TcpProtocalLinker
{ {
public override bool CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (!base.CheckRight(content)) return false; if (!base.CheckRight(content).Value) return false;
//长度校验失败 //长度校验失败
if (content[5] != content.Length - 6) if (content[5] != content.Length - 6)
{ {

View File

@@ -22,6 +22,9 @@ namespace Modbus.Net.Modbus
{ {
private ModbusType _modbusType; private ModbusType _modbusType;
public override bool GetLittleEndian => Wrapper[typeof (ReadDataModbusProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteDataModbusProtocal)].IsLittleEndian;
protected string ConnectionStringIp protected string ConnectionStringIp
{ {
get get
@@ -94,7 +97,7 @@ namespace Modbus.Net.Modbus
ModbusType = (ModbusType) connectionType; ModbusType = (ModbusType) connectionType;
} }
public override async Task<GetDataReturnDef> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) public override async Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
{ {
try try
{ {
@@ -103,11 +106,7 @@ namespace Modbus.Net.Modbus
var outputStruct = await var outputStruct = await
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as
ReadDataModbusOutputStruct; ReadDataModbusOutputStruct;
return new GetDataReturnDef() return outputStruct?.DataValue;
{
ReturnValue = outputStruct?.DataValue,
IsLittleEndian = Wrapper[typeof(ReadDataModbusProtocal)].IsLittleEndian,
};
} }
catch catch
{ {

View File

@@ -95,7 +95,13 @@ namespace Modbus.Net.OPC
{ {
try try
{ {
string tag = Encoding.UTF8.GetString(message); var pos = 0;
var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos);
if (protocal == 0)
{
byte[] tagBytes = new byte[message.Length - 1];
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
string tag = Encoding.UTF8.GetString(tagBytes);
var result = await _daClient.ReadAsync(tag); var result = await _daClient.ReadAsync(tag);
if (result.QualityGood) if (result.QualityGood)
{ {
@@ -106,13 +112,49 @@ namespace Modbus.Net.OPC
return Encoding.ASCII.GetBytes("NoData"); return Encoding.ASCII.GetBytes("NoData");
} }
} }
else
{
int index = 0;
for (int i = 1; i < message.Length - 3; i++)
{
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
message[i + 3] == 0x00)
{
index = i;
break;
}
}
int index2 = 0;
for (int i = index + 4; i < message.Length - 3; i++)
{
if (message[i] == 0x00 && message[i + 1] == 0xff && message[i + 2] == 0xff &&
message[i + 3] == 0x00)
{
index = i;
break;
}
}
byte[] tagBytes = new byte[index - 1];
Array.Copy(message, 1, tagBytes, 0, tagBytes.Length);
string tag = Encoding.UTF8.GetString(tagBytes);
byte[] typeBytes = new byte[index2 - index - 4];
Array.Copy(message, index + 4, typeBytes, 0, typeBytes.Length);
Type type = Type.GetType(Encoding.UTF8.GetString(typeBytes));
byte[] valueBytes = new byte[message.Length - index2 - 4];
Array.Copy(message, index2 + 4, valueBytes, 0, valueBytes.Length);
int mainpos = 0, subpos = 0;
object value = BigEndianValueHelper.Instance.GetValue(valueBytes, ref mainpos, ref subpos, type);
await _daClient.WriteAsync(tag, value);
return new byte[] {1};
}
}
catch (Exception e) catch (Exception e)
{ {
//AddInfo("opc client exception:" + e); //AddInfo("opc client exception:" + e);
return Encoding.ASCII.GetBytes("NoData"); return Encoding.ASCII.GetBytes("NoData");
//return null; //return null;
} }
} }
private void AddInfo(string message) private void AddInfo(string message)

View File

@@ -18,11 +18,11 @@ namespace Modbus.Net.OPC
_baseConnector = OpcDaConnector.Instance(host); _baseConnector = OpcDaConnector.Instance(host);
} }
public override bool CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData") if (content != null && content.Length == 6 && Encoding.ASCII.GetString(content) == "NoData")
{ {
return false; return null;
} }
return base.CheckRight(content); return base.CheckRight(content);
} }

View File

@@ -8,6 +8,9 @@ namespace Modbus.Net.OPC
{ {
public class OpcDaUtility : BaseUtility public class OpcDaUtility : BaseUtility
{ {
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestOpcProtocal)].IsLittleEndian;
public OpcDaUtility(string connectionString) public OpcDaUtility(string connectionString)
{ {
ConnectionString = connectionString; ConnectionString = connectionString;
@@ -19,19 +22,15 @@ namespace Modbus.Net.OPC
{ {
} }
public override async Task<GetDataReturnDef> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) public override async Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
{ {
try try
{ {
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, getByteCount); var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress);
var readRequestOpcOutputStruct = var readRequestOpcOutputStruct =
await await
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct) as ReadRequestOpcOutputStruct; Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct) as ReadRequestOpcOutputStruct;
return new GetDataReturnDef() return readRequestOpcOutputStruct?.GetValue;
{
ReturnValue = readRequestOpcOutputStruct?.GetValue,
IsLittleEndian = Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian
};
} }
catch (Exception) catch (Exception)
{ {
@@ -39,9 +38,20 @@ namespace Modbus.Net.OPC
} }
} }
public override Task<bool> SetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, object[] setContents) public override async Task<bool> SetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, object[] setContents)
{ {
throw new NotImplementedException(); try
{
var writeRequestOpcInputStruct = new WriteRequestOpcInputStruct(startAddress, setContents[0]);
var writeRequestOpcOutputStruct =
await
Wrapper.SendReceiveAsync(Wrapper[typeof(WriteRequestOpcProtocal)], writeRequestOpcInputStruct) as WriteRequestOpcOutputStruct;
return writeRequestOpcOutputStruct?.WriteResult == true;
}
catch (Exception)
{
return false;
}
} }
} }
} }

View File

@@ -13,14 +13,12 @@ namespace Modbus.Net.OPC
public class ReadRequestOpcInputStruct : InputStruct public class ReadRequestOpcInputStruct : InputStruct
{ {
public ReadRequestOpcInputStruct(string tag, int getCount) public ReadRequestOpcInputStruct(string tag)
{ {
Tag = tag; Tag = tag;
GetCount = getCount;
} }
public string Tag { get; private set; } public string Tag { get; private set; }
public int GetCount { get; private set; }
} }
public class ReadRequestOpcOutputStruct : OutputStruct public class ReadRequestOpcOutputStruct : OutputStruct
@@ -38,7 +36,7 @@ namespace Modbus.Net.OPC
public override byte[] Format(InputStruct message) public override byte[] Format(InputStruct message)
{ {
var r_message = (ReadRequestOpcInputStruct) message; var r_message = (ReadRequestOpcInputStruct) message;
return Format(Encoding.UTF8.GetBytes(r_message.Tag)); return Format((byte)0x00, Encoding.UTF8.GetBytes(r_message.Tag));
} }
public override OutputStruct Unformat(byte[] messageBytes, ref int pos) public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
@@ -47,77 +45,43 @@ namespace Modbus.Net.OPC
} }
} }
/*public class WriteRequestSiemensInputStruct : InputStruct public class WriteRequestOpcInputStruct : InputStruct
{ {
public WriteRequestSiemensInputStruct(ushort pduRef, string startAddress, object[] writeValue, AddressTranslator addressTranslator) public WriteRequestOpcInputStruct(string tag, object setValue)
{ {
PduRef = pduRef; Tag = tag;
var address = addressTranslator.AddressTranslate(startAddress, true); SetValue = setValue;
Offset = address.Key;
int area = address.Value;
Area = (byte)(area % 256);
DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0;
WriteValue = writeValue;
} }
public ushort PduRef { get; private set; } public string Tag { get; private set; }
public ushort DbBlock { get; private set; } public object SetValue { get; private set; }
public byte Area { get; private set; }
public int Offset { get; private set; }
public object[] WriteValue { get; private set; }
} }
public class WriteRequestSiemensOutputStruct : OutputStruct public class WriteRequestOpcOutputStruct : OutputStruct
{ {
public WriteRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult) public WriteRequestOpcOutputStruct(bool writeResult)
{ {
PduRef = pduRef; WriteResult = writeResult;
AccessResult = accessResult;
} }
public ushort PduRef { get; private set; } public bool WriteResult { get; private set; }
public SiemensAccessResult AccessResult { get; private set; }
} }
public class WriteRequestSiemensProtocal : ProtocalUnit public class WriteRequestOpcProtocal : ProtocalUnit
{ {
public override byte[] Format(InputStruct message) public override byte[] Format(InputStruct message)
{ {
var r_message = (WriteRequestSiemensInputStruct)message; var r_message = (WriteRequestOpcInputStruct)message;
byte[] valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue); byte[] tag = Encoding.UTF8.GetBytes(r_message.Tag);
const byte protoId = 0x32; return Format((byte)0x00, tag, (int)0x00ffff00, r_message.SetValue.GetType().FullName, (int)0x00ffff00, r_message.SetValue);
const byte rosctr = 0x01;
const ushort redId = 0x0000;
ushort pduRef = r_message.PduRef;
const ushort parLg = 14; // 参数字节数2+12的倍数目前仅为14
ushort datLg = (ushort)(4 + valueBytes.Length); // 数据字节数
const byte serviceId = 0x05;
const byte numberOfVariables = 1;
const byte variableSpec = 0x12;
const byte vAddrLg = 0x0A;
const byte syntaxId = 0x10;
const byte typeR = (byte)SiemensTypeCode.Byte;
ushort numberOfElements = (ushort)valueBytes.Length;
ushort dbBlock = r_message.DbBlock;
byte area = r_message.Area;
int offsetBit = r_message.Offset * 8;
byte[] offsetBitBytes = BigEndianValueHelper.Instance.GetBytes(offsetBit);
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
, variableSpec, vAddrLg, syntaxId, typeR, numberOfElements, dbBlock, area,
offsetBitBytes.Skip(1).ToArray(), reserved, type, numberOfWriteBits, valueBytes);
} }
public override OutputStruct Unformat(byte[] messageBytes, ref int pos) public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
{ {
pos = 4; var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos); var ans = ansByte != 0;
pos = 14; return new WriteRequestOpcOutputStruct(ans);
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos); }
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult);
} }
}*/
} }

View File

@@ -4,9 +4,9 @@ namespace Modbus.Net.Siemens
{ {
public class SiemensTcpProtocalLinker : TcpProtocalLinker public class SiemensTcpProtocalLinker : TcpProtocalLinker
{ {
public override bool CheckRight(byte[] content) public override bool? CheckRight(byte[] content)
{ {
if (!base.CheckRight(content)) return false; if (!base.CheckRight(content).Value) return false;
switch (content[5]) switch (content[5])
{ {
case 0xd0: case 0xd0:

View File

@@ -30,6 +30,9 @@ namespace Modbus.Net.Siemens
private readonly ushort _maxCalled; private readonly ushort _maxCalled;
private readonly ushort _maxPdu; private readonly ushort _maxPdu;
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestSiemensProtocal)].IsLittleEndian;
protected string ConnectionStringIp protected string ConnectionStringIp
{ {
get get
@@ -148,7 +151,7 @@ namespace Modbus.Net.Siemens
ConnectionType = (SiemensType) connectionType; ConnectionType = (SiemensType) connectionType;
} }
public override async Task<GetDataReturnDef> GetDatasAsync(byte belongAddress, byte materAddress, string startAddress, int getByteCount) public override async Task<byte[]> GetDatasAsync(byte belongAddress, byte materAddress, string startAddress, int getByteCount)
{ {
try try
{ {
@@ -157,11 +160,7 @@ namespace Modbus.Net.Siemens
await await
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)], Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)],
readRequestSiemensInputStruct) as ReadRequestSiemensOutputStruct; readRequestSiemensInputStruct) as ReadRequestSiemensOutputStruct;
return new GetDataReturnDef() return readRequestSiemensOutputStruct?.GetValue;
{
ReturnValue = readRequestSiemensOutputStruct?.GetValue,
IsLittleEndian = Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian
};
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -41,7 +41,12 @@ namespace Modbus.Net
double getCount = 0; double getCount = 0;
double byteCount = 0; double byteCount = 0;
List<AddressUnit> originalAddresses = new List<AddressUnit>(); List<AddressUnit> originalAddresses = new List<AddressUnit>();
foreach (var address in groupedAddress.OrderBy(address => address.Address + address.SubAddress * (0.125 / AddressTranslator.GetAreaByteLength(address.Area)))) var orderedAddresses =
groupedAddress.OrderBy(
address =>
address.Address +
address.SubAddress*(0.125/AddressTranslator.GetAreaByteLength(address.Area)));
foreach (var address in orderedAddresses)
{ {
if (initNum < 0) if (initNum < 0)
{ {
@@ -70,7 +75,7 @@ namespace Modbus.Net
{ {
Area = area, Area = area,
Address = (int) Math.Floor(initNum), Address = (int) Math.Floor(initNum),
GetCount = (int) Math.Ceiling(byteCount), GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum) + 1) * AddressTranslator.GetAreaByteLength(address.Area)),
DataType = typeof (byte), DataType = typeof (byte),
OriginalAddresses = originalAddresses.ToList(), OriginalAddresses = originalAddresses.ToList(),
}); });
@@ -96,7 +101,7 @@ namespace Modbus.Net
{ {
Area = area, Area = area,
Address = (int)Math.Floor(initNum), Address = (int)Math.Floor(initNum),
GetCount = (int)Math.Ceiling(byteCount), GetCount = (int)Math.Ceiling(((int)Math.Floor(preNum) - (int)Math.Floor(initNum) + 1) * AddressTranslator.GetAreaByteLength(area)),
DataType = typeof (byte), DataType = typeof (byte),
OriginalAddresses = originalAddresses.ToList() OriginalAddresses = originalAddresses.ToList()
}); });

View File

@@ -160,7 +160,7 @@ namespace Modbus.Net
foreach (var communicateAddress in CommunicateAddresses) foreach (var communicateAddress in CommunicateAddresses)
{ {
//获取数据 //获取数据
var datasReturn = var datas =
await await
BaseUtility.GetDatasAsync(2, 0, BaseUtility.GetDatasAsync(2, 0,
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0), AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
@@ -169,30 +169,21 @@ namespace Modbus.Net
BigEndianValueHelper.Instance.ByteLength[ BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName])); communicateAddress.DataType.FullName]));
byte[] datas;
//如果设备本身能获取到数据但是没有数据
if (datasReturn == null)
{
datas = null;
}
else
{
datas = datasReturn.ReturnValue;
//如果没有数据,终止 //如果没有数据,终止
if (datas == null || datas.Length == 0 || datas.Length < if (datas == null || (datas.Length != 0 && datas.Length <
(int) (int)
Math.Ceiling(communicateAddress.GetCount* Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[ BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName])) communicateAddress.DataType.FullName])))
return null; return null;
}
foreach (var address in communicateAddress.OriginalAddresses) foreach (var address in communicateAddress.OriginalAddresses)
{ {
var localPos = (address.Address - communicateAddress.Address)* var localPos = (address.Address - communicateAddress.Address)*
AddressTranslator.GetAreaByteLength(communicateAddress.Area)+address.SubAddress/8.0; AddressTranslator.GetAreaByteLength(communicateAddress.Area) +
address.SubAddress/8.0;
var localMainPos = (int) localPos; var localMainPos = (int) localPos;
var localSubPos = (int) ((localPos - localMainPos)*8); var localSubPos = (int) ((localPos - localMainPos)*8);
@@ -216,7 +207,7 @@ namespace Modbus.Net
} }
} }
if (datas == null) if (datas.Length == 0)
{ {
ans.Add(key, new ReturnUnit ans.Add(key, new ReturnUnit
{ {
@@ -232,10 +223,12 @@ namespace Modbus.Net
{ {
PlcValue = PlcValue =
Convert.ToDouble( Convert.ToDouble(
datasReturn.IsLittleEndian BaseUtility.GetLittleEndian
? ValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos, address.DataType) ? ValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos,
address.DataType)
.ToString() .ToString()
: BigEndianValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos, : BigEndianValueHelper.Instance.GetValue(datas, ref localMainPos,
ref localSubPos,
address.DataType))*address.Zoom, address.DataType))*address.Zoom,
UnitExtend = address.UnitExtend UnitExtend = address.UnitExtend
}); });
@@ -303,7 +296,11 @@ namespace Modbus.Net
case MachineSetDataType.Address: case MachineSetDataType.Address:
{ {
address = address =
GetAddresses.SingleOrDefault(p => AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key || (p.DataType != typeof(bool) && AddressFormater.FormatAddress(p.Area, p.Address) == value.Key)); GetAddresses.SingleOrDefault(
p =>
AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key ||
(p.DataType != typeof (bool) &&
AddressFormater.FormatAddress(p.Area, p.Address) == value.Key));
break; break;
} }
case MachineSetDataType.CommunicationTag: case MachineSetDataType.CommunicationTag:
@@ -324,42 +321,57 @@ namespace Modbus.Net
} }
addresses.Add(address); addresses.Add(address);
} }
//将地址编码成与实际设备通讯的地址,注意这个地址必须是连续的 //将地址编码成与实际设备通讯的地址
var communcationUnits = AddressCombinerSet.Combine(addresses); var communcationUnits = AddressCombinerSet.Combine(addresses);
//遍历每条通讯的连续地址 //遍历每条通讯的连续地址
foreach (var communicateAddress in communcationUnits) foreach (var communicateAddress in communcationUnits)
{ {
List<object> datasList = new List<object>();
//需要设置的字节数,计数
var setCount =
communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[communicateAddress.DataType.FullName];
//总数
var allBytes = setCount;
//编码开始地址 //编码开始地址
var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address); communicateAddress.Address);
while (setCount > 0) var datasReturn = await BaseUtility.GetDatasAsync(2, 0,
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
(int)
Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]));
var valueHelper = BaseUtility.SetLittleEndian
? ValueHelper.Instance
: BigEndianValueHelper.Instance;
//如果设备本身能获取到数据但是没有数据
var datas = datasReturn;
//如果没有数据,终止
if (datas == null || datas.Length <
(int)
Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]))
return false;
foreach (var addressUnit in communicateAddress.OriginalAddresses)
{ {
var localPos = (allBytes - setCount) / AddressTranslator.GetAreaByteLength(communicateAddress.Area); var byteCount = (addressUnit.Address - communicateAddress.Address +
addressUnit.SubAddress*0.125/
AddressTranslator.GetAreaByteLength(communicateAddress.Area)) *
AddressTranslator.GetAreaByteLength(communicateAddress.Area);
var mainByteCount = (int) byteCount;
var localByteCount = (int) ((byteCount - (int) byteCount)*8);
var localPos = byteCount/AddressTranslator.GetAreaByteLength(communicateAddress.Area);
//编码当前地址 //编码当前地址
var subPos = (int)((localPos - (int)localPos) / (0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area))); var subPos =
(int)
((localPos - (int) localPos)/
(0.125/AddressTranslator.GetAreaByteLength(communicateAddress.Area)));
var address = AddressFormater.FormatAddress(communicateAddress.Area, var address = AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address + (int) localPos, subPos); communicateAddress.Address + (int) localPos, subPos);
var address2 = subPos != 0 var address2 = subPos != 0
? null ? null
: AddressFormater.FormatAddress(communicateAddress.Area, : AddressFormater.FormatAddress(communicateAddress.Area,
communicateAddress.Address + (int) localPos); communicateAddress.Address + (int) localPos);
//找到对应的描述地址
var addressUnit =
GetAddresses.SingleOrDefault(
p =>
p.Area == communicateAddress.Area &&
p.Address == communicateAddress.Address + (int) localPos &&
p.SubAddress == subPos);
//如果没有相应地址,跳过
if (addressUnit == null) continue;
//获取写入类型 //获取写入类型
Type dataType = addressUnit.DataType; Type dataType = addressUnit.DataType;
switch (setDataType) switch (setDataType)
@@ -367,22 +379,31 @@ namespace Modbus.Net
case MachineSetDataType.Address: case MachineSetDataType.Address:
{ {
//获取要写入的值 //获取要写入的值
var value = values.SingleOrDefault(p => p.Key == address || (address2 != null && p.Key == address2)); var value =
values.SingleOrDefault(
p => p.Key == address || (address2 != null && p.Key == address2));
//将要写入的值加入队列 //将要写入的值加入队列
datasList.Add(Convert.ChangeType(value.Value / addressUnit.Zoom, dataType)); var data = Convert.ChangeType(value.Value/addressUnit.Zoom, dataType);
if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data))
return false;
break; break;
} }
case MachineSetDataType.CommunicationTag: case MachineSetDataType.CommunicationTag:
{ {
var value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag); var value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag);
datasList.Add(Convert.ChangeType(value.Value / addressUnit.Zoom, dataType)); var data = Convert.ChangeType(value.Value/addressUnit.Zoom, dataType);
if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data))
return false;
break; break;
} }
} }
setCount -= BigEndianValueHelper.Instance.ByteLength[dataType.FullName];
} }
//写入数据 //写入数据
await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray()); await
BaseUtility.SetDatasAsync(2, 0, addressStart,
valueHelper.ByteArrayToObjectArray(datas,
new KeyValuePair<Type, int>(typeof (byte), datas.Length)));
} }
} }
catch (Exception e) catch (Exception e)

View File

@@ -5,12 +5,6 @@ using System.Threading.Tasks;
namespace Modbus.Net namespace Modbus.Net
{ {
public class GetDataReturnDef
{
public byte[] ReturnValue { get; set; }
public bool IsLittleEndian { get; set; }
}
public abstract class BaseUtility public abstract class BaseUtility
{ {
/// <summary> /// <summary>
@@ -19,6 +13,15 @@ namespace Modbus.Net
protected BaseProtocal Wrapper; protected BaseProtocal Wrapper;
protected string ConnectionString { get; set; } protected string ConnectionString { get; set; }
/// <summary>
/// 获取协议是否遵循小端格式
/// </summary>
public abstract bool GetLittleEndian { get; }
/// <summary>
/// 设置协议是否遵循小端格式
/// </summary>
public abstract bool SetLittleEndian { get; }
/// <summary> /// <summary>
/// 设备是否已经连接 /// 设备是否已经连接
/// </summary> /// </summary>
@@ -56,7 +59,7 @@ namespace Modbus.Net
/// <param name="startAddress">开始地址</param> /// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取字节数个数</param> /// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的byte数据</returns> /// <returns>接收到的byte数据</returns>
public virtual GetDataReturnDef GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount) public virtual byte[] GetDatas(byte belongAddress, byte masterAddress, string startAddress, int getByteCount)
{ {
return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getByteCount)); return AsyncHelper.RunSync(() => GetDatasAsync(belongAddress, masterAddress, startAddress, getByteCount));
} }
@@ -69,7 +72,7 @@ namespace Modbus.Net
/// <param name="startAddress">开始地址</param> /// <param name="startAddress">开始地址</param>
/// <param name="getByteCount">获取字节数个数</param> /// <param name="getByteCount">获取字节数个数</param>
/// <returns>接收到的byte数据</returns> /// <returns>接收到的byte数据</returns>
public abstract Task<GetDataReturnDef> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount); public abstract Task<byte[]> GetDatasAsync(byte belongAddress, byte masterAddress, string startAddress, int getByteCount);
/// <summary> /// <summary>
/// 获取数据 /// 获取数据
@@ -102,8 +105,8 @@ namespace Modbus.Net
double bCount = BigEndianValueHelper.Instance.ByteLength[typeName]; double bCount = BigEndianValueHelper.Instance.ByteLength[typeName];
var getReturnValue = await GetDatasAsync(belongAddress, masterAddress, startAddress, var getReturnValue = await GetDatasAsync(belongAddress, masterAddress, startAddress,
(int)Math.Ceiling(bCount * getTypeAndCount.Value)); (int)Math.Ceiling(bCount * getTypeAndCount.Value));
var getBytes = getReturnValue.ReturnValue; var getBytes = getReturnValue;
return getReturnValue.IsLittleEndian return GetLittleEndian
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount) ? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount)
: BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount); : BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, getTypeAndCount);
} }
@@ -187,8 +190,8 @@ namespace Modbus.Net
let bCount = BigEndianValueHelper.Instance.ByteLength[typeName] let bCount = BigEndianValueHelper.Instance.ByteLength[typeName]
select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum(); select (int) Math.Ceiling(bCount*getTypeAndCount.Value)).Sum();
var getReturnValue = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount); var getReturnValue = await GetDatasAsync(belongAddress, masterAddress, startAddress, bAllCount);
byte[] getBytes = getReturnValue.ReturnValue; byte[] getBytes = getReturnValue;
return getReturnValue.IsLittleEndian return GetLittleEndian
? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount) ? ValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount)
: BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount); : BigEndianValueHelper.Instance.ByteArrayToObjectArray(getBytes, translateTypeAndCount);
} }

View File

@@ -64,7 +64,7 @@ namespace Modbus.Net
{ {
byte[] extBytes = BytesExtend(content); byte[] extBytes = BytesExtend(content);
byte[] receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes); byte[] receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
return receiveBytes == null ? null : BytesDecact(receiveBytes); return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
} }
/// <summary> /// <summary>
@@ -87,7 +87,8 @@ namespace Modbus.Net
//发送数据 //发送数据
byte[] receiveBytes = await _baseConnector.SendMsgAsync(content); byte[] receiveBytes = await _baseConnector.SendMsgAsync(content);
//容错处理 //容错处理
return !CheckRight(receiveBytes) ? null : receiveBytes; var checkRight = CheckRight(receiveBytes);
return checkRight == null ? new byte[0] : (!checkRight.Value ? null : receiveBytes);
//返回字符 //返回字符
} }
@@ -96,7 +97,7 @@ namespace Modbus.Net
/// </summary> /// </summary>
/// <param name="content">接收协议的内容</param> /// <param name="content">接收协议的内容</param>
/// <returns>协议是否是正确的</returns> /// <returns>协议是否是正确的</returns>
public virtual bool CheckRight(byte[] content) public virtual bool? CheckRight(byte[] content)
{ {
if (content != null) return true; if (content != null) return true;
Disconnect(); Disconnect();

View File

@@ -259,7 +259,7 @@ namespace Modbus.Net
} }
case "System.Boolean": case "System.Boolean":
{ {
bool value = Instance.GetBit(data, ref pos, ref subPos); bool value = _Instance.GetBit(data, ref pos, ref subPos);
return value; return value;
} }
default: default:
@@ -414,7 +414,7 @@ namespace Modbus.Net
/// <returns>对应位置的bit元素</returns> /// <returns>对应位置的bit元素</returns>
public bool GetBit(byte number, ref int pos, ref int subPos) public bool GetBit(byte number, ref int pos, ref int subPos)
{ {
if (subPos < 0 && subPos > 8) throw new IndexOutOfRangeException(); if (subPos < 0 && subPos >= 8) throw new IndexOutOfRangeException();
int ans = number % 2; int ans = number % 2;
int i = 7; int i = 7;
while (i >= subPos) while (i >= subPos)
@@ -424,7 +424,7 @@ namespace Modbus.Net
i--; i--;
} }
subPos += 1; subPos += 1;
if (subPos >= 8) if (subPos < 0)
{ {
pos++; pos++;
subPos = 0; subPos = 0;
@@ -697,6 +697,90 @@ namespace Modbus.Net
return array; return array;
} }
public bool SetValue(byte[] contents, int setPos, int subPos, object setValue)
{
var type = setValue.GetType();
switch (type.FullName)
{
case "System.Int16":
{
bool success = _Instance.SetValue(contents, setPos, (short)setValue);
return success;
}
case "System.Int32":
{
bool success = _Instance.SetValue(contents, setPos, (int) setValue);
return success;
}
case "System.Int64":
{
bool success = _Instance.SetValue(contents, setPos, (long) setValue);
return success;
}
case "System.UInt16":
{
bool success = _Instance.SetValue(contents, setPos, (ushort) setValue);
return success;
}
case "System.UInt32":
{
bool success = _Instance.SetValue(contents, setPos, (uint) setValue);
return success;
}
case "System.UInt64":
{
bool success = _Instance.SetValue(contents, setPos, (ulong) setValue);
return success;
}
case "System.Single":
{
bool success = _Instance.SetValue(contents, setPos, (float) setValue);
return success;
}
case "System.Double":
{
bool success = _Instance.SetValue(contents, setPos, (double) setValue);
return success;
}
case "System.Byte":
{
bool success = _Instance.SetValue(contents, setPos, (byte) setValue);
return success;
}
case "System.Boolean":
{
bool success = _Instance.SetBit(contents, setPos, subPos, (bool) setValue);
return success;
}
default:
{
throw new NotImplementedException("没有实现除整数以外的其它转换方式");
}
}
}
/// <summary>
/// 将short值设置到byte数组中
/// </summary>
/// <param name="contents">待设置的byte数组</param>
/// <param name="pos">设置的位置</param>
/// <param name="setValue">要设置的值</param>
/// <returns></returns>
public virtual bool SetValue(byte[] contents, int pos, object setValue)
{
try
{
byte[] datas = _Instance.GetBytes(setValue, setValue.GetType());
Array.Copy(datas, 0, contents, pos, datas.Length);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary> /// <summary>
/// 设置对应数字中相应位置的bit的值 /// 设置对应数字中相应位置的bit的值
/// </summary> /// </summary>
@@ -709,7 +793,7 @@ namespace Modbus.Net
int creation = 0; int creation = 0;
if (setBit) if (setBit)
{ {
for (int i = 0; i < 8; i++) for (int i = 7; i >= 0; i--)
{ {
creation *= 2; creation *= 2;
if (i == subPos) creation++; if (i == subPos) creation++;
@@ -718,7 +802,7 @@ namespace Modbus.Net
} }
else else
{ {
for (int i = 0; i < 8; i++) for (int i = 7; i >= 0; i--)
{ {
creation *= 2; creation *= 2;
if (i != subPos) creation++; if (i != subPos) creation++;
@@ -727,10 +811,25 @@ namespace Modbus.Net
} }
} }
public virtual byte SetBit(byte[] number, int pos, int subPos, bool setBit) /// <summary>
/// 设置一组数据中的一个bit
/// </summary>
/// <param name="contents">待设置的字节数组</param>
/// <param name="pos">位置</param>
/// <param name="subPos">bit位置</param>
/// <param name="setValue">bit数</param>
/// <returns></returns>
public virtual bool SetBit(byte[] contents, int pos, int subPos, bool setValue)
{ {
SetBit(number[pos], subPos, setBit); try
return GetByte(number, ref pos); {
contents[pos] = SetBit(contents[pos], subPos, setValue);
return true;
}
catch (Exception)
{
return false;
}
} }
} }
@@ -855,9 +954,16 @@ namespace Modbus.Net
public override bool GetBit(byte[] number, ref int pos, ref int subPos) public override bool GetBit(byte[] number, ref int pos, ref int subPos)
{ {
var tpos = 7 - subPos; if (subPos < 0 && subPos > 7) throw new IndexOutOfRangeException();
var bit = base.GetBit(number[pos], ref pos, ref tpos); var tspos = 7 - subPos;
subPos = tpos - 7; var tpos = pos;
var bit = GetBit(number[pos], ref tpos, ref tspos);
subPos += 1;
if (subPos > 7)
{
pos++;
subPos = 0;
}
return bit; return bit;
} }
@@ -874,10 +980,9 @@ namespace Modbus.Net
return t; return t;
} }
public override byte SetBit(byte[] number, int pos, int subPos, bool setBit) public override bool SetBit(byte[] number, int pos, int subPos, bool setBit)
{ {
Array.Reverse(number); return base.SetBit(number, pos, 7 - subPos, setBit);
return base.SetBit(number, pos, subPos, setBit);
} }
private Byte[] Reverse(Byte[] data) private Byte[] Reverse(Byte[] data)