internal override ModbusRequest DeserializeRequest(RequestBuffer buffer) { ModbusRequest result = null; while (!buffer.Channel.IsDisposed) { if (errorBuffer.Count >= 256) { RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray()); errorBuffer.Clear(); } while (buffer.Count < 8 && !buffer.Channel.IsDisposed) { buffer.Read(); } if (buffer.Channel.IsDisposed) { break; } var slaveAddress = buffer[0]; int messageLength = 0; if (buffer.ModbusSlave.IsValidSlaveAddress(slaveAddress, buffer.Channel) && Enum.IsDefined(typeof(ModbusFunction), buffer[1])) { ModbusFunction function = (ModbusFunction)buffer[1]; var address = ToUInt16(buffer, 2); var valueOrLength = ToUInt16(buffer, 4); switch (function) { case ModbusFunction.ReadCoils: case ModbusFunction.ReadDiscreteInputs: case ModbusFunction.ReadHoldingRegisters: case ModbusFunction.ReadInputRegisters: case ModbusFunction.WriteSingleCoil: case ModbusFunction.WriteSingleHoldingRegister: if (CalculateCrc(buffer.Take(6)).SequenceEqual(buffer.Skip(6).Take(2))) { messageLength = 8; switch (function) { case ModbusFunction.ReadCoils: case ModbusFunction.ReadDiscreteInputs: case ModbusFunction.ReadHoldingRegisters: case ModbusFunction.ReadInputRegisters: result = new ModbusReadRequest(slaveAddress, (ModbusObjectType)(byte)function, address, valueOrLength); break; case ModbusFunction.WriteSingleCoil: if (valueOrLength != 0xff00 && valueOrLength != 0) { result = new ModbusWriteCoilRequest(slaveAddress, address); } else { result = new ModbusWriteCoilRequest(slaveAddress, address, valueOrLength == 0xff00); } break; case ModbusFunction.WriteSingleHoldingRegister: result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, valueOrLength); break; } } break; case ModbusFunction.WriteMultipleCoils: case ModbusFunction.WriteMultipleHoldingRegisters: if (buffer.Count < 7 && !buffer.Channel.IsDisposed) { buffer.Read(); } if (buffer.Channel.IsDisposed) { break; } var byteLength = buffer[6]; messageLength = byteLength + 9; if (function == ModbusFunction.WriteMultipleCoils && byteLength == Math.Ceiling(valueOrLength / 8d) || function == ModbusFunction.WriteMultipleHoldingRegisters && byteLength == valueOrLength * 2) { while (buffer.Count < messageLength && !buffer.Channel.IsDisposed) { buffer.Read(); } if (buffer.Channel.IsDisposed) { break; } if (CalculateCrc(buffer.Take(byteLength + 7)).SequenceEqual(buffer.Skip(byteLength + 7).Take(2))) { switch (function) { case ModbusFunction.WriteMultipleCoils: result = new ModbusWriteCoilRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).SelectMany(b => ByteToBooleanArray(b)).Take(valueOrLength).ToArray()); break; case ModbusFunction.WriteMultipleHoldingRegisters: result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).ToArray()); break; } } } break; } } if (result != null) { if (errorBuffer.Count > 0) { RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray()); errorBuffer.Clear(); } return(result); } else { errorBuffer.Add(buffer[0]); buffer.RemoveAt(0); continue; } } return(null); }
internal override ModbusRequest DeserializeRequest(RequestBuffer rawBuffer) { ModbusRequest result = null; while (!rawBuffer.Channel.IsDisposed) { if (errorBuffer.Count >= 256) { RaiseUnrecognized(rawBuffer.Channel, errorBuffer.ToArray()); errorBuffer.Clear(); } while (rawBuffer.Count < 17 && !rawBuffer.Channel.IsDisposed) { rawBuffer.Read(); } if (rawBuffer.Channel.IsDisposed) { break; } int messageLength = 0; if (rawBuffer[0] == 0x3a) { List <byte> buffer = new List <byte>(); for (int i = 0; i < 7; i++) { if (TryParseFromHex(rawBuffer, i * 2 + 1, out var byteValue)) { buffer.Add(byteValue); } else { break; } } if (buffer.Count < 7) { errorBuffer.AddRange(rawBuffer.Take((buffer.Count + 1) * 2 + 1)); rawBuffer.RemoveRange(0, (buffer.Count + 1) * 2 + 1); continue; } var slaveAddress = buffer[0]; if (rawBuffer.ModbusSlave.IsValidSlaveAddress(slaveAddress, rawBuffer.Channel) && Enum.IsDefined(typeof(ModbusFunction), buffer[1])) { ModbusFunction function = (ModbusFunction)buffer[1]; var address = ToUInt16(buffer, 2); var valueOrLength = ToUInt16(buffer, 4); switch (function) { case ModbusFunction.ReadCoils: case ModbusFunction.ReadDiscreteInputs: case ModbusFunction.ReadHoldingRegisters: case ModbusFunction.ReadInputRegisters: case ModbusFunction.WriteSingleCoil: case ModbusFunction.WriteSingleHoldingRegister: if ((-buffer.Take(6).Sum(b => b) & 0xff) == buffer[6] && rawBuffer[15] == '\r' && rawBuffer[16] == '\n') { messageLength = 17; switch (function) { case ModbusFunction.ReadCoils: case ModbusFunction.ReadDiscreteInputs: case ModbusFunction.ReadHoldingRegisters: case ModbusFunction.ReadInputRegisters: result = new ModbusReadRequest(slaveAddress, (ModbusObjectType)(byte)function, address, valueOrLength); break; case ModbusFunction.WriteSingleCoil: if (valueOrLength != 0xff00 && valueOrLength != 0) { result = new ModbusWriteCoilRequest(slaveAddress, address); } else { result = new ModbusWriteCoilRequest(slaveAddress, address, valueOrLength == 0xff00); } break; case ModbusFunction.WriteSingleHoldingRegister: result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, valueOrLength); break; } } break; case ModbusFunction.WriteMultipleCoils: case ModbusFunction.WriteMultipleHoldingRegisters: var byteLength = buffer[6]; messageLength = byteLength * 2 + 19; if (function == ModbusFunction.WriteMultipleCoils && byteLength == Math.Ceiling(valueOrLength / 8d) || function == ModbusFunction.WriteMultipleHoldingRegisters && byteLength == valueOrLength * 2) { while (rawBuffer.Count < messageLength && !rawBuffer.Channel.IsDisposed) { rawBuffer.Read(); } if (rawBuffer.Channel.IsDisposed) { break; } for (int i = 0; i < byteLength + 1; i++) { if (TryParseFromHex(rawBuffer, i * 2 + 15, out var byteValue)) { buffer.Add(byteValue); } else { break; } } if (buffer.Count < 8 + byteLength) { errorBuffer.AddRange(rawBuffer.Take((buffer.Count + 1) * 2 + 1)); rawBuffer.RemoveRange(0, (buffer.Count + 1) * 2 + 1); continue; } if ((-buffer.Take(7 + byteLength).Sum(b => b) & 0xff) == buffer[6] && rawBuffer[15] == '\r' && rawBuffer[16] == '\n') { switch (function) { case ModbusFunction.WriteMultipleCoils: result = new ModbusWriteCoilRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).SelectMany(b => ByteToBooleanArray(b)).Take(valueOrLength).ToArray()); break; case ModbusFunction.WriteMultipleHoldingRegisters: result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).ToArray()); break; } } } break; } } } if (result != null) { if (errorBuffer.Count > 0) { RaiseUnrecognized(rawBuffer.Channel, errorBuffer.ToArray()); errorBuffer.Clear(); } return(result); } else { errorBuffer.Add(rawBuffer[0]); rawBuffer.RemoveAt(0); continue; } } return(null); }