コード例 #1
0
        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);
                }
            }
        }
コード例 #2
0
        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);
                }
            }
        }
コード例 #3
0
        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);
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Handles a received message.
        /// </summary>
        /// <param name="intf">Interface by which te message was received.</param>
        /// <param name="deviceAddress">Address of the target device</param>
        /// <param name="isBroadcast">true if the message is a broadcast. For broadcast messages no reponse is sent.</param>
        /// <param name="telegramLength">Length of the message in bytes.</param>
        /// <param name="telegramContext">Interface specific message context.</param>
        /// <param name="fc">Function code.</param>
        /// <param name="dataPos">Index of function code specific data.</param>
        /// <param name="dataLength">Length of the function code specific data in bytes.</param>
        protected override void OnHandleTelegram(IModbusInterface intf, byte deviceAddress, bool isBroadcast, short telegramLength,
                                                 object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            var master = (GatewayMaster)_masterMap[deviceAddress];

            if (master != null)
            {
                short  masterTelegramLength;
                short  masterDataPos;
                object masterTelegramContext = null;

                master.MasterInterface.CreateTelegram(master.TargetAddress, (byte)fc, dataLength, master.Buffer, out masterTelegramLength, out masterDataPos, false, ref masterTelegramContext);
                Array.Copy(Buffer, dataPos, master.Buffer, masterDataPos, dataLength);

                try
                {
                    var masterDataLength = SendReceive(master.MasterInterface, master.Buffer, master.TargetAddress, fc, master.Timeout,
                                                       masterTelegramLength, -1, masterTelegramContext, ref masterDataPos);

                    intf.CreateTelegram(deviceAddress, (byte)fc, masterDataLength, Buffer, out telegramLength, out dataPos,
                                        true, ref telegramContext);
                    Array.Copy(master.Buffer, masterDataPos, Buffer, dataPos, masterDataLength);
                    intf.SendTelegram(Buffer, telegramLength);
                }
                catch (ModbusException ex)
                {
                    try
                    {
                        if (ex.ErrorCode == ModbusErrorCode.Timeout)
                        {
                            SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayTargetDeviceFailedToRespond);
                        }
                        else if (((ushort)ex.ErrorCode & 0xff00) != 0)
                        {
                            SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayTargetDeviceFailedToRespond);
                        }
                        else
                        {
                            SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ex.ErrorCode);
                        }
                    }
                    // ReSharper disable once EmptyGeneralCatchClause
                    catch { }
                }
                catch
                {
                    try
                    {
                        SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayPathUnavailable);
                    }
                    // ReSharper disable once EmptyGeneralCatchClause
                    catch { }
                }
            }
            else
            {
                base.OnHandleTelegram(intf, deviceAddress, isBroadcast, telegramLength, telegramContext, fc, dataPos, dataLength);
            }
        }
コード例 #5
0
        /// <summary>
        /// Sends a error result message.
        /// </summary>
        /// <param name="intf">Interface to send message to.</param>
        /// <param name="isBroadcast">true if the message is a broadcast. For broadcast messages no reponse is sent.</param>
        /// <param name="deviceAddress">Device address for response</param>
        /// <param name="telegramContext">Interface specific telegram context.</param>
        /// <param name="fc">Function code. The msg is automatically set.</param>
        /// <param name="modbusErrorCode">Modbus error code to send.</param>
        protected virtual void SendErrorResult(IModbusInterface intf, bool isBroadcast, byte deviceAddress, object telegramContext, ModbusFunctionCode fc, ModbusErrorCode modbusErrorCode)
        {
            if (isBroadcast)
            {
                return;
            }
            short telegramLength;
            short dataPos;

            intf.CreateTelegram(deviceAddress, (byte)((byte)fc | 0x80), 1, _buffer, out telegramLength, out dataPos, true, ref telegramContext);
            _buffer[dataPos] = (byte)modbusErrorCode;
            intf.SendTelegram(_buffer, telegramLength);
        }
コード例 #6
0
 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);
         }
     }
 }
コード例 #7
0
        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);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Is called when the device identification of this devuice is requested.
        /// </summary>
        /// <param name="intf">Interface from wich the requst was received</param>
        /// <param name="isBroadcast">true if request is a broadcast</param>
        /// <param name="telegramContext">Conext of the telegram</param>
        /// <param name="fc">Function code</param>
        /// <param name="dataPos">Posittion (offset) of the data in the buffer</param>
        /// <param name="dataLength">Length of the data in the buffer</param>
        protected virtual void ReadDeviceIdentification(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
        {
            if (isBroadcast)
            {
                return;
            }
            if (dataLength < 3)
            {
                SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
            }
            else
            {
                byte deviceIdCode = _buffer[dataPos + 1];
                if (deviceIdCode < 1 || deviceIdCode > 4)
                {
                    SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
                    return;
                }
                byte objectId = _buffer[dataPos + 2];
                byte lastObjectId;
                switch (deviceIdCode)
                {
                case 0x00:
                    lastObjectId = 0x02; // basic
                    break;

                case 0x01:
                    lastObjectId = 0x7f; // regular
                    break;

                case 0x02:
                    lastObjectId = 0xff; // extended
                    break;

                default:
                    lastObjectId = objectId; // specific
                    break;
                }

                byte[] values      = new byte[intf.MaxTelegramLength - 6];
                byte   objectCount = 0;
                short  valuePos    = 0;
                bool   moreFolows  = false;
                byte   nextId      = 0;
                for (short id = objectId; id <= lastObjectId; ++id)
                {
                    var value = OnGetDeviceIdentification((ModbusObjectId)id);
                    if (value == null)
                    {
                        // no more values
                        break;
                    }
                    if (values.Length - (valuePos + 2) >= value.Length)
                    {
                        ++objectCount;
                        values[valuePos++] = (byte)id;
                        values[valuePos++] = (byte)value.Length;
                        for (int c = 0; c < value.Length; c++)
                        {
                            values[valuePos++] = (byte)value[c];
                        }
                    }
                    else
                    {
                        // more to come
                        moreFolows = true;
                        nextId     = (byte)(id + 1);
                        break;
                    }
                }

                short telegramLength;
                intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(6 + valuePos), _buffer, out telegramLength, out dataPos, true, ref telegramContext);
                _buffer[dataPos]     = 0x0e;
                _buffer[dataPos + 1] = deviceIdCode;
                _buffer[dataPos + 2] = (byte)((byte)GetConformityLevel() & 0x80);
                _buffer[dataPos + 3] = (byte)(moreFolows ? 0xff : 0x00);
                _buffer[dataPos + 4] = nextId;
                _buffer[dataPos + 5] = objectCount;
                Array.Copy(values, 0, _buffer, dataPos + 6, valuePos);
                intf.SendTelegram(_buffer, telegramLength);
            }
        }
コード例 #9
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
 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);
       }
    }
 }
コード例 #10
0
        /// <summary>
        /// Sends a Read Coils (0x01) 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="coilCount">>Number of coils to read: 1 .. 2000</param>
        /// <param name="timeout">Timeout for response in Milli seconds.</param>
        /// <returns>Returns a byte array which contains the coils. The coils are written as single bits into the array starting with coil 1 at the lsb.</returns>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual byte[] ReadCoils(byte deviceAddress, ushort startAddress, ushort coilCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadCoils, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, coilCount);

            short desiredDataLength = (short)(1 + coilCount / 8);

            if (coilCount % 8 != 0)
            {
                ++desiredDataLength;
            }

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadCoils, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var coils = new byte[dataLength - 1];

            Array.Copy(_Buffer, dataPos + 1, coils, 0, dataLength - 1);

            // 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(coils);
        }
コード例 #11
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
 /// <summary>
 /// Sends a error result message.
 /// </summary>
 /// <param name="intf">Interface to send message to.</param>
 /// <param name="isBroadcast">true if the message is a broadcast. For broadcast messages no reponse is sent.</param>
 /// <param name="deviceAddress">Device address for response</param>
 /// <param name="telegramContext">Interface specific telegram context.</param>
 /// <param name="fc">Function code. The msg is automatically set.</param>
 /// <param name="modbusErrorCode">Modbus error code to send.</param>
 protected virtual void SendErrorResult(IModbusInterface intf, bool isBroadcast, byte deviceAddress, object telegramContext, ModbusFunctionCode fc, ModbusErrorCode modbusErrorCode)
 {
    if (isBroadcast)
    {
       return;
    }
    short telegramLength;
    short dataPos;
    intf.CreateTelegram(deviceAddress, (byte)((byte)fc | 0x80), 1, _buffer, out telegramLength, out dataPos, true, ref telegramContext);
    _buffer[dataPos] = (byte)modbusErrorCode;
    intf.SendTelegram(_buffer, telegramLength);
 }
コード例 #12
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
      /// <summary>
      /// Is called when the device identification of this devuice is requested.
      /// </summary>
      /// <param name="intf">Interface from wich the requst was received</param>
      /// <param name="isBroadcast">true if request is a broadcast</param>
      /// <param name="telegramContext">Conext of the telegram</param>
      /// <param name="fc">Function code</param>
      /// <param name="dataPos">Posittion (offset) of the data in the buffer</param>
      /// <param name="dataLength">Length of the data in the buffer</param>
      protected virtual void ReadDeviceIdentification(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
      {
         if (isBroadcast)
         {
            return;
         }
         if (dataLength < 3)
         {
            SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
         }
         else
         {
            byte deviceIdCode = _buffer[dataPos + 1];
            if (deviceIdCode < 1 || deviceIdCode > 4)
            {
               SendErrorResult(intf, false, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
               return;
            }
            byte objectId = _buffer[dataPos + 2];
            byte lastObjectId;
            switch (deviceIdCode)
            {
               case 0x00:
                  lastObjectId = 0x02; // basic
                  break;

               case 0x01:
                  lastObjectId = 0x7f; // regular
                  break;

               case 0x02:
                  lastObjectId = 0xff; // extended
                  break;

               default:
                  lastObjectId = objectId; // specific
                  break;
            }

            byte[] values = new byte[intf.MaxTelegramLength - 6];
            byte objectCount = 0;
            short valuePos = 0;
            bool moreFolows = false;
            byte nextId = 0;
            for (short id = objectId; id <= lastObjectId; ++id)
            {
               var value = OnGetDeviceIdentification((ModbusObjectId)id);
               if (value == null)
               {
                  // no more values
                  break;
               }
               if (values.Length - (valuePos + 2) >= value.Length)
               {
                  ++objectCount;
                  values[valuePos++] = (byte)id;
                  values[valuePos++] = (byte)value.Length;
                  for (int c = 0; c < value.Length; c++)
                  {
                     values[valuePos++] = (byte)value[c];
                  }
               }
               else
               {
                  // more to come
                  moreFolows = true;
                  nextId = (byte)(id + 1);
                  break;
               }
            }

            short telegramLength;
            intf.CreateTelegram(_deviceAddress, (byte)fc, (short)(6 + valuePos), _buffer, out telegramLength, out dataPos, true, ref telegramContext);
            _buffer[dataPos] = 0x0e;
            _buffer[dataPos + 1] = deviceIdCode;
            _buffer[dataPos + 2] = (byte)((byte)GetConformityLevel() & 0x80);
            _buffer[dataPos + 3] = (byte)(moreFolows ? 0xff : 0x00);
            _buffer[dataPos + 4] = nextId;
            _buffer[dataPos + 5] = objectCount;
            Array.Copy(values, 0, _buffer, dataPos + 6, valuePos);
            intf.SendTelegram(_buffer, telegramLength);
         }
      }
コード例 #13
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
      private void ReadWriteMultipleRegisters(IModbusInterface intf, bool isBroadcast, object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
      {
         if (dataLength < 9)
         {
            SendErrorResult(intf, isBroadcast, _deviceAddress, telegramContext, fc, ModbusErrorCode.IllegalDataValue);
         }
         else
         {
            ushort readStartAddress = ModbusUtils.ExtractUShort(_buffer, dataPos);
            ushort readCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 2);
            ushort writeStartAddress = ModbusUtils.ExtractUShort(_buffer, dataPos + 4);
            ushort writeCount = ModbusUtils.ExtractUShort(_buffer, dataPos + 6);
            //byte byteCount = _Buffer[dataPos + 8];
            ushort[] writeRegisters = new ushort[writeCount];
            for (int i = 0; i < writeCount; i++)
            {
               writeRegisters[i] = ModbusUtils.ExtractUShort(_buffer, dataPos + 5 + 2 * i);
            }
            ushort[] readRegisters = new ushort[readCount];

            var err = OnReadWriteMultipleRegisters(isBroadcast, writeStartAddress, writeRegisters, readStartAddress, readRegisters);
            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 * readRegisters.Length), _buffer, out telegramLength, out dataPos, true, ref telegramContext);
               _buffer[dataPos] = (byte)(2 * readRegisters.Length);
               for (int i = 0; i < readCount; i++)
               {
                  ModbusUtils.InsertUShort(_buffer, dataPos + 1 + 2 * i, readRegisters[i]);
               }
               intf.SendTelegram(_buffer, telegramLength);
            }
         }
      }
コード例 #14
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
      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);
            }
         }
      }
コード例 #15
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
      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);
            }
         }
      }
コード例 #16
0
ファイル: ModbusDevice.cs プロジェクト: gremlinc5/ModbusLib
      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);
            }
         }
      }
コード例 #17
0
ファイル: ModbusGateway.cs プロジェクト: gremlinc5/ModbusLib
      /// <summary>
      /// Handles a received message.
      /// </summary>
      /// <param name="intf">Interface by which te message was received.</param>
      /// <param name="deviceAddress">Address of the target device</param>
      /// <param name="isBroadcast">true if the message is a broadcast. For broadcast messages no reponse is sent.</param>
      /// <param name="telegramLength">Length of the message in bytes.</param>
      /// <param name="telegramContext">Interface specific message context.</param>
      /// <param name="fc">Function code.</param>
      /// <param name="dataPos">Index of function code specific data.</param>
      /// <param name="dataLength">Length of the function code specific data in bytes.</param>
      protected override void OnHandleTelegram(IModbusInterface intf, byte deviceAddress, bool isBroadcast, short telegramLength,
         object telegramContext, ModbusFunctionCode fc, short dataPos, short dataLength)
      {
         var master = (GatewayMaster)_masterMap[deviceAddress];
         if (master != null)
         {
            short masterTelegramLength;
            short masterDataPos;
            object masterTelegramContext = null;

            master.MasterInterface.CreateTelegram(master.TargetAddress, (byte)fc, dataLength, master.Buffer, out masterTelegramLength, out masterDataPos, false, ref masterTelegramContext);
            Array.Copy(Buffer, dataPos, master.Buffer, masterDataPos, dataLength);

            try
            {
               var masterDataLength = SendReceive(master.MasterInterface, master.Buffer, master.TargetAddress, fc, master.Timeout,
                  masterTelegramLength, -1, masterTelegramContext, ref masterDataPos);

               intf.CreateTelegram(deviceAddress, (byte)fc, masterDataLength, Buffer, out telegramLength, out dataPos,
                  true, ref telegramContext);
               Array.Copy(master.Buffer, masterDataPos, Buffer, dataPos, masterDataLength);
               intf.SendTelegram(Buffer, telegramLength);
            }
            catch (ModbusException ex)
            {
               try
               {
                  if (ex.ErrorCode == ModbusErrorCode.Timeout)
                  {
                     SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayTargetDeviceFailedToRespond);
                  }
                  else if (((ushort)ex.ErrorCode & 0xff00) != 0)
                  {
                     SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayTargetDeviceFailedToRespond);
                  }
                  else
                  {
                     SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ex.ErrorCode);
                  }
               }
               // ReSharper disable once EmptyGeneralCatchClause
               catch { }
            }
            catch
            {
               try
               {
                  SendErrorResult(intf, false, deviceAddress, telegramContext, fc, ModbusErrorCode.GatewayPathUnavailable);
               }
               // ReSharper disable once EmptyGeneralCatchClause
               catch { }
            }
         }
         else
         {
            base.OnHandleTelegram(intf, deviceAddress, isBroadcast, telegramLength, telegramContext, fc, dataPos, dataLength);
         }
      }
コード例 #18
0
        /// <summary>
        /// Sends a Read Coils (0x01) 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="coilCount">>Number of coils to read: 1 .. 2000</param>
        /// <param name="timeout">Timeout for response in Milli seconds.</param>
        /// <returns>Returns a byte array which contains the coils. The coils are written as single bits into the array starting with coil 1 at the lsb.</returns>
        /// <remarks>
        /// Look at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf for more details.
        /// </remarks>
        public virtual byte[] ReadCoils(byte deviceAddress, ushort startAddress, ushort coilCount, int timeout = 2000)
        {
            short  telegramLength;
            short  dataPos;
            object telegramContext = null;

            _Interface.CreateTelegram(deviceAddress, (byte)ModbusFunctionCode.ReadCoils, 4,
                                      _Buffer, out telegramLength, out dataPos, false, ref telegramContext);

            ModbusUtils.InsertUShort(_Buffer, dataPos, startAddress);
            ModbusUtils.InsertUShort(_Buffer, dataPos + 2, coilCount);

            short desiredDataLength = (short)(1 + coilCount / 8);

            if (coilCount % 8 != 0)
            {
                ++desiredDataLength;
            }

            var dataLength = SendReceive(deviceAddress, ModbusFunctionCode.ReadCoils, timeout, telegramLength, desiredDataLength, telegramContext, ref dataPos);

            if (deviceAddress == ModbusConst.BroadcastAddress)
            {
                return(null);
            }

            var coils = new byte[dataLength - 1];

            Array.Copy(_Buffer, dataPos + 1, coils, 0, dataLength - 1);

            return(coils);
        }