ModbusClient.cin

Counting the send attempts to reject packets that cannot be send (e.g. wrong network)

MakeConfig.can
  Introduced options (skip255 and useThirdIpNameForNodeName)
This commit is contained in:
Jonny007-MKD 2014-07-11 11:32:02 +00:00
parent caf58bd7d6
commit 84ab39d5b3
6 changed files with 127 additions and 66 deletions

View File

@ -1,4 +1,4 @@
;CANoe Version |4|7|1|52132 MakeConfig
;CANoe Version |4|7|1|52133 MakeConfig
Version: 8.2.40 Build 40
32 PRO
5
@ -1261,9 +1261,37 @@ Grafik-Fenster
237
0
0
1
0
0
0
-11
0
0
0
0
0
0
0
400
0
Tahoma
0
1
0
0
0
-11
0
0
0
34
0
0
0
400
0
Tahoma
0
1
1
@ -2933,7 +2961,7 @@ End_Of_Object VGrMnBox 3
VDOLocalInfoStruct 3 Begin_Of_Object
3
1
98
101
VDAOBus 4 Begin_Of_Object
1
1
@ -3063,7 +3091,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object
End_Of_Object VSimulinkModelViewerConfiguration 7
1
0
4212996857
1115474418
0
NodeSignalPanelBustypeCount 0
End_Of_Object VSimulationNode 6
@ -3101,7 +3129,7 @@ NULL
End_Of_Object VDOLocalInfoStruct 3
0.000000
0 0
1 1 0 59420 1 233 1 2882400001 98 331 371 619 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 373 373 2882400002 0 0 0 335238400 0 336542644 3
1 1 0 59420 1 233 1 2882400001 98 331 371 619 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 373 373 2882400002 0 0 0 355173376 0 423022796 3
SS_BEGIN_COMMON_INFO
1
0
@ -3113,7 +3141,7 @@ Ethernet
11
1
1
335879144 1 0 1 0 0 1 0 0 0 2000 1
422945832 1 0 1 0 0 1 0 0 0 2000 1
SS_BEGIN_COMMON_INFO
1
3
@ -3224,7 +3252,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
@ -3537,6 +3565,7 @@ End
FiltersEnd
0 0
END_OF_WORKSPACE_MEMBER_DATA
END_OF_WORKSPACE_MEMBER
1

View File

@ -25,6 +25,8 @@ variables
word ADi, ADn, ADl; // Some variables for "AnalyzeDevices"
byte ggMaxTransmissionCount;
byte useThirdIpByteForNames; // Whether the third byte of the IP address shall be used in the node name
byte skip255; // Whether the IP address .255 (broadcast in /24) shall be skipped
}
on preStart
@ -39,7 +41,12 @@ on preStart
// Scan a range of IPs for devices (if nothing was set above). Start and Stop go here
// Please note: Currently .255 will be skipped! Don't use this address for devices
strncpy(gScanFirstIp, "192.168.1.2", elCount(gScanFirstIp));
strncpy(gScanLastIp, "192.168.1.20", elCount(gScanLastIp));
strncpy(gScanLastIp, "192.168.2.20", elCount(gScanLastIp));
// Whether the third byte of the IP address shall be used in the node name
useThirdIpByteForNames = 0;
// Whether the IP address .255 (broadcast in /24) shall be skipped
skip255 = 1;
// Name of the project
strncpy(name, "Modbus", elCount(name));
@ -48,7 +55,7 @@ on preStart
strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar));
strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc));
OutputDebugLevel = Debug;//Error;
OutputDebugLevel = Error;
}
on start
@ -87,7 +94,7 @@ void PutString(byte d)
/// <Step1>
void DetectDevices()
{
write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
writeLineEx(0, 1, "Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout);
gScanFirst = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here
gScanLast = swapDWord(ipGetAddressAsNumber(gScanLastIp)); // But not here :)
@ -102,11 +109,15 @@ void DetectDevicesNext()
{
gScanFirst = swapDWord(gScanFirst);
gScanFirst++;
if ((gScanFirst & 0xFF) == 0xFF) // skip .255
if (skip255 && (gScanFirst & 0xFF) == 0xFF) // skip .255
{
gScanFirst++;
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF);
}
else if (!skip255 && (gScanFirst & 0xFF) == 0x00)
{
writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF);
}
if (gScanFirst > gScanLast)
{
@ -124,12 +135,7 @@ void DetectDevicesNext()
/// <Step1>
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
{
switch (error)
{
case FinalTimeout:
case Exception:
DetectDevicesNext(); // Timeout! We will go to the next device
}
DetectDevicesNext(); // Timeout, NotSent, Exception! We will go to the next device
}
/// <Step1>
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
@ -238,6 +244,9 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep
case FinalTimeout:
writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP);
break;
case NotSent:
writeLineEx(0, 3, "Error while analyzing %s! The device was not available! Ignoring...", gIpsSorted[ips[ADi]].IP);
break;
}
gQueueAck.Clear(); // Clear all queues
gQueuePending.Clear();
@ -317,8 +326,11 @@ void GenSysvars()
DeviceInit(gIpsSorted[ipN].Vendor);
PutString(" <namespace name=\"Client_");
//PutString(netS);
//PutString("_");
if (useThirdIpByteForNames)
{
PutString(gIpsSorted[ipN].IpNet);
PutString("_");
}
PutString(gIpsSorted[ipN].IpLsb);
PutString("\" comment=\"Server with ip address '");
PutString(gIpsSorted[ipN].Ip);
@ -466,8 +478,11 @@ void GenDbc()
for (long ipN : gIpsSorted)
{
PutString(" Client_");
//PutString(gIpsSorted[ipN].IpNet);
//PutString("_");
if (useThirdIpByteForNames)
{
PutString(gIpsSorted[ipN].IpNet);
PutString("_");
}
PutString(gIpsSorted[ipN].IpLsb);
}
PutString("\n\n\n\n");

View File

@ -38,7 +38,7 @@ variables
enum Vendor // The Vendor enum. All Vendors have to listed here and all listed vendors have to be implemented in this file
{
All = 0xFFFF,
All = 0xFF,
Wago = 23, // Wago
BuR = 2 // B&R
};

View File

@ -53,6 +53,7 @@ variables
{
word TimeoutTicks; // Time counter [ms]. Used to watch for timeouts (see gRequestTimeout)
byte Timeouts;
byte SendTries;
word Length;
byte Buffer[gModbusMaxTelegramSize];
};
@ -157,6 +158,7 @@ void _ModbusReadBits(enum ModbusFuncCode funcCode, word address, long count)
OnModbusClientPanics(AddressFailure);
return;
}
// FC1: Read Coils (DO), FC2: Read Discret Inputs (DI)
while (count > 0 && address < devEndAddr)
{
@ -279,7 +281,7 @@ void _ModbusReadRegisters(enum ModbusFuncCode funcCode, word address, long count
writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address);
curCount = devEndAddr - address;
}
write("address = 0x%04X, count = %d, curCount = %d, devStartAddr = 0x%04X, devEndAddr = 0x%04X", address, count, curCount, devStartAddr, devEndAddr);
//write("address = 0x%04X, count = %d, curCount = %d, devStartAddr = 0x%04X, devEndAddr = 0x%04X", address, count, curCount, devStartAddr, devEndAddr);
_ModbusMakeHeader(mbreq.Header, length, funcCode);
@ -440,6 +442,7 @@ void ModbusWriteBits(word address, long count, byte values[])
long offset;
// FC15: Write Multiple Bits (DOs)
offset = 0;
while (count > 0)
{
if (count > gMaxBitsPerWrite)
@ -463,7 +466,7 @@ void ModbusWriteBits(word address, long count, byte values[])
for (i = 0; i < dataLength; i++) // [264] Byte status, 8 per byte
mbreq.Data[i] = values[i+offset/8];
writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount);
writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address+offset, curCount);
memcpy_h2n(buffer, mbreq);
_ModbusSend(buffer, overallLength, mbreq.Header.TxID);
@ -955,7 +958,6 @@ void _ModbusStartQueue()
// The pending packets may be sent when there is free space in the sending window
on timer gtModbusRobin
{
struct ModbusApHeader mbap;
enum ModbusRequestError reqError;
writeDbg(ConnDebug, "gtModbusRobin: Queue Sent: %d, Queue Pending: %d, Queue Ack: %d", gQueueSent.Size(), gQueuePending.Size(), gQueueAck.Size());
@ -968,7 +970,7 @@ on timer gtModbusRobin
// timed out!
if (++gQueueSent[TxID].Timeouts < gMaxTransmissionCount) // if we may resend it
{
writeDbg(ConnInfo, "Packet 0x%04X timed out! Retrying...", TxID);
writeDbg(ConnInfo, "gtModbusRobin: Packet 0x%04X timed out! Retrying...", TxID);
gQueueSent[TxID].TimeoutTicks = 0;
_ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length); // resend it
reqError = Timeout;
@ -976,43 +978,14 @@ on timer gtModbusRobin
}
else // we will NOT resend it
{
writeDbg(ConnWarning, "Packet 0x%04X timed out! Giving up", TxID);
writeDbg(ConnWarning, "gtModbusRobin: Packet 0x%04X timed out! Giving up", TxID);
reqError = FinalTimeout;
}
memcpy_n2h(mbap, gQueueSent[TxID].Buffer);
switch(mbap.FuncCode) // throw an "error" in each case
{
case ReadBitsOut:
case ReadBitsIn:
OnModbusReadBitsFailed(reqError, None, mbap);
break;
case ReadRegistersOut:
case ReadRegistersIn:
OnModbusReadRegistersFailed(reqError, None, mbap);
break;
case WriteBit:
OnModbusWriteBitFailed(reqError, None, mbap);
break;
case WriteRegister:
OnModbusWriteRegisterFailed(reqError, None, mbap);
break;
case WriteBits:
OnModbusWriteBitsFailed(reqError, None, mbap);
break;
case WriteRegisters:
OnModbusWriteRegistersFailed(reqError, None, mbap);
break;
case MaskRegister:
OnModbusWriteMasksFailed(reqError, None, mbap);
break;
case ReadWriteRegisters:
OnModbusReadWriteRegistersFailed(reqError, None, mbap);
break;
}
if (reqError == FinalTimeout) // remove the packet from queue
gQueueSent.Remove(TxID); // wait until here to let the methods above access the request
_ModbusSendTimerError(gQueueSent[TxID].Buffer, reqError); // throw an "error" in each case
if (reqError == FinalTimeout) // remove the packet from queue
gQueueSent.Remove(TxID); // wait until here to let the methods above access the request
}
// Second: send new packets
@ -1025,16 +998,59 @@ on timer gtModbusRobin
// if packet was sent or the socket is not currently being opened
if (_ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0)
{
memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue
memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue
gQueuePending.Remove(TxID);
_ModbusRecv(); // wait for new packets
}
else if (gQueuePending[TxID].SendTries++ > 10) // We have tried to send this packet too often. Something is wrong!?
{
writeDbg(ConnError, "gtModbusRobin: The packet 0x%04X could not be sent, _ModbusSnd() rejected it several times", TxID);
_ModbusSendTimerError(gQueuePending[TxID].Buffer, NotSent);
gQueuePending.Remove(TxID);
_ModbusRecv(); // wait for new packets
}
}
// Stop timer to reduce load and latency of first new packet
if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0)
{
writeDbg(ConnDebug, "Stopping Timer gtModbusRobin");
writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer");
this.Cancel();
}
}
/// <-ModbusSend>
// This method will give an Error
void _ModbusSendTimerError(byte buffer[], enum ModbusRequestError reqError)
{
struct ModbusApHeader mbap;
memcpy_n2h(mbap, buffer);
switch(mbap.FuncCode)
{
case ReadBitsOut:
case ReadBitsIn:
OnModbusReadBitsFailed(reqError, None, mbap);
break;
case ReadRegistersOut:
case ReadRegistersIn:
OnModbusReadRegistersFailed(reqError, None, mbap);
break;
case WriteBit:
OnModbusWriteBitFailed(reqError, None, mbap);
break;
case WriteRegister:
OnModbusWriteRegisterFailed(reqError, None, mbap);
break;
case WriteBits:
OnModbusWriteBitsFailed(reqError, None, mbap);
break;
case WriteRegisters:
OnModbusWriteRegistersFailed(reqError, None, mbap);
break;
case MaskRegister:
OnModbusWriteMasksFailed(reqError, None, mbap);
break;
case ReadWriteRegisters:
OnModbusReadWriteRegistersFailed(reqError, None, mbap);
break;
}
}

View File

@ -28,7 +28,7 @@ variables
word Protocol;
word Length;
byte UnitID;
/*enum ModbusFuncCode*/ byte FuncCode;
byte FuncCode;
};
// 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
@ -95,7 +95,7 @@ variables
{
struct ModbusApHeader Header;
byte ByteCount;
word Data[gMaxRegsPerRead]; // Max length: 125 registers
word Data[gMaxRegsPerRead]; // Max length: 125 registers
};
// Confirm the write of a single bit/register
_align(1) struct ModbusResConfirmSingle
@ -127,7 +127,8 @@ variables
{
Exception,
Timeout,
FinalTimeout
FinalTimeout,
NotSent
};
enum ModbusException
{

View File

@ -33,7 +33,7 @@ NS_ :
BS_:
BU_: Client_ Client_100 Client_101
BU_: Client_2 Client_3