23#include "google/protobuf/util/json_util.h"
25#include "modules/dreamview/proto/preprocess_table.pb.h"
39using google::protobuf::util::JsonStringToMessage;
45 hmi_worker_(new
HMIWorker(monitor_log_buffer_)),
46 websocket_(websocket),
47 map_service_(map_service),
48 hmi_ws_(hmi_websocket) {
50 RegisterDBMessageHandlers();
51 RegisterMessageHandlers();
56 const std::string& channel_name,
57 nlohmann::json* subscribe_param) {
58 AINFO <<
"Start HMIStatus updater timer with data sending frequency: "
60 time_interval_ms_ = time_interval_ms;
61 if (time_interval_ms_ > 0) {
63 time_interval_ms, [
this]() { this->
OnTimer(); },
false));
70void HMI::Start(DvCallback callback_api) { hmi_worker_->Start(callback_api); }
75 AINFO <<
"HMIStatus updater timer has been stopped";
81void HMI::RegisterDBMessageHandlers() {
83 "AddOrModifyObjectToDB",
86 response[
"action"] =
"response";
87 std::string request_id;
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());
96 response[
"data"][
"requestId"] = request_id;
97 std::string key, value;
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());
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());
112 bool ret = hmi_worker_->AddOrModifyObjectToDB(key, value);
114 response[
"data"][
"info"][
"code"] = 0;
115 response[
"data"][
"info"][
"message"] =
"Success";
117 response[
"data"][
"info"][
"code"] = -1;
118 response[
"data"][
"info"][
"message"] =
119 "Failed to add or modify object to DB";
121 websocket_->
SendData(conn, response.dump());
128 response[
"action"] =
"response";
129 std::string 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());
137 response[
"data"][
"requestId"] = request_id;
138 std::string key, value;
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());
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());
157 response[
"action"] =
"response";
158 std::string 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());
166 response[
"data"][
"requestId"] = request_id;
167 std::string key, value;
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());
175 bool ret = hmi_worker_->DeleteObjectToDB(key);
177 response[
"data"][
"info"][
"code"] = 0;
178 response[
"data"][
"info"][
"message"] =
"Success";
180 response[
"data"][
"info"][
"code"] = -1;
181 response[
"data"][
"info"][
"message"] =
"Failed to delete object to DB";
183 websocket_->
SendData(conn, response.dump());
187 "GetTuplesWithTypeFromDB",
190 response[
"action"] =
"response";
191 std::string request_id;
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());
200 response[
"data"][
"requestId"] = request_id;
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());
209 auto ret = hmi_worker_->GetTuplesWithTypeFromDB(type);
210 Json tuples = Json::array();
211 for (
const auto& item : ret) {
213 tuple[
"key"] = item.first;
214 tuple[
"value"] = item.second;
215 tuples.push_back(tuple);
217 response[
"data"][
"info"][
"data"] = tuples;
218 response[
"data"][
"info"][
"code"] = 0;
219 response[
"data"][
"info"][
"message"] =
"Success";
220 websocket_->
SendData(conn, response.dump());
224void HMI::RegisterMessageHandlers() {
240 response[
"action"] =
"response";
241 std::string 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());
249 response[
"data"][
"requestId"] = request_id;
253 AERROR <<
"Truncated HMIAction request.";
257 if (!HMIAction_Parse(action, &hmi_action)) {
258 AERROR <<
"Invalid HMIAction string: " << action;
264 is_ok = hmi_worker_->Trigger(hmi_action, value);
266 is_ok = hmi_worker_->Trigger(hmi_action);
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());
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());
294 uint64_t event_time_ms;
306 hmi_worker_->SubmitAudioEvent(event_time_ms, obstacle_id, audio_type,
307 moving_result, audio_direction,
309 monitor_log_buffer_.INFO(
"Audio event added.");
311 AERROR <<
"Truncated SubmitAudioEvent request.";
312 monitor_log_buffer_.WARN(
"Failed to submit an audio event.");
321 uint64_t event_time_ms;
322 std::string event_msg;
323 std::vector<std::string> event_types;
329 hmi_worker_->SubmitDriveEvent(event_time_ms, event_msg, event_types,
331 monitor_log_buffer_.INFO(
"Drive event added.");
333 AERROR <<
"Truncated SubmitDriveEvent request.";
334 monitor_log_buffer_.WARN(
"Failed to submit a drive event.");
341 std::string request_id;
343 response[
"action"] =
"response";
348 info[
"message"] =
"Miss requestId";
349 AERROR <<
"Miss required field requestId to execute play recorder "
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";
359 response[
"data"][
"info"] = info;
360 if (!request_id.empty()) {
361 response[
"data"][
"requestId"] = request_id;
363 websocket_->
SendData(conn, response.dump());
367 "ResetRecordProgress",
369 std::string request_id;
370 std::string progress_str;
372 response[
"action"] =
"response";
376 info[
"message"] =
"Miss requestId";
377 AERROR <<
"Miss required field requestId to execute play recorder "
383 info[
"message"] =
"Miss progress";
384 AERROR <<
"Miss required field progress to reset record progress.";
387 bool valid_progress =
true;
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;
398 if (valid_progress) {
399 bool result = hmi_worker_->ResetRecordProgress(progress);
400 info[
"code"] = result ? 0 : -1;
402 info[
"message"] =
"Failed to start play recorder";
406 info[
"message"] =
"Failed to get proress value";
409 response[
"data"][
"info"] = info;
410 if (!request_id.empty()) {
411 response[
"data"][
"requestId"] = request_id;
413 websocket_->
SendData(conn, response.dump());
417 "PlayRecorderAction",
419 std::string request_id;
420 std::string action_type;
423 response[
"action"] =
"response";
428 info[
"message"] =
"Error param";
429 AERROR <<
"Failed to get param to execute play recorder action.";
434 info[
"message"] =
"Miss requestId";
435 AERROR <<
"Miss required field requestId to execute play recorder "
438 }
else if (action_type.compare(
"continue") == 0 &&
441 AERROR <<
"Miss required field progress to continue play record!";
443 info[
"message"] =
"Miss progress";
445 bool exec_action_result =
446 hmi_worker_->handlePlayRecordProcess(action_type);
447 info[
"code"] = exec_action_result ? 0 : -1;
448 if (!exec_action_result) {
450 "Failed to execute play recorder action: " + action_type;
453 response[
"data"][
"info"] = info;
454 if (!request_id.empty()) {
455 response[
"data"][
"requestId"] = request_id;
457 websocket_->
SendData(conn, response.dump());
464 response[
"action"] =
"response";
465 std::string 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());
473 response[
"data"][
"requestId"] = request_id;
475 if (hmi_worker_->GetStatus().current_operation() ==
476 HMIModeOperation::Waypoint_Follow) {
477 ret = hmi_worker_->StartRtkDataRecorder();
479 ret = hmi_worker_->StartDataRecorder();
482 response[
"data"][
"info"][
"code"] = 0;
483 response[
"data"][
"info"][
"message"] =
"Success";
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";
490 websocket_->
SendData(conn, response.dump());
497 response[
"action"] =
"response";
498 std::string 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());
506 response[
"data"][
"requestId"] = request_id;
508 if (hmi_worker_->GetStatus().current_operation() ==
509 HMIModeOperation::Waypoint_Follow) {
510 ret = hmi_worker_->StopRtkDataRecorder();
512 ret = hmi_worker_->StopDataRecorder();
515 response[
"data"][
"info"][
"code"] = 0;
516 response[
"data"][
"info"][
"message"] =
"Success";
518 response[
"data"][
"info"][
"code"] = -1;
519 response[
"data"][
"info"][
"message"] =
520 "Failed to stop data recorder: failed to stop the cyber_recorder "
523 websocket_->
SendData(conn, response.dump());
527 "StartPlayRtkRecorder",
530 response[
"action"] =
"response";
531 std::string 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());
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";
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());
554 "StopPlayRtkRecorder",
557 response[
"action"] =
"response";
558 std::string 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());
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";
573 bool ret = hmi_worker_->StopPlayRtkRecorder();
575 response[
"data"][
"info"][
"code"] = 0;
576 response[
"data"][
"info"][
"message"] =
"Success";
578 response[
"data"][
"info"][
"code"] = -1;
579 response[
"data"][
"info"][
"message"] =
580 "Failed to stop play data recorder process";
582 websocket_->
SendData(conn, response.dump());
589 response[
"action"] =
"response";
590 std::string request_id, new_name;
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());
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());
605 response[
"data"][
"requestId"] = request_id;
607 if (hmi_worker_->GetStatus().current_operation() ==
608 HMIModeOperation::Waypoint_Follow) {
609 ret = hmi_worker_->SaveRtkDataRecorder(new_name);
611 ret = hmi_worker_->SaveDataRecorder(new_name);
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";
626 response[
"data"][
"info"][
"code"] = -1;
627 response[
"data"][
"info"][
"message"] =
628 "Failed to save record: please try again or check whether your "
631 websocket_->
SendData(conn, response.dump());
635 "DeleteDataRecorder",
638 response[
"action"] =
"response";
639 std::string 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());
647 response[
"data"][
"requestId"] = request_id;
649 if (hmi_worker_->GetStatus().current_operation() ==
650 HMIModeOperation::Waypoint_Follow) {
651 ret = hmi_worker_->DeleteRtkDataRecorder();
653 ret = hmi_worker_->DeleteDataRecorder();
656 response[
"data"][
"info"][
"code"] = 0;
657 response[
"data"][
"info"][
"message"] =
"Success";
659 response[
"data"][
"info"][
"code"] = -1;
660 response[
"data"][
"info"][
"message"] =
"Failed to delete the record";
662 websocket_->
SendData(conn, response.dump());
670 response[
"action"] =
"response";
671 std::string 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());
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());
694 response[
"action"] =
"response";
695 std::string 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());
703 response[
"data"][
"requestId"] = request_id;
704 bool ret = hmi_worker_->StartTerminal();
706 response[
"data"][
"info"][
"code"] = 0;
707 response[
"data"][
"info"][
"message"] =
"Success";
709 response[
"data"][
"info"][
"code"] = -1;
710 response[
"data"][
"info"][
"message"] =
"Failed to start terminal";
712 websocket_->
SendData(conn, response.dump());
717 if (websocket_ ==
nullptr) {
721 const auto& vehicle_param =
723 const std::string json_str =
725 if (conn !=
nullptr) {
726 websocket_->
SendData(conn, json_str);
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);
749 return hmi_worker_->UpdateDynamicModelToStatus(dynamic_model_name);
753 return hmi_worker_->UpdateMapToStatus(map_name);
761 hmi_worker_->UpdateCameraSensorChannelToStatus(channel_name);
766 hmi_worker_->UpdatePointCloudChannelToStatus(channel_name);
771 return hmi_worker_->isProcessRunning(process_name);
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].
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].
static bool GetStringByPath(const nlohmann::json &json, const std::string &path, std::string *value)
Get a string value from the given json and path.
static nlohmann::json ProtoToTypedJson(const std::string &json_type, const google::protobuf::Message &proto)
Convert proto to a json string.
static bool GetBoolean(const nlohmann::json &json, const std::string &key, bool *value)
Get a boolean value from the given json[key].
static bool GetNumberByPath(const nlohmann::json &json, const std::string &path, T *value)
Get a number value from the given json and path.
static bool GetString(const nlohmann::json &json, const std::string &key, std::string *value)
Get a string value from the given json[key].
Used to perform oneshot or periodic timing tasks
void StopStream(const std::string &channel_name="") override
Stop data flow.
HMI(WebSocketHandler *websocket, MapService *map_service)
void OnTimer(const std::string &channel_name="")
void StartStream(const double &time_interval_ms, const std::string &channel_name="", nlohmann::json *subscribe_param=nullptr) override
Start data flow.
bool UpdateMapToStatus(const std::string &map_name="")
bool UpdateDynamicModelToStatus(const std::string &dynamic_model_name)
bool UpdatePointChannelToStatus(const std::string &channel_name)
bool UpdateRecordToStatus()
bool UpdateCameraChannelToStatus(const std::string &channel_name)
void PublishMessage(const std::string &channel_name="") override
Publish Message to dreamview frontend.
bool isProcessRunning(const std::string &process_name)
void Start(DvCallback callback_api)
bool UpdateVehicleToStatus()
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.
bool SetProtoToASCIIFile(const google::protobuf::Message &message, int file_descriptor)
optional VehicleParam vehicle_param