2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-09 13:45:33 +00:00
fhem-mirror/fhem/t/FHEM/98_Modbus/50_MasterSlave0.t
StefanStrobel 84a1c425fb 98_Modbus.pm: added tests
git-svn-id: https://svn.fhem.de/fhem/trunk@23485 2b470e98-0d58-463d-a4d8-8e2adae1ed80
2021-01-07 13:06:26 +00:00

232 lines
8.2 KiB
Perl

##############################################
# test master slave end to end
##############################################
package main;
use strict;
use warnings;
use Test::More;
use Time::HiRes qw( gettimeofday tv_interval); # return time as float, not just full seconds
use FHEM::HTTPMOD::Utils qw(:all);
use FHEM::Modbus::TestUtils qw(:all);
fhem 'attr global mseclog 1';
InternalTimer(gettimeofday()+5, "testStepLast", 0); # last resort
NextStep();
sub testStep1 { # preparation of slave content, enable devices
is(FhemTestUtils_gotLog('attribute'), 0, "no unknown attributes"); # logs during init are not collected.
LogStep "enable Master and set value at Slave";
fhem ('attr Master disable 0');
fhem ('setreading Slave TempWasserEin 12');
fhem ('setreading Slave Test1 1');
fhem ('setreading Slave Test2 2.123');
fhem ('setreading Slave Test3 abcdefg');
fhem ('setreading Slave Test4 40');
readingsSingleUpdate($defs{'Slave'}, 'Test5', pack('H*', 'e4f6fc'), 0);
fhem ('setreading Slave c0 1');
fhem ('setreading Slave c5 1');
fhem ('setreading Slave c17 1');
return 0.1;
}
sub testStep2 { # get holding registers
LogStep "get TempWasserEin";
fhem ('attr Master verbose 3');
fhem ('attr Slave verbose 3');
fhem ('get Master TempWasserEin');
fhem ('get Master Test1');
fhem ('get Master Test2');
fhem ('get Master Test3');
fhem ('get Master Test4');
fhem ('get Master Test5');
return 0.3;
}
sub testStep3 { # check results
LogStep "check result";
fhem ('attr Master verbose 3');
fhem ('attr Slave verbose 3');
is(FhemTestUtils_gotEvent(qr/Master:TempWasserEin:\s12/xms), 1, "Retrieve integer value from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test1: 6/), 1, "Retrieve another integer value with expressions on both sides from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test2: 2.12/), 1, "Retrieve float value from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test3: abcdefg/), 1, "Retrieve ascii value from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test4: 40/), 0, "ignoreExpr prohibits Test4 set to 40");
is(FhemTestUtils_gotEvent(qr/Master:Test5: äöü/), 1, "encode worked for Test5");
return;
}
sub testStep4 { # set holding register without allowance at salve
LogStep "set TempWasserAus at Slave";
fhem ('set Master TempWasserAus 20');
fhem ('attr Master verbose 4');
return 0.2;
}
sub testStep5 { # check that write was forbidden
LogStep "Check error response";
is(FhemTestUtils_gotLog('Master: HandleResponse got response with error code 86 / 01, illegal function'), 1, "disallow write by default");
fhem ('attr Master verbose 3');
return;
}
sub testStep6 { # allow write at slave and try again to write
LogStep "allow write and try again";
fhem ('attr Slave obj-h258-allowWrite 1');
fhem ('set Master TempWasserAus 20');
return 0.1;
}
sub testStep7 { # check that write holding register did work
LogStep "check result";
is(FhemTestUtils_gotEvent(qr/D1:TempWasserAus:\s20/xms), 1, "Write value to local slave");
return 0.1;
}
sub testStep8 { # check input validation at master and write
LogStep "set with map and min/max";
fhem ('set Master o1 one');
is(FhemTestUtils_gotLog('set Master o1 one : set value one did not match defined map'), 1, "map error message in log");
fhem ('set Master o2 0');
is(FhemTestUtils_gotLog('set Master o2 0 : value 0 is not within defined min/max range'), 1, "min error message in log");
fhem ('set Master o2 4');
is(FhemTestUtils_gotLog('set Master o2 4 : value 4 is not within defined min/max range'), 1, "max error message in log");
fhem ('attr Master verbose 4');
fhem ('set Master o2 2');
fhem ('set Master o1 on');
return 0.2;
}
sub testStep9 { # check write data
LogStep "check log for map and set o2 2";
is(FhemTestUtils_gotLog('0506000a0001698c'), 1, "set o1 on message in log");
is(FhemTestUtils_gotLog('0506000b0002784d'), 1, "set O2 2 message in log");
fhem ('attr Master verbose 3');
return 0.1;
}
sub testStep10 { # check combined read of holding registers and coils
LogStep "getUpdate with combine";
FhemTestUtils_resetEvents();
fhem ('attr Master verbose 3');
fhem ('attr Slave verbose 3');
fhem ('set Master reread');
return 0.1;
}
sub testStep11 { # check results coming from slave and write coils to slave
is(FhemTestUtils_gotEvent(qr/Master:Test1: 6/), 1, "Combined retrieve integer value with expressions on both sides from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test2: 2.12/), 1, "Combined retrieve float value from local slave");
is(FhemTestUtils_gotEvent(qr/Master:Test3: abcdefg/), 1, "Combined Retrieve ascii value from local slave");
is(FhemTestUtils_gotEvent(qr/Master:c0: 1/), 1, "Combined Retrieve coil bit 0 from local slave");
is(FhemTestUtils_gotEvent(qr/Master:c1: 0/), 1, "Combined Retrieve coil bit 1 from local slave");
is(FhemTestUtils_gotEvent(qr/Master:c17: 1/), 1, "Combined Retrieve coil bit 17 from local slave");
fhem ('attr Slave obj-c402-allowWrite 1');
fhem ('attr Master verbose 5');
fhem ('set Master c2 1');
return 0.1;
}
sub testStep12 {
LogStep "check coil comm";
is(FhemTestUtils_gotLog('sending 05050192ff002daf'), 1, "set c2 1 sending message in log");
is(FhemTestUtils_gotEvent(qr/Master:c2: 1/), 1, "fc5 response for coil shows 1 from local slave");
Log3 undef, 1, "TestStep12: try to write with fc16";
fhem ('attr Master verbose 3');
fhem ('attr Slave verbose 3');
fhem ('attr Master dev-h-write 16');
fhem ('set Master TempWasserAus 29');
return 0.1;
}
sub testStep13 {
LogStep "check write result of fc16";
is(FhemTestUtils_gotEvent(qr/D1:TempWasserAus:\s29/xms), 1, "Write value with fc16 to local slave");
return 0.1;
}
sub testStep14 {
LogStep "closeAfterResponse";
FhemTestUtils_resetEvents();
FhemTestUtils_resetLogs();
fhem ('attr Master closeAfterResponse 1');
fhem ('attr Master verbose 4');
fhem ('set Master reread');
return 0.1;
}
sub testStep15 {
is(FhemTestUtils_gotEvent(qr/Master:Test1: 6/), 1, "Retrieve Test1");
is(FhemTestUtils_gotEvent(qr/Master:Test3: abcdefg/), 1, "Retrieve Test4");
is(FhemTestUtils_gotLog('HandleResponse will close because closeAfterResponse is set and queue is empty'), 1, "closed");
return 0.1;
}
sub testStep16 {
LogStep "try get while closed";
FhemTestUtils_resetEvents();
FhemTestUtils_resetLogs();
fhem ('get Master TempWasserEin');
fhem ('attr Master queueDelay 0.3');
return 0.1;
}
sub testStep17 {
LogStep "check get result while connection closed";
is(FhemTestUtils_gotLog('device opened'), 1, "device opened");
is(FhemTestUtils_gotEvent(qr/Master:TempWasserEin:\s12/xms), 0, "No retrieve from local slave yet");
return 0.3;
}
sub testStep18 {
LogStep "check get result after another delay";
is(FhemTestUtils_gotEvent(qr/Master:TempWasserEin:\s12/xms), 1, "retrieve from local slave after open and QueueDelay");
is(FhemTestUtils_gotLog('close because closeAfterResponse'), 1, "device closed again");
return 0.1;
}
sub testStep19 {
LogStep "now that the connection is closed again, try another prioritized get";
FhemTestUtils_resetEvents();
FhemTestUtils_resetLogs();
fhem ('attr Master nonPrioritizedGet 0');
fhem ('attr Master dev-timing-timeout 0.5');
fhem ('attr Master verbose 5');
fhem ('get Master TempWasserEin');
return 0.1;
}
sub testStep20 {
LogStep "check result after prio get";
is(FhemTestUtils_gotLog('device opened'), 1, "device opened");
is(FhemTestUtils_gotLog('Master: Timeout in Readanswer'), 1, "readanswer called but slave cannot answer while sitting in readanswer");
return;
}
sub testStep21 {
LogStep "check result after prio get";
is(FhemTestUtils_gotLog('Master: read buffer: 050302000c4981'), 1, "answer arrives after readanswer timeout");
return;
}
# todo: different protocols (RTU, ASCII, TCP)
# data type definition
# swap bytes and similar
# unpack variations
# then relay mode
1;