Exemplo n.º 1
0
        public void HandleMessage(ModbusMessage message)
        {
            for (int i = 0; i < corruptionAttempts; i++)
            {
                if (random.NextDouble() < corruptionChance / corruptionAttempts)
                {
                    message.address = Utils.FlipRandomBit(message.address);
                }

                if (random.NextDouble() < corruptionChance / corruptionAttempts)
                {
                    message.function = Utils.FlipRandomBit(message.function);
                }

                for (int j = 0; j < message.data.Length; j++)
                {
                    if (random.NextDouble() < corruptionChance / corruptionAttempts)
                    {
                        message.data[j] = Utils.FlipRandomBit(message.data[j]);
                    }
                }

                if (random.NextDouble() < corruptionChance / corruptionAttempts)
                {
                    message.checksum = Utils.FlipRandomBit(message.checksum);
                }
            }

            OnMessage?.Invoke(message);
        }
Exemplo n.º 2
0
        private void Func_WriteMultipleCoils(ModbusMessage message)
        {
            int  firstCoilAddress = message.data[0] * 256 + message.data[1];
            int  coilsToWrite     = message.data[2] * 256 + message.data[3];
            byte coilByteCount    = message.data[4];

            byte[] coilBytes = message.data.Skip(5).Take(message.data.Length - 5).ToArray();

            int coilsLeft = coilsToWrite;

            for (int i = 0; i < coilByteCount; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    coils.Set(i * 8 - 1 - j + firstCoilAddress, (coilBytes[i] & (1 << j)) == 1);
                    if (--coilsLeft < 0)
                    {
                        break;
                    }
                }
            }

            bus.SendMessage(new ModbusMessage
            {
                address  = id,
                function = 15,
                data     = new byte[4] {
                    (byte)((firstCoilAddress & 0xFF00) >> 8), (byte)(firstCoilAddress & 0x00FF), (byte)((coilsToWrite & 0xFF00) >> 8), (byte)(coilsToWrite & 0x00FF)
                }
            });
        }
Exemplo n.º 3
0
        private void Func_ReadCoils(ModbusMessage message)
        {
            int firstCoilAddress = message.data[0] * 256 + message.data[1];
            int coilsToRead      = message.data[2] * 256 + message.data[3];

            byte[] readData  = new byte[coilsToRead / 8 + 1];
            int    coilsLeft = coilsToRead;

            for (int i = 0; i < readData.Length; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    readData[i] |= (byte)((coils.Get(i * 8 + j + firstCoilAddress) ? 1 : 0) << j);
                    if (--coilsLeft < 0)
                    {
                        break;
                    }
                }
            }

            bus.SendMessage(new ModbusMessage
            {
                address  = id,
                function = 1,
                data     = new byte[1] {
                    (byte)readData.Length
                }.Concat(readData).ToArray()
            });
        }
Exemplo n.º 4
0
        private void Func_WriteSingleCoil(ModbusMessage message)
        {
            int coilAddress = message.data[0] * 256 + message.data[1];

            coils.Set(coilAddress, message.data[2] * 256 + message.data[3] == 0xFF00);

            bus.SendMessage(message);
        }
Exemplo n.º 5
0
        private void Func_WriteHoldingRegister(ModbusMessage message)
        {
            int registerAddress = message.data[0] * 256 + message.data[1];
            int value           = message.data[2] * 256 + message.data[3];

            holdingRegisters[registerAddress] = (ushort)value;

            bus.SendMessage(message);
        }
Exemplo n.º 6
0
        public void SendMessage(ModbusMessage message, bool isFromMaster = false, bool recalcChecksum = true)
        {
            message.isFromMaster = isFromMaster;
            if (recalcChecksum)
            {
                message.RecalculateChecksum();
            }

            HandleMessage(message);
        }
Exemplo n.º 7
0
        private void CheckForResponse(ModbusMessage message)
        {
            Thread.Sleep(timeout);
            waitingForResponse.TryGetValue(message.address, out bool waiting);

            if (waiting)
            {
                Logger.Warn($"Device {message.address} has not responded yet, resending message");
                SendMessage(message);
            }
        }
Exemplo n.º 8
0
 public static ModbusMessage CreateException(ModbusMessage message, ModbusExceptionType type)
 {
     return(new ModbusMessage
     {
         address = message.address,
         function = (byte)(message.function + 0x80),
         data = new byte[1] {
             (byte)type
         }
     });
 }
Exemplo n.º 9
0
        public void SendMessage(ModbusMessage message)
        {
            if (!message.VerifyChecksum(out ushort actualChecksum))
            {
                Logger.Warn($"Sending message to device {message.address} with wrong checksum (is {message.checksum.ToString("x2")}, should be {actualChecksum.ToString("x2")})");
            }

            bus.SendMessage(message, true);
            waitingForResponse.TryUpdate(message.address, true, false);

            Task.Factory.StartNew(() => CheckForResponse(message));
        }
Exemplo n.º 10
0
        public override void OnMessageReceived(ModbusMessage message)
        {
            if (message.address == id && message.isFromMaster)
            {
                if (message.VerifyChecksum(out _))
                {
                    Logger.Log($"(Slave {id}) Received message from master: {message.PrettyPrint()}");

                    Task.Factory.StartNew(() => HandleMessage(message));
                }
                else
                {
                    Logger.Warn($"(Slave {id}) Message has invalid checksum, ignoring");
                }
            }
        }
Exemplo n.º 11
0
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Logger.Error("Command file not specified. Please provide a path to the command file.");
            }

            ModbusFileParser.LoadFile(args[0]);

            ModbusProperties properties = ModbusFileParser.GetProperties();

            Bus bus = new Bus(new MasterDevice(0, properties.masterTimeout), properties.corruptionChance, properties.corruptionAttempts);

            for (int i = 0; i < properties.slaveCount; i++)
            {
                bus.Connect(new SlaveDevice((byte)(i + 1), properties.slaveProcessingTime, properties.slaveProcessingTimeJitter));
            }

            foreach (string[] tokens in ModbusFileParser.GetInstructions())
            {
                if (tokens.Length >= 2)
                {
                    switch (tokens[0])
                    {
                    case "Delay":
                        Thread.Sleep(int.Parse(tokens[1]));
                        break;

                    default:
                        break;
                    }
                }
                else
                {
                    bus.master.SendMessage(ModbusMessage.FromASCII(tokens[0], properties.useChecksum));
                }
            }

            Logger.Log("Executed all instructions");

            Console.ReadKey();
        }
Exemplo n.º 12
0
        public override void OnMessageReceived(ModbusMessage message)
        {
            if (!message.isFromMaster)
            {
                if (message.VerifyChecksum(out _))
                {
                    Logger.Log($"Received response from slave {message.address}: {message.PrettyPrint()}");

                    waitingForResponse.TryUpdate(message.address, false, true);

                    if (message.function >= 0x80)
                    {
                        Logger.Warn($"Slave {message.address} threw an exception: {(ModbusExceptionType)message.data[0]}");
                    }
                }
                else
                {
                    Logger.Warn("Message has invalid checksum, ignoring");
                }
            }
        }
Exemplo n.º 13
0
        public static ModbusMessage FromBinary(byte[] input, bool hasChecksum = true)
        {
            byte[] checksum = input.Skip(input.Length - 2).Take(2).ToArray();

            ModbusMessage message = new ModbusMessage
            {
                address  = input[0],
                function = input[1],
                data     = input.Skip(2).Take(input.Length - (hasChecksum ? 4 : 2)).ToArray()
            };

            if (hasChecksum)
            {
                message.checksum = (ushort)(checksum[0] << 8 + checksum[1]);
            }
            else
            {
                message.RecalculateChecksum();
            }

            return(message);
        }
Exemplo n.º 14
0
        private void Func_WriteMultipleHoldingRegisters(ModbusMessage message)
        {
            int  firstRegisterAddress = message.data[0] * 256 + message.data[1];
            int  registersToWrite     = message.data[2] * 256 + message.data[3];
            byte registerByteCount    = message.data[4];

            byte[] registerBytes = message.data.Skip(5).Take(registerByteCount).ToArray();

            for (int i = 0; i < registersToWrite; i++)
            {
                holdingRegisters[i + firstRegisterAddress] = (ushort)(registerBytes[i] * 256 + registerBytes[i + 1]);
            }

            bus.SendMessage(new ModbusMessage
            {
                address  = id,
                function = 16,
                data     = new byte[4] {
                    (byte)((firstRegisterAddress & 0xFF00) >> 8), (byte)(firstRegisterAddress & 0x00FF), (byte)((registerByteCount & 0xFF00) >> 8), (byte)(registerByteCount & 0x00FF)
                }
            });
        }
Exemplo n.º 15
0
        private void Func_ReadInputRegisters(ModbusMessage message)
        {
            int firstRegisterAddress = message.data[0] * 256 + message.data[1];
            int registersToRead      = message.data[2] * 256 + message.data[3];

            ushort[] registers     = inputRegisters.Skip(firstRegisterAddress).Take(registersToRead).ToArray();
            byte[]   registerBytes = new byte[registersToRead * 2];

            for (int i = 0; i < registersToRead; i++)
            {
                registerBytes[i * 2]     = (byte)((registers[i] & 0xFF00) >> 8);
                registerBytes[i * 2 + 1] = (byte)(registers[i] & 0x00FF);
            }

            bus.SendMessage(new ModbusMessage
            {
                address  = id,
                function = 4,
                data     = new byte[1] {
                    (byte)registerBytes.Length
                }.Concat(registerBytes).ToArray()
            });
        }
Exemplo n.º 16
0
 public abstract void OnMessageReceived(ModbusMessage message);
Exemplo n.º 17
0
 public virtual void RespondToMessage(ModbusMessage message)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 18
0
        private void HandleMessage(ModbusMessage message)
        {
            if (isBusy)
            {
                bus.SendMessage(ModbusMessage.CreateException(message, ModbusExceptionType.SlaveDeviceBusy));
                return;
            }

            isBusy = true;

            Thread.Sleep(Math.Max(processingTime + random.Next(-processingTimeJitter, processingTimeJitter), 0));

            try
            {
                switch (message.function)
                {
                case 1:         // Read coils
                    Func_ReadCoils(message);
                    break;

                case 2:         // Read discrete inputs
                    Func_ReadDiscreteInputs(message);
                    break;

                case 5:         // Write single coil
                    Func_WriteSingleCoil(message);
                    break;

                case 15:        // Write multiple codes
                    Func_WriteMultipleCoils(message);
                    break;

                case 3:         // Read holding registers
                    Func_ReadHoldingRegisters(message);
                    break;

                case 4:         // Read input registers
                    Func_ReadInputRegisters(message);
                    break;

                case 6:         // Write single holding register
                    Func_WriteHoldingRegister(message);
                    break;

                case 16:        // Write multiple holding registers
                    Func_WriteMultipleHoldingRegisters(message);
                    break;

                default:
                    RespondToMessage(message);
                    break;
                }
            }
            catch (NotImplementedException)
            {
                bus.SendMessage(ModbusMessage.CreateException(message, ModbusExceptionType.IllegalFunction));
            }
            catch (IndexOutOfRangeException)
            {
                bus.SendMessage(ModbusMessage.CreateException(message, ModbusExceptionType.IllegalDataAddress));
            }
            catch (ModbusException e)
            {
                bus.SendMessage(ModbusMessage.CreateException(message, e.Type));
            }
            catch (Exception)
            {
                bus.SendMessage(ModbusMessage.CreateException(message, ModbusExceptionType.SlaveDeviceFailure));
            }

            isBusy = false;
        }