Before we introduce the RPC module, let's have a brief chat about RPC and the circumstances under which you need to know this article .
- RPC Description
Remote Procedure Call (RPC, Remote Procedure Call) is a network communication protocol that allows a program to call a program or service on another computer as if it were a local program.The main purpose of RPC is to simplify distributed computing by eliminating the need for developers to concern themselves with the details of underlying network communications. - When do I need to know about this article?
Users who have developed a corresponding application project based on TSMaster and want to automate the control of TSMaster in an external program can consult this article.(Note: In addition to RPC, TSMaster also provides COM-based interfaces, which can be found in a separate article.)
This article applies to the program control mode: TSMaster1 control TSMaster2, or other processes control TSMaster process (using TSMaster.dll) for the language: C + + + , Python, C# and other languages.
Table of Contents for this article
01 | Basic Concepts of RPC
Client and Server:
Client: The program that initiates the RPC request.
Server: The program that receives the RPC request and performs the corresponding procedure.
Representation.
Client Agent: Encapsulates the request and sends it to the server.
Server Proxy: receives the request, unpacks it and invokes the local procedure, after which it returns the result to the client proxy.
Communication mechanisms.
Transport Protocol: The protocol used by the underlying layer, e.g. TCP, UDP.
Data Serialization: Converting data structures or objects into a format that can be transmitted, such as JSON, XML, Protocol Buffers.
RPC Workflow.
- Client calls local proxy method: the client calls a method that appears to be local, but is actually handled by the client proxy;
- Client agent serialization request: packages information such as method names, parameters, etc. into a message;
- Message Transfer: The client agent transfers the message over the network to the server;
- Server proxy unpacking request: after receiving the message, the server proxy unpacks the message and calls the actual local method;
- Execute method and generate response: After the local method is executed, generate the response result;
- Server agent packages the response: the server agent packages the result into a message and sends it back to the client over the network;
- Client Agent Unpacking Response: After receiving the response message, the client agent unpacks it and returns the result to the client.
02. TSMaster RPC Application
1|RPC Function
Based on TSMaster's RPC mechanism, users can build a complete project in TSMaster's host environment, covering a series of processes from test case development to programmed device management, bus communication configuration and control board operation. Through this mechanism, users can efficiently control the TSMaster server remotely from the client.Read and write operations to system variables, CAN signals, LIN signals, FlexRay signals, Ethernet (ETH) signals, etc. can be realized. In addition, the user can call various functions defined on the TSMaster server, further expanding and customizing the system's functionality.
This integrated solution makes engineering management and automated testing more convenient and efficient. Users do not need to switch between multiple platforms to accomplish complex tasks including hardware configuration, signal monitoring, data acquisition and test execution. Through TSMaster's RPC mechanism, users can realize remote program control of the server on the client side, which simplifies the operation process, improves the efficiency of testing and development, and ensures the stability and reliability of the system.
TSMaster provides powerful interfaces and rich functional modules, which can be flexibly combined and used by users according to their needs to realize fine control and management of various signals and devices. This architecture is not only suitable for the R&D testing stage, but also for real-time monitoring and troubleshooting in the production environment, which greatly improves the overall quality and efficiency of engineering projects.
In addition, TSMaster's RPC mechanism supports a variety of topologies, enabling not only one-to-one communication between client and server, but also the following complex communication topologies:
- One-to-Many:A single client can control multiple TSMaster servers at the same time, for situations where multiple test environments or devices need to be managed at the same time.
- Many-to-One:Multiple clients can connect to one TSMaster server at the same time, so that different users or test systems can share the same server resources to realize collaborative work and resource sharing.
- Many-to-Many:Flexible communication and control between multiple clients and multiple servers is possible to build complex distributed test and control systems, suitable for large-scale engineering projects and distributed test environments.
This flexible topology enables TSMaster to adapt to a variety of complex engineering needs, providing an efficient and reliable solution both in a single project and in distributed testing across projects and geographic regions. Through this diversified communication mode, users can maximize the use of hardware and software resources, improve the scalability and flexibility of the system, and meet the needs of engineering projects of different scales and complexity.
03. TSMaster RPC User's Guide
1|Activate server
To open the server side, do the following:
Create a new C script and enter the following code in the startup event, which means that the rpc server of the current project is activated rpc_tsmaster_activate_server(true);
In fact, the RPC feature has been activated by default for all TSMaster projects after the TSMaster v2024.06.05.1124 release.
2|Live client
native_int h; //client handle
// Parameter 1 is the name of the TSMaster application providing the rpc service.
com.rpc_tsmaster_create_client("TSMaster",&h);
// Activate the client side
Com.rpc_tsmaster_activate_client(h,true);
3|Modify server-side data
3.1 Starting and stopping the server project
Launching the project:
TSMaster applet:
com.rpc_tsmaster_cmd_start_simulation(h);
API (C\C++\C#\Python).
rpc_tsmaster_cmd_start_simulation(h).
3.2 Reading and writing system variables
Set system variables:
TSMaster applet:
com.rpc_tsmaster_cmd_write_system_var(h, "Var1", "1.2345");
API (C\C++\C#\Python).
rpc_tsmaster_cmd_write_system_var(h, "Var1″, "1.2345″);
Get system variables:
TSMaster applet:
com.rpc_tsmaster_cmd_read_system_var(h, "Var1", "1.2345");
API (C\C++\C#\Python).
rpc_tsmaster_cmd_read_system_var(h, "Var1″, "1.2345″);
3.3 Reading and writing CAN signals
Set the CAN signal:
TSMaster applet:
com.rpc_tsmaster_cmd_set_can_signal(h, "chnidx/net/node/msg/signal", 1234)
API (C\C++\C#\Python).
rpc_tsmaster_cmd_set_can_signal(h, "chnidx/net/node/msg/signal", 1234)
Get CAN signal:
double d = 0;
TSMaster applet:
com.rpc_tsmaster_cmd_get_can_signal(h, "chnidx/net/node/msg/signal", %d)
API (C\C++\C#\Python).
rpc_tsmaster_cmd_get_can_signal(h, "chnidx/net/node/msg/signal", %d)
3.4 Reading and writing LIN signals
Set the LIN signal:
TSMaster applet:
com.rpc_tsmaster_cmd_set_lin_signal(h, "chnidx/net/node/msg/signal", 1234);
API (C\C++\C#\Python).
rpc_tsmaster_cmd_set_lin_signal(h, "chnidx/net/node/msg/signal", 1234);
Get LIN signal:
double d = 0;
TSMaster applet:
com.rpc_tsmaster_cmd_get_lin_signal(h, "chnidx/net/node/msg/signal", %d);
API (C\C++\C#\Python).
rpc_tsmaster_cmd_get_lin_signal(h, "chnidx/net/node/msg/signal", %d);
3.5 Reading and Writing FlexRay Signals
Set the FR signal:
TSMaster applet:
com.rpc_tsmaster_cmd_set_flexray_signal(h, "chnidx/net/node/msg/signal", 1234);
API (C\C++\C#\Python).
rpc_tsmaster_cmd_set_flexray_signal(h, "chnidx/net/node/msg/signal", 1234);
Acquire the FR signal:
double d = 0;
TSMaster applet:
com.rpc_tsmaster_cmd_get_can_signal(h, "chnidx/net/node/msg/signal", %d);
API (C\C++\C#\Python).
rpc_tsmaster_cmd_get_can_signal(h, "chnidx/net/node/msg/signal", %d)
3.6 RPC Using the TSMaster System Functions
// The first step is to prepare the input parameters for the function call.
#define STR_BUFFER_SIZE 1024
char args[4][STR_BUFFER_SIZE];
char* pArgs[4] = {&args[0][0], &args[1][0], &args[2][0], &args[3][0]};
sprintf_s(pArgs[0], STR_BUFFER_SIZE, "%s", "var1");
sprintf_s(pArgs[1], STR_BUFFER_SIZE, "%d", svtString);
sprintf_s(pArgs[2], STR_BUFFER_SIZE, "%s", "string default value");
sprintf_s(pArgs[3], STR_BUFFER_SIZE, "%s", "this is a comment");
// Step 2: Call any API
s32 ret.
ret = com.rpc_tsmaster_call_system_api(h, "app.create_system_var", 4, STR_BUFFER_SIZE,
&pArgs[0]).
// Step 3: Process return values in parameters (if available)
s32 i.
log("API call result = %d", ret);
for (i=0; i<4; i++){
log("Argument %d: %s", i+1, pArgs[i]);
}
The above code is equivalent to using app.create_system_var in the TSMaster process to create a system variable, i.e.: app.create_system_var(var1,svtString, "string default value ", "this is a comment");
Note that calling system functions within TSMaster in this way does not allow you to use functions whose arguments are of pointer type (except for message types).
3.7 RPC Using Applet Library Functions
// The first step is to prepare the input parameters for the function call.
#define STR_BUFFER_SIZE 1024
char args[4][STR_BUFFER_SIZE];
char* pArgs[4] = {&args[0][0], &args[1][0], &args[2][0], &args[3][0]};
sprintf_s(pArgs[0], STR_BUFFER_SIZE, "%s", "var1");
sprintf_s(pArgs[1], STR_BUFFER_SIZE, "%d", svtString);
sprintf_s(pArgs[2], STR_BUFFER_SIZE, "%s", "string default value");
sprintf_s(pArgs[3], STR_BUFFER_SIZE, "%s", "this is a comment");
/Step 2: Call any API
s32 ret;TSMaster RPC Programming Guide
ret = com.rpc_tsmaster_call_library_api(h, "mylib.create_system_var", 4, STR_BUFFER_SIZE,
&pArgs[0]).
// Step 3: Process return values in parameters (if available)
s32 i.
log("API call result = %d", ret);
for (i=0; i<4; i++){
log("Argument %d: %s", i+1, pArgs[i]);
}
04, TSMaster RPC function description
1|rpc_tsmaster_create_client
2|rpc_tsmaster_activate_client
function name | UInt32 rpc_tsmaster_activate_client(const size_t AHandle,const bool AActivate) |
Function | Activating or deactivating a TSMaster Rpc client |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle AActivate: true=activate, false=deactivate |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_activate_client(h, true) |
3|rpc_tsmaster_is_simulation_running
function name | UInt32 rpc_tsmaster_is_simulation_running(const size_t AHandle,const pbool AIsRunning) |
Function | Getting the Status of a Remote TSMaster Emulation Run |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle AIsRunning: data pointer to the state of the remote TSMaster emulation running True = running, false = not running |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | bool b. if (0 == com.rpc_tsmaster_is_simulation_running(h, &b)){ if (b){ // current simulation is running } } |
4|rpc_tsmaster_cmd_set_mode_realtime
function name | UInt32 rpc_tsmaster_cmd_set_mode_realtime(const size_t AHandle) |
Function | Configuring the TSMaster Rpc server to real-time mode |
call location | After creating the TSMaster Rpc client and before running the simulation |
input parameter | AHandle : TSMaster Rpc Client Handle |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_cmd_set_mode_realtime(h) |
5|rpc_tsmaster_cmd_set_mode_sim
function name | UInt32 rpc_tsmaster_cmd_set_mode_sim(const size_t AHandle) |
Function | Configure the TSMaster Rpc server to emulation mode |
call location | After creating the TSMaster Rpc client and before running the simulation |
input parameter | AHandle : TSMaster Rpc Client Handle |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_cmd_set_mode_sim(h) |
6|rpc_tsmaster_cmd_start_simulation
function name | UInt32 rpc_tsmaster_cmd_start_simulation(const size_t AHandle) |
Function | Start the TSMaster Rpc server emulation |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_cmd_start_simulation(h) |
7|rpc_tsmaster_cmd_set_can_signal
function name | UInt32 rpc_tsmaster_cmd_set_can_signal(const size_t AHandle,const char* ASgnAddress,const double AValue) |
Function | Modifying CAN signal values in the database on a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | if(0==rpc_tsmaster_cmd_set_can_signal(h, "0/CAN_FD_Powertrain/Engine/EngineData/EngSpeed", 1234)){ // signal written } |
8|rpc_tsmaster_cmd_get_can_signal
function name | UInt32 rpc_tsmaster_cmd_get_can_signal(const size_t AHandle,const char* ASgnAddress,const pdouble AValue) |
Function | Getting CAN Signal Values in the Database on a Remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: Pointer to signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | double d. if(0==rpc_tsmaster_cmd_get_can_signal(h, "0/CAN_FD_Powertrain/Engine/EngineData/EngSpeed", &d)){ // signal is retrieved } |
9|rpc_tsmaster_cmd_set_lin_signal
function name | UInt32 rpc_tsmaster_cmd_set_lin_signal(const size_t AHandle,const char* ASgnAddress,const double AValue) |
Function | Modifying LIN signal values in the database on a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | if(0==rpc_tsmaster_cmd_set_lin_signal(h, "chnidx/net/node/msg/signal", 1234)){ // signal written } |
10|rpc_tsmaster_cmd_get_lin_signal
function name | UInt32 rpc_tsmaster_cmd_get_lin_signal(const size_t AHandle,const char* ASgnAddress,const pdouble AValue) |
Function | Getting LIN Signal Values in the Database on a Remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: Pointer to signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | double d. if(0==rpc_tsmaster_cmd_get_lin_signal(h, "chnidx/net/node/msg/signal", &d)){ // signal is retrieved } |
11|rpc_tsmaster_cmd_set_flexray_signal
function name | UInt32 rpc_tsmaster_cmd_set_flexray_signal(const size_t AHandle,const char* ASgnAddress,const double AValue) |
Function | Modifying flexray signal values in the database on a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | if(0==rpc_tsmaster_cmd_set_flexray_signal(h, "chnidx/net/node/msg/signal", 1234)){ // signal written } |
12|rpc_tsmaster_cmd_get_flexray_signal
function name | UInt32 rpc_tsmaster_cmd_get_flexray_signal(const size_t AHandle,const char* ASgnAddress,const pdouble AValue) |
Function | Getting the flexray signal value in the database on a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASgnAddress: path to the signal in the database AValue: Pointer to signal value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | double d. if(0==rpc_tsmaster_cmd_get_flexray_signal(h, "chnidx/net/node/msg/signal", &d)){ // signal is retrieved } |
13|rpc_tsmaster_cmd_write_system_var
function name | UInt32 rpc_tsmaster_cmd_write_system_var(const size_t AHandle,const char* ACompleteName,const char* AValue) |
Function | Writing System Variables by Name from a Remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ACompleteName: system variable name AValue: Data value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_cmd_write_system_var(h, "v1", "1.2345") |
14|rpc_tsmaster_cmd_read_system_var
function name | UInt32 rpc_tsmaster_cmd_read_system_var(const size_t AHandle,const char* ASysVarName,const pdouble AValue) |
Function | Reading System Variables by Name from a Remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ASysVarName: system variable name AValue: data value pointer |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | double d. if (0 == rpc_tsmaster_cmd_read_system_var(h, "v1", &d)){ log("value = %f", d). } |
15|rpc_tsmaster_cmd_write_signal
function name | UInt32 rpc_tsmaster_cmd_write_signal(const size_t AHandle,const TLIBApplicationChannelType ABusType,const char* AAddr,const double AValue) |
Function | Write signal values by name from a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ABusType: bus type AAddr: path to the signal in the database AValue: Data value |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | if(0==rpc_tsmaster_cmd_write_signal(h,APP_CAN, "0/Powertrain/Engine/EngSpeed", 1234)){ // value written } |
16|rpc_tsmaster_cmd_read_signal
function name | UInt32 rpc_tsmaster_cmd_read_signal(const size_t AHandle,const TLIBApplicationChannelType ABusType,const char* AAddr,const pdouble AValue) |
Function | Reading signals by name from a remote TSMaster |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle ABusType: bus type AAddr: path to the signal in the database AValue: data value pointer |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | double d. if(0==rpc_tsmaster_cmd_read_signal(h,APP_CAN, "0/Powertrain/Engine/EngSpeed", &d)){ log("signal value = %f", d); } |
17|rpc_tsmaster_delete_client
function name | UInt32 rpc_tsmaster_delete_client(const size_t AHandle) |
Function | Delete rpc client |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_delete_client(h) |
18|rpc_tsmaster_cmd_stop_simulation
function name | UInt32 rpc_tsmaster_cmd_stop_simulation(const size_t AHandle) |
Function | Stop the remote TSMaster emulation |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | rpc_tsmaster_cmd_stop_simulation(h) |
19|rpc_tsmaster_call_system_api
function name | UInt32 rpc_tsmaster_call_system_api(const size_t AHandle,const char* AAPIName,const s32 AArgCount,const s32 AArgCapacity,const char** AArgs) |
Function | Client calls server to use system functions |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle AAPIName: name of the system function, "app.create_system_var" AArgCount: number of function arguments AArgCapacity: length of parameter string AArgs: array of argument strings |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | // The first step is to prepare the input parameters for the function call. #define STR_BUFFER_SIZE 1024 char args[4][STR_BUFFER_SIZE]; char* pArgs[4] = {&args[0][0], &args[1][0], &args[2][0], &args[3][0]}; sprintf_s(pArgs[0], STR_BUFFER_SIZE, "%s", "var1"); sprintf_s(pArgs[1], STR_BUFFER_SIZE, "%d", svtString); sprintf_s(pArgs[2], STR_BUFFER_SIZE, "%s", "string default value"); sprintf_s(pArgs[3], STR_BUFFER_SIZE, "%s", "this is a comment"); // Step 2: Call any API s32 ret. ret = com.rpc_tsmaster_call_system_api(h, "app.create_system_var", 4, STR_BUFFER_SIZE, &pArgs[0]); // Step 3: Process return values in parameters (if available) s32 i. log("API call result = %d", ret); for (i=0; i<4; i++){ log("Argument %d: %s", i+1, pArgs[i]); } |
20|rpc_tsmaster_call_library_api
function name | UInt32 rpc_tsmaster_call_library_api(const size_t AHandle,const char* AAPIName,const s32 AArgCount,const s32 AArgCapacity,const char** AArgs) |
Function | Client calls server to use system functions |
call location | After creating the TSMaster Rpc client |
input parameter | AHandle : TSMaster Rpc Client Handle AAPIName: applet library function name, "mylib.create_system_var" AArgCount: number of function arguments AArgCapacity: length of parameter string AArgs: array of argument strings |
return value | ==0: function executed successfully Other values: function execution failed |
typical example | // The first step is to prepare the input parameters for the function call. #define STR_BUFFER_SIZE 1024 char args[4][STR_BUFFER_SIZE]; char* pArgs[4] = {&args[0][0], &args[1][0], &args[2][0], &args[3][0]}; sprintf_s(pArgs[0], STR_BUFFER_SIZE, "%s", "var1"); sprintf_s(pArgs[1], STR_BUFFER_SIZE, "%d", svtString); sprintf_s(pArgs[2], STR_BUFFER_SIZE, "%s", "string default value"); sprintf_s(pArgs[3], STR_BUFFER_SIZE, "%s", "this is a comment"); /Step 2: Call any API s32 ret. ret = com.rpc_tsmaster_call_library_api(h, "mylib.create_system_var", 4, STR_BUFFER_SIZE, &pArgs[0]); // Step 3: Process return values in parameters (if available) s32 i. log("API call result = %d", ret); for (i=0; i<4; i++){ log("Argument %d: %s", i+1, pArgs[i]); } |