RPC User Services Connection Guide
Overview: During plugin development
- The plugin sdk may not have a special service interface that meets the user's needs. At this point, this interface can be implemented locally, and then the RPC interface can be used to provide services in the
aubo_scop
scripting system .- Maybe the user has already completed the interface implementation of various services required locally. If the
aubo_caps
system is used to re-implement it, it will consume a lot of manpower and resources, then use theaubo_scope
scripting system to provide the RPC interface to remotely call ouraubo_caps
plug-in system outside the implementation of the various types of services.- Note: The port number of the server side of this example is 8988, which is given in the code. If necessary, you can set up the interface so that the user can set the port number, and then read the value set by the user in the corresponding place.
Use of the sample project: package it using the commands in the
README
, then refer to https://docs.aubo-robotics.cn/application_notes/07-plugin_load_unload/ to load it into theaubo_scope
Below, the author will demonstrate the whole process by using building two projects, where user_service
is user service and json_rpc_test
is plugin system.
Adjusting the code structure
In the plug-in development process, it is recommended that the user services and plug-in system code is managed separately. This code structure is clear and easy to maintain.
As shown in the figure: link the user service as a sub-project to the plugin system
Create a new folder in the src directory of the plugin system for storing user services.
Write
CMakeLilsts.txt
in the user service file to manage the user service code and to facilitate the linking of plug-in systems.The part commented out here is what needs to be implemented for subsequent use of
json_rpc
, and needs to be added here after implementation.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 server-side 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}")
Add the user service as a sub-project to the plugin system (write the following command in
CMakeLists.txt
in the plugin system, note the path).cmakeadd_subdirectory(src/user_service)
Re
Cmake
the whole project, and the project structure will be programmed to match the user's desired structure.
-Download and link json-rpc-cxx
to your local project.
First write the following command in the CMakeLists.txt
file of the plugin system:
CPMAddPackage(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"
)
Because for the time beingthe plugin system json_rpc_testdoes not need to use the json_rpc
service, and the json_rpc
service is needed in the user service systemuser_service
, linking the downloaded packages to the user service system only requires writing the following command in the user service system CMakeLists.txt
with the following command:
target_link_libraries(user_service PUBLIC json-rpc-cxx nlohmann_json)
user service system
user_service
inducthttplib.h
cpphttplibconnector.hpp
file
httplib.h File Link:src/httplib.h cpphttplibconnector.hpp File Link: src/cpphttplibconnector.hpp
Linking these two files to the User Services system requires writing the following command in the User ServicesCMakeLists.txt
httplib.h
cpphttplibconnector.hpp
Introducing user services
Here the author customized the
test.h
abstract class and derived theuser_service.h
class from it, and implemented thetestFunction()
interface in theuser_service.h
class to mimic the various types of service interfaces already implemented by users.Here, the author's test case is structured as follows:
Linking test cases to the**user service system
user_service
: **cmakeuser_service.h user_service.cpp test.h
test.h:
c++#ifndef TEST_H #define TEST_H #include <string> #include <vector> #include <map> #include <memory> // User Service Abstract Interface, do one implementation for one model class Test { public: virtual ~Test() = default; virtual int testFunction() = 0; }; using TestPtr = std::shared_ptr<Test>; #endif // TEST_H
user_service.h
: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
user_service.cpp
:c++#include "user_service.h" UserService::UserService() { } int UserService::testFunction() { int test_result{12345}; return test_result; }
Add an rpc service to the test case: (Here, a functional module that enables RPC service needs to be implemented, and users need to add interfaces from their function module to this rpc service)
user_service_rpc_service.h
document: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
user_service_rpc_service.cpp
document:C++#include "user_service_rpc_service.h" UserServiceRpcService::UserServiceRpcService(int port) { // Set the ip and port number of the server side of the user service system, after this part is done, it will be set in the aubo_scope // Connect to this server in the script connector_ = std::shared_ptr<CppHttpLibServerConnector>( new CppHttpLibServerConnector(*this, port)); // Instantiate a UserService ,for use in placing UserService // Add the required interfaces inside 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(); }
Starting the user service as a server
Here, since the add_deecutable command was written in the cmakeLists.txt file to generate the user_Service executable program, simply starting the executable program will start the user_Service as the server. There are two ways to start it: manually starting the file or starting it in the plugin system.
The idea of starting this file in the plugin system: start this server as soon as the user enters the plugin system. The specific implementation is as follows:
Because the function of connecting external devices to the aubo_stope plugin system is located on the installation node, the server can be started by enabling external programs in the installation node program.
- First, add an external program interface to the installation node:
- Package the generated server-side file (generated user service system executable file) into the plug-in system zip file to facilitate the plug-in system to start the file.
CMakeinstall(TARGETS user_service DESTINATION .)
Effect: Packaging the plugin will add a
user_service
executable under arcs_ws/estensions/json_rpc_test/.- Finally, start the program in the plugin system
json_rpc_test
installation node:
Reads the set
user_service
path:(1) Pass the project path into the installation node in the activation function
(2) Save the
aubo_caps
working path to theservice
class(3) Pass the
aubo_caps
working path into thenode
node for ease of useWhen installing the node construct, start the user server program:
c++user_server_ = new QProcess(); // FIXME: Finding the correct load 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) { // }); // Starting the user server user_server_->start();
Connect the plugin to the user service server
Write the connection script in the plugin system installation node:
C++// Connecting to the server script_writer->appendLine( QString( "local api = sched.jsonrpc.proxy('http://127.0.0.1:%1/jsonrpc')") .arg(8988) .toStdString());
Add the required services (interfaces) on the user service server side
C++// Services provided by UserService Add("testFunction", jsonrpccxx::GetHandle(&UserService::testFunction, *user_service_), {});
Using services (interfaces) that have been added to the server in aubo_scope scripts
C++// Testing calls to external interfaces script_writer->appendLine("local result = api.testFunction()"); script_writer->appendLine( "print(1111111111111111111111111111111111111111111111)"); // Printing the obtained results script_writer->appendLine("print(result)");