diff --git a/fhem/t/FHEM/98_Modbus/10_Timer.t b/fhem/t/FHEM/98_Modbus/10_Timer.t index 01ca5cb7a..1c6331619 100644 --- a/fhem/t/FHEM/98_Modbus/10_Timer.t +++ b/fhem/t/FHEM/98_Modbus/10_Timer.t @@ -13,7 +13,7 @@ is(FhemTestUtils_gotLog("set interval test not valid"), 1, "invalid interval in InternalTimer(time()+1, sub() { - isnt(FhemTestUtils_gotLog("GetUpdate called"), 0, "GetUpdate in log"); + isnt(FhemTestUtils_gotLog("GetUpdate .* called from"), 0, "GetUpdate in log"); isnt(FhemTestUtils_gotLog("UpdateTimer called from.*GetUpdate"), 0, "UpdateTimer in log"); done_testing; diff --git a/fhem/t/FHEM/98_Modbus/41_Passive.t b/fhem/t/FHEM/98_Modbus/41_Passive.t index 00fd5b853..1a6a06da3 100644 --- a/fhem/t/FHEM/98_Modbus/41_Passive.t +++ b/fhem/t/FHEM/98_Modbus/41_Passive.t @@ -60,7 +60,7 @@ sub testStep5 { sub testStep6 { LogStep "check reception of reply and send another repeated reply"; - is(FhemTestUtils_gotLog('ParseObj has no information about handling h356'), 1, "try parsing registers"); + is(FhemTestUtils_gotLog('has no information about handling h356'), 1, "try parsing registers"); FhemTestUtils_resetLogs(); FhemTestUtils_resetEvents(); SimRead('MS', 'fe03100000000b000000400000011a00000167f378'); # the reply repeated @@ -70,7 +70,7 @@ sub testStep6 { sub testStep7 { LogStep "check reception of repeated reply"; - is(FhemTestUtils_gotLog('ParseObj has no information about handling'), 0, "no try parsing registers again since request is missing"); + is(FhemTestUtils_gotLog('has no information about handling'), 0, "no try parsing registers again since request is missing"); is(FhemTestUtils_gotLog('HandleResponse got data but we don.t have a request'), 1, "next response without a request seen"); FhemTestUtils_resetLogs(); FhemTestUtils_resetEvents(); diff --git a/fhem/t/FHEM/98_Modbus/42_MasterRTU.t b/fhem/t/FHEM/98_Modbus/42_MasterRTU.t index cebc31d9d..54816a20c 100644 --- a/fhem/t/FHEM/98_Modbus/42_MasterRTU.t +++ b/fhem/t/FHEM/98_Modbus/42_MasterRTU.t @@ -140,7 +140,7 @@ sub testStep21 { sub testStep22 { LogStep('check reception of response with added 0'); - is(FhemTestUtils_gotLog('ParseObj called from HandleResponse with data hex 0137, type h'), 1, "correct data part extracted"); + is(FhemTestUtils_gotLog('called from HandleResponse with data hex 0137, type h'), 1, "correct data part extracted"); is(FhemTestUtils_gotEvent(qr/PWP:dummy500:\s311/xms), 1, "Parse h500"); fhem 'attr PWP verbose 3'; return; diff --git a/fhem/t/FHEM/98_Modbus/50_MasterSlave0.cfg b/fhem/t/FHEM/98_Modbus/50_MasterSlave0.cfg index e21c6d6e2..a6a0806ad 100644 --- a/fhem/t/FHEM/98_Modbus/50_MasterSlave0.cfg +++ b/fhem/t/FHEM/98_Modbus/50_MasterSlave0.cfg @@ -94,6 +94,9 @@ attr Master obj-h10-map 0:off, 1:on attr Master obj-h11-reading o2 attr Master obj-h11-min 1 attr Master obj-h11-max 3 + +attr Master obj-h999-reading NoReading + attr Master dev-h-defSet 1 attr Master dev-c-defSet 1 attr Master dev-h-defShowGet 1 diff --git a/fhem/t/FHEM/98_Modbus/50_MasterSlave0.t b/fhem/t/FHEM/98_Modbus/50_MasterSlave0.t index f16185fd5..0fa523490 100644 --- a/fhem/t/FHEM/98_Modbus/50_MasterSlave0.t +++ b/fhem/t/FHEM/98_Modbus/50_MasterSlave0.t @@ -34,7 +34,7 @@ sub testStep1 { # preparation of slave content, enable devices sub testStep2 { # get holding registers LogStep "get TempWasserEin"; fhem ('attr Master verbose 3'); - fhem ('attr Slave verbose 3'); + fhem ('attr Slave verbose 3'); fhem ('get Master TempWasserEin'); fhem ('get Master Test1'); fhem ('get Master Test2'); @@ -104,15 +104,14 @@ 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"); + CheckAndReset(); 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 Master verbose 5'); # 3 fhem ('attr Slave verbose 3'); fhem ('set Master reread'); return 0.15; @@ -159,20 +158,19 @@ sub testStep14 { fhem ('attr Master closeAfterResponse 1'); fhem ('attr Master verbose 4'); fhem ('set Master reread'); - return 0.1; + return 0.2; } 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"); + CheckAndReset(); 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; @@ -189,18 +187,17 @@ 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"); + CheckAndReset(); 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'); + 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; } @@ -215,7 +212,44 @@ sub testStep20 { sub testStep21 { LogStep "check result after prio get"; is(FhemTestUtils_gotLog('Master: read.* buffer: 050302000c4981'), 1, "answer arrives after readanswer timeout"); + CheckAndReset(); return; } + +sub testStep30 { + LogStep "try to read non existant register from slave"; + fhem ('attr Master closeAfterResponse 0'); + fhem 'attr Slave verbose 5'; + fhem 'attr Master nonPrioritizedGet 1'; + fhem 'get Master NoReading'; + return 0.2; +} + +sub testStep31 { + LogStep "check read NoReading result"; + is(FhemTestUtils_gotLog('HandleResponse done.*fCode 131'), 1, "got address error from Slave"); + CheckAndReset(); + return 0.1; +} + +sub testStep35 { + LogStep "try to read non existant register from slave with error code set to 0"; + fhem 'attr Slave dev-addressErrCode 0'; + fhem 'get Master NoReading'; + return 0.2; +} + +sub testStep36 { + LogStep "check read NoReading result"; + is(FhemTestUtils_gotLog('HandleResponse done.*fCode 131'), 0, "got no address error from Slave"); + return 0.1; +} + +sub testStep32 { + #LogStep ""; + #is(FhemTestUtils_gotEvent(qr/D1:TempWasserAus:\s20/xms), 1, "Write value to local slave"); + return 0.1; +} + 1; diff --git a/fhem/t/FHEM/98_Modbus/50_MasterSlave1.cfg b/fhem/t/FHEM/98_Modbus/50_MasterSlave1.cfg new file mode 100644 index 000000000..f2dad9735 --- /dev/null +++ b/fhem/t/FHEM/98_Modbus/50_MasterSlave1.cfg @@ -0,0 +1,21 @@ +attr global mseclog 1 + +define Slave ModbusAttr 5 slave global:5501 +attr Slave obj-h256-reading TempWasserEin +attr Slave obj-h258-reading TempWasserAus + +define Master ModbusAttr 5 0 localhost:5501 +attr Master disable 1 +attr Master verbose 3 +attr Master nonPrioritizedGet 1 +attr Master nonPrioritizedSet 1 + +attr Master dev-timing-sendDelay 0 +attr Master dev-timing-commDelay 0 +attr Master dev-h-defSet 1 +attr Master dev-h-defShowGet 1 +attr Master dev-h-combine 19 + +attr Master obj-h256-reading TempWasserEin +attr Master obj-h258-reading TempWasserAus + diff --git a/fhem/t/FHEM/98_Modbus/50_MasterSlave1.t b/fhem/t/FHEM/98_Modbus/50_MasterSlave1.t new file mode 100644 index 000000000..4b4c457fa --- /dev/null +++ b/fhem/t/FHEM/98_Modbus/50_MasterSlave1.t @@ -0,0 +1,58 @@ +############################################## +# test master slave with setexpr +############################################## + +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'; +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 ('attr Master obj-h258-setExpr $val * 3'); + fhem ('setreading Slave TempWasserEin 12'); + return 0.1; +} + +sub testStep10 { # set with setexpr + fhem ('attr Slave obj-h258-allowWrite 1'); + fhem ('attr Master obj-h258-setexpr $val * 2'); + fhem ('set Master TempWasserAus 20'); + return 0.1; +} + +sub testStep11 { # check that write holding register did work + LogStep "check result"; + is(FhemTestUtils_gotEvent(qr/Slave:TempWasserAus:\s40/xms), 1, "Write value to local slave"); + return 0.1; +} + +sub setExprSub { + my $val = shift; + return $val * 3; +} + +sub testStep20 { + fhem ('attr Slave obj-h258-allowWrite 1'); + fhem ('attr Master obj-h258-setexpr setExprSub ($val)'); + fhem ('attr Master verbose 5'); + fhem ('set Master TempWasserAus 20'); + return 0.1; +} + +sub testStep21 { # check that write holding register did work + LogStep "check result"; + is(FhemTestUtils_gotEvent(qr/Slave:TempWasserAus:\s60/xms), 1, "Write value to local slave"); + return 0.1; +} + +1; diff --git a/fhem/t/FHEM/98_Modbus/51_Combine.cfg b/fhem/t/FHEM/98_Modbus/51_Combine.cfg index 2019cae12..1c2fa65dc 100644 --- a/fhem/t/FHEM/98_Modbus/51_Combine.cfg +++ b/fhem/t/FHEM/98_Modbus/51_Combine.cfg @@ -1,6 +1,7 @@ attr global mseclog 1 define Slave ModbusAttr 5 slave global:5501 +attr Slave dev-addressErrCode 0 attr Slave obj-h256-reading TempWasserEin attr Slave obj-h258-reading TempWasserAus @@ -20,9 +21,14 @@ attr Slave obj-h120-unpack f> attr Slave obj-h120-len 2 attr Slave obj-h130-reading Test5 -attr Slave obj-h130-unpack a* +attr Slave obj-h130-unpack f< attr Slave obj-h130-len 2 +attr Slave obj-h132-reading Test6 +attr Slave obj-h132-poll 1 +attr Slave obj-h132-unpack n +attr Slave obj-h132-polldelay 0 + attr Slave obj-c400-reading c0 attr Slave obj-c401-reading c1 attr Slave obj-c402-reading c2 @@ -83,9 +89,13 @@ attr Master obj-h120-ignoreExpr $val > 10 attr Master obj-h120-polldelay 0 attr Master obj-h130-reading Test5 -attr Master obj-h130-unpack a* +attr Master obj-h130-unpack f< attr Master obj-h130-len 2 -attr Master obj-h130-encode utf8 + +attr Master obj-h132-reading Test6 +attr Master obj-h132-poll 1 +attr Master obj-h132-unpack n +attr Master obj-h132-polldelay 0 attr Master obj-h10-reading o1 attr Master obj-h10-map 0:off, 1:on @@ -123,4 +133,4 @@ attr Master obj-c406-poll 1 attr Master obj-c417-poll 1 attr Master dev-h-combine 19 -attr Master dev-c-combine 32 \ No newline at end of file +attr Master dev-c-combine 32 diff --git a/fhem/t/FHEM/98_Modbus/51_Combine.t b/fhem/t/FHEM/98_Modbus/51_Combine.t index 7d8055e26..f748b5aec 100644 --- a/fhem/t/FHEM/98_Modbus/51_Combine.t +++ b/fhem/t/FHEM/98_Modbus/51_Combine.t @@ -17,27 +17,28 @@ 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'); - fhem ('setreading Slave c0 1'); - fhem ('setreading Slave c5 1'); - fhem ('setreading Slave c17 1'); - readingsSingleUpdate($defs{'Slave'}, 'Test5', pack('H*', 'e4f6fc'), 0); - fhem ('attr Master verbose 4'); - fhem ('attr Slave verbose 3'); + 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'; + fhem 'setreading Slave Test5 10'; + fhem 'setreading Slave Test6 6'; + fhem 'setreading Slave c0 1'; + fhem 'setreading Slave c5 1'; + fhem 'setreading Slave c17 1'; + fhem 'attr Master verbose 5'; # 4 + fhem 'attr Slave verbose 3'; #3 + CheckAndReset(); return 0.1; } sub testStep10 { # check combined read of holding registers and coils LogStep "getUpdate with combine"; - FhemTestUtils_resetEvents(); - fhem ('set Master reread'); - return 0.2; + fhem 'set Master reread'; + return 0.7; } sub testStep11 { # check results coming from slave @@ -48,21 +49,27 @@ sub testStep11 { # check results coming from 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"); + ok(FhemTestUtils_gotLog('read fc 3 h100, len 7') >= 2,'saw right first combination in log'); + ok(FhemTestUtils_gotLog('read fc 3 h120, len 13') >= 2,'saw right second combination in log'); + + CheckAndReset(); return 0.1; } sub testStep20 { # check timeout handling / logging LogStep "getUpdate with timeout"; - FhemTestUtils_resetEvents(); fhem 'defmod Slave ModbusAttr 55 slave global:5501'; + fhem 'attr Master dev-timing-timeout 0.2'; fhem 'set Master reread'; - return 1; + return 1.5; } sub testStep21 { # check results coming from slave + ok(FhemTestUtils_gotLog('Timeout waiting for a modbus response') > 1,'timeout for missing salve'); return; } + 1; diff --git a/fhem/t/FHEM/98_Modbus/52_Combine2.cfg b/fhem/t/FHEM/98_Modbus/52_Combine2.cfg new file mode 100644 index 000000000..b2ffe56b1 --- /dev/null +++ b/fhem/t/FHEM/98_Modbus/52_Combine2.cfg @@ -0,0 +1,106 @@ +attr global mseclog 1 + +define Slave ModbusAttr 5 slave global:5501 +attr Slave dev-addressErrCode 0 +attr Slave obj-h256-reading TempWasserEin +attr Slave obj-h258-reading TempWasserAus + +attr Slave obj-h100-reading Test1 + +attr Slave obj-h101-reading Test2 +attr Slave obj-h101-unpack f> +attr Slave obj-h101-len 2 + +attr Slave obj-h103-reading Test2m + +attr Slave obj-h120-reading Test4a +attr Slave obj-h120-unpack f> +attr Slave obj-h120-len 2 + +attr Slave obj-h122-reading Test4b +attr Slave obj-h122-unpack f> +attr Slave obj-h122-len 2 + + +attr Slave obj-h130-reading Test5 +attr Slave obj-h130-unpack f< +attr Slave obj-h130-len 2 + +attr Slave obj-h132-reading Test5m +attr Slave obj-h132-unpack n + + +define Master ModbusAttr 5 0 localhost:5501 +attr Master disable 1 +attr Master verbose 3 +attr Master nonPrioritizedGet 1 +attr Master nonPrioritizedSet 1 + +attr Master dev-timing-sendDelay 0 +attr Master dev-timing-commDelay 0 +attr Master dev-timing-timeout 0.5 + +attr Master obj-h256-reading TempWasserEin +attr Master obj-h256-poll 1 +attr Master obj-h258-reading TempWasserAus +attr Master obj-h258-poll 1 + +attr Master obj-h100-reading Test1 +attr Master obj-h100-expr $val + 2 +attr Master obj-h100-poll 1 +attr Master obj-h100-polldelay 0 + +attr Master obj-h101-reading Test2 +attr Master obj-h101-unpack f> +attr Master obj-h101-len 2 +attr Master obj-h101-format %.2f +attr Master obj-h101-poll 1 +attr Master obj-h101-polldelay 0 +attr Master obj-h101-group 2-2 +attr Master obj-h101-expr ReadingsVal($name, 'Test2m', 0) * $val + +attr Master obj-h103-reading Test2m +attr Master obj-h103-poll 1 +attr Master obj-h103-polldelay 0 +attr Master obj-h103-group 2-1 + +attr Master obj-h120-reading Test4a +attr Master obj-h120-unpack f> +attr Master obj-h120-len 2 +attr Master obj-h120-format %.2f +attr Master obj-h120-poll 1 +attr Master obj-h120-polldelay 0 +attr Master obj-h120-group 3-1 + +attr Master obj-h122-reading Test4b +attr Master obj-h122-unpack f> +attr Master obj-h122-len 2 +attr Master obj-h122-format %.2f +attr Master obj-h122-poll 1 +attr Master obj-h122-polldelay 0 +attr Master obj-h122-group 3-2 +attr Master obj-h122-expr ReadingsVal($name, 'Test4a', 0) + $val + +attr Master obj-h130-reading Test5 +attr Master obj-h130-unpack f< +attr Master obj-h130-len 2 +attr Master obj-h130-group 1-1 +attr Master obj-h130-poll 1 +attr Master obj-h130-expr ReadingsVal($name, 'Test5m', 0) * $val + +attr Master obj-h132-reading Test5m +attr Master obj-h132-unpack n +attr Master obj-h132-polldelay 0 +attr Master obj-h132-group 1-2 + +attr Master obj-h10-reading o1 +attr Master obj-h10-map 0:off, 1:on + +attr Master obj-h11-reading o2 +attr Master obj-h11-min 1 +attr Master obj-h11-max 3 +attr Master dev-h-defSet 1 +attr Master dev-c-defSet 1 +attr Master dev-h-defShowGet 1 + +attr Master dev-h-combine 22 diff --git a/fhem/t/FHEM/98_Modbus/52_Combine2.t b/fhem/t/FHEM/98_Modbus/52_Combine2.t new file mode 100644 index 000000000..de9c4f026 --- /dev/null +++ b/fhem/t/FHEM/98_Modbus/52_Combine2.t @@ -0,0 +1,72 @@ +############################################## +# 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'; +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 Test1 1'; + fhem 'setreading Slave TempWasserEin 12'; + fhem 'setreading Slave TempWasserAus 14'; + + fhem 'setreading Slave Test2 2.123'; + fhem 'setreading Slave Test2m 2'; + + fhem 'setreading Slave Test4a 10'; + fhem 'setreading Slave Test4b 20'; + + fhem 'setreading Slave Test5 10'; + fhem 'setreading Slave Test5m 6'; + + # initialize readings at master to check the order later + fhem 'setreading Master Test1 1'; + + fhem 'setreading Master Test2 1'; + fhem 'setreading Master Test2m 1'; + + fhem 'setreading Master Test3 1'; + + fhem 'setreading Master Test4a 1'; + fhem 'setreading Master Test4b 1'; + + fhem 'setreading Master Test5 1'; + fhem 'setreading Master Test5m 1'; + + fhem 'attr Master verbose 4'; # 4 + fhem 'attr Slave verbose 3'; #3 + CheckAndReset(); + return 0.1; +} + + +sub testStep10 { # check combined read of holding registers and coils + LogStep "getUpdate with combine"; + fhem 'set Master reread'; + return 1; +} + +sub testStep11 { # check results coming from slave + is(FhemTestUtils_gotEvent(qr/Master:Test2: 4.25/), 1, "Combined retrieve float value from local slave"); + is(FhemTestUtils_gotEvent(qr/Master:Test4b: 30/), 1, "Combined retrieve float value from local slave"); + is(FhemTestUtils_gotEvent(qr/Master:Test5: 10/), 1, "Combined retrieve float value from local slave"); + is(FhemTestUtils_gotEvent(qr/Master:Test5m: 6/), 1, "Combined retrieve float value from local slave"); + + CheckAndReset(); + return 0.1; +} + + +1; diff --git a/fhem/t/FHEM/98_Modbus/56_Scan.t b/fhem/t/FHEM/98_Modbus/56_Scan.t index 826b1e0fd..ba7d24a02 100644 --- a/fhem/t/FHEM/98_Modbus/56_Scan.t +++ b/fhem/t/FHEM/98_Modbus/56_Scan.t @@ -62,11 +62,11 @@ sub testStep6 { } sub testStep7 { - #fhem ('attr Master verbose 5'); - #fhem ('attr Slave verbose 5'); + fhem ('attr Master verbose 4'); + fhem ('attr Slave verbose 5'); fhem ('attr Master dev-timing-timeout 0.3'); fhem ('set Master scanModbusId 1-8 h100'); - return 2; + return 6; }