private void GetParametersWriteInfo( IEnumerable <WriteParameter> parameters, out Dictionary <byte, SlaveWriteInfo> infos) { infos = new Dictionary <byte, SlaveWriteInfo>(); int index = -1; foreach (WriteParameter parameter in parameters) { ++index; var regex = new Regex(DevicePattern); Match match = regex.Match(parameter.Address); if (!match.Success) { throw new Exception(parameter.Address + " is not a valid device address"); } #region Get slave address byte slaveAddress = _defaultAddress; string match1 = match.Groups[1].ToString(); if (!string.IsNullOrEmpty(match1) && match1.Length > 1) { int i; if (int.TryParse(match1.Substring(0, match1.Length - 1), out i)) { if (i >= byte.MinValue && i <= byte.MaxValue) { slaveAddress = (byte)i; } else { throw new Exception(parameter.Address + ": slave address incorrect"); } } } #endregion Get slave address #region Get device address ushort deviceAddress; if (!ushort.TryParse(match.Groups[3].ToString(), out deviceAddress) || deviceAddress == 0) { throw new Exception(parameter.Address + ": device index not supported"); } deviceAddress -= 1; string match2 = match.Groups[2].ToString(); int? length; if (parameter.Value is bool) { if (match2 != "0" && match2 != "1") { throw new Exception("Type " + parameter.Value.GetType().Name + " is not supported for " + parameter.Address); } length = 1; } else { if (match2 != "3" && match2 != "4") { throw new Exception("Type " + parameter.Value.GetType().Name + " is not supported for " + parameter.Address); } length = TypeToRegistersCount(parameter.Value.GetType()); if (length == null) { throw new Exception("Type " + parameter.Value.GetType().Name + " is not supported for " + parameter.Address); } } #endregion Get device address #region Check device index int deviceLength = length.Value; if (deviceLength + deviceAddress - 1 > ushort.MaxValue) { throw new Exception(parameter.Address + ": device index is out of range"); } #endregion Check device index #region WriteInfo SlaveWriteInfo writeInfo; if (!infos.TryGetValue(slaveAddress, out writeInfo)) { writeInfo = new SlaveWriteInfo(); infos.Add(slaveAddress, writeInfo); } #endregion WriteInfo #region Fill WriteInfo switch (match2) { case "0": var coil = new CoilWriteInfo { Address = deviceAddress, Index = index, WriteParameter = parameter }; writeInfo.Coils.Add(coil); break; case "4": var hr = new HoldingRegisterWriteInfo { Address = new KeyValuePair <ushort, int>(deviceAddress, deviceLength), Index = index, WriteParameter = parameter }; writeInfo.HoldingRegisters.Add(hr); break; } #endregion Fill WriteInfo } }
public void WriteOnce(WriteParameter[] writeParameters) { if (writeParameters == null) { return; } var result = new bool[writeParameters.Count()]; Dictionary <byte, SlaveWriteInfo> writeInfos; GetParametersWriteInfo(writeParameters, out writeInfos); foreach (var slaveWriteInfo in writeInfos) { byte slaveAddress = slaveWriteInfo.Key; SlaveWriteInfo writeInfo = slaveWriteInfo.Value; SortWriteInfoDevices(writeInfo); for (var i = 0; i < writeInfo.Coils.Count; ++i) { CoilWriteInfo coil = writeInfo.Coils[i]; ushort address = coil.Address; const int maxLength = MaxWriteBytesLength * 8; var bools = new List <bool>(maxLength) { coil.WriteParameter.Value as bool? == true }; for (var j = 1; j < maxLength && i + j < writeInfo.Coils.Count; ++j) { CoilWriteInfo c = writeInfo.Coils[i + j]; if (c.Address == address + j) { bools.Add(c.WriteParameter.Value as bool? == true); } else { break; } } if (_mb.WriteCoils(slaveAddress, address, BoolsToBytes(bools), bools.Count)) { for (int j = i; j < bools.Count + i; ++j) { result[writeInfo.Coils[j].Index] = true; } } i += bools.Count - 1; } for (var i = 0; i < writeInfo.HoldingRegisters.Count; ++i) { HoldingRegisterWriteInfo hr = writeInfo.HoldingRegisters[i]; var address = hr.Address; const int maxLength = MaxWriteBytesLength / 2; var bytes = new byte[MaxWriteBytesLength]; int length = address.Value; var valueBytes = GetBytes(hr.WriteParameter.Value); valueBytes = _bytesToRegistersConverter.GetBytes(valueBytes, 0, hr.Address.Value); for (var j = 0; j < valueBytes.Length; ++j) { bytes[j] = valueBytes[j]; } int oldI = i; for (var j = 1; i + j < writeInfo.HoldingRegisters.Count; ++j) { HoldingRegisterWriteInfo h = writeInfo.HoldingRegisters[i + j]; if (h.Address.Key <= address.Key + length) { int newLength = h.Address.Key + h.Address.Value - address.Key; if (newLength < maxLength) { var vBytes = GetBytes(h.WriteParameter.Value); vBytes = _bytesToRegistersConverter.GetBytes(vBytes, 0, h.Address.Value); for (var k = 0; k < vBytes.Length; ++k) { bytes[k + (h.Address.Key - address.Key) * 2] = vBytes[k]; } if (newLength > length) { length = newLength; } ++i; continue; } } break; } var byteList = new List <byte>(length * 2); for (var j = 0; j < length * 2; ++j) { byteList.Add(bytes[j]); } if (_mb.WriteHoldingRegisters(slaveAddress, address.Key, byteList, length)) { for (int j = oldI; j <= i; ++j) { result[writeInfo.HoldingRegisters[j].Index] = true; } } } } }