Add ExtendedCall to PLCObject as a replacement of RemoteExec and reflect it in eRPC interface.
ExtendedCall is a generic remote procedure call that runtime code can register to and that IDE extensions can call.
For example a fieldbus extension can use ExtendedCall to browse the fieldbus devices connected to the runtime.
--- a/C_runtime/PLCObject.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/PLCObject.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -675,3 +675,13 @@
"TraceThreadProc ended normally");
+uint32_t PLCObject::ExtendedCall(const char * method, const binary_t * argument, binary_t * answer) + answer->data = (uint8_t*)""; + answer->dataLength = 0; --- a/C_runtime/PLCObject.hpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/PLCObject.hpp Mon Oct 28 16:02:47 2024 +0100
@@ -71,6 +71,7 @@
uint32_t SetTraceVariablesList(const list_trace_order_1_t * orders, int32_t * debugtoken);
uint32_t StopPLC(bool * success);
+ uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer); // Public interface used by runtime
--- a/C_runtime/c_erpc_PLCObject_client.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/c_erpc_PLCObject_client.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -132,6 +132,14 @@
+uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer) + result = s_BeremizPLCObjectService_client->ExtendedCall(method, argument, answer); void initBeremizPLCObjectService_client(erpc_client_t client)
#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC
--- a/C_runtime/c_erpc_PLCObject_client.h Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/c_erpc_PLCObject_client.h Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -38,6 +38,7 @@
kBeremizPLCObjectService_SetTraceVariablesList_id = 12,
kBeremizPLCObjectService_StartPLC_id = 13,
kBeremizPLCObjectService_StopPLC_id = 14,
+ kBeremizPLCObjectService_ExtendedCall_id = 15, //! @name BeremizPLCObjectService
@@ -69,6 +70,8 @@
uint32_t StopPLC(bool * success);
+uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer); #endif // ERPC_FUNCTIONS_DEFINITIONS
--- a/C_runtime/c_erpc_PLCObject_server.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/c_erpc_PLCObject_server.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -132,6 +132,14 @@
+ uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer) + result = ::ExtendedCall(method, argument, answer); ERPC_MANUALLY_CONSTRUCTED_STATIC(BeremizPLCObjectService_service, s_BeremizPLCObjectService_service);
--- a/C_runtime/c_erpc_PLCObject_server.h Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/c_erpc_PLCObject_server.h Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -39,6 +39,7 @@
kBeremizPLCObjectService_SetTraceVariablesList_id = 12,
kBeremizPLCObjectService_StartPLC_id = 13,
kBeremizPLCObjectService_StopPLC_id = 14,
+ kBeremizPLCObjectService_ExtendedCall_id = 15, //! @name BeremizPLCObjectService
@@ -70,6 +71,8 @@
uint32_t StopPLC(bool * success);
+uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer); --- a/C_runtime/erpc_PLCObject_client.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_client.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -1213,3 +1213,74 @@
+// BeremizPLCObjectService interface ExtendedCall function client shim. +uint32_t BeremizPLCObjectService_client::ExtendedCall(const char * method, const binary_t * argument, binary_t * answer) + erpc_status_t err = kErpcStatus_Success; +#if ERPC_PRE_POST_ACTION + pre_post_action_cb preCB = m_clientManager->getPreCB(); + RequestContext request = m_clientManager->createRequest(false); + Codec * codec = request.getCodec(); + err = kErpcStatus_MemoryError; + codec->startWriteMessage(message_type_t::kInvocationMessage, m_serviceId, m_ExtendedCallId, request.getSequence()); + uint32_t method_len = strlen((const char*)method); + codec->writeString(method_len, (const char*)method); + write_binary_t_struct(codec, argument); + // Send message to server + // Codec status is checked inside this function. + m_clientManager->performRequest(request); + read_binary_t_struct(codec, answer); + err = codec->getStatus(); + // Dispose of the request. + m_clientManager->releaseRequest(request); + // Invoke error handler callback function + m_clientManager->callErrorHandler(err, m_ExtendedCallId); +#if ERPC_PRE_POST_ACTION + pre_post_action_cb postCB = m_clientManager->getPostCB(); + if (err != kErpcStatus_Success) --- a/C_runtime/erpc_PLCObject_client.hpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_client.hpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -50,6 +50,8 @@
virtual uint32_t StopPLC(bool * success);
+ virtual uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer); erpc::ClientManager *m_clientManager;
--- a/C_runtime/erpc_PLCObject_common.h Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_common.h Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
--- a/C_runtime/erpc_PLCObject_common.hpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_common.hpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
--- a/C_runtime/erpc_PLCObject_interface.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_interface.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
--- a/C_runtime/erpc_PLCObject_interface.hpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_interface.hpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -33,6 +33,7 @@
static const uint8_t m_SetTraceVariablesListId = 12;
static const uint8_t m_StartPLCId = 13;
static const uint8_t m_StopPLCId = 14;
+ static const uint8_t m_ExtendedCallId = 15; virtual ~BeremizPLCObjectService_interface(void);
@@ -63,6 +64,8 @@
virtual uint32_t StartPLC(void) = 0;
virtual uint32_t StopPLC(bool * success) = 0;
+ virtual uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer) = 0; --- a/C_runtime/erpc_PLCObject_server.cpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_server.cpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -501,6 +501,12 @@
+ case BeremizPLCObjectService_interface::m_ExtendedCallId: + erpcStatus = ExtendedCall_shim(codec, messageFactory, transport, sequence); erpcStatus = kErpcStatus_InvalidArgument;
@@ -1313,3 +1319,92 @@
+// Server shim for ExtendedCall of BeremizPLCObjectService interface. +erpc_status_t BeremizPLCObjectService_service::ExtendedCall_shim(Codec * codec, MessageBufferFactory *messageFactory, Transport * transport, uint32_t sequence) + erpc_status_t err = kErpcStatus_Success; + binary_t *argument = NULL; + argument = (binary_t *) erpc_malloc(sizeof(binary_t)); + codec->updateStatus(kErpcStatus_MemoryError); + binary_t *answer = NULL; + // startReadMessage() was already called before this shim was invoked. + codec->readString(method_len, &method_local); + method = (char*) erpc_malloc((method_len + 1) * sizeof(char)); + if ((method == NULL) || (method_local == NULL)) + codec->updateStatus(kErpcStatus_MemoryError); + memcpy(method, method_local, method_len); + (method)[method_len] = 0; + read_binary_t_struct(codec, argument); + answer = (binary_t *) erpc_malloc(sizeof(binary_t)); + codec->updateStatus(kErpcStatus_MemoryError); + err = codec->getStatus(); + if (err == kErpcStatus_Success) + // Invoke the actual served function. +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = true; + result = m_handler->ExtendedCall(method, argument, answer); +#if ERPC_NESTED_CALLS_DETECTION + nestingDetection = false; + // preparing MessageBuffer for serializing data + err = messageFactory->prepareServerBufferForSend(codec->getBufferRef(), transport->reserveHeaderSize()); + if (err == kErpcStatus_Success) + // preparing codec for serializing data + codec->reset(transport->reserveHeaderSize()); + // Build response message. + codec->startWriteMessage(message_type_t::kReplyMessage, BeremizPLCObjectService_interface::m_serviceId, BeremizPLCObjectService_interface::m_ExtendedCallId, sequence); + write_binary_t_struct(codec, answer); + err = codec->getStatus(); + free_binary_t_struct(argument); + free_binary_t_struct(answer); --- a/C_runtime/erpc_PLCObject_server.hpp Fri Oct 25 14:51:38 2024 +0200
+++ b/C_runtime/erpc_PLCObject_server.hpp Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
- * Generated by erpcgen 1.12.0 on Mon May 20 17:54:19 2024.
+ * Generated by erpcgen 1.12.0 on Mon Oct 28 15:10:14 2024. * AUTOGENERATED - DO NOT EDIT
@@ -80,6 +80,9 @@
/*! @brief Server shim for StopPLC of BeremizPLCObjectService interface. */
erpc_status_t StopPLC_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence);
+ /*! @brief Server shim for ExtendedCall of BeremizPLCObjectService interface. */ + erpc_status_t ExtendedCall_shim(erpc::Codec * codec, erpc::MessageBufferFactory *messageFactory, erpc::Transport * transport, uint32_t sequence); --- a/ProjectController.py Fri Oct 25 14:51:38 2024 +0200
+++ b/ProjectController.py Mon Oct 28 16:02:47 2024 +0100
@@ -1919,6 +1919,9 @@
self.logger.write_error(_("Connection failed to %s!\n") % uri)
+ VersionsInfoBytes = self._connector.ExtendedCall("GetVersions", bytes()) + VersionsInfo = VersionsInfoBytes.decode() + self.logger.write(f"Version string: {VersionsInfo}\n") self.CompareLocalAndRemotePLC()
# Init with actual PLC status and print it
--- a/connectors/ERPC/__init__.py Fri Oct 25 14:51:38 2024 +0200
+++ b/connectors/ERPC/__init__.py Mon Oct 28 16:02:47 2024 +0100
@@ -61,6 +61,7 @@
"SeedBlob":ReturnAsLastOutput,
"SetTraceVariablesList": ReturnAsLastOutput,
"StopPLC":ReturnAsLastOutput,
+ "ExtendedCall":ReturnAsLastOutput, --- a/erpc_interface/__init__.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/__init__.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
--- a/erpc_interface/erpc_PLCObject.erpc Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject.erpc Mon Oct 28 16:02:47 2024 +0100
@@ -61,11 +61,11 @@
MatchMD5(in string MD5, out bool match) -> uint32
NewPLC(in string md5sum, in binary plcObjectBlobID, in list<extra_file> extrafiles, out bool success) -> uint32
- /* NOT TO DO : RemoteExec(in ) -> uint32 */
ResetLogCount() -> uint32
SeedBlob(in binary seed, out binary blobID) -> uint32
SetTraceVariablesList(in list<trace_order> orders, out int32 debugtoken) -> uint32
StopPLC(out bool success) -> uint32
+ ExtendedCall(in string method, in binary argument, out binary answer ) -> uint32 --- a/erpc_interface/erpc_PLCObject/__init__.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject/__init__.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
--- a/erpc_interface/erpc_PLCObject/client.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject/client.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
@@ -292,4 +292,28 @@
_result = codec.read_uint32()
+ def ExtendedCall(self, method, argument, answer): + assert type(answer) is erpc.Reference, "out parameter must be a Reference object" + # Build remote function invocation message. + request = self._clientManager.create_request() + codec.start_write_message(erpc.codec.MessageInfo( + type=erpc.codec.MessageType.kInvocationMessage, + service=self.SERVICE_ID, + request=self.EXTENDEDCALL_ID, + sequence=request.sequence)) + raise ValueError("method is None") + codec.write_string(method) + raise ValueError("argument is None") + codec.write_binary(argument) + # Send request and process reply. + self._clientManager.perform_request(request) + answer.value = codec.read_binary() + _result = codec.read_uint32() --- a/erpc_interface/erpc_PLCObject/common.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject/common.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
--- a/erpc_interface/erpc_PLCObject/interface.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject/interface.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
@@ -21,6 +21,7 @@
SETTRACEVARIABLESLIST_ID = 12
def AppendChunkToBlob(self, data, blobID, newBlobID):
raise NotImplementedError()
@@ -64,4 +65,7 @@
def StopPLC(self, success):
raise NotImplementedError()
+ def ExtendedCall(self, method, argument, answer): + raise NotImplementedError() --- a/erpc_interface/erpc_PLCObject/server.py Fri Oct 25 14:51:38 2024 +0200
+++ b/erpc_interface/erpc_PLCObject/server.py Mon Oct 28 16:02:47 2024 +0100
@@ -1,5 +1,5 @@
-# Generated by erpcgen 1.12.0 on Mon May 20 17:53:37 2024.
+# Generated by erpcgen 1.12.0 on Mon Oct 28 11:30:03 2024. # AUTOGENERATED - DO NOT EDIT
@@ -27,6 +27,7 @@
interface.IBeremizPLCObjectService.SETTRACEVARIABLESLIST_ID: self._handle_SetTraceVariablesList,
interface.IBeremizPLCObjectService.STARTPLC_ID: self._handle_StartPLC,
interface.IBeremizPLCObjectService.STOPPLC_ID: self._handle_StopPLC,
+ interface.IBeremizPLCObjectService.EXTENDEDCALL_ID: self._handle_ExtendedCall, def _handle_AppendChunkToBlob(self, sequence, codec):
@@ -348,4 +349,29 @@
codec.write_bool(success.value)
codec.write_uint32(_result)
+ def _handle_ExtendedCall(self, sequence, codec): + # Create reference objects to pass into handler for out/inout parameters. + answer = erpc.Reference() + # Read incoming parameters. + method = codec.read_string() + argument = codec.read_binary() + # Invoke user implementation of remote function. + _result = self._handler.ExtendedCall(method, argument, answer) + # Prepare codec for reply message. + # Construct reply message. + codec.start_write_message(erpc.codec.MessageInfo( + type=erpc.codec.MessageType.kReplyMessage, + service=interface.IBeremizPLCObjectService.SERVICE_ID, + request=interface.IBeremizPLCObjectService.EXTENDEDCALL_ID, + if answer.value is None: + raise ValueError("answer.value is None") + codec.write_binary(answer.value) + codec.write_uint32(_result) --- a/runtime/PLCObject.py Fri Oct 25 14:51:38 2024 +0200
+++ b/runtime/PLCObject.py Mon Oct 28 16:02:47 2024 +0100
@@ -103,6 +103,9 @@
+ # initialize extended calls with GetVersions call, ignoring arguments + self.extended_calls = {"GetVersions":lambda *_args:self.GetVersions().encode()} # First task of worker -> no @RunInMain
def AutoLoad(self, autostart):
@@ -818,16 +821,17 @@
- def RemoteExec(self, script, *kwargs):
- _e_type, e_value, e_traceback = sys.exc_info()
- line_no = traceback.tb_lineno(get_last_traceback(e_traceback))
- return (-1, "RemoteExec script failed!\n\nLine %d: %s\n\t%s" %
- (line_no, e_value, script.splitlines()[line_no - 1]))
- return (0, kwargs.get("returnVal", None))
return platform_module.system() + " " + platform_module.release()
+ def ExtendedCall(self, method, argument): + """ Dispatch argument to registered service """ + return self.extended_calls[method](argument) + def RegisterExtendedCall(method, callback): + self.extended_calls[method] = callback + def UnregisterExtendedCall(method): + del self.extended_calls[method] --- a/runtime/eRPCServer.py Fri Oct 25 14:51:38 2024 +0200
+++ b/runtime/eRPCServer.py Mon Oct 28 16:02:47 2024 +0100
@@ -47,6 +47,7 @@
"SeedBlob":ReturnAsLastOutput,
"SetTraceVariablesList": ReturnAsLastOutput,
"StopPLC":ReturnAsLastOutput,
+ "ExtendedCall":ReturnAsLastOutput,