Added configuration that runs some tests with the stack
This commit is contained in:
parent
2d26d89db0
commit
c851e7832a
4 changed files with 5682 additions and 0 deletions
4855
Modbus-CAPL/TestTheStack.cfg
Normal file
4855
Modbus-CAPL/TestTheStack.cfg
Normal file
File diff suppressed because it is too large
Load diff
745
Modbus-CAPL/include/CAPL/TestTheStack.can
Normal file
745
Modbus-CAPL/include/CAPL/TestTheStack.can
Normal file
|
@ -0,0 +1,745 @@
|
||||||
|
/*@!Encoding:1252*/
|
||||||
|
includes
|
||||||
|
{
|
||||||
|
#include "include/DeviceInformation.cin"
|
||||||
|
#include "include/ModbusUdp.cin"
|
||||||
|
#include "include/ModbusClient.cin"
|
||||||
|
}
|
||||||
|
|
||||||
|
variables
|
||||||
|
{
|
||||||
|
word state = 0;
|
||||||
|
byte s0i = 0;
|
||||||
|
struct device s0dev;
|
||||||
|
byte s20i = 1;
|
||||||
|
msTimer timr;
|
||||||
|
byte skipOutput = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
on preStart
|
||||||
|
{
|
||||||
|
setStartdelay(100);
|
||||||
|
OutputDebugLevel = Debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
on start
|
||||||
|
{
|
||||||
|
char ip[16];
|
||||||
|
sysGetVariableString("Device::Config", "IP", ip, 16);
|
||||||
|
|
||||||
|
DeviceInit(@sysvar::Device::Config::Vendor);
|
||||||
|
ModbusInit(ip, @sysvar::Config::Modbus::Port, @sysvar::Config::Modbus::RequestTimeout, 1/*retry*/);
|
||||||
|
|
||||||
|
if (gSocketState < CONNECTING) // We are not connecting and not connected
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Start the Test
|
||||||
|
s0dev.Vendor = (enum Vendor)@sysvar::Device::Config::Vendor;
|
||||||
|
s0i = _DeviceGetInformation((enum Vendor)@sysvar::Device::Config::Vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
on preStop
|
||||||
|
{
|
||||||
|
ModbusEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqRead mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusReadBitsFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d output bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d input bit from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
case 60:
|
||||||
|
case 120:
|
||||||
|
case 130:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d output bits from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
if (error == FinalTimeout)
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "State %d. Packet timed out! Receive window size: %d", state, s20i-1);
|
||||||
|
state = 210;
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
writeDbg(MbError, "State %d. Error while writing bit: %s", state, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq)
|
||||||
|
{
|
||||||
|
byte i;
|
||||||
|
word s6[1] = {0x5555};
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d output bit from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1);
|
||||||
|
state = 10;
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d input bit from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
ModbusReadInRegisters(thisDev.Addr.Read.InputRegisters, 1);
|
||||||
|
state = 30;
|
||||||
|
break;
|
||||||
|
case 60:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d output bits from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
for (i = 0; i < mbreq.Count; i++)
|
||||||
|
{
|
||||||
|
writeDbg(MbWarning, "i: %d, Status: %d, Expected: %d", i, bitStatus[i], (i != 2));
|
||||||
|
if (bitStatus[i] != (i != 2))
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "State of output bit %d was incorrect: %d (expected %d)", i, bitStatus[i], (i != 2));
|
||||||
|
runError(1001, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// OK.
|
||||||
|
writeDbg(MbDebug, "State %d. Status of these output bits was correct.", state);
|
||||||
|
ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 1, s6);
|
||||||
|
state = 70;
|
||||||
|
break;
|
||||||
|
case 120:
|
||||||
|
state = 130;
|
||||||
|
break;
|
||||||
|
case 130:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully received the Read-Bits telegrams (as expected)", state);
|
||||||
|
state = 140;
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
if (gQueueSent.Size() > 0 || gQueuePending.Size() > 0)
|
||||||
|
break;
|
||||||
|
++s20i;
|
||||||
|
for (i = 0; i < s20i && i < 100; i++)
|
||||||
|
ModbusReadBits(thisDev.Addr.Read.InputBits, 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusReadBitsSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqRead mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusReadRegistersFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 10:
|
||||||
|
case 110:
|
||||||
|
case 75:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d output register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d input register from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
case 140:
|
||||||
|
case 145:
|
||||||
|
case 150:
|
||||||
|
writeDbg(MbError, "State %d. Reading %d output registers from 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
s0i--;
|
||||||
|
_DeviceParseRegister(s0dev, mbreq.Address, mbres.Data, 0);
|
||||||
|
|
||||||
|
if (s0i == 0)
|
||||||
|
{
|
||||||
|
if (s0dev.DeviceIOs.OutputBits / 8 + s0dev.DeviceIOs.OutputRegisters < 2)
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "Please connect more output! %d bits and %d registers are not enough, we need at least 1 word (2 bytes). (Input: %d bits, %d regs)", s0dev.DeviceIOs.OutputBits, s0dev.DeviceIOs.OutputRegisters, s0dev.DeviceIOs.InputBits, s0dev.DeviceIOs.InputRegisters);
|
||||||
|
skipOutput = 1;
|
||||||
|
//runError(1001, 0);
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
ModbusReadInBits(thisDev.Addr.Read.InputBits, 1);
|
||||||
|
state = 20;
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
if (skipOutput)
|
||||||
|
state = 140;
|
||||||
|
else
|
||||||
|
state = 40;
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
case 75:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d input register from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
if (mbres.Data[0] != 0x5555)
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x5555). ModbusWriteRegisters failed!", state, mbres.Data[0]);
|
||||||
|
runError(1001, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ModbusWriteRegister(thisDev.Addr.Write.OutputRegisters, 0x9999);
|
||||||
|
state = 80;
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
if (mbres.Data[0] != 0x9999)
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "State %d. Value of output register 0 was incorrect: 0x%04X (expected 0x9999). ModbusWriteRegister failed!", state, mbres.Data[0]);
|
||||||
|
runError(1001, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ModbusWriteMasks(thisDev.Addr.Write.OutputRegisters, 0x00F9, 0x0006);
|
||||||
|
state = 100;
|
||||||
|
break;
|
||||||
|
case 110:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully read %d output register from 0x%04X", state, mbreq.Count, mbreq.Address);
|
||||||
|
if (mbres.Data[0] != 0x009F)
|
||||||
|
{
|
||||||
|
writeDbg(MbError, "State %d. Value of register at 0x%04X is incorrect: 0x%04X (expected 0x009F). ModbusWriteMasks failed!", state, mbreq.Address, mbres.Data[0]);
|
||||||
|
runError(1001, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully applied the masks at 0x%04X", state, mbreq.Address);
|
||||||
|
ModbusReadInBits(thisDev.Addr.Read.InputBits, 3000);
|
||||||
|
state = 120;
|
||||||
|
if (s0dev.Vendor == Wago) // This test does not work with Wago
|
||||||
|
state = 130;
|
||||||
|
break;
|
||||||
|
case 140:
|
||||||
|
state = 145;
|
||||||
|
break;
|
||||||
|
case 145:
|
||||||
|
state = 150;
|
||||||
|
break;
|
||||||
|
case 150:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully received three Read-Registers telegrams (as expected)", state);
|
||||||
|
if (skipOutput)
|
||||||
|
state = 200;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 160;
|
||||||
|
if (s0dev.Vendor == Wago) // This test does not work with Wago
|
||||||
|
state = 170;
|
||||||
|
}
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusReadRegistersSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqWriteSingle mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusWriteBitFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 50:
|
||||||
|
writeDbg(MbError, "State %d. Setting bit at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbres)
|
||||||
|
{
|
||||||
|
byte i;
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 50:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully set bit at 0x%04X", state, mbres.Address);
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqWriteSingle mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusWriteRegisterFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 80:
|
||||||
|
writeDbg(MbError, "State %d. Writing output register at 0x%04X did not work! Reason: %s", state, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbres)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 80:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully set output register at 0x%04X to 0x%04X", state, mbres.Address, mbres.Value);
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegisterSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqWriteMasks mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusWriteMasksFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 100:
|
||||||
|
writeDbg(MbError, "State %d. Applying masks &0x%04X |0x%04X at 0x%04X did not work! Reason: %s", state, mbreq.And, mbreq.Or, mbreq.Address);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbres)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 100:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully applied masks &0x%04X |0x%04X at 0x%04X", state, mbres.And, mbres.Or, mbres.Address);
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteMasksSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqReadWriteRegisters mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusReadWriteRegistersFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusReadWriteRegistersFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqWriteBits mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusWriteBitsFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 40:
|
||||||
|
case 160:
|
||||||
|
case 170:
|
||||||
|
writeDbg(MbError, "State %d. Writing %d bits at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbres)
|
||||||
|
{
|
||||||
|
word s17[200];
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 40:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully set %d bits at 0x%04X", state, mbres.Count, mbres.Address);
|
||||||
|
ModbusWriteBit(thisDev.Addr.Write.OutputBits+2, 0);
|
||||||
|
state = 50;
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
state = 170;
|
||||||
|
break;
|
||||||
|
case 170:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully received two Write-Bits telegrams (as expected)", state);
|
||||||
|
ModbusWriteRegisters(thisDev.Addr.Write.OutputRegisters, 200, s17);
|
||||||
|
state = 180;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteBitsSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap)
|
||||||
|
{
|
||||||
|
char reason[100];
|
||||||
|
struct ModbusReqWriteRegisters mbreq;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Timeout:
|
||||||
|
break;
|
||||||
|
case FinalTimeout:
|
||||||
|
strncpy(reason, "Timeout", elCount(reason));
|
||||||
|
break;
|
||||||
|
case Exception:
|
||||||
|
snprintf(reason, elCount(reason), "Exception: %s", ModbusExceptions[ex-1]);
|
||||||
|
break;
|
||||||
|
case NotSent:
|
||||||
|
strncpy(reason, "Impossible to send", elCount(reason));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "OnModbusWriteRegistersFailed: Unkown error: %d", error);
|
||||||
|
OnModbusClientPanics(SwitchArgumentInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_n2h(mbreq, gQueueAck[mbap.TxID].Buffer);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 70:
|
||||||
|
case 180:
|
||||||
|
case 190:
|
||||||
|
writeDbg(MbError, "State %d. Writing %d registers at 0x%04X did not work! Reason: %s", state, mbreq.Count, mbreq.Address, reason);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersFailed()!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbres)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 70:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully set %d output registers at 0x%04X", state, mbres.Count, mbres.Address);
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
case 180:
|
||||||
|
state = 190;
|
||||||
|
break;
|
||||||
|
case 190:
|
||||||
|
writeDbg(MbDebug, "State %d. Successfully received two Write-Registers telegrams (as expected)", state);
|
||||||
|
state = 200;
|
||||||
|
timr.Set(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in OnModbusWriteRegistersSuccess()!", state);
|
||||||
|
runError(1001, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnModbusClientPanics(enum FatalErrors reason)
|
||||||
|
{
|
||||||
|
switch (reason)
|
||||||
|
{
|
||||||
|
case ParsingBuffer:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR while parsing received buffer", state);
|
||||||
|
break;
|
||||||
|
case ModbusPackageWasSplit:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: Modbus package was split", state);
|
||||||
|
break;
|
||||||
|
case DeviceCodeUnknown:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: Device code unknown", state);
|
||||||
|
break;
|
||||||
|
case VendorIdUnknown:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: Vendor Id unknown", state);
|
||||||
|
break;
|
||||||
|
case ConnectionError:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: Connection Error", state);
|
||||||
|
break;
|
||||||
|
case FuncCodeIncorrect:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: FuncCode Incorrect", state);
|
||||||
|
break;
|
||||||
|
case AddressFailure:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: Some Modbus Address Failure", state);
|
||||||
|
break;
|
||||||
|
case SwitchArgumentInvalid:
|
||||||
|
writeDbg(MbError, "State %d. FATAL ERROR: A argument of a switch statement is incorrect");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop();
|
||||||
|
runError(1001, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
on timer timr
|
||||||
|
{
|
||||||
|
byte s3[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||||
|
byte s15[3000];
|
||||||
|
|
||||||
|
switch(state)
|
||||||
|
{
|
||||||
|
case 40:
|
||||||
|
ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 10, s3);
|
||||||
|
break;
|
||||||
|
case 50:
|
||||||
|
ModbusReadOutBits(thisDev.Addr.Read.OutputBits, 10);
|
||||||
|
state = 60;
|
||||||
|
break;
|
||||||
|
case 70:
|
||||||
|
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1);
|
||||||
|
state = 75;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1);
|
||||||
|
state = 90;
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
ModbusReadOutRegisters(thisDev.Addr.Read.OutputRegisters, 1);
|
||||||
|
state = 110;
|
||||||
|
break;
|
||||||
|
case 140:
|
||||||
|
ModbusReadRegisters(thisDev.Addr.Read.InputRegisters, 300);
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
case 170:
|
||||||
|
ModbusWriteBitsB(thisDev.Addr.Write.OutputBits, 3000, s15);
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
ModbusReadBits(thisDev.Addr.Read.InputBits, 1);
|
||||||
|
thisDev.ReceiveWindow = 0xFF; // Set receive window to maximum to test the limit
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writeDbg(MbError, "I did not expect state %d in timer timr!", state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
49
Modbus-CAPL/include/DBC/TestTheStack.dbc
Normal file
49
Modbus-CAPL/include/DBC/TestTheStack.dbc
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
VERSION ""
|
||||||
|
|
||||||
|
|
||||||
|
NS_ :
|
||||||
|
NS_DESC_
|
||||||
|
CM_
|
||||||
|
BA_DEF_
|
||||||
|
BA_
|
||||||
|
VAL_
|
||||||
|
CAT_DEF_
|
||||||
|
CAT_
|
||||||
|
FILTER
|
||||||
|
BA_DEF_DEF_
|
||||||
|
EV_DATA_
|
||||||
|
ENVVAR_DATA_
|
||||||
|
SGTYPE_
|
||||||
|
SGTYPE_VAL_
|
||||||
|
BA_DEF_SGTYPE_
|
||||||
|
BA_SGTYPE_
|
||||||
|
SIG_TYPE_REF_
|
||||||
|
VAL_TABLE_
|
||||||
|
SIG_GROUP_
|
||||||
|
SIG_VALTYPE_
|
||||||
|
SIGTYPE_VALTYPE_
|
||||||
|
BO_TX_BU_
|
||||||
|
BA_DEF_REL_
|
||||||
|
BA_REL_
|
||||||
|
BA_DEF_DEF_REL_
|
||||||
|
BU_SG_REL_
|
||||||
|
BU_EV_REL_
|
||||||
|
BU_BO_REL_
|
||||||
|
SG_MUL_VAL_
|
||||||
|
|
||||||
|
BS_:
|
||||||
|
|
||||||
|
BU_: TestTheStack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BA_DEF_ BU_ "NodeLayerModules" STRING ;
|
||||||
|
BA_DEF_ "DBName" STRING ;
|
||||||
|
BA_DEF_ "BusType" STRING ;
|
||||||
|
BA_DEF_DEF_ "NodeLayerModules" "ETHERNET_IL.dll";
|
||||||
|
BA_DEF_DEF_ "DBName" "";
|
||||||
|
BA_DEF_DEF_ "BusType" "Ethernet";
|
||||||
|
BA_ "BusType" "Ethernet";
|
||||||
|
BA_ "DBName" "TestTheStack";
|
||||||
|
|
33
Modbus-CAPL/include/SysVars/testthestack.vsysvar
Normal file
33
Modbus-CAPL/include/SysVars/testthestack.vsysvar
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<systemvariables version="4">
|
||||||
|
<namespace name="" comment="">
|
||||||
|
<namespace name="Device" comment="Server with ip address '192.168.1.100'">
|
||||||
|
<namespace name="Config" comment="Configuration section for this server">
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="IP" comment="The IP address of this server" bitcount="8" isSigned="true" encoding="65001" type="string" startValue="192.168.1.3" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="ms" name="Interval" comment="The interval with which the device will be queried" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="100" minValue="10" minValuePhys="10" maxValue="10000" maxValuePhys="10000" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Vendor" comment="The vendor of the device" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="2" minValue="2" minValuePhys="2" maxValue="23" maxValuePhys="23">
|
||||||
|
<valuetable definesMinMax="true">
|
||||||
|
<valuetableentry value="2" description="BuR" />
|
||||||
|
<valuetableentry value="23" description="Wago" />
|
||||||
|
</valuetable>
|
||||||
|
</variable>
|
||||||
|
</namespace>
|
||||||
|
<namespace name="Info" comment="Some information about the device">
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="InputRegisters" comment="Number of input registers" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="256" maxValuePhys="256" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Modules" comment="The type and number of inputs of modules that are connected to the server" bitcount="8" isSigned="true" encoding="65001" type="string" startValue="DI2,DO16,DO16" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="SerialCode" comment="The serial code of the server" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="750" minValue="1" minValuePhys="1" maxValue="10000" maxValuePhys="10000" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="DeviceCode" comment="The device code of the server" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="881" minValue="1" minValuePhys="1" maxValue="10000" maxValuePhys="10000" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="InputBits" comment="Number of input bits" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="2" minValue="0" minValuePhys="0" maxValue="256" maxValuePhys="256" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="OutputBits" comment="Number of output bits" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="32" minValue="0" minValuePhys="0" maxValue="256" maxValuePhys="256" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="OutputRegisters" comment="Number of output registers" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="0" minValue="0" minValuePhys="0" maxValue="256" maxValuePhys="256" />
|
||||||
|
</namespace>
|
||||||
|
</namespace>
|
||||||
|
<namespace name="Config" comment="">
|
||||||
|
<namespace name="Modbus" comment="">
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="ms" name="RequestTimeout" comment="The maximum duration for a Modbus-UDP/-TCP request in milliseconds. After timeout a retransmission may be started (see MaxRetransmissionCount). Use `ping` to get the maximum latency to a device, double it and add 2-3 ms for processing." bitcount="32" isSigned="true" encoding="65001" type="int" startValue="30" minValue="1" minValuePhys="1" maxValue="1000" maxValuePhys="1000" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="" name="Port" comment="" bitcount="32" isSigned="true" encoding="65001" type="int" startValue="502" minValue="1" minValuePhys="1" maxValue="65535" maxValuePhys="65535" />
|
||||||
|
<variable anlyzLocal="2" readOnly="false" valueSequence="false" unit="times" name="MaxTransmissionCount" comment="How often a retransmission of a request will be sent until it gets discarded and an error is thrown." bitcount="32" isSigned="true" encoding="65001" type="int" startValue="1" minValue="1" minValuePhys="1" maxValue="10" maxValuePhys="10" />
|
||||||
|
</namespace>
|
||||||
|
</namespace>
|
||||||
|
</namespace>
|
||||||
|
</systemvariables>
|
Loading…
Reference in a new issue