private void WriteMultipleCoils(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength) { if (dataLength < 5) { SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue); } else { ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos); ushort outputCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2); byte byteCount = _buffer[dataPos + 4]; byte[] values = new byte[byteCount]; Array.Copy(_buffer, dataPos + 5, values, 0, values.Length); var err = OnWriteMultipleCoils(isBroadcast, startAddress, outputCount, values); if (isBroadcast) { return; } if (err != ModbusErrorCode.NoError) { SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err); } else { short telegramLength; intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext); ModbusUtils.InsertUShort(_buffer, dataPos, startAddress); ModbusUtils.InsertUShort(_buffer, dataPos + 2, outputCount); intf.SendTelegram(_buffer, telegramLength); } } }
private void ReadInputRegisters(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength) { if (dataLength < 4) { SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue); } else { ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos); ushort registerCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2); ushort[] registers = new ushort[registerCount]; var err = OnReadInputRegisters(isBroadcast, startAddress, registers); if (isBroadcast) { return; } if (err != ModbusErrorCode.NoError) { SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err); } else { short telegramLength; intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(1 + 2 * registers.Length), _buffer, out telegramLength, out dataPos, true, ref telegramContext); _buffer[dataPos] = (byte)(2 * registers.Length); for (int i = 0; i < registerCount; i++) { ModbusUtils.InsertUShort(_buffer, dataPos + 1 + 2 * i, registers[i]); } intf.SendTelegram(_buffer, telegramLength); } } }
private void WriteSingleRegister(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength) { if (dataLength < 4) { SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue); } else { ushort address = ModbusUtils.ExtractUShort(_buffer, dataPos); ushort value = ModbusUtils.ExtractUShort(_buffer, dataPos + 2); var err = OnWriteSingleRegister(isBroadcast, address, value); if (isBroadcast) { return; } if (err != ModbusErrorCode.NoError) { SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err); } else { short telegramLength; intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext); ModbusUtils.InsertUShort(_buffer, dataPos, address); ModbusUtils.InsertUShort(_buffer, dataPos + 2, value); intf.SendTelegram(_buffer, telegramLength); } } }
/// <summary> /// Sends a Read Write Multiple Coils (0x17) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="writeStartAddress">Address of the 1st write register: 0x0000 .. 0xFFFF</param> /// <param name="writeRegisters">Register values to write</param> /// <param name="readStartAddress">Address of the 1st read register: 0x0000 .. 0xFFFF</param> /// <param name="readCount">Number of registers to read</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <returns>Returns a unsigned short array with the register values.</returns> /// <remarks> /// The write operation is performed before the read operation. /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual ushort[] ReadWriteMultipleRegisters(byte deviceAddress, ushort writeStartAddress, ushort[] writeRegisters, ushort readStartAddress, ushort readCount, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadWriteMultipleRegisters, (short)(9 + 2 * writeRegisters.Length), _Buffer, out telegramLength, out dataPos, false, ref telegramContext); ModbusUtils.InsertUShort(_Buffer, dataPos, readStartAddress); ModbusUtils.InsertUShort(_Buffer, dataPos + 2, readCount); ModbusUtils.InsertUShort(_Buffer, dataPos + 4, writeStartAddress); ModbusUtils.InsertUShort(_Buffer, dataPos + 6, (ushort)writeRegisters.Length); _Buffer[dataPos + 8] = (byte)(2 * writeRegisters.Length); for (int i = 0; i < writeRegisters.Length; i++) { ModbusUtils.InsertUShort(_Buffer, dataPos + 9 + 2 * i, writeRegisters[i]); } SendReceive(deviceAddress, ModbusFunctionCode.ReadWriteMultipleRegisters, timeout, telegramLength, (short)(1 + 2 * readCount), telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { return(null); } var readRegisters = new ushort[readCount]; for (int n = 0; n < readRegisters.Length; ++n) { readRegisters[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n); } return(readRegisters); }
/// <summary> /// Sends a Get Comm Event Log (0x0C) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="status">Receives the status word of the device.</param> /// <param name="eventCount">Receives the event counter of the device.</param> /// <param name="messageCount">Receives the event message count.</param> /// <param name="events">Receives 0 - 64 bytes, with each byte corresponding to the status of one MODBUS send or receive operation for the remote device. /// Byte 0 is the most recent.</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <remarks> /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual void GetCommEventLog(byte deviceAddress, out ushort status, out ushort eventCount, out ushort messageCount, out byte[] events, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.GetCommEventLog, 0, _Buffer, out telegramLength, out dataPos, false, ref telegramContext); SendReceive(deviceAddress, ModbusFunctionCode.GetCommEventLog, timeout, telegramLength, -1, telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { status = 0; eventCount = 0; messageCount = 0; events = null; return; } var byteCnt = _Buffer[dataPos]; status = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1); eventCount = ModbusUtils.ExtractUShort(_Buffer, dataPos + 3); messageCount = ModbusUtils.ExtractUShort(_Buffer, dataPos + 5); events = new byte[byteCnt - 6]; Array.Copy(_Buffer, dataPos + 7, events, 0, events.Length); }
/// <summary> /// Sends a Diagnostics (0x08) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="subFunction">Sub function code.</param> /// <param name="data">Data</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <returns>Returns a unsigned short array with diagnostic data.</returns> /// <remarks> /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual ushort[] Diagnostics(byte deviceAddress, ushort subFunction, ushort[] data, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.Diagnostics, (short)(2 + 2 * data.Length), _Buffer, out telegramLength, out dataPos, false, ref telegramContext); ModbusUtils.InsertUShort(_Buffer, dataPos, subFunction); for (int n = 0; n < data.Length; ++n) { ModbusUtils.InsertUShort(_Buffer, dataPos + 2 + 2 * n, data[n]); } var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.Diagnostics, timeout, telegramLength, (short)(2 + 2 * data.Length), telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { return(null); } data = new ushort[(dataLength - 2) / 2]; for (int n = 0; n < data.Length; ++n) { data[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 2 + 2 * n); } return(data); }
/// <summary> /// Sends a Read Input Registers (0x04) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param> /// <param name="registerCount">Number of the registers to read.</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <returns>Returns an array of 16 bit register values.</returns> /// <remarks> /// A register is a 16 bit unsigned value. /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual ushort[] ReadInputRegisters(byte deviceAddress, ushort startAddress, ushort registerCount, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadInputRegisters, 4, _Buffer, out telegramLength, out dataPos, false, ref telegramContext); ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress); ModbusUtils.InsertUShort(_Buffer, dataPos + 2, registerCount); short desiredDataLength = (short)(1 + 2 * registerCount); var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadInputRegisters, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { return(null); } var registers = new ushort[(dataLength - 1) / 2]; for (int n = 0; n < registers.Length; ++n) { registers[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n); } return(registers); }
/// <summary> /// Sends a Get Comm Event Counter (0x0B) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="status">Receives the status word of the device.</param> /// <param name="eventCount">Receives the event counter of the device.</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <remarks> /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual void GetCommEventCounter(byte deviceAddress, out ushort status, out ushort eventCount, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.GetCommEventCounter, 0, _Buffer, out telegramLength, out dataPos, false, ref telegramContext); SendReceive(deviceAddress, ModbusFunctionCode.GetCommEventCounter, timeout, telegramLength, 4, telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { status = 0; eventCount = 0; return; } status = ModbusUtils.ExtractUShort(_Buffer, dataPos); eventCount = ModbusUtils.ExtractUShort(_Buffer, dataPos + 2); }
private void ReadDiscreteInputs(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength) { if (dataLength < 4) { SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue); } else { ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos); ushort inputCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2); byte[] inputs; if (inputCount % 8 == 0) { inputs = new byte[inputCount / 8]; } else { inputs = new byte[inputCount / 8 + 1]; inputs[inputs.Length - 1] = 0; } var err = OnReadDiscreteInputs(isBroadcast, startAddress, inputCount, inputs); if (isBroadcast) { return; } if (err != ModbusErrorCode.NoError) { SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err); } else { short telegramLength; intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(1 + inputs.Length), _buffer, out telegramLength, out dataPos, true, ref telegramContext); _buffer[dataPos] = (byte)(inputs.Length); Array.Copy(inputs, 0, _buffer, dataPos + 1, inputs.Length); intf.SendTelegram(_buffer, telegramLength); } } }
/// <summary> /// Sends a Read Holding Registers (0x03) telegram to a device and waits for the response /// </summary> /// <param name="deviceAddress">Address of the modbus device.</param> /// <param name="startAddress">Start address: 0x0000 .. 0xFFFF</param> /// <param name="registerCount">Number of the registers to read.</param> /// <param name="timeout">Timeout for response in milli seconds.</param> /// <returns>Returns an array of 16 bit register values.</returns> /// <remarks> /// A register is a 16 bit unsigned value. /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details. /// </remarks> public virtual ushort[] ReadHoldingRegisters(byte deviceAddress, ushort startAddress, ushort registerCount, int timeout = 2000) { short telegramLength; short dataPos; object telegramContext = null; _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadHoldingRegisters, 4, _Buffer, out telegramLength, out dataPos, false, ref telegramContext); ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress); ModbusUtils.InsertUShort(_Buffer, dataPos + 2, registerCount); short desiredDataLength = (short)(1 + 2 * registerCount); var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadHoldingRegisters, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos); if (deviceAddress == ModbusConst.BroadcastAddress) { return(null); } var registers = new ushort[(dataLength - 1) / 2]; for (int n = 0; n < registers.Length; ++n) { registers[n] = ModbusUtils.ExtractUShort(_Buffer, dataPos + 1 + 2 * n); } // Send data to whom ever interested string displayString = "<-- " + HexEncoding.ToString(_Buffer, 0, dataLength + 4) + "\r\n"; if (NewSerialDataRecieved != null) { NewSerialDataRecieved(this, new ReceivedDataEventArgs(displayString)); } //* return(registers); }
private void WriteMultipleRegisters(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength) { if (dataLength < 5) { SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue); } else { ushort startAddress = ModbusUtils.ExtractUShort(_buffer, dataPos); ushort registerCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2); //byte byteCount = _Buffer[dataPos + 4]; ushort[] registers = new ushort[registerCount]; for (int i = 0; i < registerCount; i++) { registers[i] = ModbusUtils.ExtractUShort(_buffer, dataPos + 5 + 2 * i); } var err = OnWriteMultipleRegisters(isBroadcast, startAddress, registers); if (isBroadcast) { return; } if (err != ModbusErrorCode.NoError) { SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, err); } else { short telegramLength; intf.CreateTelegram(_deviceAddress, (byte)fc, 4, _buffer, out telegramLength, out dataPos, true, ref telegramContext); ModbusUtils.InsertUShort(_buffer, dataPos, startAddress); ModbusUtils.InsertUShort(_buffer, dataPos + 2, registerCount); intf.SendTelegram(_buffer, telegramLength); } } }