Modbus: add CI test + test project
--- a/tests/Makefile Wed Apr 03 13:02:50 2024 +0200
+++ b/tests/Makefile Thu Apr 04 17:31:49 2024 +0200
@@ -71,7 +71,7 @@
-BUILT_PROJECTS=beremiz matiec open62541
+BUILT_PROJECTS=beremiz matiec open62541 Modbus tar_opts=--absolute-names --exclude=.hg --exclude=.git --exclude=.*.pyc --exclude=.*.swp
@@ -105,7 +105,12 @@
cmake -D UA_ENABLE_ENCRYPTION=OPENSSL .. && \
-built_apps: $(build_dir)/matiec/iec2c $(build_dir)/beremiz/$(beremiz_checksum).sha1 $(build_dir)/open62541/build/bin/libopen62541.a
+$(build_dir)/Modbus/libmb.a: | $(build_dir)/Modbus/$(Modbus_checksum).sha1 + cd $(build_dir)/Modbus && \ +built_apps: $(build_dir)/matiec/iec2c $(build_dir)/beremiz/$(beremiz_checksum).sha1 $(build_dir)/open62541/build/bin/libopen62541.a $(build_dir)/Modbus/libmb.a --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cli_tests/modbus_test_tcp.bash Thu Apr 04 17:31:49 2024 +0200
@@ -0,0 +1,15 @@
+# Run python example throug command line, and check usual output +coproc setsid $BEREMIZPYTHONPATH $BEREMIZPATH/Beremiz_cli.py -k --project-home $BEREMIZPATH/tests/projects/modbus_test_tcp build transfer run; +while read -u ${COPROC[0]} line; do + if [[ "$line" == "TEST OK" ]]; then + pkill -9 -s $COPROC_PID --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/modbus_test_tcp/beremiz.xml Thu Apr 04 17:31:49 2024 +0200
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='utf-8'?> +<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="LOCAL://"> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/modbus_test_tcp/modbus_0@modbus/baseconfnode.xml Thu Apr 04 17:31:49 2024 +0200
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='utf-8'?> +<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="0" Name="modbus_0"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/modbus_test_tcp/modbus_0@modbus/confnode.xml Thu Apr 04 17:31:49 2024 +0200
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='utf-8'?> +<ModbusRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/modbus_test_tcp/plc.xml Thu Apr 04 17:31:49 2024 +0200
@@ -0,0 +1,390 @@
+<?xml version='1.0' encoding='utf-8'?> +<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201"> + <fileHeader companyName="Beremiz" productName="Beremiz" productVersion="1" creationDateTime="2018-07-27T13:19:12"/> + <contentHeader name="Modbus" modificationDateTime="2024-04-04T17:20:49"> + <pou name="program0" pouType="program"> + <variable name="Counter"> + <variable name="CounterReadBack"> + <variable name="MasterWriteToReg0" address="%QW0.0.0.0"> + <variable name="MasterReadFromReg1" address="%IW0.0.1.0"> + <variable name="SlaveHoldReg0" address="%IW0.1.0.0"> + <variable name="SlaveInputReg0" address="%QW0.1.1.0"> + <variable name="Generator0"> + <derived name="Generator"/> + <variable name="TestAllEqual0"> + <derived name="TestAllEqual"/> + <comment localId="4" height="109" width="350"> + <position x="102" y="438"/> + <xhtml:p><![CDATA[Modbus TCP Master writes counter value to one holding register on Modbus TCP Slave and reads it back from other input register.]]></xhtml:p> + <comment localId="3" height="407" width="680"> + <position x="21" y="15"/> + <xhtml:p><![CDATA[This examples shows how to work with Modbus extension. It uses Modbus TCP, but the same functions are available for Modbus RTU as well. Buth protocols are supported. +Modbus extensions requires native Modbus RTU/TCP library to be installed nearby Beremiz. +Following directory structure is expected: +If Modbus library is installed elsewhere, then place corresponding paths +in CFLAGS/LDFLAGS in project settings. +For GNU/Linux to install Modbus library in parent directory run following commands: +$ hg clone https://bitbucket.org/mjsousa/modbus Modbus +After that Modbus extension is ready to be used in Beremiz projects.]]></xhtml:p> + <block localId="5" typeName="CTU" instanceName="CTU0" executionOrderId="0" height="80" width="52"> + <position x="346" y="605"/> + <variable formalParameter="CU" edge="rising"> + <relPosition x="0" y="30"/> + <connection refLocalId="6" formalParameter="OUT"> + <position x="346" y="635"/> + <position x="303" y="635"/> + <variable formalParameter="R"> + <relPosition x="0" y="50"/> + <variable formalParameter="PV"> + <relPosition x="0" y="70"/> + <connection refLocalId="7"> + <position x="346" y="675"/> + <position x="324" y="675"/> + <position x="324" y="703"/> + <position x="302" y="703"/> + <variable formalParameter="Q"> + <relPosition x="52" y="30"/> + <variable formalParameter="CV"> + <relPosition x="52" y="50"/> + <block localId="6" typeName="Generator" instanceName="Generator0" executionOrderId="0" height="60" width="82"> + <position x="224" y="605"/> + <variable formalParameter="PON"> + <relPosition x="0" y="30"/> + <connection refLocalId="1"> + <position x="224" y="635"/> + <position x="154" y="635"/> + <variable formalParameter="POFF"> + <relPosition x="0" y="50"/> + <connection refLocalId="1"> + <position x="224" y="655"/> + <position x="189" y="655"/> + <position x="189" y="635"/> + <position x="154" y="635"/> + <variable formalParameter="OUT"> + <relPosition x="82" y="30"/> + <inVariable localId="1" executionOrderId="0" height="30" width="138" negated="false"> + <position x="16" y="620"/> + <relPosition x="138" y="15"/> + <expression>T#1s</expression> + <inVariable localId="7" executionOrderId="0" height="30" width="138" negated="false"> + <position x="164" y="688"/> + <relPosition x="138" y="15"/> + <expression>32767</expression> + <inOutVariable localId="2" executionOrderId="0" height="30" width="138" negatedOut="false" negatedIn="false"> + <position x="544" y="640"/> + <relPosition x="0" y="15"/> + <connection refLocalId="5" formalParameter="CV"> + <position x="544" y="655"/> + <position x="398" y="655"/> + <relPosition x="138" y="15"/> + <expression>Counter</expression> + <outVariable localId="8" executionOrderId="0" height="30" width="146" negated="false"> + <position x="762" y="640"/> + <relPosition x="0" y="15"/> + <connection refLocalId="2"> + <position x="762" y="655"/> + <position x="682" y="655"/> + <expression>MasterWriteToReg0</expression> + <inVariable localId="9" executionOrderId="0" height="30" width="154" negated="false"> + <position x="81" y="747"/> + <relPosition x="154" y="15"/> + <expression>MasterReadFromReg1</expression> + <comment localId="11" height="109" width="350"> + <position x="85" y="825"/> + <xhtml:p><![CDATA[Modbus TCP Slave just copies received register value from holding register to input register.]]></xhtml:p> + <inVariable localId="12" executionOrderId="0" height="30" width="152" negated="false"> + <position x="82" y="970"/> + <relPosition x="152" y="15"/> + <expression>SlaveHoldReg0</expression> + <outVariable localId="13" executionOrderId="0" height="30" width="123" negated="false"> + <position x="548" y="970"/> + <relPosition x="0" y="15"/> + <connection refLocalId="12"> + <position x="548" y="985"/> + <position x="234" y="985"/> + <expression>SlaveInputReg0</expression> + <block localId="14" typeName="TestAllEqual" instanceName="TestAllEqual0" executionOrderId="0" width="106" height="100"> + <position x="763" y="712"/> + <variable formalParameter="in0"> + <relPosition x="0" y="30"/> + <variable formalParameter="in1"> + <relPosition x="0" y="50"/> + <variable formalParameter="in2"> + <relPosition x="0" y="70"/> + <variable formalParameter="success"> + <relPosition x="0" y="90"/> + <inOutVariable localId="10" executionOrderId="0" width="137" height="30" negatedOut="false" negatedIn="false"> + <position x="547" y="747"/> + <relPosition x="0" y="15"/> + <connection refLocalId="9"> + <position x="547" y="762"/> + <position x="235" y="762"/> + <relPosition x="137" y="15"/> + <expression>CounterReadBack</expression> + <inVariable localId="15" executionOrderId="0" width="26" height="24" negated="false"> + <position x="705" y="770"/> + <relPosition x="26" y="12"/> + <expression>5</expression> + <pou name="Generator" pouType="functionBlock"> + <xhtml:p><![CDATA[T1( IN := NOT T2.Q, PT := POFF); +T2( IN := T1.Q, PT := PON); +OUT := T2.Q;]]></xhtml:p> + <pou name="TestAllEqual" pouType="functionBlock"> + <variable name="success"> + <xhtml:p><![CDATA[IF in0 = in1 AND in1 = in2 AND NOT(success) THEN + { printf("TEST OK\n"); fflush(stdout); } + <configuration name="config"> + <resource name="resource1"> + <task name="task0" priority="0" interval="T#20ms"> + <pouInstance name="instance0" typeName="program0"/>