Transport-agnostic remote API for operating Hakoniwa worlds, assets, and runtimes from external processes.
The Remote API exposes a small RPC surface area that clients use to join a Hakoniwa simulation, query state, control the simulation, and acknowledge events. Configuration is provided via remote-api.json, which points to the RPC service definition, endpoints configuration, and poll timing.
flowchart LR
subgraph Client Process
CC[ClientCore]
CLI[Client app]
end
subgraph Server Process
SC[ServerCore]
H[Service Handlers]
Hako[Hakoniwa Core APIs]
end
subgraph Config Files
RA[remote-api.json]
RPC[rpc.json]
EPS[endpoints.json]
EP[endpoint/*.json]
PDU[pdudef.json]
end
CLI --> CC
CC -->|RPC calls| SC
SC --> H --> Hako
RA --> RPC --> EPS --> EP
RPC --> PDU
CC -.loads.-> RA
SC -.loads.-> RA
All RPC services are declared in config/sample/rpc/rpc.json and implemented by the server handlers in src/server/concrete_service_handler.cpp.
| Service | Purpose | Request | Response |
|---|---|---|---|
HakoRemoteApi/Join |
Register a client with the server. | name (client node ID) |
status_code, message |
HakoRemoteApi/GetSimState |
Retrieve the current simulation state. | name (client node ID) |
sim_state, master_time, is_pdu_created, is_simulation_mode, is_pdu_sync_mode |
HakoRemoteApi/SimControl |
Start/stop/reset the simulation. | name, op (HakoSimulationControlCommand) |
status_code, message |
HakoRemoteApi/GetEvent |
Get the next pending event for the client. | name |
event_code |
HakoRemoteApi/AckEvent |
Acknowledge an event after handling. | name, event_code, result_code |
(no body status; see below) |
Responses use hakoniwa::pdu::rpc::HAKO_SERVICE_RESULT_CODE_* to report success, invalid requests, or internal errors. AckEvent does not set a status in its response body; clients should rely on the RPC header result code. The server validates the client name before processing requests.
The server-facing public API is exposed via hakoniwa::api::ServerCore.
ServerCore(std::string config_path, std::string node_id, bool enable_conductor = false)- Loads configuration from
remote-api.jsonand binds to the specified server node ID.
- Loads configuration from
bool initialize(std::shared_ptr<hakoniwa::pdu::EndpointContainer> endpoint_container)- Parses configuration, validates server/client pairing, and registers service handlers.
bool initialize_rpc_services()- Initializes RPC services after
initialize(...)has been called.
- Initializes RPC services after
bool start()- Starts RPC services and spawns worker threads.
bool stop()- Stops RPC services and joins worker threads (idempotent).
bool is_running() const- Reports whether the server is running.
std::string last_error() const- Returns the last error message.
The client-facing public API is exposed via hakoniwa::api::ClientCore.
ClientCore(std::string node_id, std::string config_path)- Loads configuration and binds to the specified client node ID.
bool initialize(std::shared_ptr<hakoniwa::pdu::EndpointContainer> endpoint_container)- Parses configuration and initializes the RPC client.
bool start()/bool stop()- Starts or stops RPC services.
bool is_pdu_end_point_running()- Returns whether the client endpoint is available.
bool join()- Calls
HakoRemoteApi/Join.
- Calls
bool get_sim_state(HakoSimulationStateInfo &state)- Calls
HakoRemoteApi/GetSimState.
- Calls
bool sim_control(HakoSimulationControlCommand command)- Calls
HakoRemoteApi/SimControl.
- Calls
bool get_event(HakoSimulationAssetEvent &event)- Calls
HakoRemoteApi/GetEvent.
- Calls
bool ack_event(HakoSimulationAssetEvent event)- Calls
HakoRemoteApi/AckEvent.
- Calls
std::string last_error() const- Returns the last error message.
- C++20 toolchain
- CMake 3.10+
- Hakoniwa runtime libraries and headers installed under
/usr/local/hakoniwa hakoniwa-pdu-rpcsubmodule initialized- Installed
hakoniwa-pdu-endpoint(headers and library)
git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
cmake --build .The build generates the hakoniwa_remote_api library and sample server/client executables.
hakoniwa-pdu-endpoint is no longer a submodule of hakoniwa-pdu-rpc. It must be installed separately (default prefix is /usr/local/hakoniwa).
If your install prefix is non-standard, pass it to CMake:
cmake -S . -B build -DHAKO_PDU_ENDPOINT_PREFIX=/path/to/prefixOr specify include/library paths directly:
cmake -S . -B build \
-DHAKO_PDU_ENDPOINT_INCLUDE_DIR=/path/to/include \
-DHAKO_PDU_ENDPOINT_LIBRARY=/path/to/lib/libhakoniwa_pdu_endpoint.aThe sample executables wire up endpoints explicitly and then initialize the core APIs:
- Create
EndpointContainerwith<server_nodeId>and<endpoints.json>. EndpointContainer::initialize()ServerCore::initialize(endpoint_container)EndpointContainer::start_all()ServerCore::initialize_rpc_services()ServerCore::start()
- Create
EndpointContainerwith<client_nodeId>and<endpoints.json>. EndpointContainer::initialize()ClientCore::initialize(endpoint_container)EndpointContainer::start_all()ClientCore::start()
Note: ServerCore::start() requires initialize_rpc_services() to have been called. If you are using the sample src/main/server.cpp as-is and see "Server is not properly initialized.", add a call to server.initialize_rpc_services() before server.start().
config/sample/remote-api.jsondefines server nodes, participants, time source, poll sleep timing, and points torpc.jsonandendpoints.json.poll_sleep_time_usec: server-side poll sleep interval.time_source_type: time source for server polling (e.g.,real).participants[].poll_sleep_time_usec: client-side poll sleep interval.
config/sample/rpc/rpc.jsondefines the 5 RPC services.config/sample/rpc/endpoints.jsonmaps node IDs to endpoint config files.config/sample/endpoint/*.jsonconfigures transports, caches, and PDU definitions.config/sample/pdudef/pdudef.jsondefines PDU types and sizes.
- Transport-agnostic RPC: The RPC layer is configured via JSON and is not tied to a single transport implementation.
- Small, explicit API surface: The Remote API focuses on 5 core operations that cover join, state query, simulation control, and event handling.
- Configuration-driven wiring: Endpoints, channels, node IDs, and poll timing are declared in configuration files; RPC endpoint implementation names are currently fixed in code.
- Strict validation: Configuration is validated via schemas and a cross-file linter to catch inconsistencies early.
Use the repo-level linter for remote-api.json, and the RPC validator for rpc.json:
python/hakoniwa_remote_api/validate_configs.pychecksremote-api.jsonstructure and referencedrpc_service_config_pathexistence.python/hakoniwa_remote_api/validate_configs.pyalso cross-checks participantnodeIdentries against therpc.jsonendpoints list.hakoniwa-pdu-rpc/tools/validate_configs.pyvalidates RPC configs, endpoints, and endpoint schemas, and checks RPC semantics (e.g., unique names, channel collisions, maxClients constraints).
These commands use the sample configs shipped in this repository.
git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
cmake --build ../server ../config/sample/remote-api.json node0-1 ../config/sample/rpc/endpoints.jsonIf the server exits with "Server is not properly initialized.", update src/main/server.cpp to call server.initialize_rpc_services() before server.start(), rebuild, and retry.
./client ../config/sample/remote-api.json node1 ../config/sample/rpc/endpoints.jsonOnce the client is running, type one of the following commands and press Enter:
join(register with server)state(read simulation state)g:event(get next event)c:start/c:stop/c:reset(simulation control)a:start/a:stop/a:reset(ack event)q/quit/exit(quit)
このユーティリティは、PDUサイズ定義ファイルに基づいて rpc.json 設定ファイル内の pduSize フィールドを自動的に更新します。これにより、RPCサービス設定が常に正しいPDUサイズを反映し、手動エラーを防ぎ、更新プロセスを効率化します。
使用方法:
python3 python/hakoniwa_remote_api/update_pdusize.py <path_to_rpc_json> <path_to_pdu_size_dir><path_to_rpc_json>:rpc.jsonファイルへのパス (例:config/sample/rpc/rpc.json)。<path_to_pdu_size_dir>: PDUサイズ定義ファイルが配置されているルートディレクトリ (例:messages/impl/pdu_size)。
例:
python3 python/hakoniwa_remote_api/update_pdusize.py config/sample/rpc/rpc.json messages/impl/pdu_size