4242// Per-device information collected during the scan
4343// --------------------------------------------------------------------------
4444
45+ struct ConfigInfo {
46+ std::string firmware_version;
47+ std::string work_mode;
48+ int32_t pcl_data_type;
49+ int32_t scan_pattern;
50+ uint32_t blind_spot;
51+ bool dual_emit;
52+ bool imu_enabled;
53+ bool config_queried;
54+
55+ ConfigInfo () : pcl_data_type(-1 ), scan_pattern(-1 ), blind_spot(0 ),
56+ dual_emit (false ), imu_enabled(false ), config_queried(false ) {}
57+ };
58+
4559struct DeviceEntry {
4660 uint32_t handle;
4761 std::string lidar_ip;
4862 std::string sn;
4963 uint8_t dev_type;
64+ ConfigInfo config;
5065};
5166
5267// --------------------------------------------------------------------------
@@ -79,6 +94,101 @@ static const char* DevTypeName(uint8_t dev_type) {
7994 }
8095}
8196
97+ // --------------------------------------------------------------------------
98+ // Helper: convert point data type enum to string
99+ // --------------------------------------------------------------------------
100+ static const char * DataTypeName (int32_t type) {
101+ switch (type) {
102+ case 0x01 : return " Cartesian High" ;
103+ case 0x02 : return " Cartesian Low" ;
104+ case 0x03 : return " Spherical" ;
105+ default : return " Unknown" ;
106+ }
107+ }
108+
109+ // --------------------------------------------------------------------------
110+ // Helper: convert scan pattern enum to string
111+ // --------------------------------------------------------------------------
112+ static const char * ScanPatternName (int32_t pattern) {
113+ switch (pattern) {
114+ case 0x00 : return " Non-Repetitive" ;
115+ case 0x01 : return " Repetitive" ;
116+ case 0x02 : return " Repetitive Low FPS" ;
117+ default : return " Unknown" ;
118+ }
119+ }
120+
121+ // --------------------------------------------------------------------------
122+ // Helper: find device entry by handle
123+ // --------------------------------------------------------------------------
124+ static DeviceEntry* FindDeviceByHandle (uint32_t handle) {
125+ std::lock_guard<std::mutex> lock (g_scan.mtx );
126+ for (auto & d : g_scan.devices ) {
127+ if (d.handle == handle) return &d;
128+ }
129+ return nullptr ;
130+ }
131+
132+ // --------------------------------------------------------------------------
133+ // Callback: firmware version query response
134+ // --------------------------------------------------------------------------
135+ static void OnFirmwareVersionQuery (livox_status status,
136+ uint32_t handle,
137+ LivoxLidarDiagInternalInfoResponse* response,
138+ void * /* client_data*/ ) {
139+ DeviceEntry* dev = FindDeviceByHandle (handle);
140+ if (!dev) return ;
141+
142+ if (status == kLivoxLidarStatusSuccess && response && response->ret_code == 0 ) {
143+ // Parse firmware version from response data
144+ // The format is typically a param_num followed by key-value pairs
145+ if (response->param_num > 0 && response->data [0 ]) {
146+ // Simple extraction - firmware version is typically a string
147+ dev->config .firmware_version = std::string (reinterpret_cast <const char *>(response->data ));
148+ }
149+ }
150+ dev->config .config_queried = true ;
151+ }
152+
153+ // --------------------------------------------------------------------------
154+ // Callback: internal info query response
155+ // --------------------------------------------------------------------------
156+ static void OnInternalInfoQuery (livox_status status,
157+ uint32_t handle,
158+ LivoxLidarDiagInternalInfoResponse* response,
159+ void * /* client_data*/ ) {
160+ DeviceEntry* dev = FindDeviceByHandle (handle);
161+ if (!dev) return ;
162+
163+ if (status == kLivoxLidarStatusSuccess && response && response->ret_code == 0 ) {
164+ std::cout << " [info] Received internal config for " << dev->lidar_ip
165+ << " (param_num=" << response->param_num << " )\n " ;
166+
167+ // Parse key-value parameters from the response
168+ // The data format is: [key(2B)][length(2B)][value(length B)] repeated
169+ uint8_t * ptr = response->data ;
170+ size_t offset = 0 ;
171+
172+ for (int i = 0 ; i < response->param_num && offset < 1024 ; ++i) {
173+ if (offset + 4 > 1024 ) break ;
174+
175+ uint16_t key = *reinterpret_cast <uint16_t *>(ptr + offset);
176+ offset += 2 ;
177+ uint16_t length = *reinterpret_cast <uint16_t *>(ptr + offset);
178+ offset += 2 ;
179+
180+ if (offset + length > 1024 ) break ;
181+
182+ // Parse based on key - common keys include work mode, data type, etc.
183+ // Key values would need to be determined from SDK documentation
184+ std::cout << " [param] key=0x" << std::hex << key
185+ << " length=" << std::dec << length << " \n " ;
186+
187+ offset += length;
188+ }
189+ }
190+ }
191+
82192// --------------------------------------------------------------------------
83193// Callback: called by the SDK whenever a lidar is discovered or its info
84194// changes (multiple calls for the same device are de-duplicated)
@@ -88,25 +198,38 @@ static void OnLidarInfoChange(const uint32_t handle,
88198 void * /* client_data*/ ) {
89199 if (!info) return ;
90200
91- std::lock_guard<std::mutex> lock (g_scan.mtx );
201+ bool should_query = false ;
202+ {
203+ std::lock_guard<std::mutex> lock (g_scan.mtx );
92204
93- // De-duplicate by handle
94- for (const auto & d : g_scan.devices ) {
95- if (d.handle == handle) return ;
96- }
205+ // De-duplicate by handle
206+ for (const auto & d : g_scan.devices ) {
207+ if (d.handle == handle) return ;
208+ }
97209
98- DeviceEntry entry;
99- entry.handle = handle;
100- entry.lidar_ip = info->lidar_ip ;
101- entry.sn = info->sn ;
102- entry.dev_type = info->dev_type ;
210+ DeviceEntry entry;
211+ entry.handle = handle;
212+ entry.lidar_ip = info->lidar_ip ;
213+ entry.sn = info->sn ;
214+ entry.dev_type = info->dev_type ;
103215
104- std::cout << " [found] " << entry.lidar_ip
105- << " type=" << DevTypeName (entry.dev_type )
106- << " sn=" << entry.sn
107- << " \n " ;
216+ std::cout << " [found] " << entry.lidar_ip
217+ << " type=" << DevTypeName (entry.dev_type )
218+ << " sn=" << entry.sn
219+ << " \n " ;
108220
109- g_scan.devices .push_back (std::move (entry));
221+ g_scan.devices .push_back (std::move (entry));
222+ should_query = true ;
223+ }
224+
225+ // Query device configuration outside the lock
226+ if (should_query) {
227+ // Query firmware version
228+ QueryLivoxLidarFirmwareVer (handle, OnFirmwareVersionQuery, nullptr );
229+
230+ // Query internal info (includes various config parameters)
231+ QueryLivoxLidarInternalInfo (handle, OnInternalInfoQuery, nullptr );
232+ }
110233}
111234
112235// --------------------------------------------------------------------------
@@ -267,7 +390,7 @@ int main(int argc, char** argv) {
267390 std::cout << " [result] Found " << devs.size ()
268391 << " device(s):\n\n " ;
269392
270- // Column widths
393+ // Print basic info table
271394 const int w_ip = 16 ;
272395 const int w_type = 16 ;
273396 const int w_sn = 18 ;
@@ -296,5 +419,41 @@ int main(int argc, char** argv) {
296419 hline ();
297420 std::cout << " \n " ;
298421
422+ // Print detailed configuration for each device
423+ std::cout << " === Device Configuration Details ===\n\n " ;
424+
425+ for (const auto & d : devs) {
426+ std::cout << " Device: " << d.lidar_ip << " (" << d.sn << " )\n " ;
427+ std::cout << " Type: " << DevTypeName (d.dev_type ) << " \n " ;
428+
429+ if (!d.config .firmware_version .empty ()) {
430+ std::cout << " Firmware Version: " << d.config .firmware_version << " \n " ;
431+ }
432+
433+ if (d.config .pcl_data_type >= 0 ) {
434+ std::cout << " Point Data Type: " << DataTypeName (d.config .pcl_data_type )
435+ << " (" << d.config .pcl_data_type << " )\n " ;
436+ }
437+
438+ if (d.config .scan_pattern >= 0 ) {
439+ std::cout << " Scan Pattern: " << ScanPatternName (d.config .scan_pattern )
440+ << " (" << d.config .scan_pattern << " )\n " ;
441+ }
442+
443+ if (d.config .blind_spot > 0 ) {
444+ std::cout << " Blind Spot: " << d.config .blind_spot << " cm\n " ;
445+ }
446+
447+ std::cout << " Dual Emit: " << (d.config .dual_emit ? " Enabled" : " Disabled" ) << " \n " ;
448+ std::cout << " IMU Data: " << (d.config .imu_enabled ? " Enabled" : " Disabled" ) << " \n " ;
449+
450+ if (!d.config .work_mode .empty ()) {
451+ std::cout << " Work Mode: " << d.config .work_mode << " \n " ;
452+ }
453+
454+ std::cout << " Config Queried: " << (d.config .config_queried ? " Yes" : " No" ) << " \n " ;
455+ std::cout << " \n " ;
456+ }
457+
299458 return 0 ;
300459}
0 commit comments