diff --git a/Modbus-DLL/ModbusNet.cfg b/Modbus-DLL/ModbusNet.cfg index ae6f88a..5c8bf72 100644 --- a/Modbus-DLL/ModbusNet.cfg +++ b/Modbus-DLL/ModbusNet.cfg @@ -1,4 +1,4 @@ -;CANoe Version |4|7|1|38833 ModbusNet +;CANoe Version |4|7|1|38817 ModbusNet Version: 8.2.40 Build 40 32 PRO 10 @@ -67,25 +67,24 @@ DialogBegin 1 285 569 816 1103 SymbolExplorerDialogBegin - 1 HistoryBegin 1 0 HistoryEnd FiltersBegin Begin -3 0 -1 +3 0 2 5 Bus statistic signals ( 1 ( 1 ( 0 ) 0 ) 0 ) -Busstatistik Signale - ( 1 ( 1 ( 0 ) 0 ) 0 ) Modbus ( 2 ( 0 ) 0) TE0001 ( 2 ( 2 ( 0 ) 0 ) 0 ) TE0002 ( 2 ( 2 ( 0 ) 0 ) 0 ) +Busstatistik Signale + ( 1 ( 0 ) 0 ) SymbSelHeaderMgrBegin 1 6 0 1 278 0 0 @@ -214,7 +213,7 @@ Begin Modbus Systemvariablen - ( 1 ( 1 ( 0 ) 2 ( 0 ) 0 ) 3 ( 1 ( 2 ( 3 ( 0 ) 0 ) 0 ) 0 ) 0 ) + ( 1 ( 1 ( 0 ) 0 ) 0 ) SymbSelHeaderMgrBegin 1 4 0 1 200 0 0 @@ -333,7 +332,7 @@ SymbSelHeaderMgrEnd End FiltersEnd -1 12 +1 0 SymbolExplorerDialogEnd DialogEnd @@ -742,9 +741,9 @@ Begin_Of_Multi_Line_String Copyright (c) 2001-2006 Actipro Software LLC. All rights reserved. http://www.ActiproSoftware.com/Products/DotNet/ ---> 1 "ModbusTcpCommon.cin" @@ -4850,6 +4879,16 @@ NDebugger::VFile 9 Begin_Of_Object 1 "include\CAPL\include\ModbusStructs.cin" 42 End_Of_Object NDebugger::VFile 9 +NDebugger::VFile 9 Begin_Of_Object +1 + 1 "include\CAPL\include\EilDllCommon.cin" +43 +End_Of_Object NDebugger::VFile 9 +NDebugger::VFile 9 Begin_Of_Object +1 + 1 "include\CAPL\include\ModbusEilDllClientCommon.cin" +44 +End_Of_Object NDebugger::VFile 9 VNETStandaloneComponent 9 Begin_Of_Object 1 VNETControlBox 10 Begin_Of_Object @@ -4859,23 +4898,24 @@ VUniqueBox 11 Begin_Of_Object VBoxRoot 12 Begin_Of_Object 1 3 -1 -1 2 3 -1 -1 -8 -30 171 76 688 306 -Debugger - Client_2 +1 -1 0 1 -1 -1 -1 -1 35 -12 567 364 +Debugger - Programm: Client_2 [Debugging ausgeschaltet] 1 MDI_DOCK_INFO_END 5 1 6 -2 3 -1 -1 -1 -1 171 76 688 306 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 +0 1 -1 -1 -1 -1 35 -12 567 364 +6 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 END_OF_DOCK_INFO 0 -1 +1 +0 1 -1 -1 -1 -1 6 66 542 446 0 -0 -0 -859 382 +1 +157 389 END_OF_DESKTOP_DATA 6 0 1 0 0 -1 -1 171 76 688 306 @@ -5089,7 +5129,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object End_Of_Object VSimulinkModelViewerConfiguration 7 1 0 -657298843 +1716208489 0 NodeSignalPanelBustypeCount 0 End_Of_Object VSimulationNode 6 @@ -5122,7 +5162,7 @@ VBoxRoot 9 Begin_Of_Object 1 3 1 1 1 1 0 166 -8 -30 61 86 1093 577 - +Ethernet Packet Builder 1 MDI_DOCK_INFO_END @@ -5200,105 +5240,11 @@ EOF_MBSSDATA 1 0 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + @@ -5309,10 +5255,104 @@ EOF_MBSSDATA - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + End_Of_Object VSSPlugInConfiguration 6 NULL @@ -5348,7 +5388,7 @@ NULL End_Of_Object VDOLocalInfoStruct 3 0.000000 0 0 -1 1 0 59420 1 176 1 2882400001 639 815 319 694 2882400002 0 0 0 0 0 0 1 2882400001 1280 1280 321 321 2882400002 0 0 0 1437687448 0 0 3 +1 1 0 59420 1 176 1 2882400001 639 815 319 694 2882400002 0 0 0 0 0 0 1 2882400001 1280 1280 321 321 2882400002 0 0 0 0 0 0 3 SS_BEGIN_COMMON_INFO 1 0 @@ -5360,14 +5400,12 @@ Ether1 11 1 1 -504289040 1 0 1 0 1 1 0 81 42 2000 1 +492214664 1 0 1 0 1 1 0 0 0 2000 1 SS_BEGIN_COMMON_INFO 1 -3 +2 Channels 1 -Databases -1 Misc 1 SS_END_COMMON_INFO @@ -5471,7 +5509,7 @@ End_Of_Serialized_Data 2 End_Of_Object VWriteBox 2 VWinStore 2 Begin_Of_Object 1 -22 2 3 -1 -1 -1 -1 -10088 -10000 -9070 -9233 +22 2 3 -32088 -32000 -1 -1 -10088 -10000 -9070 -9233 End_Of_Child_List End_Of_Object VWinStore 2 VWinStore 2 Begin_Of_Object @@ -5792,6 +5830,7 @@ End FiltersEnd 1 1 + END_OF_WORKSPACE_MEMBER_DATA END_OF_WORKSPACE_MEMBER 1 @@ -6365,7 +6404,7 @@ VUniqueBox 4 Begin_Of_Object VBoxRoot 5 Begin_Of_Object 1 3 -1 1 1 1 160 166 -1 -1 172 63 788 501 +1 1 0 1 -1 -1 -1 -1 4 7 620 445 Startwerte 1 @@ -6373,15 +6412,16 @@ MDI_DOCK_INFO_END 5 1 6 -1 1 160 166 -1 -1 172 63 788 501 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 +0 1 -1 -1 -1 -1 4 7 620 445 +6 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 32767 0 0 0 0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 END_OF_DOCK_INFO 0 1 -0 +1 +0 1 -1 -1 -1 -1 242 174 862 616 0 1 -963 193 +95 389 END_OF_DESKTOP_DATA 6 0 1 0 0 -1 -1 199 118 815 556 diff --git a/Modbus-DLL/include/CAPL/ModbusClient.can b/Modbus-DLL/include/CAPL/ModbusClient.can index af2bfa7..5391fad 100644 --- a/Modbus-DLL/include/CAPL/ModbusClient.can +++ b/Modbus-DLL/include/CAPL/ModbusClient.can @@ -10,8 +10,8 @@ variables { msTimer gtRead; - message Client_2_RecBits rb; - message Client_2_Ex81 ex; + //message Client_2_RecBits rb; + //message Client_2_Ex81 ex; } // Get information of local network interface such like ip address @@ -20,14 +20,13 @@ on preStart { writeClear(0); setStartdelay(10); - OutputDebugLevel = Warning; + OutputDebugLevel = Debug; } on start { ModbusInit(); - // Read serial code, additional stuff is done in OnModbusReceiveRegisters // This has to be done by MakeConfig to properly size the arrays //ModbusReadRegisters(0x2011, 1); @@ -36,8 +35,8 @@ on start //ModbusReadRegisters(0x2031, 64); //ModbusReadRegisters(0x2032, 64); //ModbusReadRegisters(0x2033, 63); - if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits > 0) - ModbusReadBits(0x200, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits); + //if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits > 0) + // ModbusReadBits(0x200, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits); setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval); } diff --git a/Modbus-DLL/include/CAPL/ModbusClient.cbf b/Modbus-DLL/include/CAPL/ModbusClient.cbf index bc161f4..064c745 100644 Binary files a/Modbus-DLL/include/CAPL/ModbusClient.cbf and b/Modbus-DLL/include/CAPL/ModbusClient.cbf differ diff --git a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin b/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin index a81aa5d..bc2df20 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusClientCommon.cin @@ -7,7 +7,7 @@ includes variables { - const word gMaxPacketLength = 259; //__size_of(struct ModbusReqWriteRegisters); + const word gMaxPacketLength = __size_of(struct ModbusReqWriteRegisters); msTimer gtRobin; // Timer that sends the packets and watches for timeouts word gTxID = 0x0000; // Transaction Identifier for Modbus. Used as index for gQueue @@ -15,6 +15,7 @@ variables // Global storage for pending and sent requests, associated by TxID struct QueueElement { + byte FuncCode; word TimeoutTicks; byte Timeouts; word Length; @@ -48,32 +49,23 @@ void ModbusInit() ModbusConnectTo(ip, @sysvar::Config::Modbus::Port); } -void ModbusMakeHeader(struct ModbusApHeader mbap, word length) -{ - EthSetTokenInt(gPacket, "modbus", "TxId", gTxID++); -} - // REGION: ModbusReadBits ------------------------------------------------------------- /// void ModbusReadBits(word address, word count) { - const byte length = 12; //__size_of(struct ModbusReqRead); + const byte length = __size_of(struct ModbusReqRead); const byte funcCode = 0x01; - byte buffer[4] = {0x0B, 0x22, 0x00, 0x02}; struct ModbusReqRead mbr; - ModbusMakeHeader(mbr.Header, length); - // Payload - EthSetTokenInt(gPacket, "modbus", "FuncCode", funcCode); - EthResizeToken(gPacket, "modbus", "data" , 4*8); - EthSetTokenData(gPacket, "modbus", "data" , 4, buffer); + mbr.Address = address; + mbr.Count = count; writeDbg(MbDebug, "Sending 'Read Bits' (0x01) command. Addr: 0x%04X, Count: %d", address, count); - - EthCompletePacket(gPacket); - EthOutputPacket(gPacket); + + memcpy_h2n(buffer, mbr); + ModbusSend(buffer, length, funcCode); } /// @@ -120,17 +112,14 @@ void ModbusReadRegisters(word address, word count) // 16 bit const byte funcCode = 0x03; byte buffer[length]; struct ModbusReqRead mbr; - - ModbusMakeHeader(mbr.Header, length); - // Payload - mbr.Header.FuncCode = funcCode; // [1] Function Code; 3: Read Holding Registers (AI), 4: Read Input Registers (AIO), seems to be the same for WAGO 750-881 + mbr.Address = address; // [2] Start address mbr.Count = count; // [2] Number of items; 1:max 125=0x7D writeDbg(MbDebug, "Sending 'Read Registers' (0x03) command. Addr: 0x%04X, Count: %d", address, count); memcpy_h2n(buffer, mbr); - ModbusSend(buffer, length, mbr.Header.TxID); + ModbusSend(buffer, length, funcCode); } /// @@ -170,16 +159,13 @@ void ModbusWriteBit(word address, byte value) if (value >= 1) value = 0xFF; - ModbusMakeHeader(mbw.Header, length); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 5: Write Single Coil (DO) mbw.Address = address; // [2] Output address mbw.Value = value << 8; // [2] Output value (0x0000: Off, 0xFF00: On) writeDbg(Debug, "Sending 'Write Bit' (0x05) command. Addr: 0x%04X, Value: 0x%02X", address, value); memcpy_h2n(buffer, mbw); - ModbusSend(buffer, length, mbw.Header.TxID); + ModbusSend(buffer, length, funcCode); } /// @@ -214,16 +200,13 @@ void ModbusWriteRegister(word address, int value) byte buffer[length]; struct ModbusReqWriteSingle mbw; - ModbusMakeHeader(mbw.Header, length); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 5: Write Single Register (AO) mbw.Address = address; // [2] Output address mbw.Value = value; // [2] Output value writeDbg(MbDebug, "Sending 'Write Register' (0x06) command. Addr: 0x%04X, Value: 0x%02X", address, value); memcpy_h2n(buffer, mbw); - ModbusSend(buffer, length, mbw.Header.TxID); + ModbusSend(buffer, length, funcCode); } /// @@ -265,9 +248,7 @@ void ModbusWriteBits(word address, word count, byte values[]) dataLength = _ceil(count / 8.0); overallLength = maxLength - 1968/8 + dataLength; - ModbusMakeHeader(mbw.Header, overallLength); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 15: Write Multiple Bits (DOs) + mbw.Address = address; // [2] Output address mbw.Count = count; // [2] Number of items; 1:max 1968=0x7B0 mbw.ByteCount = dataLength; // [1] Number of bytes; = ceil(count/8) @@ -276,7 +257,7 @@ void ModbusWriteBits(word address, word count, byte values[]) writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. Addr: 0x%04X, Count: %d", address, count); memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, mbw.Header.TxID); + ModbusSend(buffer, overallLength, funcCode); } /// @@ -357,9 +338,6 @@ void ModbusWriteRegisters(word address, word count, word values[]) dataLength = 2 * count; overallLength = maxLength - 2*123 + dataLength; - ModbusMakeHeader(mbw.Header, overallLength); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 16: Write Multiple Registers (AOs) mbw.Address = address; // [2] Output address mbw.Count = count; // [2] Number of items; 1:max 123=0x7B mbw.ByteCount = dataLength; // [1] Number of bytes; = 2 * count @@ -368,7 +346,7 @@ void ModbusWriteRegisters(word address, word count, word values[]) mbw.Data[i] = values[i]; memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, mbw.Header.TxID); + ModbusSend(buffer, overallLength, funcCode); } /// @@ -404,15 +382,12 @@ void ModbusWriteMasks(word address, word and, word or) byte buffer[length]; struct ModbusReqWriteMasks mbw; - ModbusMakeHeader(mbw.Header, length); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 22: Mask Write Registers (AO) mbw.Address = address; // [2] Output address mbw.And = and; // [2] AND mask mbw.Or = or; // [2] OR mask memcpy_h2n(buffer, mbw); - ModbusSend(buffer, length, mbw.Header.TxID); + ModbusSend(buffer, length, funcCode); } /// @@ -453,9 +428,6 @@ void ModbusReadWriteRegisters(word readAddress, word readCount, word writeAddres dataLength = 2 * writeCount; overallLength = maxLength - 2*121 + dataLength; - ModbusMakeHeader(mbw.Header, overallLength); - // Payload - mbw.Header.FuncCode = funcCode; // [1] Function Code; 16: Write Multiple Registers (AOs) mbw.ReadAddress = readAddress; // [2] Input address mbw.ReadCount = readCount; // [2] Number of items; 1:max 125=0x7D mbw.WriteAddress = writeAddress;// [2] Output address @@ -466,7 +438,7 @@ void ModbusReadWriteRegisters(word readAddress, word readCount, word writeAddres mbw.Data[i] = values[i]; memcpy_h2n(buffer, mbw); - ModbusSend(buffer, overallLength, mbw.Header.TxID); + ModbusSend(buffer, overallLength, funcCode); } /// @@ -677,10 +649,14 @@ void OnModbusReceive2Exceptions(byte exCode, struct ModbusApHeader mbap) // ------------------------------------------------------------------------------------ // REGION: ModbusSend ----------------------------------------------------------------- /// <-ModbusSend> -void ModbusSend(byte buffer[], word length, word TxID) +void ModbusSend(byte buffer[], word length, byte funcCode) { struct QueueElement qe; + word TxID; + TxID = gTxID++; + + qe.FuncCode = funcCode; qe.Length = length; memcpy(qe.Buffer, buffer, length); @@ -715,6 +691,8 @@ on timer gtRobin { writeDbg(ConnInfo, "Packet 0x%04X timed out! Retrying...", TxID); gQueueSent[TxID].TimeoutTicks = 0; + EthSetTokenInt(gPacket, "modbus", "TxId", TxID); + EthSetTokenInt(gPacket, "modbus", "FuncCode", gQueueSent[TxID].FuncCode); ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length); // resend it reqError = Timeout; ModbusRecv(); diff --git a/Modbus-DLL/include/CAPL/include/ModbusStructs.cin b/Modbus-DLL/include/CAPL/include/ModbusStructs.cin index 814eff7..1d8224a 100644 --- a/Modbus-DLL/include/CAPL/include/ModbusStructs.cin +++ b/Modbus-DLL/include/CAPL/include/ModbusStructs.cin @@ -13,21 +13,18 @@ variables // Read Data from the host. We only need the start address and the number of bits/registers we want to read _align(1) struct ModbusReqRead { - struct ModbusApHeader Header; word Address; word Count; }; // Write a single value to a bit/register _align(1) struct ModbusReqWriteSingle { - struct ModbusApHeader Header; word Address; word Value; }; // Write several values to a bit/register starting with Address _align(1) struct ModbusReqWriteBits { - struct ModbusApHeader Header; word Address; word Count; byte ByteCount; @@ -36,7 +33,6 @@ variables // Write several values to bits starting with Address _align(1) struct ModbusReqWriteRegisters { - struct ModbusApHeader Header; word Address; word Count; byte ByteCount; @@ -45,7 +41,6 @@ variables // Write AND and OR masks to a holding register _align(1) struct ModbusReqWriteMasks { - struct ModbusApHeader Header; word Address; word And; word Or; @@ -53,7 +48,6 @@ variables // Read and write multiple registers _align(1) struct ModbusReqReadWriteRegisters { - struct ModbusApHeader Header; word ReadAddress; word ReadCount; word WriteAddress; @@ -66,35 +60,30 @@ variables // Receive several bit values _align(1) struct ModbusResReceiveBits { - struct ModbusApHeader Header; byte ByteCount; byte Data[250]; // Max length: 2000 bits }; // Receive several register values _align(1) struct ModbusResReceiveRegisters { - struct ModbusApHeader Header; byte ByteCount; word Data[125]; // Max length: 125 registers }; // Confirm the write of a single bit/register _align(1) struct ModbusResConfirmSingle { - struct ModbusApHeader Header; word Address; - int Value; + word Value; }; // Confirm the write of several bits/registers _align(1) struct ModbusResConfirmMultiple { - struct ModbusApHeader Header; word Address; word Count; }; // Confirm the write of AND and OR mask _align(1) struct ModbusResConfirmMasks { - struct ModbusApHeader Header; word Address; word And; word Or; diff --git a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.cpp b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.cpp index 49bb0ab..559d90d 100644 --- a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.cpp +++ b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.cpp @@ -350,7 +350,7 @@ VDEF ModbusProtocol::GetToken( const NIPB::VProtocolToken /*in*/ *protocolToken, else if (tokenId == mFuncCode) return MakeHeaderToken( protocolToken, mFuncCode, 56, 8, token ); else if (tokenId == NIPB::kData) - return this->MakePayloadToken( protocolToken, NIPB::kData, this->kHeaderBitLength, protocolToken->bitLength, token ); + return this->MakePayloadToken( protocolToken, NIPB::kData, 0, protocolToken->bitLength, token ); else if (tokenId == NIPB::kHeader) return this->MakeHeaderToken( protocolToken, NIPB::kHeader, 0, this->kHeaderBitLength, token ); else @@ -385,7 +385,7 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc return NIPB::kError; NIPB::IFormatter *formatter = 0; - ULONG val; + ULONG valA, valB; // TODO: Make InspectProtocol nice and smooth switch(type) @@ -396,21 +396,21 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc { formatter->FormatString( "MB: [" ); - val = GetTxId( packetData, packetLength, *protocolToken ); - formatter->FormatUnsigned(val, 2, 10); + valA = GetTxId( packetData, packetLength, *protocolToken ); + formatter->FormatUnsigned(valA, 2, 10); formatter->FormatString( "] " ); - val = GetFuncCode( packetData, packetLength, *protocolToken ); - if (val > 0x80) + valA = GetFuncCode( packetData, packetLength, *protocolToken ); + valB = GetFirstDataByte( packetData, packetLength, *protocolToken ); // Exception Code OR number of bytes + if (valA > 0x80) { formatter->FormatString( "(0x" ); - formatter->FormatUnsigned( val & 0x0F, 1, 16 ); + formatter->FormatUnsigned( valA & 0x0F, 1, 16 ); - val = GetExCode( packetData, packetLength, *protocolToken ); - formatter->FormatString( ") Ex 0x" ); - formatter->FormatUnsigned( val, 1, 16); - switch (val) // exCode + formatter->FormatString( ") Ex" ); + formatter->FormatUnsigned( valB, 1, 10); + switch (valB) // exCode { case 0x01: formatter->FormatString( ": Illegal func code!" ); @@ -442,21 +442,56 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc } else { - switch (val) // funcCode + switch (valA) // funcCode { case 0x01: case 0x02: - formatter->FormatString( "Read bits" ); + if (protocolToken->bitLength == BY2BI(valB+1)) // if the first byte gives the count of following bytes --> response + { + formatter->FormatString( "Read bits response" ); + } + else + { + formatter->FormatString( "Read " ); + valB = GetAddrNCount( packetData, packetLength, *protocolToken ); + formatter->FormatUnsigned( valB & 0xFFFF, 2, 10 ); + formatter->FormatString( " bits from 0x" ); + formatter->FormatUnsigned( valB >> 16, 2, 16 ); + } break; case 0x03: case 0x04: - formatter->FormatString( "Read regs" ); + if (protocolToken->bitLength == BY2BI(valB+1)) // if the first byte gives the count of following bytes --> response + { + formatter->FormatString( "Read regs response" ); + } + else + { + formatter->FormatString( "Read " ); + valB = GetAddrNCount( packetData, packetLength, *protocolToken ); + formatter->FormatUnsigned( valB & 0xFFFF, 2, 10 ); + formatter->FormatString( " regs from 0x" ); + formatter->FormatUnsigned( valB >> 16, 2, 16 ); + } break; case 0x05: - formatter->FormatString( "Write bit" ); + formatter->FormatString( "Set bit 0x" ); + formatter->FormatUnsigned( valB >> 16, 2, 16 ); + + valB = GetAddrNCount( packetData, packetLength, *protocolToken ); + formatter->FormatString( " to " ); + if (valB & 0xFFFF > 0xFF00) + formatter->FormatString( "1" ); + else + formatter->FormatString( "0" ); break; case 0x06: - formatter->FormatString( "Write reg" ); + formatter->FormatString( "Set reg 0x" ); + formatter->FormatUnsigned( valB >> 16, 2, 16 ); + + valB = GetAddrNCount( packetData, packetLength, *protocolToken ); + formatter->FormatString( " to " ); + formatter->FormatUnsigned( valB & 0xFFFF, 2, 10 ); break; case 0x0F: formatter->FormatString( "Write bits" ); @@ -472,7 +507,7 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc break; default: formatter->FormatString( "[0x" ); - formatter->FormatUnsigned(val, 1, 16); + formatter->FormatUnsigned(valA, 1, 16); formatter->FormatString( "]" ); break; } @@ -486,8 +521,8 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc if (inspector->SelectField( NIPB::kFieldLabel, &formatter ) == NIPB::kOK) formatter->FormatString( "ModbusDetail" ); - val = GetContentId( packetData, packetLength, *protocolToken ); - FormatUnsigned( inspector, "TxIDDetail", mTxId, val, 2 ); + valB = GetContentId( packetData, packetLength, *protocolToken ); + FormatUnsigned( inspector, "TxIDDetail", mTxId, valB, 2 ); break; } @@ -504,7 +539,7 @@ VDEF ModbusProtocol::InspectProtocol ( const NIPB::VProtocolToken /*in*/ *protoc //! Returns the content ID /*! */ -ULONG ModbusProtocol::GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) +ULONG ModbusProtocol::GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) { ULONG ip = GetIp( packetData, packetLength, protocol ); BYTE funcCode = GetFuncCode( packetData, packetLength, protocol ); @@ -516,7 +551,7 @@ ULONG ModbusProtocol::GetContentId( const BYTE *packetData, ULONG packetLength, //! Returns the TxID /*! */ -WORD ModbusProtocol::GetTxId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) +WORD ModbusProtocol::GetTxId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) { ULONG offset = BI2BY(protocol.headerBitOffset); @@ -530,11 +565,11 @@ WORD ModbusProtocol::GetTxId( const BYTE *packetData, ULONG packetLength, const //! Returns the FuncCode /*! */ -BYTE ModbusProtocol::GetFuncCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) +BYTE ModbusProtocol::GetFuncCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) { ULONG offset = BI2BY(protocol.headerBitOffset) + 7; - if (offset+1 < packetLength) + if (offset < packetLength) { return packetData[offset]; } @@ -548,7 +583,7 @@ BYTE ModbusProtocol::GetFuncCode( const BYTE *packetData, ULONG packetLength, co //! Returns the DestinationIP /*! */ -ULONG ModbusProtocol::GetIp( const BYTE * /*packetData*/, ULONG /*packetLength*/, const NIPB::VProtocolToken &/*protocol*/ ) +ULONG ModbusProtocol::GetIp( const BYTE * /*packetData*/, ULONG /*packetLength*/, const NIPB::VProtocolToken &/*protocol*/ ) { // TODO: GetDestIp /*NIPB::VToken *ipv4DestIp; @@ -569,11 +604,15 @@ ULONG ModbusProtocol::GetIp( const BYTE * /*packetData*/, ULONG /*packetLength*/ return 0xC0A80102; } -BYTE ModbusProtocol::GetExCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) +/*--------------------------------------------------------------------*/ +//! Returns the first byte of the payload +/*! +*/ +BYTE ModbusProtocol::GetFirstDataByte( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) { ULONG offset = BI2BY(protocol.bitOffset); - if (offset+1 < packetLength) + if (offset < packetLength) { return packetData[offset]; } @@ -583,6 +622,29 @@ BYTE ModbusProtocol::GetExCode( const BYTE *packetData, ULONG packetLength, cons } } +/*--------------------------------------------------------------------*/ +//! Returns the first two words of the payload +/*! +*/ +ULONG ModbusProtocol::GetAddrNCount( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ) +{ + ULONG offset = BI2BY(protocol.bitOffset); + ULONG value; + + if (offset+3 < packetLength) + { + value = packetData[offset] << 8 | packetData[offset+1]; // LE/BE + value <<= 16; + offset += 2; + value |= packetData[offset] << 8 | packetData[offset+1]; // LE/BE + return value; + } + else + { + return 0; + } +} + /*--------------------------------------------------------------------*/ //! Fill a VToken structure. /*! diff --git a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.dll b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.dll index b8182f5..600da5c 100644 Binary files a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.dll and b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.dll differ diff --git a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.h b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.h index 8ff2ecd..a64d800 100644 --- a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.h +++ b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.h @@ -141,11 +141,12 @@ public: // Methods // public: - ULONG GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); - WORD GetTxId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); - ULONG GetIp( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); - BYTE GetFuncCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); - BYTE GetExCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + ULONG GetContentId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + WORD GetTxId( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + ULONG GetIp( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + BYTE GetFuncCode( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + BYTE GetFirstDataByte( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); + ULONG GetAddrNCount( const BYTE *packetData, ULONG packetLength, const NIPB::VProtocolToken &protocol ); static NIPB::VResult MakeHeaderToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token ); static NIPB::VResult MakePayloadToken( const NIPB::VProtocolToken /*in*/ *protocolToken, NIPB::VTokenId /*in*/ tokenId, ULONG /*in*/ offset, ULONG /*in*/ length, NIPB::VToken /*out*/ *token ); diff --git a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.ilk b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.ilk index 374a6e5..6e6a539 100644 Binary files a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.ilk and b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocol.ilk differ diff --git a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocolDLL.cpp b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocolDLL.cpp index c29b713..1406b38 100644 --- a/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocolDLL.cpp +++ b/Modbus-DLL/include/ModbusProtocolDLL/ModbusProtocolDLL.cpp @@ -35,7 +35,7 @@ STDAPI DllRegisterAddOn( NIPB::IAddOnRegistrar* registrar ) // UDP is used. // ModbusProtocolAddOn *mbpao = new ModbusProtocolAddOn(); - if (registrar->RegisterProtocol( "modbus", mbpao, "udp", ModbusProtocol::kServerPort, 0xFFFFFFFF ) != NIPB::kOK) + if (registrar->RegisterProtocol( "modbus", mbpao, "udp", ModbusProtocol::kServerPort, ModbusProtocol::kClientPort ) != NIPB::kOK) { log << "Could not register UDP 502 -> 50002\n"; log.close(); diff --git a/Modbus-DLL/log.txt b/Modbus-DLL/log.txt index 323b995..1942e0d 100644 --- a/Modbus-DLL/log.txt +++ b/Modbus-DLL/log.txt @@ -3,43 +3,22 @@ Initializing Defining fields MyProtocolId = 4896. InitProtocol. CompleteProtocol: Modbus->bitLength = 32, --> Length = 6. ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 12 - Data = 00 01 00 00 00 06 ff 01 00 00 00 00 + Data = 00 01 00 00 00 06 ff 01 00 00 00 02 --> byteOffset = 50, byteLength = 4 --> ContentId = 1020001. -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 9 - Data = 00 01 00 00 00 03 ff 81 03 - --> byteOffset = 50, byteLength = 1 - --> ContentId = 1020081. +ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 10 + Data = 00 01 00 00 00 04 ff 01 01 00 + --> byteOffset = 50, byteLength = 2 + --> ContentId = 1020001. ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 12 - Data = 00 01 00 00 00 06 ff 01 00 00 00 00 + Data = 00 01 00 00 00 06 ff 01 00 00 00 02 --> byteOffset = 50, byteLength = 4 --> ContentId = 1020001. -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 9 - Data = 00 01 00 00 00 03 ff 81 03 - --> byteOffset = 50, byteLength = 1 - --> ContentId = 1020081. - -CompleteProtocol: Modbus->bitLength = 32, --> Length = 6. -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 12 - Data = 00 02 00 00 00 06 ff 01 00 00 00 00 - --> byteOffset = 50, byteLength = 4 +ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 10 + Data = 00 01 00 00 00 04 ff 01 01 00 + --> byteOffset = 50, byteLength = 2 --> ContentId = 1020001. -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 9 - Data = 00 02 00 00 00 03 ff 81 03 - --> byteOffset = 50, byteLength = 1 - --> ContentId = 1020081. - -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 12 - Data = 00 02 00 00 00 06 ff 01 00 00 00 00 - --> byteOffset = 50, byteLength = 4 - --> ContentId = 1020001. - -ParsePacket topProtocolToken->tokenId = 352 byteOffset = 42, byteLength = 9 - Data = 00 02 00 00 00 03 ff 81 03 - --> byteOffset = 50, byteLength = 1 - --> ContentId = 1020081. -