/// <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); }
/// <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; } }
/// <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; } } }
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; } }