private void InnerServiceFCServerAndStateRelay() { if (portBaseStateObserver.IsUpdateNeeded) { portBaseStateObserver.Update(); SetBaseState(portBaseStateObserver.Object, "Republishing from port", true); } fcServer.Service(); }
/// <summary> /// Services the previously decoded request ADU packet by invoking the correspondingly selected method in the given IModbusFCServer instance and using /// the response and data that it provides to generate the response packet (if any) that can be sent back to the client. /// Returns true if a response packet is available to send or false if this request produced no response packet. /// </summary> /// <returns>true if a response packet is available to send or false if this request produced no response packet.</returns> public bool ServiceDecodedRequest(IModbusFCServer fcServer) { fcServer.Service(); // update the responseAdu as an appropriate response to the requestAdu responseAdu.PktBuf.Clear(); responseAdu.FCInfo = requestAdu.FCInfo; responseAdu.ADUType = requestAdu.ADUType; responseAdu.NumItemsInResponse = requestAdu.NumReadItemsInRequest; responseAdu.ExceptionCodeToSend = ExceptionCode.None; if (RespondToAllTargets) { // respond as whatever target the request was aimed at if (ADUType == ADUType.RTU) { responseAdu.RTUAddr = requestAdu.RTUAddr; } else { responseAdu.UnitID = requestAdu.UnitID; } } else { if (ADUType == ADUType.RTU) { if (requestAdu.RTUAddr != RTUAddr) { Debug.Emitter.Emit("Ignoring miss-addressed request {0} {1} RTUAddr:{2}", requestAdu.ADUType, requestAdu.FCInfo.FC, requestAdu.RTUAddr); return(false); // the request is not for us } responseAdu.RTUAddr = RTUAddr; } else { if (requestAdu.UnitID != MBAPUnitID) { Debug.Emitter.Emit("Ignoring miss-addressed request {0} {1} UnitID:{2}", requestAdu.ADUType, requestAdu.FCInfo.FC, requestAdu.UnitID); return(false); // the request is not for us } responseAdu.UnitID = MBAPUnitID; } } responseAdu.InitializeResponsePDU(); // sets up internal pointer to count/length values for later use. ExceptionCode exceptionCode = ExceptionCode.None; try { // extract the relevant data from the requestADU if (exceptionCode == ExceptionCode.None) { // get the correct data from the request bool getDataSuccess = true; switch (requestAdu.FCInfo.FC) { case FunctionCode.FC0f_WriteMultipleCoils: getDataSuccess = GetDiscretes(false, coilArray, 0, requestAdu.NumWriteItemsInRequest); break; case FunctionCode.FC10_WriteMutlipleHoldingRegisters: getDataSuccess = GetRegisters(false, holdingRegisterArray, 0, requestAdu.NumWriteItemsInRequest); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: getDataSuccess = GetRegisters(false, holdingRegisterArray, 0, requestAdu.NumWriteItemsInRequest); break; default: break; } if (!getDataSuccess) { exceptionCode = ExceptionCode.IllegalDataValue; } } // ask the fcServer to perform the requested action if (exceptionCode == ExceptionCode.None) { switch (requestAdu.FCInfo.FC) { case FunctionCode.FC00_None: exceptionCode = ExceptionCode.IllegalFunction; break; case FunctionCode.FC01_ReadCoils: exceptionCode = fcServer.FC01_ReadCoils(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, coilArray); break; case FunctionCode.FC02_ReadDiscretes: exceptionCode = fcServer.FC02_ReadDiscretes(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, discreteArray); break; case FunctionCode.FC03_ReadHoldingRegisters: exceptionCode = fcServer.FC03_ReadHoldingRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC04_ReadInputRegisters: exceptionCode = fcServer.FC04_ReadInputRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, inputRegisterArray); break; case FunctionCode.FC05_WriteSingleCoil: exceptionCode = fcServer.FC05_WriteSingleCoil(requestAdu.FirstWriteItemAddrInRequest, (HeaderWord2 != 0)); break; case FunctionCode.FC06_WriteSingleHoldingRegister: exceptionCode = fcServer.FC06_WriteSingleHoldingRegister(requestAdu.FirstWriteItemAddrInRequest, unchecked ((Int16)HeaderWord2)); break; case FunctionCode.FC08_Diagnostics: exceptionCode = ExceptionCode.IllegalFunction; break; case FunctionCode.FC0f_WriteMultipleCoils: exceptionCode = fcServer.FC0f_WriteCoils(requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, coilArray); break; case FunctionCode.FC10_WriteMutlipleHoldingRegisters: exceptionCode = fcServer.FC10_WriteMutlipleHoldingRegisters(requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC16_MaskWriteRegister: exceptionCode = fcServer.FC16_MaskWriteRegister(requestAdu.FirstWriteItemAddrInRequest, unchecked ((Int16)HeaderWord2), unchecked ((Int16)HeaderWord3)); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: exceptionCode = fcServer.FC17_ReadWriteMultipleRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, inputRegisterArray, requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC2b_EncapsulatedInterfaceTransport: exceptionCode = ExceptionCode.IllegalFunction; break; default: exceptionCode = ExceptionCode.IllegalFunction; break; } } // if the fcServer operation succeeded then build a normal response packet if (exceptionCode == ExceptionCode.None) { // put the correct data into the response bool putDataSuccess = true; switch (requestAdu.FCInfo.FC) { case FunctionCode.FC01_ReadCoils: putDataSuccess = SetDiscretes(true, coilArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC02_ReadDiscretes: putDataSuccess = SetDiscretes(true, discreteArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC03_ReadHoldingRegisters: putDataSuccess = SetRegisters(true, holdingRegisterArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC04_ReadInputRegisters: putDataSuccess = SetRegisters(true, inputRegisterArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: putDataSuccess = SetRegisters(true, inputRegisterArray, 0, responseAdu.NumItemsInResponse); break; default: break; } if (!putDataSuccess) { exceptionCode = ExceptionCode.IllegalDataValue; } } if (exceptionCode == ExceptionCode.None) { responseAdu.InitializeResponsePDUForSend(); responseAdu.PrepareToSendResponse(requestAdu); return(true); } } catch (System.Exception ex) { Issue.Emitter.Emit("Modbus Server '{0}' threw unexpected exception: fc:{1} {2}", fcServer.Name, requestAdu.FCInfo.FC, ex.ToString(ExceptionFormat.TypeAndMessage)); Debug.Emitter.Emit(ex.ToString(ExceptionFormat.Full)); exceptionCode = ExceptionCode.SlaveDeviceFailure; } if (exceptionCode != ExceptionCode.IgnoreRequest) { // build an exception response packet responseAdu.ExceptionCodeToSend = exceptionCode; responseAdu.InitializeResponsePDUForSend(); responseAdu.PrepareToSendResponse(requestAdu); return(true); } else { // make this packet invalid so that it cannot be sent responseAdu.PktBuf.Invalidate(); return(false); } }
/// <summary> /// Services the previously decoded request ADU packet by invoking the correspondingly selected method in the given IModbusFCServer instance and using /// the response and data that it provides to generate the response packet (if any) that can be sent back to the client. /// Returns true if a response packet is available to send or false if this request produced no response packet. /// </summary> /// <returns>true if a response packet is available to send or false if this request produced no response packet.</returns> public bool ServiceDecodedRequest(IModbusFCServer fcServer) { fcServer.Service(); // update the responseAdu as an appropriate response to the requestAdu responseAdu.PktBuf.Clear(); responseAdu.FCInfo = requestAdu.FCInfo; responseAdu.ADUType = requestAdu.ADUType; responseAdu.NumItemsInResponse = requestAdu.NumReadItemsInRequest; responseAdu.ExceptionCodeToSend = ExceptionCode.None; if (RespondToAllTargets) { // respond as whatever target the request was aimed at if (ADUType == ADUType.RTU) responseAdu.RTUAddr = requestAdu.RTUAddr; else responseAdu.UnitID = requestAdu.UnitID; } else { if (ADUType == ADUType.RTU) { if (requestAdu.RTUAddr != RTUAddr) { Debug.Emitter.Emit("Ignoring miss-addressed request {0} {1} RTUAddr:{2}", requestAdu.ADUType, requestAdu.FCInfo.FC, requestAdu.RTUAddr); return false; // the request is not for us } responseAdu.RTUAddr = RTUAddr; } else { if (requestAdu.UnitID != MBAPUnitID) { Debug.Emitter.Emit("Ignoring miss-addressed request {0} {1} UnitID:{2}", requestAdu.ADUType, requestAdu.FCInfo.FC, requestAdu.UnitID); return false; // the request is not for us } responseAdu.UnitID = MBAPUnitID; } } responseAdu.InitializeResponsePDU(); // sets up internal pointer to count/length values for later use. ExceptionCode exceptionCode = ExceptionCode.None; try { // extract the relevant data from the requestADU if (exceptionCode == ExceptionCode.None) { // get the correct data from the request bool getDataSuccess = true; switch (requestAdu.FCInfo.FC) { case FunctionCode.FC0f_WriteMultipleCoils: getDataSuccess = GetDiscretes(false, coilArray, 0, requestAdu.NumWriteItemsInRequest); break; case FunctionCode.FC10_WriteMutlipleHoldingRegisters: getDataSuccess = GetRegisters(false, holdingRegisterArray, 0, requestAdu.NumWriteItemsInRequest); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: getDataSuccess = GetRegisters(false, holdingRegisterArray, 0, requestAdu.NumWriteItemsInRequest); break; default: break; } if (!getDataSuccess) exceptionCode = ExceptionCode.IllegalDataValue; } // ask the fcServer to perform the requested action if (exceptionCode == ExceptionCode.None) { switch (requestAdu.FCInfo.FC) { case FunctionCode.FC00_None: exceptionCode = ExceptionCode.IllegalFunction; break; case FunctionCode.FC01_ReadCoils: exceptionCode = fcServer.FC01_ReadCoils(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, coilArray); break; case FunctionCode.FC02_ReadDiscretes: exceptionCode = fcServer.FC02_ReadDiscretes(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, discreteArray); break; case FunctionCode.FC03_ReadHoldingRegisters: exceptionCode = fcServer.FC03_ReadHoldingRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC04_ReadInputRegisters: exceptionCode = fcServer.FC04_ReadInputRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, inputRegisterArray); break; case FunctionCode.FC05_WriteSingleCoil: exceptionCode = fcServer.FC05_WriteSingleCoil(requestAdu.FirstWriteItemAddrInRequest, (HeaderWord2 != 0)); break; case FunctionCode.FC06_WriteSingleHoldingRegister: exceptionCode = fcServer.FC06_WriteSingleHoldingRegister(requestAdu.FirstWriteItemAddrInRequest, unchecked((Int16) HeaderWord2)); break; case FunctionCode.FC08_Diagnostics: exceptionCode = ExceptionCode.IllegalFunction; break; case FunctionCode.FC0f_WriteMultipleCoils: exceptionCode = fcServer.FC0f_WriteCoils(requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, coilArray); break; case FunctionCode.FC10_WriteMutlipleHoldingRegisters: exceptionCode = fcServer.FC10_WriteMutlipleHoldingRegisters(requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC16_MaskWriteRegister: exceptionCode = fcServer.FC16_MaskWriteRegister(requestAdu.FirstWriteItemAddrInRequest, unchecked((Int16) HeaderWord2), unchecked((Int16) HeaderWord3)); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: exceptionCode = fcServer.FC17_ReadWriteMultipleRegisters(requestAdu.FirstReadItemAddrInRequest, requestAdu.NumReadItemsInRequest, inputRegisterArray, requestAdu.FirstWriteItemAddrInRequest, requestAdu.NumWriteItemsInRequest, holdingRegisterArray); break; case FunctionCode.FC2b_EncapsulatedInterfaceTransport: exceptionCode = ExceptionCode.IllegalFunction; break; default: exceptionCode = ExceptionCode.IllegalFunction; break; } } // if the fcServer operation succeeded then build a normal response packet if (exceptionCode == ExceptionCode.None) { // put the correct data into the response bool putDataSuccess = true; switch (requestAdu.FCInfo.FC) { case FunctionCode.FC01_ReadCoils: putDataSuccess = SetDiscretes(true, coilArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC02_ReadDiscretes: putDataSuccess = SetDiscretes(true, discreteArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC03_ReadHoldingRegisters: putDataSuccess = SetRegisters(true, holdingRegisterArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC04_ReadInputRegisters: putDataSuccess = SetRegisters(true, inputRegisterArray, 0, responseAdu.NumItemsInResponse); break; case FunctionCode.FC17_ReadWriteMultipleRegisters: putDataSuccess = SetRegisters(true, inputRegisterArray, 0, responseAdu.NumItemsInResponse); break; default: break; } if (!putDataSuccess) exceptionCode = ExceptionCode.IllegalDataValue; } if (exceptionCode == ExceptionCode.None) { responseAdu.InitializeResponsePDUForSend(); responseAdu.PrepareToSendResponse(requestAdu); return true; } } catch (System.Exception ex) { Issue.Emitter.Emit("Modbus Servier '{0}' threw unexpected exception: fc:{1} ex:{2}", fcServer.Name, requestAdu.FCInfo.FC, ex); exceptionCode = ExceptionCode.SlaveDeviceFailure; } if (exceptionCode != ExceptionCode.IgnoreRequest) { // build an excpetion response packet responseAdu.ExceptionCodeToSend = exceptionCode; responseAdu.InitializeResponsePDUForSend(); responseAdu.PrepareToSendResponse(requestAdu); return true; } else { // make this packet invalid so that it cannot be sent responseAdu.PktBuf.Invalidate(); return false; } }