Skip to content
TREN
Atlıhan Harita

Lixel OpenAPI User Manual · C++

Client & Examples

Chapter 09.2 / 09Manual version v1.1.0English

The C++ client library lives in the lixel::openapi namespace, with public headers in cpp/include/lixel/openapi/. This page covers what it offers and how to use it.

Headers at a glance

HeaderWhat it gives you
client.hClient: Connect, Request, Publish, Subscribe, SubscribeMessage, RemoveSubscription
scan.hRunScan: start a scan, wait until the device is really scanning, stop, wait for standby
pointcloud.hDecodePointCloud: decode the lio_pcl payload into scaled points
codec.hmessage by name, protobuf to and from JSON
catalog.hthe table of 18 interfaces and their 34 topics
codes.h, result.hdevice status codes, Result and Errc

The Client

Connect

lixel::openapi::ClientOptions options;
options.transport.host = "192.168.55.1";
options.openapi_key = "<provided by XGRIDS>";

lixel::openapi::Client client(options);
lixel::openapi::Result r = client.Connect();   // blocks until connected

A failed Connect() returns Errc::ConnectFailed or Errc::ConnectTimeout, and the client can be used for another Connect() afterwards.

Request-response

openapi::aiot_msgs::DeviceInfoRequest req;
openapi::aiot_msgs::DeviceInfoResponse rsp;
lixel::openapi::Result r = client.Request(
    "lixel/application/request/device_info", req,
    "lixel/application/response/device_info", &rsp);

Return codes of Request:

CodeMeaning
OkA response arrived and its Error.code is a success code
DeviceErrorA response arrived but with an error code (see Result::device_code, desc); response is filled
RequestTimeoutNo response with the same seq within the timeout. The device may still have carried out the request; confirm with it before assuming otherwise
NotConnectedNot connected, or the connection dropped while waiting
CalledFromCallbackRequest was called from a subscription callback

Subscribe to reports

client.SubscribeMessage(
    "lixel/application/report/device_status", "DeviceStatusReport",
    [](const std::string& topic, const google::protobuf::Message& msg) {
      // msg is already parsed into the matching protobuf message
    });

Note: subscription callbacks run on the MQTT layer's thread, one message at a time; keep them short. A callback must not call Connect or Disconnect; calling Request returns Errc::CalledFromCallback instead of blocking. The strings passed to a callback are valid only for the duration of the call; copy what you need.

Point cloud decoding

The real-time point cloud (report/lio_pcl, MqttCompressMsg) is decoded with DecodePointCloud, which decompresses and deserializes in one step:

#include "lixel/openapi/pointcloud.h"

lixel::openapi::PointCloud cloud;
lixel::openapi::Result r = lixel::openapi::DecodePointCloud(payload, &cloud);
// On success, each point's x/y/z in cloud.points is reconstructed by header.scaler (the device sends scaler as 1000).

The compression is LZ4 block (not frame). A Zstd-compressed point cloud and a negative scaler return Errc::Unsupported. A point's rgbi is passed through unchanged (the proto only notes R+G+B+Intensity, with no further byte-order convention).

Scan flow

Starting and stopping a scan are asynchronous on the device: the response to AC_START only means the request was accepted, and the device then goes standby → starting → scanning. RunScan wraps the whole flow — subscribe to the device status, wait for standby, start, wait until really scanning, watch for a while, stop, and wait for standby:

#include "lixel/openapi/scan.h"

lixel::openapi::ScanOptions options;
options.project_name = "demo";
options.watch = std::chrono::seconds(8);

lixel::openapi::ScanReport report = lixel::openapi::RunScan(client, options);
return report.exit_code();   // 0 success, others see ScanOutcome

RunScan blocks the calling thread, requires a connected client, and must not be called from a subscription callback. The ScanOutcome result: Completed (0), Timeout (1), NotStandby (2), StartRejected (3), NoResponse (4), Error (5), Interrupted (130).

The 18 command line examples

cpp/examples/ has one C++ program for each script in python/example/usage/, with the same name and options, built with the library (on by default) into cpp/build/examples/:

./cpp/build/examples/heartbeat --seconds 5                 # no key needed
./cpp/build/examples/device_info --key <provided by XGRIDS>
./cpp/build/examples/modeling --key <provided by XGRIDS> --project demo --watch 8
./cpp/build/examples/lio_pcl --key <provided by XGRIDS> --seconds 20   # while the device scans

Common options: --host (default 192.168.55.1), --port, --tls, --username, --password, --key, --timeout; for TLS also --ca-file and --insecure. Exit codes: 0 success, 1 could not connect or no answer, 2 bad option (modeling: the device was not in standby), 3 the device answered with an error code, 130 interrupted.

The 18 examples: control_point, data_unpack, device_config, device_control, device_info, device_status, get_ntrip_profile, get_rtk_advance, heartbeat, lio_pcl, lio_pose, measure_point, modeling, modeling_status, project_list, set_ntrip_profile, set_rtk_advance, system_error.

Note: among them, device_control, device_config, set_ntrip_profile, set_rtk_advance, control_point, and measure_point change the device, and device_control can power it off or format the disk — confirm before use.

Differences from the Python client

The C++ client intentionally differs in a few places:

AspectC++Python
Response matchingBy header.seq, which the device copies backThe first message on the response topic
JSON conversionStrict: a misspelled field or enum name is an errorDropped silently
MQTTS certificateVerifies the server certificate by default; the self-signed device certificate needs --ca-file, or --insecure to turn verification offNever verifies
Calling Request in a callbackReturns Errc::CalledFromCallbackBlocks

Other limits:

  • Several Client objects in one process share one MQTT worker thread; opening a second connection takes about 2 seconds. Each example uses one Client and is not affected.
  • A Request that is waiting cannot be cancelled; it ends within request_timeout.

Next steps

This chapter is from the official XGRIDS user manual. Official source (opens in a new tab) · Updated:

XGRIDS Türkiye

We're With You During Setup and in the Field

Atlıhan Harita provides training and technical support for device setup, firmware updates, software use, and field applications. Send us your question and our specialist will get back to you.

+90 216 546 0804