mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-09 13:45:33 +00:00
232 lines
8.2 KiB
Perl
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;
|