Apollo 11.0
自动驾驶开放平台
hmi.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <string>
20#include <vector>
21#include <utility>
22
23#include "google/protobuf/util/json_util.h"
24
25#include "modules/dreamview/proto/preprocess_table.pb.h"
26
27#include "cyber/common/file.h"
33
34namespace apollo {
35namespace dreamview {
36
39using google::protobuf::util::JsonStringToMessage;
41
42HMI::HMI(WebSocketHandler* websocket, MapService* map_service,
43 WebSocketHandler* hmi_websocket)
44 : monitor_log_buffer_(apollo::common::monitor::MonitorMessageItem::HMI),
45 hmi_worker_(new HMIWorker(monitor_log_buffer_)),
46 websocket_(websocket),
47 map_service_(map_service),
48 hmi_ws_(hmi_websocket) {
49 if (websocket_) {
50 RegisterDBMessageHandlers();
51 RegisterMessageHandlers();
52 }
53}
54
55void HMI::StartStream(const double& time_interval_ms,
56 const std::string& channel_name,
57 nlohmann::json* subscribe_param) {
58 AINFO << "Start HMIStatus updater timer with data sending frequency: "
59 << time_interval_ms;
60 time_interval_ms_ = time_interval_ms;
61 if (time_interval_ms_ > 0) {
62 timer_.reset(new cyber::Timer(
63 time_interval_ms, [this]() { this->OnTimer(); }, false));
64 timer_->Start();
65 } else {
66 this->OnTimer();
67 }
68}
69
70void HMI::Start(DvCallback callback_api) { hmi_worker_->Start(callback_api); }
71
72void HMI::Stop() { hmi_worker_->Stop(); }
73
74void HMI::StopStream(const std::string& channel_name) {
75 AINFO << "HMIStatus updater timer has been stopped";
76 if (timer_) {
77 timer_->Stop();
78 }
79}
80
81void HMI::RegisterDBMessageHandlers() {
82 websocket_->RegisterMessageHandler(
83 "AddOrModifyObjectToDB",
84 [this](const Json& json, WebSocketHandler::Connection* conn) {
85 Json response;
86 response["action"] = "response";
87 std::string request_id;
88 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
89 AERROR
90 << "Failed to add or modify object to DB: requestId not found.";
91 response["data"]["info"]["code"] = -1;
92 response["data"]["info"]["message"] = "Miss requestId";
93 websocket_->SendData(conn, response.dump());
94 return;
95 }
96 response["data"]["requestId"] = request_id;
97 std::string key, value;
98 if (!JsonUtil::GetStringByPath(json, "data.info.key", &key)) {
99 AERROR << "Failed to add or modify object to DB: key not found.";
100 response["data"]["info"]["code"] = -1;
101 response["data"]["info"]["message"] = "Miss key";
102 websocket_->SendData(conn, response.dump());
103 return;
104 } else if (!JsonUtil::GetStringByPath(json, "data.info.value",
105 &value)) {
106 AERROR << "Failed to add or modify object to DB: value not found.";
107 response["data"]["info"]["code"] = -1;
108 response["data"]["info"]["message"] = "Miss value";
109 websocket_->SendData(conn, response.dump());
110 return;
111 }
112 bool ret = hmi_worker_->AddOrModifyObjectToDB(key, value);
113 if (ret) {
114 response["data"]["info"]["code"] = 0;
115 response["data"]["info"]["message"] = "Success";
116 } else {
117 response["data"]["info"]["code"] = -1;
118 response["data"]["info"]["message"] =
119 "Failed to add or modify object to DB";
120 }
121 websocket_->SendData(conn, response.dump());
122 });
123
124 websocket_->RegisterMessageHandler(
125 "GetObjectFromDB",
126 [this](const Json& json, WebSocketHandler::Connection* conn) {
127 Json response;
128 response["action"] = "response";
129 std::string request_id;
130 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
131 AERROR << "Failed to get object from DB: requestId not found.";
132 response["data"]["info"]["code"] = -1;
133 response["data"]["info"]["message"] = "Miss requestId";
134 websocket_->SendData(conn, response.dump());
135 return;
136 }
137 response["data"]["requestId"] = request_id;
138 std::string key, value;
139 if (!JsonUtil::GetStringByPath(json, "data.info.key", &key)) {
140 AERROR << "Failed to get object from DB: key not found.";
141 response["data"]["info"]["code"] = -1;
142 response["data"]["info"]["message"] = "Miss key";
143 websocket_->SendData(conn, response.dump());
144 return;
145 }
146 std::string ret = hmi_worker_->GetObjectFromDB(key);
147 response["data"]["info"]["data"] = ret;
148 response["data"]["info"]["code"] = 0;
149 response["data"]["info"]["message"] = "Success";
150 websocket_->SendData(conn, response.dump());
151 });
152
153 websocket_->RegisterMessageHandler(
154 "DeleteObjectToDB",
155 [this](const Json& json, WebSocketHandler::Connection* conn) {
156 Json response;
157 response["action"] = "response";
158 std::string request_id;
159 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
160 AERROR << "Failed to delete object to DB: requestId not found.";
161 response["data"]["info"]["code"] = -1;
162 response["data"]["info"]["message"] = "Miss requestId";
163 websocket_->SendData(conn, response.dump());
164 return;
165 }
166 response["data"]["requestId"] = request_id;
167 std::string key, value;
168 if (!JsonUtil::GetStringByPath(json, "data.info.key", &key)) {
169 AERROR << "Failed to delete object to DB: key not found.";
170 response["data"]["info"]["code"] = -1;
171 response["data"]["info"]["message"] = "Miss key";
172 websocket_->SendData(conn, response.dump());
173 return;
174 }
175 bool ret = hmi_worker_->DeleteObjectToDB(key);
176 if (ret) {
177 response["data"]["info"]["code"] = 0;
178 response["data"]["info"]["message"] = "Success";
179 } else {
180 response["data"]["info"]["code"] = -1;
181 response["data"]["info"]["message"] = "Failed to delete object to DB";
182 }
183 websocket_->SendData(conn, response.dump());
184 });
185
186 websocket_->RegisterMessageHandler(
187 "GetTuplesWithTypeFromDB",
188 [this](const Json& json, WebSocketHandler::Connection* conn) {
189 Json response;
190 response["action"] = "response";
191 std::string request_id;
192 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
193 AERROR
194 << "Failed to get tuples with type from DB: requestId not found.";
195 response["data"]["info"]["code"] = -1;
196 response["data"]["info"]["message"] = "Miss requestId";
197 websocket_->SendData(conn, response.dump());
198 return;
199 }
200 response["data"]["requestId"] = request_id;
201 std::string type;
202 if (!JsonUtil::GetStringByPath(json, "data.info.type", &type)) {
203 AERROR << "Failed to get tuples with type from DB: type not found.";
204 response["data"]["info"]["code"] = -1;
205 response["data"]["info"]["message"] = "Miss type";
206 websocket_->SendData(conn, response.dump());
207 return;
208 }
209 auto ret = hmi_worker_->GetTuplesWithTypeFromDB(type);
210 Json tuples = Json::array();
211 for (const auto& item : ret) {
212 Json tuple;
213 tuple["key"] = item.first;
214 tuple["value"] = item.second;
215 tuples.push_back(tuple);
216 }
217 response["data"]["info"]["data"] = tuples;
218 response["data"]["info"]["code"] = 0;
219 response["data"]["info"]["message"] = "Success";
220 websocket_->SendData(conn, response.dump());
221 });
222}
223
224void HMI::RegisterMessageHandlers() {
225 // Send current status and vehicle param to newly joined client.
226 // websocket_->RegisterConnectionReadyHandler(
227 // [this](WebSocketHandler::Connection* conn) {
228 // // SendStatus(conn);
229 // SendVehicleParam(conn);
230 // });
231
232 websocket_->RegisterMessageHandler(
233 "HMIAction",
234 [this](const Json& json, WebSocketHandler::Connection* conn) {
235 // Run HMIWorker::Trigger(action) if json is {action: "<action>"}
236 // Run HMIWorker::Trigger(action, value) if "value" field is provided.
237
238 // response is used for interfaces that require a reply
239 Json response;
240 response["action"] = "response";
241 std::string request_id;
242 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
243 AERROR << "Failed to start hmi action: requestId not found.";
244 response["data"]["info"]["code"] = -1;
245 response["data"]["info"]["message"] = "Miss requestId";
246 websocket_->SendData(conn, response.dump());
247 return;
248 }
249 response["data"]["requestId"] = request_id;
250
251 std::string action;
252 if (!JsonUtil::GetStringByPath(json, "data.info.action", &action)) {
253 AERROR << "Truncated HMIAction request.";
254 return;
255 }
256 HMIAction hmi_action;
257 if (!HMIAction_Parse(action, &hmi_action)) {
258 AERROR << "Invalid HMIAction string: " << action;
259 return;
260 }
261 bool is_ok = false;
262 std::string value;
263 if (JsonUtil::GetStringByPath(json, "data.info.value", &value)) {
264 is_ok = hmi_worker_->Trigger(hmi_action, value);
265 } else {
266 is_ok = hmi_worker_->Trigger(hmi_action);
267 }
268
269 // Extra works for current Dreamview.
270 if (hmi_action == HMIAction::CHANGE_VEHICLE) {
271 // Reload lidar params for point cloud service.
272 SendVehicleParam();
273 } else if (hmi_action == HMIAction::CHANGE_MAP) {
274 response["data"]["info"]["data"]["isOk"] = is_ok;
275 response["data"]["info"]["code"] = 0;
276 response["data"]["info"]["message"] =
277 is_ok ? "Success" : "Failed to change map";
278 websocket_->SendData(conn, response.dump());
279 } else if (hmi_action == HMIAction::CHANGE_OPERATION ||
280 hmi_action == HMIAction::CHANGE_MODE) {
281 response["data"]["info"]["data"]["isOk"] = true;
282 response["data"]["info"]["code"] = 0;
283 response["data"]["info"]["message"] = "Success";
284 websocket_->SendData(conn, response.dump());
285 }
286 });
287
288 // HMI client asks for adding new AudioEvent.
289 websocket_->RegisterMessageHandler(
290 "SubmitAudioEvent",
291 [this](const Json& json, WebSocketHandler::Connection* conn) {
292 // json should contain event_time_ms, obstacle_id, audio_type,
293 // moving_result, audio_direction and is_siren_on.
294 uint64_t event_time_ms;
295 int obstacle_id;
296 int audio_type;
297 int moving_result;
298 int audio_direction;
299 bool is_siren_on;
300 if (JsonUtil::GetNumber(json, "event_time_ms", &event_time_ms) &&
301 JsonUtil::GetNumber(json, "obstacle_id", &obstacle_id) &&
302 JsonUtil::GetNumber(json, "audio_type", &audio_type) &&
303 JsonUtil::GetNumber(json, "moving_result", &moving_result) &&
304 JsonUtil::GetNumber(json, "audio_direction", &audio_direction) &&
305 JsonUtil::GetBoolean(json, "is_siren_on", &is_siren_on)) {
306 hmi_worker_->SubmitAudioEvent(event_time_ms, obstacle_id, audio_type,
307 moving_result, audio_direction,
308 is_siren_on);
309 monitor_log_buffer_.INFO("Audio event added.");
310 } else {
311 AERROR << "Truncated SubmitAudioEvent request.";
312 monitor_log_buffer_.WARN("Failed to submit an audio event.");
313 }
314 });
315
316 // HMI client asks for adding new DriveEvent.
317 websocket_->RegisterMessageHandler(
318 "SubmitDriveEvent",
319 [this](const Json& json, WebSocketHandler::Connection* conn) {
320 // json should contain event_time_ms and event_msg.
321 uint64_t event_time_ms;
322 std::string event_msg;
323 std::vector<std::string> event_types;
324 bool is_reportable;
325 if (JsonUtil::GetNumber(json, "event_time_ms", &event_time_ms) &&
326 JsonUtil::GetString(json, "event_msg", &event_msg) &&
327 JsonUtil::GetStringVector(json, "event_type", &event_types) &&
328 JsonUtil::GetBoolean(json, "is_reportable", &is_reportable)) {
329 hmi_worker_->SubmitDriveEvent(event_time_ms, event_msg, event_types,
330 is_reportable);
331 monitor_log_buffer_.INFO("Drive event added.");
332 } else {
333 AERROR << "Truncated SubmitDriveEvent request.";
334 monitor_log_buffer_.WARN("Failed to submit a drive event.");
335 }
336 });
337
338 websocket_->RegisterMessageHandler(
339 "StartPlayRecorder",
340 [this](const Json& json, WebSocketHandler::Connection* conn) {
341 std::string request_id;
342 Json response({});
343 response["action"] = "response";
344 Json info({});
345 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
346 // 失败情况
347 info["code"] = -1;
348 info["message"] = "Miss requestId";
349 AERROR << "Miss required field requestId to execute play recorder "
350 "action.";
351
352 } else {
353 bool exec_action_result = hmi_worker_->RePlayRecord();
354 info["code"] = exec_action_result ? 0 : -1;
355 if (!exec_action_result) {
356 info["message"] = "Failed to start play recorder";
357 }
358 }
359 response["data"]["info"] = info;
360 if (!request_id.empty()) {
361 response["data"]["requestId"] = request_id;
362 }
363 websocket_->SendData(conn, response.dump());
364 });
365
366 websocket_->RegisterMessageHandler(
367 "ResetRecordProgress",
368 [this](const Json& json, WebSocketHandler::Connection* conn) {
369 std::string request_id;
370 std::string progress_str;
371 Json response({});
372 response["action"] = "response";
373 Json info({});
374 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
375 info["code"] = -1;
376 info["message"] = "Miss requestId";
377 AERROR << "Miss required field requestId to execute play recorder "
378 "action.";
379
380 } else if (!JsonUtil::GetStringByPath(json, "data.info.progress",
381 &progress_str)) {
382 info["code"] = -1;
383 info["message"] = "Miss progress";
384 AERROR << "Miss required field progress to reset record progress.";
385 } else {
386 double progress;
387 bool valid_progress = true;
388 try {
389 progress = std::stod(progress_str);
390 AINFO << "Progress: " << progress;
391 } catch (const std::invalid_argument& ia) {
392 AERROR << "Invalid argument progress: " << progress_str;
393 valid_progress = false;
394 } catch (const std::out_of_range& e) {
395 AERROR << "Argument is out of range: " << progress_str;
396 valid_progress = false;
397 }
398 if (valid_progress) {
399 bool result = hmi_worker_->ResetRecordProgress(progress);
400 info["code"] = result ? 0 : -1;
401 if (!result) {
402 info["message"] = "Failed to start play recorder";
403 }
404 } else {
405 info["code"] = -1;
406 info["message"] = "Failed to get proress value";
407 }
408 }
409 response["data"]["info"] = info;
410 if (!request_id.empty()) {
411 response["data"]["requestId"] = request_id;
412 }
413 websocket_->SendData(conn, response.dump());
414 });
415
416 websocket_->RegisterMessageHandler(
417 "PlayRecorderAction",
418 [this](const Json& json, WebSocketHandler::Connection* conn) {
419 std::string request_id;
420 std::string action_type;
421 double progress;
422 Json response({});
423 response["action"] = "response";
424 Json info({});
425 if (!JsonUtil::GetStringByPath(json, "data.info.actionType",
426 &action_type)) {
427 info["code"] = -1;
428 info["message"] = "Error param";
429 AERROR << "Failed to get param to execute play recorder action.";
430 } else if (!JsonUtil::GetStringByPath(json, "data.requestId",
431 &request_id)) {
432 // 失败情况
433 info["code"] = -1;
434 info["message"] = "Miss requestId";
435 AERROR << "Miss required field requestId to execute play recorder "
436 "action.";
437
438 } else if (action_type.compare("continue") == 0 &&
439 !JsonUtil::GetNumberByPath(json, "data.info.progress",
440 &progress)) {
441 AERROR << "Miss required field progress to continue play record!";
442 info["code"] = -1;
443 info["message"] = "Miss progress";
444 } else {
445 bool exec_action_result =
446 hmi_worker_->handlePlayRecordProcess(action_type);
447 info["code"] = exec_action_result ? 0 : -1;
448 if (!exec_action_result) {
449 info["message"] =
450 "Failed to execute play recorder action: " + action_type;
451 }
452 }
453 response["data"]["info"] = info;
454 if (!request_id.empty()) {
455 response["data"]["requestId"] = request_id;
456 }
457 websocket_->SendData(conn, response.dump());
458 });
459
460 websocket_->RegisterMessageHandler(
461 "StartDataRecorder",
462 [this](const Json& json, WebSocketHandler::Connection* conn) {
463 Json response;
464 response["action"] = "response";
465 std::string request_id;
466 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
467 AERROR << "Failed to start data recorder: requestId not found.";
468 response["data"]["info"]["code"] = -1;
469 response["data"]["info"]["message"] = "Miss requestId";
470 websocket_->SendData(conn, response.dump());
471 return;
472 }
473 response["data"]["requestId"] = request_id;
474 bool ret;
475 if (hmi_worker_->GetStatus().current_operation() ==
476 HMIModeOperation::Waypoint_Follow) {
477 ret = hmi_worker_->StartRtkDataRecorder();
478 } else {
479 ret = hmi_worker_->StartDataRecorder();
480 }
481 if (ret) {
482 response["data"]["info"]["code"] = 0;
483 response["data"]["info"]["message"] = "Success";
484 } else {
485 response["data"]["info"]["code"] = -1;
486 response["data"]["info"]["message"] =
487 "Failed to start data recorder:Failed to start the "
488 "cyber_recorder process";
489 }
490 websocket_->SendData(conn, response.dump());
491 });
492
493 websocket_->RegisterMessageHandler(
494 "StopDataRecorder",
495 [this](const Json& json, WebSocketHandler::Connection* conn) {
496 Json response;
497 response["action"] = "response";
498 std::string request_id;
499 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
500 AERROR << "Failed to start data recorder: requestId not found.";
501 response["data"]["info"]["code"] = -1;
502 response["data"]["info"]["message"] = "Miss requestId";
503 websocket_->SendData(conn, response.dump());
504 return;
505 }
506 response["data"]["requestId"] = request_id;
507 bool ret;
508 if (hmi_worker_->GetStatus().current_operation() ==
509 HMIModeOperation::Waypoint_Follow) {
510 ret = hmi_worker_->StopRtkDataRecorder();
511 } else {
512 ret = hmi_worker_->StopDataRecorder();
513 }
514 if (ret) {
515 response["data"]["info"]["code"] = 0;
516 response["data"]["info"]["message"] = "Success";
517 } else {
518 response["data"]["info"]["code"] = -1;
519 response["data"]["info"]["message"] =
520 "Failed to stop data recorder: failed to stop the cyber_recorder "
521 "process";
522 }
523 websocket_->SendData(conn, response.dump());
524 });
525
526 websocket_->RegisterMessageHandler(
527 "StartPlayRtkRecorder",
528 [this](const Json& json, WebSocketHandler::Connection* conn) {
529 Json response;
530 response["action"] = "response";
531 std::string request_id;
532 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
533 AERROR << "Failed to start data recorder: requestId not found.";
534 response["data"]["info"]["code"] = -1;
535 response["data"]["info"]["message"] = "Miss requestId";
536 websocket_->SendData(conn, response.dump());
537 return;
538 }
539 response["data"]["requestId"] = request_id;
540 if (hmi_worker_->GetStatus().current_operation() !=
541 HMIModeOperation::Waypoint_Follow) {
542 response["data"]["info"]["code"] = -1;
543 response["data"]["info"]["message"] =
544 "The current operation is not a Waypoint_ Follow";
545 }
546 Json result = hmi_worker_->StartPlayRtkRecorder();
547 response["data"]["info"]["code"] = result["isOk"] ? 0 : -1;
548 response["data"]["info"]["message"] =
549 result["isOk"] ? "Success" : result["error"];
550 websocket_->SendData(conn, response.dump());
551 });
552
553 websocket_->RegisterMessageHandler(
554 "StopPlayRtkRecorder",
555 [this](const Json& json, WebSocketHandler::Connection* conn) {
556 Json response;
557 response["action"] = "response";
558 std::string request_id;
559 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
560 AERROR << "Failed to start data recorder: requestId not found.";
561 response["data"]["info"]["code"] = -1;
562 response["data"]["info"]["message"] = "Miss requestId";
563 websocket_->SendData(conn, response.dump());
564 return;
565 }
566 response["data"]["requestId"] = request_id;
567 if (hmi_worker_->GetStatus().current_operation() !=
568 HMIModeOperation::Waypoint_Follow) {
569 response["data"]["info"]["code"] = -1;
570 response["data"]["info"]["message"] =
571 "The current operation is not a Waypoint_ Follow";
572 }
573 bool ret = hmi_worker_->StopPlayRtkRecorder();
574 if (ret) {
575 response["data"]["info"]["code"] = 0;
576 response["data"]["info"]["message"] = "Success";
577 } else {
578 response["data"]["info"]["code"] = -1;
579 response["data"]["info"]["message"] =
580 "Failed to stop play data recorder process";
581 }
582 websocket_->SendData(conn, response.dump());
583 });
584
585 websocket_->RegisterMessageHandler(
586 "SaveDataRecorder",
587 [this](const Json& json, WebSocketHandler::Connection* conn) {
588 Json response;
589 response["action"] = "response";
590 std::string request_id, new_name;
591 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
592 AERROR << "Failed to save record: requestId not found.";
593 response["data"]["info"]["code"] = -1;
594 response["data"]["info"]["message"] = "Miss requestId";
595 websocket_->SendData(conn, response.dump());
596 return;
597 } else if (!JsonUtil::GetStringByPath(json, "data.info.newName",
598 &new_name)) {
599 AERROR << "Failed to save record: newName not found.";
600 response["data"]["info"]["code"] = -1;
601 response["data"]["info"]["message"] = "Miss newName";
602 websocket_->SendData(conn, response.dump());
603 return;
604 }
605 response["data"]["requestId"] = request_id;
606 int ret;
607 if (hmi_worker_->GetStatus().current_operation() ==
608 HMIModeOperation::Waypoint_Follow) {
609 ret = hmi_worker_->SaveRtkDataRecorder(new_name);
610 } else {
611 ret = hmi_worker_->SaveDataRecorder(new_name);
612 }
613 if (ret == 1) {
614 response["data"]["info"]["code"] = 0;
615 response["data"]["info"]["message"] = "Success";
616 } else if (ret == -1) {
617 response["data"]["info"]["code"] = -1;
618 response["data"]["info"]["message"] =
619 "Failed to save record: a file with the same name exists";
620 } else if (ret == -2) {
621 response["data"]["info"]["code"] = -1;
622 response["data"]["info"]["message"] =
623 "Failed to save the record: the dreamview recording record does "
624 "not exist, please record through dreamview";
625 } else {
626 response["data"]["info"]["code"] = -1;
627 response["data"]["info"]["message"] =
628 "Failed to save record: please try again or check whether your "
629 "record is legal";
630 }
631 websocket_->SendData(conn, response.dump());
632 });
633
634 websocket_->RegisterMessageHandler(
635 "DeleteDataRecorder",
636 [this](const Json& json, WebSocketHandler::Connection* conn) {
637 Json response;
638 response["action"] = "response";
639 std::string request_id;
640 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
641 AERROR << "Failed to start data recorder: requestId not found.";
642 response["data"]["info"]["code"] = -1;
643 response["data"]["info"]["message"] = "Miss requestId";
644 websocket_->SendData(conn, response.dump());
645 return;
646 }
647 response["data"]["requestId"] = request_id;
648 bool ret;
649 if (hmi_worker_->GetStatus().current_operation() ==
650 HMIModeOperation::Waypoint_Follow) {
651 ret = hmi_worker_->DeleteRtkDataRecorder();
652 } else {
653 ret = hmi_worker_->DeleteDataRecorder();
654 }
655 if (ret) {
656 response["data"]["info"]["code"] = 0;
657 response["data"]["info"]["message"] = "Success";
658 } else {
659 response["data"]["info"]["code"] = -1;
660 response["data"]["info"]["message"] = "Failed to delete the record";
661 }
662 websocket_->SendData(conn, response.dump());
663 });
664
665 // To speed up the preloading process, fetching from hmi is relatively slow.
666 websocket_->RegisterMessageHandler(
667 "GetInitData",
668 [this](const Json& json, WebSocketHandler::Connection* conn) {
669 Json response;
670 response["action"] = "response";
671 std::string request_id;
672 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
673 AERROR << "Failed to get current mode: requestId not found.";
674 response["data"]["info"]["code"] = -1;
675 response["data"]["info"]["message"] = "Miss requestId";
676 websocket_->SendData(conn, response.dump());
677 return;
678 }
679 response["data"]["requestId"] = request_id;
680 std::string current_mode = hmi_worker_->GetStatus().current_mode();
681 auto current_operation = hmi_worker_->GetStatus().current_operation();
682 response["data"]["info"]["data"]["currentMode"] = current_mode;
683 response["data"]["info"]["data"]["currentOperation"] =
684 HMIModeOperation_Name(current_operation);
685 response["data"]["info"]["code"] = 0;
686 response["data"]["info"]["message"] = "Success";
687 websocket_->SendData(conn, response.dump());
688 });
689
690 websocket_->RegisterMessageHandler(
691 "StartTerminal",
692 [this](const Json& json, WebSocketHandler::Connection* conn) {
693 Json response;
694 response["action"] = "response";
695 std::string request_id;
696 if (!JsonUtil::GetStringByPath(json, "data.requestId", &request_id)) {
697 AERROR << "Failed to start terminal: requestId not found.";
698 response["data"]["info"]["code"] = -1;
699 response["data"]["info"]["message"] = "Miss requestId";
700 websocket_->SendData(conn, response.dump());
701 return;
702 }
703 response["data"]["requestId"] = request_id;
704 bool ret = hmi_worker_->StartTerminal();
705 if (ret) {
706 response["data"]["info"]["code"] = 0;
707 response["data"]["info"]["message"] = "Success";
708 } else {
709 response["data"]["info"]["code"] = -1;
710 response["data"]["info"]["message"] = "Failed to start terminal";
711 }
712 websocket_->SendData(conn, response.dump());
713 });
714}
715
716void HMI::SendVehicleParam(WebSocketHandler::Connection* conn) {
717 if (websocket_ == nullptr) {
718 return;
719 }
720
721 const auto& vehicle_param =
723 const std::string json_str =
724 JsonUtil::ProtoToTypedJson("VehicleParam", vehicle_param).dump();
725 if (conn != nullptr) {
726 websocket_->SendData(conn, json_str);
727 } else {
728 websocket_->BroadcastData(json_str);
729 }
730}
731
732void HMI::OnTimer(const std::string& channel_name) { PublishMessage(); }
733
734void HMI::PublishMessage(const std::string& channel_name) {
735 StreamData response;
736 response.set_action("stream");
737 response.set_data_name("hmistatus");
738 std::string hmi_status_str;
739 hmi_worker_->GetStatus().SerializeToString(&hmi_status_str);
740 std::vector<uint8_t> byte_data(hmi_status_str.begin(), hmi_status_str.end());
741 response.set_data(&(byte_data[0]), byte_data.size());
742 response.set_type("hmistatus");
743 std::string response_str;
744 response.SerializeToString(&response_str);
745 hmi_ws_->BroadcastBinaryData(response_str);
746}
747
748bool HMI::UpdateDynamicModelToStatus(const std::string& dynamic_model_name) {
749 return hmi_worker_->UpdateDynamicModelToStatus(dynamic_model_name);
750}
751
752bool HMI::UpdateMapToStatus(const std::string& map_name) {
753 return hmi_worker_->UpdateMapToStatus(map_name);
754}
755
756bool HMI::UpdateRecordToStatus() { return hmi_worker_->LoadRecords(); }
757
758bool HMI::UpdateVehicleToStatus() { return hmi_worker_->ReloadVehicles(); }
759
760bool HMI::UpdateCameraChannelToStatus(const std::string& channel_name) {
761 hmi_worker_->UpdateCameraSensorChannelToStatus(channel_name);
762 return true;
763}
764
765bool HMI::UpdatePointChannelToStatus(const std::string& channel_name) {
766 hmi_worker_->UpdatePointCloudChannelToStatus(channel_name);
767 return true;
768}
769
770bool HMI::isProcessRunning(const std::string& process_name) {
771 return hmi_worker_->isProcessRunning(process_name);
772}
773
774} // namespace dreamview
775} // namespace apollo
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
static bool GetNumber(const nlohmann::json &json, const std::string &key, T *value)
Get a number value from the given json[key].
Definition json_util.h:59
static bool GetStringVector(const nlohmann::json &json, const std::string &key, std::vector< std::string > *value)
Get a string vector from the given json[key].
Definition json_util.cc:109
static bool GetStringByPath(const nlohmann::json &json, const std::string &path, std::string *value)
Get a string value from the given json and path.
Definition json_util.cc:97
static nlohmann::json ProtoToTypedJson(const std::string &json_type, const google::protobuf::Message &proto)
Convert proto to a json string.
Definition json_util.cc:37
static bool GetBoolean(const nlohmann::json &json, const std::string &key, bool *value)
Get a boolean value from the given json[key].
Definition json_util.cc:137
static bool GetNumberByPath(const nlohmann::json &json, const std::string &path, T *value)
Get a number value from the given json and path.
Definition json_util.h:120
static bool GetString(const nlohmann::json &json, const std::string &key, std::string *value)
Get a string value from the given json[key].
Definition json_util.cc:58
Used to perform oneshot or periodic timing tasks
Definition timer.h:71
void StopStream(const std::string &channel_name="") override
Stop data flow.
Definition hmi.cc:74
HMI(WebSocketHandler *websocket, MapService *map_service)
Definition hmi.cc:42
void OnTimer(const std::string &channel_name="")
Definition hmi.cc:732
void StartStream(const double &time_interval_ms, const std::string &channel_name="", nlohmann::json *subscribe_param=nullptr) override
Start data flow.
Definition hmi.cc:55
bool UpdateMapToStatus(const std::string &map_name="")
Definition hmi.cc:752
bool UpdateDynamicModelToStatus(const std::string &dynamic_model_name)
Definition hmi.cc:243
bool UpdatePointChannelToStatus(const std::string &channel_name)
Definition hmi.cc:256
bool UpdateRecordToStatus()
Definition hmi.cc:247
bool UpdateCameraChannelToStatus(const std::string &channel_name)
Definition hmi.cc:251
void PublishMessage(const std::string &channel_name="") override
Publish Message to dreamview frontend.
Definition hmi.cc:734
bool isProcessRunning(const std::string &process_name)
Definition hmi.cc:770
void Start(DvCallback callback_api)
Definition hmi.cc:52
bool UpdateVehicleToStatus()
Definition hmi.cc:249
The WebSocketHandler, built on top of CivetWebSocketHandler, is a websocket handler that handles diff...
bool BroadcastData(const std::string &data, bool skippable=false)
Sends the provided data to all the connected clients.
bool BroadcastBinaryData(const std::string &data, bool skippable=false)
Sends the provided binary data to all the connected clients.
void RegisterMessageHandler(std::string type, MessageHandler handler)
Add a new message handler for a message type.
bool SendData(Connection *conn, const std::string &data, bool skippable=false, int op_code=MG_WEBSOCKET_OPCODE_TEXT)
Sends the provided data to a specific connected client.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
nlohmann::json Json
bool SetProtoToASCIIFile(const google::protobuf::Message &message, int file_descriptor)
Definition file.cc:43
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param