private void ReadObjects(ModbusReadRequest request) { try { switch (request.ObjectType) { case ObjectType.Coil: ReadCoils(request); break; case ObjectType.DiscreteInput: ReadDiscreteInputs(request); break; case ObjectType.InputRegister: ReadInputRegisters(request); break; case ObjectType.HoldingRegister: ReadHoldingRegisters(request); break; default: throw new ArgumentException("request"); } } catch (Exception e) { PublishException(e); } }
static void Main(string[] args) { var logger = new ConsoleModbusLogger(); var modbusMaster = new ModbusMaster { Channel = new TcpClientModbusChannel("127.0.0.1", 502, 1000) //Channel = new UdpClientModbusChannel("127.0.0.1", 502) { Logger = logger }, //Serializer = new ModbusRtuSerializer(), Serializer = new ModbusTcpSerializer(), //Serializer = new ModbusAsciiSerializer(), Logger = logger, }; while (true) { Thread.Sleep(1000); try { var request = new ModbusReadRequest(1, ModbusObjectType.InputRegister, 100, 2); var resposne = modbusMaster.Request(request, 1000); Console.WriteLine((resposne as ModbusReadRegisterResponse).GetSingle(100)); } catch { } } }
private ModbusReadResponse CreateResponse(ModbusReadRequest request, dynamic data) { return(new ModbusReadResponse() { ObjectType = request.ObjectType, MasterId = request.MasterId, SlaveId = request.SlaveId, StartAddress = request.StartAddress, Data = data }); }
/// <summary> /// Reading request to Modbus target device /// </summary> public override Task <ModbusReadResponse> ReadModbus(ModbusReadRequest request, ServerCallContext context) { // Get required device var address = Convert.ToString(request.Ip); var port = Convert.ToUInt16(request.Port); var device = new Tuple <string, ushort>(address, port); DeviceContextsPool = ModbusContextMultiton.GetInstance(device); var registerType = request.RegisterType; var startAddress = Convert.ToUInt16(request.StartAddress); var readCnt = Convert.ToUInt16(request.ReadCnt); // Request Modbus slave // TODO: Fix type conversions in library // TODO: Think more about logic to call required function byte[] seq = null; switch (registerType) { case ModbusRegisters.Coil: var resultCoil = DeviceContextsPool.ModbusContext.ReadCoils(startAddress, readCnt); seq = Array.ConvertAll(resultCoil, b => b ? (byte)1 : (byte)0); break; case ModbusRegisters.DiscreteInput: var resultInput = DeviceContextsPool.ModbusContext.ReadDiscreteInputs(startAddress, readCnt); seq = Array.ConvertAll(resultInput, b => b ? (byte)1 : (byte)0); break; case ModbusRegisters.Holding: // var result_holding = device_context.ReadHolding(startAddress, readCnt); // seq = Array.ConvertAll(result_holding, b => b ? (byte) 1 : (byte) 0); break; case ModbusRegisters.Input: // var result_input_registers = device_context.ReadInputRegisters(startAddress, readCnt); // seq = Array.ConvertAll(result_input_registers, b => b ? (byte) 1 : (byte) 0); break; } Console.WriteLine(ByteString.CopyFrom(seq)); return(Task.FromResult(new ModbusReadResponse { Seq = ByteString.CopyFrom(seq) })); }
internal abstract ModbusResponse DeserializeReadRegisterResponse(ResponseBuffer buffer, ModbusReadRequest request, int timeout);
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 ModbusResponse DeserializeReadRegisterResponse(ResponseBuffer buffer, ModbusReadRequest request, int timeout) { if (IsException(buffer, request, timeout, out var responseMessage)) { return(responseMessage); } byte byteLength = Read(buffer, 2, timeout); if (IsErrorCRC(buffer, 3 + byteLength, request, timeout)) { throw new ModbusCommException(ModbusCommErrorCode.ErrorCRC, buffer, request); } if (Read(buffer, 0, timeout) != request.SlaveAddress) { throw new ModbusCommException(ModbusCommErrorCode.ResponseSlaveAddressDoNotMatch, buffer, request); } if ((Read(buffer, 1, timeout) & 0x7f) != (byte)request.Function) { throw new ModbusCommException(ModbusCommErrorCode.ResponseFunctionDoNotMatch, buffer, request); } if (byteLength != (byte)(request.Length * 2)) { throw new ModbusCommException(ModbusCommErrorCode.ResponseLengthDoNotMatch, buffer, request); } return(new ModbusReadRegisterResponse(Read(buffer, 3, byteLength, timeout).ToArray(), request)); }
private void ReadHoldingRegisters(ModbusReadRequest request) { UInt16[] result = _masters[request.MasterId].ReadHoldingRegisters( request.SlaveId, request.StartAddress, request.NumberOfPoints); PublishResponse(CreateResponse(request, result)); }
private void ReadCoils(ModbusReadRequest request) { bool[] result = _masters[request.MasterId].ReadCoils( request.SlaveId, request.StartAddress, request.NumberOfPoints); PublishResponse(CreateResponse(request, result)); }
internal override ModbusResponse DeserializeReadBooleanResponse(ResponseBuffer buffer, ModbusReadRequest request, int timeout) { if (IsException(buffer, request, timeout, out var responseMessage)) { return(responseMessage); } byte byteLength = Read(buffer, 8, timeout); if (Read(buffer, 6, timeout) != request.SlaveAddress) { return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseSlaveAddressDoNotMatch, buffer, request)); } if ((Read(buffer, 7, timeout) & 0x7f) != (byte)request.Function) { return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseFunctionDoNotMatch, buffer, request)); } if (byteLength != (byte)Math.Ceiling(request.Length / 8d)) { return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseLengthDoNotMatch, buffer, request)); } return(new ModbusReadBooleanResponse(Read(buffer, 9, byteLength, timeout).SelectMany(b => ByteToBooleanArray(b)).Take(request.Length).ToArray(), request)); }
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); }