--- a/.github/workflows/run_tests_in_docker.yml Wed Jun 05 15:05:54 2024 +0200
+++ b/.github/workflows/run_tests_in_docker.yml Wed Jun 05 15:18:15 2024 +0200
@@ -24,7 +24,8 @@
- uses: actions/checkout@v3
repository: open62541/open62541
+ ref: b8ac9e77f703e6ba5c012b886a8821037503daa6 @@ -34,6 +35,13 @@
ref: 4d7d67a8e911d744165709c20a254b5cb924ec71
+ - uses: actions/checkout@v3 + repository: EmbeddedRPC/erpc + ref: 85d3dd8656ccce4c2d929a69484fb8d88ec6c6c3 - name: Restore cached docker image
uses: actions/cache/restore@v3
--- a/C_runtime/PLCObject.cpp Wed Jun 05 15:05:54 2024 +0200
+++ b/C_runtime/PLCObject.cpp Wed Jun 05 15:18:15 2024 +0200
@@ -79,6 +79,26 @@
+uint32_t PLCObject::AutoLoad() + uint32_t res = LoadPLC(); #define LOG_READ_BUFFER_SIZE 1 << 10 // 1KB
uint32_t PLCObject::GetLogMessage(
@@ -89,24 +109,24 @@
- uint32_t resultLen = m_PLCSyms.GetLogMessage(
- level, msgID, buf, LOG_READ_BUFFER_SIZE - 1,
- &tick, &tv_sec, &tv_nsec);
+ if(m_status.PLCstatus == Empty){ + resultLen = m_PLCSyms.GetLogMessage( + level, msgID, buf, LOG_READ_BUFFER_SIZE - 1, + &tick, &tv_sec, &tv_nsec); // Get log message with given msgID
- message->msg = (char *)malloc(resultLen);
+ message->msg = (char *)malloc(resultLen + 1); if (message->msg == NULL)
// Copy the log message into eRPC message
memcpy(message->msg, buf, resultLen);
- message->msg[resultLen + 1] = '\0';
+ message->msg[resultLen] = '\0'; @@ -141,6 +161,16 @@
uint32_t PLCObject::GetPLCstatus(PLCstatus *status)
+ if(m_status.PLCstatus == Empty){ + for(int lvl = 0; lvl < 4; lvl++){ + m_status.logcounts[lvl] = 0; + for(int lvl = 0; lvl < 4; lvl++){ + m_status.logcounts[lvl] = m_PLCSyms.GetLogCount(lvl); --- a/C_runtime/PLCObject.hpp Wed Jun 05 15:05:54 2024 +0200
+++ b/C_runtime/PLCObject.hpp Wed Jun 05 15:18:15 2024 +0200
@@ -71,6 +71,7 @@
uint32_t SetTraceVariablesList(const list_trace_order_1_t * orders, int32_t * debugtoken);
uint32_t StopPLC(bool * success);
// A map of all the blobs
--- a/C_runtime/posix_main.cpp Wed Jun 05 15:05:54 2024 +0200
+++ b/C_runtime/posix_main.cpp Wed Jun 05 15:18:15 2024 +0200
@@ -71,6 +71,7 @@
@@ -83,6 +84,7 @@
-b/--baudrate <baudrate> Baud rate.\n\
-p/--port <port> Port name or port number.\n\
-h/--host <host> Host definition.\n\
+ -a/--autoload Autoload.\n\ Available transports (use with -t option):\n\
tcp Tcp transport type (host, port number).\n\
@@ -127,6 +129,7 @@
uint32_t m_baudrate; /*!< Baudrate rate speed. */
const char *m_port; /*!< Name or number of port. Based on used transport. */
const char *m_host; /*!< Host name */
+ bool m_autoload = false; /*!< Autoload flag. */ @@ -239,6 +242,12 @@
Log::error("error: unrecognized option\n\n");
@@ -363,17 +372,21 @@
BasicCodecFactory _basicCodecFactory;
- BeremizPLCObjectService_service *svc;
Log::info("Starting ERPC server...\n");
_server.setMessageBufferFactory(&_msgFactory);
_server.setTransport(_transport);
_server.setCodecFactory(&_basicCodecFactory);
- svc = new BeremizPLCObjectService_service(new PLCObject());
+ PLCObject plc_object = PLCObject(); + BeremizPLCObjectService_service svc = BeremizPLCObjectService_service(&plc_object); + _server.addService(&svc); - _server.addService(svc);
--- a/runtime/PLCObject.py Wed Jun 05 15:05:54 2024 +0200
+++ b/runtime/PLCObject.py Wed Jun 05 15:18:15 2024 +0200
@@ -330,7 +330,7 @@
- def PythonRuntimeCall(self, methodname, reverse_order=False):
+ def PythonRuntimeCall(self, methodname, use_evaluator=True, reverse_order=False): Calls init, start, stop or cleanup method provided by
runtime python files, loaded when new PLC uploaded
@@ -339,7 +339,10 @@
methods = reversed(methods)
- _res, exp = default_evaluator(method)
+ _res, exp = self.evaluator(method) + _res, exp = default_evaluator(method) self.LogMessage(0, '\n'.join(traceback.format_exception(*exp)))
@@ -403,7 +406,7 @@
self.LogMessage(0, traceback.format_exc())
- self.PythonRuntimeCall("init")
+ self.PythonRuntimeCall("init", use_evaluator=False) self.PythonThreadCondLock = Lock()
self.PythonThreadCmdCond = Condition(self.PythonThreadCondLock)
@@ -418,7 +421,7 @@
if self.python_runtime_vars is not None:
self.PythonThreadCommand("Finish")
- self.PythonRuntimeCall("cleanup", reverse_order=True)
+ self.PythonRuntimeCall("cleanup", use_evaluator=False, reverse_order=True) self.python_runtime_vars = None
--- a/tests/Makefile Wed Jun 05 15:05:54 2024 +0200
+++ b/tests/Makefile Wed Jun 05 15:18:15 2024 +0200
@@ -71,7 +71,7 @@
-BUILT_PROJECTS=beremiz matiec open62541 Modbus
+BUILT_PROJECTS=beremiz matiec open62541 Modbus erpc tar_opts=--absolute-names --exclude=.hg --exclude=.git --exclude=.*.pyc --exclude=.*.swp
@@ -109,8 +109,11 @@
cd $(build_dir)/Modbus && \
+$(build_dir)/beremiz/C_runtime/beremiz_runtime: | $(build_dir)/erpc/$(erpc_checksum).sha1 + cd $(build_dir)/beremiz/C_runtime && \ -built_apps: $(build_dir)/matiec/iec2c $(build_dir)/beremiz/$(beremiz_checksum).sha1 $(build_dir)/open62541/build/bin/libopen62541.a $(build_dir)/Modbus/libmb.a
+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)/beremiz/C_runtime/beremiz_runtime --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cli_tests/C_runtime.bash Wed Jun 05 15:18:15 2024 +0200
@@ -0,0 +1,55 @@
+$BEREMIZPATH/C_runtime/beremiz_runtime -v -t tcp -p 61131 -h localhost > >( + echo "Start PLC stdout reader loop" + # Wait for server to print modified value + if [[ "$line" == "C runtime OK #3" ]]; then + echo "End PLC stdout reader loop" +# Start PLC with C runtime test +setsid $BEREMIZPYTHONPATH $BEREMIZPATH/Beremiz_cli.py -k \ + --project-home $BEREMIZPATH/tests/projects/c_runtime build transfer run > >( + # Wait for CLI to output expected PLC log message on stdout + if [[ $line =~ .*C\ runtime\ log\ OK\ #3$ ]]; then +echo all subprocess started, start polling results +res=110 # default to ETIMEDOUT + if [[ -a ./PLC_OK && -a ./CLI_OK ]]; then +# Kill PLC and subprocess +echo will kill CLI:$CLI_PID and PLC:$PLC_PID --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/c_runtime/beremiz.xml Wed Jun 05 15:18:15 2024 +0200
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8'?> +<BeremizRoot URI_location="ERPC://localhost:61131"> + <Libraries Enable_Native_Library="true" Enable_Python_Library="false"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/projects/c_runtime/plc.xml Wed Jun 05 15:18:15 2024 +0200
@@ -0,0 +1,399 @@
+<?xml version='1.0' encoding='utf-8'?> +<project xmlns="http://www.plcopen.org/xml/tc6_0201" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xsi:schemaLocation="http://www.plcopen.org/xml/tc6_0201"> + <fileHeader companyName="Unknown" productName="Generic PLC" productVersion="1" creationDateTime="2013-01-29T14:01:00" contentDescription="This example shows logging functionality in Beremiz. Here are shown two ways of logging: - from IEC PLC program; - from python extension. "/> + <contentHeader name="Logging example" modificationDateTime="2024-06-03T22:15:34"> + <pou name="C_Pragma" pouType="functionBlock"> + <variable name="rtrig"> + <derived name="R_TRIG"/> + <xhtml:p><![CDATA[rtrig(CLK := TRIG); + short inval = GetFbVar(IN); + printf("C runtime OK #%d\n", inval); + <pou name="program0" pouType="program"> + <variable name="count"> + <variable name="LOGGER0"> + <derived name="LOGGER"/> + <derived name="LOGLEVEL"/> + <simpleValue value="INFO"/> + <variable name="Timer"> + <variable name="C_Pragma0"> + <derived name="C_Pragma"/> + <inVariable localId="2" height="30" width="218" executionOrderId="0" negated="false"> + <position x="859" y="365"/> + <relPosition x="218" y="15"/> + <expression>'C runtime log OK #'</expression> + <block localId="3" width="59" height="40" typeName="NOT" executionOrderId="0"> + <position x="241" y="287"/> + <variable formalParameter="IN"> + <relPosition x="0" y="30"/> + <connection refLocalId="14" formalParameter="Q"> + <position x="241" y="317"/> + <position x="197" y="317"/> + <variable formalParameter="OUT"> + <relPosition x="59" y="30"/> + <inOutVariable localId="4" height="30" width="60" executionOrderId="0" negatedOut="false" negatedIn="false"> + <position x="57" y="302"/> + <relPosition x="0" y="15"/> + <connection refLocalId="3" formalParameter="OUT"> + <position x="57" y="317"/> + <position x="37" y="317"/> + <position x="37" y="390"/> + <position x="314" y="390"/> + <position x="314" y="317"/> + <position x="300" y="317"/> + <relPosition x="60" y="15"/> + <expression>beat</expression> + <block localId="5" width="68" height="98" typeName="ADD" executionOrderId="0"> + <position x="463" y="403"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="39"/> + <connection refLocalId="10" formalParameter="OUT"> + <position x="463" y="442"/> + <position x="455" y="442"/> + <position x="439" y="442"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="78"/> + <connection refLocalId="6"> + <position x="463" y="481"/> + <position x="438" y="481"/> + <variable formalParameter="OUT"> + <relPosition x="68" y="39"/> + <inOutVariable localId="6" height="30" width="103" executionOrderId="0" negatedOut="false" negatedIn="false"> + <position x="335" y="466"/> + <relPosition x="0" y="15"/> + <connection refLocalId="5" formalParameter="OUT"> + <position x="335" y="481"/> + <position x="320" y="481"/> + <position x="320" y="518"/> + <position x="544" y="518"/> + <position x="544" y="442"/> + <position x="531" y="442"/> + <relPosition x="103" y="15"/> + <expression>count</expression> + <block localId="8" width="67" height="144" typeName="CONCAT" executionOrderId="0"> + <position x="1127" y="329"/> + <variable formalParameter="IN1"> + <relPosition x="0" y="51"/> + <connection refLocalId="2"> + <position x="1127" y="380"/> + <position x="1077" y="380"/> + <variable formalParameter="IN2"> + <relPosition x="0" y="113"/> + <connection refLocalId="9" formalParameter="OUT"> + <position x="1127" y="442"/> + <position x="1080" y="442"/> + <variable formalParameter="OUT"> + <relPosition x="67" y="51"/> + <block localId="9" width="119" height="40" typeName="INT_TO_STRING" executionOrderId="0"> + <position x="961" y="412"/> + <variable formalParameter="IN"> + <relPosition x="0" y="30"/> + <connection refLocalId="5" formalParameter="OUT"> + <position x="961" y="442"/> + <position x="531" y="442"/> + <variable formalParameter="OUT"> + <relPosition x="119" y="30"/> + <block localId="10" width="106" height="40" typeName="BOOL_TO_INT" executionOrderId="0"> + <position x="333" y="412"/> + <variable formalParameter="IN" edge="rising"> + <relPosition x="0" y="30"/> + <connection refLocalId="3" formalParameter="OUT"> + <position x="333" y="442"/> + <position x="314" y="442"/> + <position x="314" y="317"/> + <position x="300" y="317"/> + <variable formalParameter="OUT"> + <relPosition x="106" y="30"/> + <block localId="11" width="65" height="209" typeName="LOGGER" instanceName="LOGGER0" executionOrderId="0"> + <position x="1307" y="266"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="51"/> + <connection refLocalId="3" formalParameter="OUT"> + <position x="1307" y="317"/> + <position x="300" y="317"/> + <variable formalParameter="MSG"> + <relPosition x="0" y="114"/> + <connection refLocalId="8" formalParameter="OUT"> + <position x="1307" y="380"/> + <position x="1194" y="380"/> + <variable formalParameter="LEVEL"> + <relPosition x="0" y="177"/> + <connection refLocalId="12"> + <position x="1307" y="443"/> + <position x="1280" y="443"/> + <inVariable localId="12" height="30" width="79" executionOrderId="0" negated="false"> + <position x="1201" y="428"/> + <relPosition x="79" y="15"/> + <expression>lvl</expression> + <block localId="14" typeName="TOF" instanceName="Timer" executionOrderId="0" height="98" width="47"> + <position x="150" y="278"/> + <variable formalParameter="IN"> + <relPosition x="0" y="39"/> + <connection refLocalId="4"> + <position x="150" y="317"/> + <position x="117" y="317"/> + <variable formalParameter="PT"> + <relPosition x="0" y="78"/> + <connection refLocalId="1"> + <position x="150" y="356"/> + <position x="117" y="356"/> + <variable formalParameter="Q"> + <relPosition x="47" y="39"/> + <variable formalParameter="ET"> + <relPosition x="47" y="78"/> + <inVariable localId="1" executionOrderId="0" height="30" width="61" negated="false"> + <position x="56" y="341"/> + <relPosition x="61" y="15"/> + <expression>T#1s</expression> + <block localId="15" typeName="C_Pragma" instanceName="C_Pragma0" executionOrderId="0" width="74" height="60"> + <position x="594" y="336"/> + <variable formalParameter="TRIG"> + <relPosition x="0" y="30"/> + <connection refLocalId="3" formalParameter="OUT"> + <position x="594" y="366"/> + <position x="447" y="366"/> + <position x="447" y="317"/> + <position x="300" y="317"/> + <variable formalParameter="IN"> + <relPosition x="0" y="50"/> + <connection refLocalId="5" formalParameter="OUT"> + <position x="594" y="386"/> + <position x="562" y="386"/> + <position x="562" y="442"/> + <position x="531" y="442"/> + <configuration name="config"> + <resource name="resource1"> + <task name="task0" priority="0" interval="T#100ms"> + <pouInstance name="prg" typeName="program0"/>