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);
FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort)translateAddress.Address;
WriteCount = (ushort)writeValue.Length;
WriteCount = (ushort)Math.Ceiling(writeValue.Length / 2.0);
WriteByteCount = 0;
WriteValue = writeValue;
}

View File

@@ -2,9 +2,9 @@
{
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校验失败
if (!Crc16.GetInstance().CrcEfficacy(content))
{

View File

@@ -2,9 +2,9 @@
{
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)
{

View File

@@ -22,6 +22,9 @@ namespace Modbus.Net.Modbus
{
private ModbusType _modbusType;
public override bool GetLittleEndian => Wrapper[typeof (ReadDataModbusProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteDataModbusProtocal)].IsLittleEndian;
protected string ConnectionStringIp
{
get
@@ -94,7 +97,7 @@ namespace Modbus.Net.Modbus
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
{
@@ -103,11 +106,7 @@ namespace Modbus.Net.Modbus
var outputStruct = await
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadDataModbusProtocal)], inputStruct) as
ReadDataModbusOutputStruct;
return new GetDataReturnDef()
{
ReturnValue = outputStruct?.DataValue,
IsLittleEndian = Wrapper[typeof(ReadDataModbusProtocal)].IsLittleEndian,
};
return outputStruct?.DataValue;
}
catch
{

View File

@@ -95,15 +95,58 @@ namespace Modbus.Net.OPC
{
try
{
string tag = Encoding.UTF8.GetString(message);
var result = await _daClient.ReadAsync(tag);
if (result.QualityGood)
var pos = 0;
var protocal = BigEndianValueHelper.Instance.GetByte(message, ref pos);
if (protocal == 0)
{
return BigEndianValueHelper.Instance.GetBytes(result.Value, result.Value.GetType());
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);
if (result.QualityGood)
{
return BigEndianValueHelper.Instance.GetBytes(result.Value, result.Value.GetType());
}
else
{
return Encoding.ASCII.GetBytes("NoData");
}
}
else
{
return Encoding.ASCII.GetBytes("NoData");
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)
@@ -112,7 +155,6 @@ namespace Modbus.Net.OPC
return Encoding.ASCII.GetBytes("NoData");
//return null;
}
}
private void AddInfo(string message)

View File

@@ -18,11 +18,11 @@ namespace Modbus.Net.OPC
_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")
{
return false;
return null;
}
return base.CheckRight(content);
}

View File

@@ -8,6 +8,9 @@ namespace Modbus.Net.OPC
{
public class OpcDaUtility : BaseUtility
{
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestOpcProtocal)].IsLittleEndian;
public OpcDaUtility(string 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
{
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress, getByteCount);
var readRequestOpcInputStruct = new ReadRequestOpcInputStruct(startAddress);
var readRequestOpcOutputStruct =
await
Wrapper.SendReceiveAsync(Wrapper[typeof(ReadRequestOpcProtocal)], readRequestOpcInputStruct) as ReadRequestOpcOutputStruct;
return new GetDataReturnDef()
{
ReturnValue = readRequestOpcOutputStruct?.GetValue,
IsLittleEndian = Wrapper[typeof (ReadRequestOpcProtocal)].IsLittleEndian
};
return readRequestOpcOutputStruct?.GetValue;
}
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 ReadRequestOpcInputStruct(string tag, int getCount)
public ReadRequestOpcInputStruct(string tag)
{
Tag = tag;
GetCount = getCount;
}
public string Tag { get; private set; }
public int GetCount { get; private set; }
}
public class ReadRequestOpcOutputStruct : OutputStruct
@@ -38,7 +36,7 @@ namespace Modbus.Net.OPC
public override byte[] Format(InputStruct 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)
@@ -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;
var address = addressTranslator.AddressTranslate(startAddress, true);
Offset = address.Key;
int area = address.Value;
Area = (byte)(area % 256);
DbBlock = Area == 0x84 ? (ushort)(area / 256) : (ushort)0;
WriteValue = writeValue;
Tag = tag;
SetValue = setValue;
}
public ushort PduRef { get; private set; }
public ushort DbBlock { get; private set; }
public byte Area { get; private set; }
public int Offset { get; private set; }
public object[] WriteValue { get; private set; }
public string Tag { get; private set; }
public object SetValue { get; private set; }
}
public class WriteRequestSiemensOutputStruct : OutputStruct
public class WriteRequestOpcOutputStruct : OutputStruct
{
public WriteRequestSiemensOutputStruct(ushort pduRef, SiemensAccessResult accessResult)
public WriteRequestOpcOutputStruct(bool writeResult)
{
PduRef = pduRef;
AccessResult = accessResult;
WriteResult = writeResult;
}
public ushort PduRef { get; private set; }
public SiemensAccessResult AccessResult { get; private set; }
public bool WriteResult { get; private set; }
}
public class WriteRequestSiemensProtocal : ProtocalUnit
public class WriteRequestOpcProtocal : ProtocalUnit
{
public override byte[] Format(InputStruct message)
{
var r_message = (WriteRequestSiemensInputStruct)message;
byte[] valueBytes = BigEndianValueHelper.Instance.ObjectArrayToByteArray(r_message.WriteValue);
const byte protoId = 0x32;
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);
var r_message = (WriteRequestOpcInputStruct)message;
byte[] tag = Encoding.UTF8.GetBytes(r_message.Tag);
return Format((byte)0x00, tag, (int)0x00ffff00, r_message.SetValue.GetType().FullName, (int)0x00ffff00, r_message.SetValue);
}
public override OutputStruct Unformat(byte[] messageBytes, ref int pos)
{
pos = 4;
ushort pduRef = BigEndianValueHelper.Instance.GetUShort(messageBytes, ref pos);
pos = 14;
byte accessResult = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
return new WriteRequestSiemensOutputStruct(pduRef, (SiemensAccessResult)accessResult);
var ansByte = BigEndianValueHelper.Instance.GetByte(messageBytes, ref pos);
var ans = ansByte != 0;
return new WriteRequestOpcOutputStruct(ans);
}
}*/
}
}

View File

@@ -4,9 +4,9 @@ namespace Modbus.Net.Siemens
{
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])
{
case 0xd0:

View File

@@ -30,6 +30,9 @@ namespace Modbus.Net.Siemens
private readonly ushort _maxCalled;
private readonly ushort _maxPdu;
public override bool GetLittleEndian => Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian;
public override bool SetLittleEndian => Wrapper[typeof (WriteRequestSiemensProtocal)].IsLittleEndian;
protected string ConnectionStringIp
{
get
@@ -148,7 +151,7 @@ namespace Modbus.Net.Siemens
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
{
@@ -157,11 +160,7 @@ namespace Modbus.Net.Siemens
await
Wrapper.SendReceiveAsync(Wrapper[typeof (ReadRequestSiemensProtocal)],
readRequestSiemensInputStruct) as ReadRequestSiemensOutputStruct;
return new GetDataReturnDef()
{
ReturnValue = readRequestSiemensOutputStruct?.GetValue,
IsLittleEndian = Wrapper[typeof (ReadRequestSiemensProtocal)].IsLittleEndian
};
return readRequestSiemensOutputStruct?.GetValue;
}
catch (Exception)
{

View File

@@ -41,7 +41,12 @@ namespace Modbus.Net
double getCount = 0;
double byteCount = 0;
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)
{
@@ -70,7 +75,7 @@ namespace Modbus.Net
{
Area = area,
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),
OriginalAddresses = originalAddresses.ToList(),
});
@@ -96,7 +101,7 @@ namespace Modbus.Net
{
Area = area,
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),
OriginalAddresses = originalAddresses.ToList()
});

View File

@@ -144,7 +144,7 @@ namespace Modbus.Net
/// 读取数据
/// </summary>
/// <returns>从设备读取的数据</returns>
public async Task<Dictionary<string,ReturnUnit>> GetDatasAsync(MachineGetDataType getDataType)
public async Task<Dictionary<string, ReturnUnit>> GetDatasAsync(MachineGetDataType getDataType)
{
try
{
@@ -160,7 +160,7 @@ namespace Modbus.Net
foreach (var communicateAddress in CommunicateAddresses)
{
//获取数据
var datasReturn =
var datas =
await
BaseUtility.GetDatasAsync(2, 0,
AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
@@ -169,30 +169,21 @@ namespace Modbus.Net
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]));
byte[] datas;
//如果设备本身能获取到数据但是没有数据
if (datasReturn == null)
{
datas = null;
}
else
{
datas = datasReturn.ReturnValue;
//如果没有数据,终止
if (datas == null || (datas.Length != 0 && datas.Length <
(int)
Math.Ceiling(communicateAddress.GetCount*
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName])))
return null;
//如果没有数据,终止
if (datas == null || datas.Length == 0 || datas.Length <
(int)
Math.Ceiling(communicateAddress.GetCount *
BigEndianValueHelper.Instance.ByteLength[
communicateAddress.DataType.FullName]))
return null;
}
foreach (var address in communicateAddress.OriginalAddresses)
{
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 localSubPos = (int) ((localPos - localMainPos)*8);
@@ -200,23 +191,23 @@ namespace Modbus.Net
switch (getDataType)
{
case MachineGetDataType.CommunicationTag:
{
key = address.CommunicationTag;
break;
}
{
key = address.CommunicationTag;
break;
}
case MachineGetDataType.Address:
{
key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress);
break;
}
{
key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress);
break;
}
default:
{
key = address.CommunicationTag;
break;
}
{
key = address.CommunicationTag;
break;
}
}
if (datas == null)
if (datas.Length == 0)
{
ans.Add(key, new ReturnUnit
{
@@ -232,11 +223,13 @@ namespace Modbus.Net
{
PlcValue =
Convert.ToDouble(
datasReturn.IsLittleEndian
? ValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos, address.DataType)
BaseUtility.GetLittleEndian
? ValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos,
address.DataType)
.ToString()
: BigEndianValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos,
address.DataType)) * address.Zoom,
: BigEndianValueHelper.Instance.GetValue(datas, ref localMainPos,
ref localSubPos,
address.DataType))*address.Zoom,
UnitExtend = address.UnitExtend
});
}
@@ -303,7 +296,11 @@ namespace Modbus.Net
case MachineSetDataType.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;
}
case MachineSetDataType.CommunicationTag:
@@ -324,42 +321,57 @@ namespace Modbus.Net
}
addresses.Add(address);
}
//将地址编码成与实际设备通讯的地址,注意这个地址必须是连续的
//将地址编码成与实际设备通讯的地址
var communcationUnits = AddressCombinerSet.Combine(addresses);
//遍历每条通讯的连续地址
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,
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,
communicateAddress.Address + (int) localPos, subPos);
var address2 = subPos != 0
? null
: AddressFormater.FormatAddress(communicateAddress.Area,
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;
switch (setDataType)
@@ -367,22 +379,31 @@ namespace Modbus.Net
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;
}
case MachineSetDataType.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;
}
}
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)

View File

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

View File

@@ -64,7 +64,7 @@ namespace Modbus.Net
{
byte[] extBytes = BytesExtend(content);
byte[] receiveBytes = await SendReceiveWithoutExtAndDecAsync(extBytes);
return receiveBytes == null ? null : BytesDecact(receiveBytes);
return receiveBytes == null ? null : receiveBytes.Length == 0 ? receiveBytes : BytesDecact(receiveBytes);
}
/// <summary>
@@ -87,7 +87,8 @@ namespace Modbus.Net
//发送数据
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>
/// <param name="content">接收协议的内容</param>
/// <returns>协议是否是正确的</returns>
public virtual bool CheckRight(byte[] content)
public virtual bool? CheckRight(byte[] content)
{
if (content != null) return true;
Disconnect();

View File

@@ -259,7 +259,7 @@ namespace Modbus.Net
}
case "System.Boolean":
{
bool value = Instance.GetBit(data, ref pos, ref subPos);
bool value = _Instance.GetBit(data, ref pos, ref subPos);
return value;
}
default:
@@ -414,7 +414,7 @@ namespace Modbus.Net
/// <returns>对应位置的bit元素</returns>
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 i = 7;
while (i >= subPos)
@@ -424,7 +424,7 @@ namespace Modbus.Net
i--;
}
subPos += 1;
if (subPos >= 8)
if (subPos < 0)
{
pos++;
subPos = 0;
@@ -697,6 +697,90 @@ namespace Modbus.Net
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>
/// 设置对应数字中相应位置的bit的值
/// </summary>
@@ -709,28 +793,43 @@ namespace Modbus.Net
int creation = 0;
if (setBit)
{
for (int i = 0; i < 8; i++)
for (int i = 7; i >= 0; i--)
{
creation *= 2;
if (i == subPos) creation++;
}
return (byte) (number | creation);
return (byte)(number | creation);
}
else
{
for (int i = 0; i < 8; i++)
for (int i = 7; i >= 0; i--)
{
creation *= 2;
if (i != subPos) creation++;
}
return (byte) (number & creation);
return (byte)(number & creation);
}
}
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);
return GetByte(number, ref pos);
try
{
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)
{
var tpos = 7 - subPos;
var bit = base.GetBit(number[pos], ref pos, ref tpos);
subPos = tpos - 7;
if (subPos < 0 && subPos > 7) throw new IndexOutOfRangeException();
var tspos = 7 - subPos;
var tpos = pos;
var bit = GetBit(number[pos], ref tpos, ref tspos);
subPos += 1;
if (subPos > 7)
{
pos++;
subPos = 0;
}
return bit;
}
@@ -874,10 +980,9 @@ namespace Modbus.Net
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, subPos, setBit);
return base.SetBit(number, pos, 7 - subPos, setBit);
}
private Byte[] Reverse(Byte[] data)