forked from IntelRealSense/librealsense
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rs-terminal.cpp
422 lines (371 loc) · 14.6 KB
/
rs-terminal.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <librealsense2/rs.hpp>
#include <librealsense2/utilities/string/string-utilities.h>
#include "tclap/CmdLine.h"
#include "parser.hpp"
#include "auto-complete.h"
using namespace std;
using namespace TCLAP;
vector<uint8_t> build_raw_command_data(const command& command, const vector<string>& params)
{
if (params.size() > command.parameters.size() && !command.is_cmd_write_data)
throw runtime_error("Input string was not in a correct format!");
vector<parameter> vec_parameters;
for (auto param_index = 0; param_index < params.size(); ++param_index)
{
auto is_there_write_data = param_index >= int(command.parameters.size());
auto name = (is_there_write_data) ? "" : command.parameters[param_index].name;
auto is_reverse_bytes = (is_there_write_data) ? false : command.parameters[param_index].is_reverse_bytes;
auto is_decimal = (is_there_write_data) ? false : command.parameters[param_index].is_decimal;
auto format_length = (is_there_write_data) ? -1 : command.parameters[param_index].format_length;
vec_parameters.push_back(parameter(name, params[param_index], is_decimal, is_reverse_bytes, format_length));
}
vector<uint8_t> raw_data;
encode_raw_data_command(command, vec_parameters, raw_data);
return raw_data;
}
void xml_mode(const string& line, const commands_xml& cmd_xml, rs2::device& dev, map<string, xml_parser_function>& format_type_to_lambda)
{
vector<string> tokens;
stringstream ss(line);
string word;
while (ss >> word)
{
stringstream converter;
converter << hex << word;
tokens.push_back(word);
}
if (tokens.empty())
throw runtime_error("Invalid input! - no arguments provided");
auto command_str = utilities::string::to_lower(tokens.front());
auto it = cmd_xml.commands.find(command_str);
if (it == cmd_xml.commands.end())
throw runtime_error("Command " + command_str + " was not found!");
auto command = it->second;
vector<string> params;
for (auto i = 1; i < tokens.size(); ++i)
params.push_back(tokens[i]);
// In case of sending data from file, the data will be retrieved and converted into raw format
file_argument_to_blob(params);
auto raw_data = build_raw_command_data(command, params);
for (auto b : raw_data)
{
cout << hex << fixed << setfill('0') << setw(2) << (int)b << " ";
}
cout << endl;
auto result = dev.as<rs2::debug_protocol>().send_and_receive_raw_data(raw_data);
unsigned returned_opcode = *result.data();
// check returned opcode
if (command.op_code != returned_opcode)
{
stringstream msg;
msg << "OpCodes do not match! Sent 0x" << hex << command.op_code << " but received 0x" << hex << (returned_opcode) << "!";
throw runtime_error(msg.str());
}
if (command.is_read_command)
{
string data;
decode_string_from_raw_data(command, cmd_xml.custom_formatters, result.data(), result.size(), data, format_type_to_lambda);
cout << endl << data << endl;
}
else
{
cout << endl << "Done!" << endl;
}
}
void hex_mode(const string& line, rs2::device& dev)
{
vector<uint8_t> raw_data;
stringstream ss(line);
string word;
while (ss >> word)
{
stringstream converter;
int temp;
converter << hex << word;
converter >> temp;
raw_data.push_back(temp);
}
if (raw_data.empty())
throw runtime_error("Wrong input!");
auto result = dev.as<rs2::debug_protocol>().send_and_receive_raw_data(raw_data);
cout << endl;
for (auto& elem : result)
cout << setfill('0') << setw(2) << hex << static_cast<int>(elem) << " ";
}
auto_complete get_auto_complete_obj(bool is_application_in_hex_mode, const map<string, command>& commands_map)
{
set<string> commands;
if (!is_application_in_hex_mode)
{
for (auto& elem : commands_map)
commands.insert(elem.first);
}
return auto_complete(commands, is_application_in_hex_mode);
}
void read_script_file(const string& full_file_path, vector<string>& hex_lines)
{
ifstream myfile(full_file_path);
if (myfile.is_open())
{
string line;
while (getline(myfile, line))
hex_lines.push_back(line);
myfile.close();
return;
}
throw runtime_error("Script file not found!");
}
rs2::device wait_for_device(const rs2::device_hub& hub, bool print_info = true)
{
if (print_info)
cout << "\nWaiting for RealSense device to connect...\n";
auto dev = hub.wait_for_device();
if (print_info)
cout << "RealSense device has connected...\n";
return dev;
}
int main(int argc, char** argv)
{
CmdLine cmd("librealsense rs-terminal tool", ' ', RS2_API_VERSION_STR);
ValueArg<string> xml_arg("l", "load", "Full file path of commands XML file", false, "", "Load commands XML file");
ValueArg<int> device_id_arg("d", "deviceId", "Device ID could be obtain from rs-enumerate-devices example", false, 0, "Select a device to work with");
ValueArg<string> specific_SN_arg("n", "serialNum", "Serial Number can be obtain from rs-enumerate-devices example", false, "", "Select a device serial number to work with");
SwitchArg all_devices_arg("a", "allDevices", "Do this command to all attached Realsense Devices", false);
ValueArg<string> hex_cmd_arg("s", "send", "Hexadecimal raw data", false, "", "Send hexadecimal raw data to device");
ValueArg<string> hex_script_arg("r", "raw", "Full file path of hexadecimal raw data script", false, "", "Send raw data line by line from script file");
ValueArg<string> commands_script_arg("c", "cmd", "Full file path of commands script", false, "", "Send commands line by line from script file");
cmd.add(xml_arg);
cmd.add(device_id_arg);
cmd.add(specific_SN_arg);
cmd.add(all_devices_arg);
cmd.add(hex_cmd_arg);
cmd.add(hex_script_arg);
cmd.add(commands_script_arg);
cmd.parse(argc, argv);
// parse command.xml
rs2::log_to_file(RS2_LOG_SEVERITY_WARN, "librealsense.log");
// Obtain a list of devices currently present on the system
rs2::context ctx = rs2::context();
rs2::device_hub hub(ctx);
rs2::device_list all_device_list = ctx.query_devices();
if (all_device_list.size() == 0) {
std::cout << "\nLibrealsense is not detecting any devices" << std::endl;
return EXIT_FAILURE;
};
std::vector<rs2::device> rs_device_list;
//Ensure that diviceList only has realsense devices in it. tmpList contains webcams as well
for (uint32_t i = 0; i < all_device_list.size(); i++) {
try {
all_device_list[i].get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);
rs_device_list.push_back(all_device_list[i]);
}
catch (...) {
continue;
}
}
auto num_rs_devices = rs_device_list.size();
if (rs_device_list.size() == 0) {
std::cout << "\nLibrealsense is not detecting any Realsense cameras" << std::endl;
return EXIT_FAILURE;
};
auto xml_full_file_path = xml_arg.getValue();
map<string, xml_parser_function> format_type_to_lambda;
commands_xml cmd_xml;
auto is_application_in_hex_mode = true;
if (!xml_full_file_path.empty())
{
auto sts = parse_xml_from_file(xml_full_file_path, cmd_xml);
if (!sts)
{
cout << "Commands dictionary " << xml_full_file_path << " is invalid, aborting!\n";
return EXIT_FAILURE;
}
update_format_type_to_lambda(format_type_to_lambda);
is_application_in_hex_mode = false;
cout << "Commands XML file - " << xml_full_file_path << " was loaded successfully.\n Type commands by name (e.g.'gvd'`).\n";
}
else
{
cout << "Commands XML file not provided.\nyou still can send raw data to device in hexadecimal\nseparated by spaces.\n";
cout << "Example GVD command for the SR3XX:\n14 00 ab cd 3b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n";
cout << "Example GVD command for the D4XX:\n14 00 ab cd 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n";
}
auto auto_comp = get_auto_complete_obj(is_application_in_hex_mode, cmd_xml.commands);
std::vector<rs2::device> selected_rs_devices;
while (true)
{
if (all_devices_arg.isSet()) {
for (size_t i = 0; i < num_rs_devices; i++) {
std::string sn = std::string(rs_device_list[i].get_info(RS2_CAMERA_INFO_SERIAL_NUMBER));
selected_rs_devices.push_back(rs_device_list[i]);
std::cout << "\nDevice with Serial Number: " << rs_device_list[i].get_info(RS2_CAMERA_INFO_SERIAL_NUMBER) << " has loaded.\n";
}
}
else if (specific_SN_arg.isSet()) {
auto desired_sn = specific_SN_arg.getValue();
bool device_not_found = true;
for (size_t i = 0; i < num_rs_devices; i++) {
std::string device_sn = std::string(rs_device_list[i].get_info(RS2_CAMERA_INFO_SERIAL_NUMBER));
if (device_sn.compare(desired_sn) == 0) { //std::compare returns 0 if the strings are the same
selected_rs_devices.push_back(rs_device_list[i]);
device_not_found = false;
std::cout << "\nDevice with SN: " << device_sn << " has loaded.\n";
break;
}
}
if (device_not_found) {
std::cout << "\nGiven device serial number doesn't exist! desired serial number=" << desired_sn << std::endl;
return EXIT_FAILURE;
}
}
else if (device_id_arg.isSet())
{
auto dev_id = device_id_arg.getValue();
if (num_rs_devices < (dev_id + 1))
{
std::cout << "\nGiven device_id doesn't exist! device_id=" <<
dev_id << " ; connected devices=" << num_rs_devices << std::endl;
return EXIT_FAILURE;
}
for (int i = 0; i < (num_rs_devices - 1); ++i)
{
wait_for_device(hub, true);
}
selected_rs_devices.push_back(rs_device_list[dev_id]);
std::cout << "\nDevice ID " << dev_id << " has loaded.\n";
}
else if (rs_device_list.size() == 1)
{
selected_rs_devices.push_back(rs_device_list[0]);
}
else
{
std::cout << "\nEnter a command line option:" << std::endl;
std::cout << "-d to choose by device number" << std::endl;
std::cout << "-n to choose by serial number" << std::endl;
std::cout << "-a to send to all devices" << std::endl;
return EXIT_FAILURE;
}
if (selected_rs_devices.empty()) {
std::cout << "\nNo devices were selected. Recheck input arguments" << std::endl;
return EXIT_FAILURE;
}
fflush(nullptr);
if (hex_cmd_arg.isSet())
{
for (auto dev : selected_rs_devices) {
auto line = hex_cmd_arg.getValue();
try
{
hex_mode(line, dev);
}
catch (const exception& ex)
{
cout << endl << ex.what() << endl;
continue;
}
}
return EXIT_SUCCESS;
}
std::string script_file("");
vector<string> script_lines;
if (hex_script_arg.isSet())
{
script_file = hex_script_arg.getValue();
}
else if (commands_script_arg.isSet())
{
script_file = commands_script_arg.getValue();
}
if (!script_file.empty())
{
read_script_file(script_file, script_lines);
cout << "Executing the following command from script file " << script_file << endl;
for (auto& ln : script_lines)
cout << utilities::string::to_upper(ln) << endl;
cout << endl;
}
if (hex_script_arg.isSet())
{
for (auto& dev : selected_rs_devices) {
try
{
for (auto& elem : script_lines)
hex_mode(elem, dev);
}
catch (const exception& ex)
{
cout << endl << ex.what() << endl;
continue;
}
}
return EXIT_SUCCESS;
}
if (commands_script_arg.isSet())
{
for (auto dev : selected_rs_devices) {
try
{
for (auto& elem : script_lines)
xml_mode(elem, cmd_xml, dev, format_type_to_lambda);
}
catch (const exception& ex)
{
cout << endl << ex.what() << endl;
continue;
}
}
return EXIT_SUCCESS;
}
auto dev = selected_rs_devices[0];
while (hub.is_connected(dev))
{
try
{
cout << "\n\n#>";
fflush(nullptr);
string line = "";
line = auto_comp.get_line([&]() {return !hub.is_connected(dev); });
if (!hub.is_connected(dev))
continue;
if (line == "next")
{
dev = wait_for_device(hub);
continue;
}
if (line == "exit")
{
return EXIT_SUCCESS;
}
for (auto&& dev : selected_rs_devices)
{
if (!hub.is_connected(dev))
continue;
if (is_application_in_hex_mode)
{
hex_mode(line, dev);
}
else
{
xml_mode(line, cmd_xml, dev, format_type_to_lambda);
}
cout << endl;
}
}
catch (const rs2::error & e)
{
cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << endl;
}
catch (const exception & e)
{
cerr << e.what() << endl;
}
}
}
}