Beispiel #1
0
        /// <inheritdoc />
        public void ExecuteReadCommand(IConfigItem configItem, ushort transactionId, byte remoteUnitAddress, ushort startAddress, ushort numberOfPoints)
        {
            ModbusReadCommandParameters p  = new ModbusReadCommandParameters(6, (byte)GetReadFunctionCode(configItem.RegistryType), startAddress, numberOfPoints, transactionId, remoteUnitAddress);
            IModbusFunction             fn = FunctionFactory.CreateModbusFunction(p);

            this.functionExecutor.EnqueueCommand(fn);
        }
Beispiel #2
0
        /// <summary>
        /// Executes a digital write command.
        /// </summary>
        /// <param name="configItem">The configuration item.</param>
        /// <param name="transactionId">The transaction identifier.</param>
        /// <param name="remoteUnitAddress">The remote unit address.</param>
        /// <param name="pointAddress">The point address.</param>
        /// <param name="value">The value.</param>
        private void ExecuteDigitalCommand(IConfigItem configItem, ushort transactionId, byte remoteUnitAddress, ushort pointAddress, int value)
        {
            ModbusWriteCommandParameters p = new ModbusWriteCommandParameters(6, (byte)ModbusFunctionCode.WRITE_SINGLE_COIL, pointAddress, (ushort)value, transactionId, remoteUnitAddress);
            IModbusFunction fn             = FunctionFactory.CreateModbusFunction(p);

            this.functionExecutor.EnqueueCommand(fn);
        }
        private async Task ExecuteCommand(IModbusFunction command)
        {
            string verboseMessage = $"{baseLogString} entering ExecuteCommand method, command's FunctionCode: {command.FunctionCode}.";

            Logger.LogVerbose(verboseMessage);

            switch (command.FunctionCode)
            {
            case ModbusFunctionCode.READ_COILS:
            case ModbusFunctionCode.READ_DISCRETE_INPUTS:
            case ModbusFunctionCode.READ_HOLDING_REGISTERS:
            case ModbusFunctionCode.READ_INPUT_REGISTERS:
                await ExecuteReadCommand((IReadModbusFunction)command);

                break;

            case ModbusFunctionCode.WRITE_SINGLE_COIL:
            case ModbusFunctionCode.WRITE_SINGLE_REGISTER:
                await ExecuteWriteSingleCommand((IWriteSingleFunction)command);

                break;

            case ModbusFunctionCode.WRITE_MULTIPLE_COILS:
            case ModbusFunctionCode.WRITE_MULTIPLE_REGISTERS:
                await ExecuteWriteMultipleCommand((IWriteMultipleFunction)command);

                break;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Executes an analog write command.
        /// </summary>
        /// <param name="configItem">The configuration item.</param>
        /// <param name="transactionId">The transaction identifier.</param>
        /// <param name="remoteUnitAddress">The remote unit address.</param>
        /// <param name="pointAddress">The point address.</param>
        /// <param name="value">The value.</param>
        private void ExecuteAnalogCommand(IConfigItem configItem, ushort transactionId, byte remoteUnitAddress, ushort pointAddress, int value)
        {
            ushort raw = eguConverter.ConvertToRaw(configItem.ScaleFactor, configItem.Deviation, value);
            ModbusWriteCommandParameters p = new ModbusWriteCommandParameters(6, (byte)ModbusFunctionCode.WRITE_SINGLE_REGISTER, pointAddress, (ushort)raw, transactionId, remoteUnitAddress);
            IModbusFunction fn             = FunctionFactory.CreateModbusFunction(p);

            this.functionExecutor.EnqueueCommand(fn);
        }
        private void ExecuteCommand(IModbusFunction command)
        {
            try
            {
                command.Execute(ModbusClient);
            }
            catch (Exception e)
            {
                string message = "Exception on currentCommand.Execute().";
                Logger.LogWarn(message, e);
                ModbusClient.Disconnect();
                return;
            }

            if (command is IReadAnalogModusFunction readAnalogCommand)
            {
                MakeAnalogEntryToMeasurementCache(readAnalogCommand.Data, true);
            }
            else if (command is IReadDiscreteModbusFunction readDiscreteCommand)
            {
                MakeDiscreteEntryToMeasurementCache(readDiscreteCommand.Data, true);
            }
            else if (command is IWriteModbusFunction writeModbusCommand)
            {
                CommandValue commandValue = new CommandValue()
                {
                    Address       = writeModbusCommand.ModbusWriteCommandParameters.OutputAddress,
                    Value         = writeModbusCommand.ModbusWriteCommandParameters.Value,
                    CommandOrigin = writeModbusCommand.CommandOrigin,
                };

                PointType pointType;
                switch (writeModbusCommand.ModbusWriteCommandParameters.FunctionCode)
                {
                case (byte)ModbusFunctionCode.WRITE_SINGLE_REGISTER:
                    pointType = PointType.ANALOG_OUTPUT;
                    break;

                case (byte)ModbusFunctionCode.WRITE_SINGLE_COIL:
                    pointType = PointType.DIGITAL_OUTPUT;
                    break;

                default:
                    Logger.LogError($"Function code {writeModbusCommand.ModbusWriteCommandParameters.FunctionCode} is not comatible with write command.");
                    return;
                }

                if (SCADAModel.CurrentAddressToGidMap[pointType].ContainsKey(commandValue.Address))
                {
                    long gid = SCADAModel.CurrentAddressToGidMap[pointType][commandValue.Address];

                    SCADAModel.CommandedValuesCache[gid] = commandValue;
                }
            }
        }
Beispiel #6
0
 protected override void WriteCommand_Execute(object obj)
 {
     try
     {
         ModbusWriteCommandParameters p = new ModbusWriteCommandParameters(6, (byte)GetWriteFunctionCode(type), address, (ushort)CommandedValue, configuration);
         IModbusFunction fn             = FunctionFactory.CreateModbusFunction(p);
         this.commandExecutor.EnqueueCommand(fn);
     }
     catch (Exception ex)
     {
         string message = $"{ex.TargetSite.ReflectedType.Name}.{ex.TargetSite.Name}: {ex.Message}";
         this.stateUpdater.LogMessage(message);
     }
 }
        void CommunicationThread()
        {
            IModbusFunction command = null;

            byte[] data       = null;
            byte[] header     = new byte[7];
            int    sendOffset = int.MaxValue;
            int    headOffset = int.MaxValue;
            int    recvOffset = int.MaxValue;

            while (!stopSignal.WaitOne(0))
            {
                if (command == null)
                {
                    if (commandQueue.TryDequeue(out command))
                    {
                        data       = command.PackRequest();
                        sendOffset = 0;
                    }
                    else
                    {
                        Thread.Sleep(100);
                        continue;
                    }
                }

                Socket socket;
                socketLock.EnterReadLock();
                {
                    socket = this.socket;
                }
                socketLock.ExitReadLock();

                if (socket == null)
                {
                    sendOffset = command == null ? int.MaxValue : 0;
                    headOffset = int.MaxValue;
                    recvOffset = int.MaxValue;
                    Reconnect();

                    Thread.Sleep(100);
                    continue;
                }

                try
                {
                    if (sendOffset != int.MaxValue)
                    {
                        sendOffset += Send(socket, 500000, data, sendOffset);

                        if (sendOffset >= data.Length)
                        {
                            sendOffset = int.MaxValue;
                            headOffset = 0;
                            data       = header;
                        }
                    }

                    if (headOffset != int.MaxValue)
                    {
                        headOffset += Receive(socket, 500000, data, headOffset);

                        if (headOffset >= data.Length)
                        {
                            headOffset = int.MaxValue;
                            recvOffset = 7;
                            int payloadSize = unchecked ((ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(header, 4)));

                            if (payloadSize > 1)
                            {
                                data = new byte[6 + payloadSize];
                                Array.Copy(header, 0, data, 0, 7);
                            }
                            else
                            {
                                recvOffset = int.MaxValue;
                                command    = null;
                            }
                        }
                    }

                    if (recvOffset != int.MaxValue)
                    {
                        recvOffset += Receive(socket, 500000, data, recvOffset);

                        if (recvOffset >= data.Length)
                        {
                            recvOffset = int.MaxValue;
                            HandleResponse(command, data);
                            command = null;
                        }
                    }
                }
                catch (SocketException e)
                {
                    if (e.SocketErrorCode != SocketError.WouldBlock)
                    {
                        sendOffset = command == null ? int.MaxValue : 0;
                        headOffset = int.MaxValue;
                        recvOffset = int.MaxValue;
                        Reconnect();
                    }
                }
                catch (Exception e)
                {
                    sendOffset = command == null ? int.MaxValue : 0;
                    headOffset = int.MaxValue;
                    recvOffset = int.MaxValue;
                    Reconnect();
                }
            }
        }
        void HandleResponse(IModbusFunction command, byte[] receivedBytes)
        {
            Dictionary <Tuple <EPointType, ushort>, ushort> pointsToUpdate = command.ParseResponse(receivedBytes, out _);

            Notify(pointsToUpdate);
        }
 public bool EnqueueCommand(IModbusFunction command)
 {
     commandQueue.Enqueue(command);
     return(true);
 }
        public async Task Start(bool isRetry = false)
        {
            string isRetryString  = isRetry ? "yes" : "no";
            string verboseMessage = $"{baseLogString} entering Start method, isRetry: {isRetryString}.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableQueuesInitialized)
            {
                await Task.Delay(1000);
            }

            try
            {
                if (modbusClient == null)
                {
                    await InitializeModbusClient();
                }

                if (!modbusClient.Connected)
                {
                    ConnectToModbusClient();
                }

                if (modbusClient.Connected)
                {
                    while ((await ModelUpdateCommandQueue.GetCountAsync()) > 0)
                    {
                        verboseMessage = $"{baseLogString} Start => Getting Command from model update command queue.";
                        Logger.LogVerbose(verboseMessage);

                        var result = await ModelUpdateCommandQueue.TryDequeueAsync();

                        if (!result.HasValue)
                        {
                            continue;
                        }

                        IModbusFunction currentCommand = result.Value;

                        string informationMessage = $"{baseLogString} Start => Command received from model update command queue about to be executed.";
                        Logger.LogInformation(informationMessage);

                        await ExecuteCommand(currentCommand);
                    }

                    while ((await WriteCommandQueue.GetCountAsync()) > 0)
                    {
                        verboseMessage = $"{baseLogString} Start => Getting Command from write command queue.";
                        Logger.LogVerbose(verboseMessage);

                        var result = await WriteCommandQueue.TryDequeueAsync();

                        if (!result.HasValue)
                        {
                            continue;
                        }

                        IModbusFunction currentCommand = result.Value;

                        string informationMessage = $"{baseLogString} Start => Command received from write command queue about to be executed.";
                        Logger.LogInformation(informationMessage);

                        await ExecuteCommand(currentCommand);
                    }
                }

                while ((await ReadCommandQueue.GetCountAsync()) > 0)
                {
                    verboseMessage = $"{baseLogString} Start => Getting Command from read command queue.";
                    Logger.LogInformation(verboseMessage);

                    var result = await ReadCommandQueue.TryDequeueAsync();

                    if (!result.HasValue)
                    {
                        continue;
                    }

                    IModbusFunction currentCommand = result.Value;

                    verboseMessage = $"{baseLogString} Start => Command received from read command queue about to be executed.";
                    Logger.LogVerbose(verboseMessage);

                    await ExecuteCommand(currentCommand);
                }
            }
            catch (Exception e)
            {
                string message = $"{baseLogString} Start => Exception caught.";
                Logger.LogError(message, e);
                throw e;
            }
        }