private async Task HandleRequestAsync() { while (true) { Logger.Debug($"Begin reading header from Master at IP: {EndPoint}"); int readBytes = await Stream.ReadAsync(_mbapHeader, 0, 6).ConfigureAwait(false); if (readBytes == 0) { Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection."); ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); return; } ushort frameLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(_mbapHeader, 4)); Logger.Debug($"Master at {EndPoint} sent header: \"{string.Join(", ", _mbapHeader)}\" with {frameLength} bytes in PDU"); _messageFrame = new byte[frameLength]; readBytes = await Stream.ReadAsync(_messageFrame, 0, frameLength).ConfigureAwait(false); if (readBytes == 0) { Logger.Debug($"0 bytes read, Master at {EndPoint} has closed Socket connection."); ModbusMasterTcpConnectionClosed?.Invoke(this, new TcpConnectionEventArgs(EndPoint)); return; } Logger.Debug($"Read frame from Master at {EndPoint} completed {readBytes} bytes"); byte[] frame = _mbapHeader.Concat(_messageFrame).ToArray(); Logger.Trace($"RX from Master at {EndPoint}: {string.Join(", ", frame)}"); var request = _modbusFactory.CreateModbusRequest(_messageFrame); request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); IModbusSlave slave = _slaveNetwork.GetSlave(request.SlaveAddress); if (slave != null) { //TODO: Determine if this is appropriate // perform action and build response IModbusMessage response = slave.ApplyRequest(request); response.TransactionId = request.TransactionId; // write response byte[] responseFrame = Transport.BuildMessageFrame(response); Logger.Information($"TX to Master at {EndPoint}: {string.Join(", ", responseFrame)}"); await Stream.WriteAsync(responseFrame, 0, responseFrame.Length).ConfigureAwait(false); } } }
/// <summary> /// Apply the request. /// </summary> /// <param name="request"></param> protected IModbusMessage ApplyRequest(IModbusMessage request) { //Check for broadcast requests if (request.SlaveAddress == 0) { //Grab each slave foreach (var slave in _slaves.Values) { try { //Apply the request slave.ApplyRequest(request); } catch (Exception /*ex*/) { //Logger.Error($"Error applying request to slave {slave.UnitId}: {ex.Message}"); } } } else { //Attempt to find a slave for this address IModbusSlave slave = GetSlave(request.SlaveAddress); // only service requests addressed to our slaves if (slave == null) { Console.WriteLine($"NModbus Slave Network ignoring request intended for NModbus Slave {request.SlaveAddress}"); } else { // perform action return(slave.ApplyRequest(request)); } } return(null); }