RPC Interface
Overview
During plugin development, developers may encounter special scenarios that exceed the current capabilities of the AuboCaps plugin system. Users may wish to implement these interfaces locally, or they may have already implemented local interfaces and want the ARCS software to directly call these local interfaces to meet various requirements. To address this situation, the AUBO development team has added RPC interfaces to the AuboCaps plugin system. Through the RPC interface, the ARCS script system can call various local services outside the AuboCaps plugin system, greatly enriching the functionality of the AuboCaps plugin system.
Example
The code for the example project in this section can be downloaded and used via the link below. The port number for the example server is "8988," but it can also be customized through the [Setting] interface.
Example project: https://github.com/AuboRobot/plugin_template/tree/main/example/example4
In the example project, the user_service
folder under the src
directory contains code related to user services, with the user service named "user_service". The installation
and program
folders contain code related to the AuboCaps plugin system, with the plugin named "json_rpc_test". During the plugin development process, to ensure a clear and maintainable code structure, it is recommended to link the user service to the plugin system as a subproject. This approach allows the user service and the plugin system code to be managed separately.
Adjusting Code Structure
In the root directory of the plugin project, under the
src
directory, create a new folder to store the user service. In this example, name it "user_service".Inside the
user_service
directory, create aCMakeLists.txt
file. This file is used to manage the user service code and facilitate linking within the plugin system.Open the
CMakeLists.txt
file and write the following code into it.- The commented sections are for implementing the
json_rpc
service, which will be required later. Once implemented, uncomment these sections.
cmakeset(CMAKE_CXX_STANDARD 17) set(CMAKE_VERBOSE_MAKEFILE ON) set(rpc_test_srcs) set(rpc_test_hdrs) set(rpc_test_hpps) file(GLOB_RECURSE rpc_test_srcs "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") file(GLOB_RECURSE rpc_test_hdrs "${CMAKE_CURRENT_SOURCE_DIR}/*.h") file(GLOB_RECURSE rpc_test_hpps "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp") find_package(Thread) # user_service 服务端 add_executable(user_service # httplib.h # user_service_test.h # user_service_test.cpp # user_service_test_server.h # user_service_test_server.cpp # user_service.h # user_service_test_demon.cpp # cpphttplibconnector.hpp ) target_include_directories(user_service PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) # target_link_libraries(user_service PUBLIC json-rpc-cxx nlohmann_json) target_link_libraries(user_service PRIVATE ${CMAKE_THREAD_LIBS_INIT}) set_target_properties(user_service PROPERTIES OUTPUT_NAME user_service PREFIX "" DEBUG_POSTFIX "" INSTALL_RPATH "$\{ORIGIN\}/lib" ) include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
- The commented sections are for implementing the
Open the plugin system's
CMakeLists.txt
and enter the following commands to add the user service as a subproject to the plugin system. Pay attention to the paths when writing.cmakeadd_subdirectory(src/user_service)
Re-execute [Run CMake] for the entire project. After completion, the project structure will be transformed into the desired configuration.
User Service Configuration RPC
This example uses the json_rpc_Cxx library via HTTP. The user service "user_service" needs to include the httplib.h
and cpphttplibconnector.hpp
files. These files have been placed in the example project and can be directly copied and reused.
httplib.h
file link: src/httplib.hcpphttplibconnector.hpp
file link: src/cpphttplibconnector.hpp
In this operation, the "json_rpc_test" plugin temporarily does not require the json_rpc
service, while the user service "user_service" needs to use the json_rpc
service.
Open the plugin system's
CMakeLists.txt
file and enter the following code:cmakeCPMAddPackage(json-rpc-cxx1 NAME json-rpc-cxx1 VERSION 0.3.0 GIT_REPOSITORY https://gitee.com/aubo-robotics/json-rpc-cxx.git EXCLUDE_FROM_ALL YES OPTIONS "COMPILE_EXAMPLES OFF" "COMPILE_TESTS OFF" ) CPMAddPackage(json1 NAME json1 VERSION 3.9.1 GIT_REPOSITORY https://gitee.com/aubo-robotics/json-v3.9.1.git EXCLUDE_FROM_ALL YES OPTIONS "JSON_BuildTests OFF" "JSON_Install OFF" )
Open the user service "user_service"
CMakeLists.txt
file and enter the following code:cmaketarget_link_libraries(user_service PUBLIC json-rpc-cxx nlohmann_json)
Copy the
httplib.h
andcpphttplibconnector.hpp
files to theuser_service
directory.Open the user service "user_service"
CMakeLists.txt
file and enter the following code to link thehttplib.h
andcpphttplibconnector.hpp
files to the user service system.
httplib.h
cpphttplibconnector.hpp
Importing User Services into Local Project
In this example project, the test.h
abstract class is derived to create the user_service.h
class. The user_service.h
class simulates various user-implemented service interfaces by implementing the testFunction()
interface.
In this operation, we will link the test cases to the user service "user_service".
Open the
CMakeLists.txt
file of the user service "user_service" and enter the following code.cmakeuser_service.h user_service.cpp test.h
Open
test.h
and enter the following code.c++#ifndef TEST_H #define TEST_H #include <string> #include <vector> #include <map> #include <memory> // Abstract interface for user services, implement once for each model type class Test { public: virtual ~Test() = default; virtual int testFunction() = 0; }; using TestPtr = std::shared_ptr<Test>; #endif // TEST_H
Open
user_service.h
and enter the following code.c++#ifndef USER_SERVICE_H #define USER_SERVICE_H #include "test.h" class UserService : public Test { public: UserService(); int testFunction() override; }; using UserServicePtr = std::shared_ptr<UserService>; #endif // USER_SERVICE_H
Open
user_service.cpp
and enter the following code.c++#include "user_service.h" UserService::UserService() { } int UserService::testFunction() { int test_result{12345}; return test_result; }
Local Project RPC Configuration
Open the
CMakeLists.txt
file in the user service "user_service" and enter the following code.cmakeuser_service_rpc_service.cpp user_service_rpc_service.h
Open
user_service_rpc_service.h
and enter the following code.c++#ifndef USERSERVICERPCSERVICE_H #define USERSERVICERPCSERVICE_H #include "cpphttplibconnector.hpp" #include "user_service.h" class UserServiceRpcService : public jsonrpccxx::JsonRpc2Server { public: UserServiceRpcService(int port = 8988); ~UserServiceRpcService(); bool startListening(); void join(); private: CppHttpLibServerConnectorPtr connector_; UserServicePtr user_service_; }; #endif // USERSERVICERPCSERVICE_H
Open
user_service_rpc_service.cpp
and enter the following code.c++#include "user_service_rpc_service.h" UserServiceRpcService::UserServiceRpcService(int port) { // Set the IP address and port number of the user service system server. // After this configuration is complete, it will connect to this server in the aubo_scope script connector_ = std::shared_ptr<CppHttpLibServerConnector>( new CppHttpLibServerConnector(*this, port)); // Instantiate a UserService to add the required interfaces // from UserService to this RPC service user_service_ = std::make_shared<UserService>(); // Services provided by UserService Add("testFunction", jsonrpccxx::GetHandle(&UserService::testFunction, *user_service_), {}); } UserServiceRpcService::~UserServiceRpcService() { } bool UserServiceRpcService::startListening() { std::cout << "start startListening" << std::endl; connector_->StartListening(); } void UserServiceRpcService::join() { connector_->join(); }
Configure User Service as Server
There are two methods to start the user service "user_service" as a server: one is to manually start the file, and the other is to launch the executable file within the plugin system.
In the series of operations mentioned above, the add_executable
command has been written in the CMakeLists.txt
file, generating the executable program for "user_service". Therefore, through the following operations, the server can be started by enabling external programs in the installation node, achieving the purpose of launching executable files within the plugin system. Once configured, the server will start automatically when users enter the plugin system.
Add external program interface in the installation node.
Package the generated server file (the user service system executable file) into the plugin system zip file to facilitate its launch within the plugin system.
Open the
CMakeLists.txt
file of "user_service" and input the following code.cmakeinstall(TARGETS user_service DESTINATION .)
Package the plugin, adding a
user_service
executable program to thearcs_ws/estensions/json_rpc_test/
directory.
Plugin System Starts Local Project
In the plugin system json_rpc_test
installation node:
Read the configured
user_service
path.Pass the project path to the installation node in the activation function.
Save the
aubo_caps
working path to theservice
class.Pass the
aubo_caps
working path to thenode
for convenient use.
When constructing the installation node, start the user server program.
c++user_server_ = new QProcess(); // FIXME: Find the correct loading path auto dir = QDir(location.c_str()); dir.cd(".."); user_server_->setProgram(QString("%1/user_service").arg(dir.path())); user_server_->setArguments(QStringList() << QString::number(8988)); QObject::connect(user_server_, &QProcess::stateChanged, [](QProcess::ProcessState newState) { // }); QObject::connect(user_server_, &QProcess::errorOccurred, [](QProcess::ProcessError error) { // }); // tart user server user_server_->start();
Plugin System Connects to User Service Server
Write connection script in the plugin system installation node.
// Server Adds Services
script_writer->appendLine(
QString(
"local api = sched.jsonrpc.proxy('http://127.0.0.1:%1/jsonrpc')")
.arg(8988)
.toStdString());
Server Adds Services
Add required services (interfaces) to the user service server.
// Services provided by UserService
Add("testFunction",
jsonrpccxx::GetHandle(&UserService::testFunction, *user_service_), {});
Script Uses Services
Use the services (interfaces) that have been added to the server in aubo_scope script.
// Test calling external interface
script_writer->appendLine("local result = api.testFunction()");
script_writer->appendLine(
"print(1111111111111111111111111111111111111111111111)");
// Print the obtained result
script_writer->appendLine("print(result)");