Apollo 11.0
自动驾驶开放平台
socket_manager.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 <vector>
20
21#include "cyber/common/file.h"
22#include "cyber/common/log.h"
28namespace apollo {
29namespace dreamview {
30
32using Json = nlohmann::json;
34
35std::map<std::string, std::pair<std::string, std::string>> filter_info = {
36 {"apollo.dreamview.Obstacles", {"perception.PerceptionObstacles", ""}},
37 {"apollo.dreamview.CameraUpdate", {"drivers.Image", ""}},
38 {"apollo.dreamview.PointCloud", {"PointCloud", "sensor"}}};
39
41 UpdaterManager *updater_manager,
42 DvPluginManager *dv_plugin_manager)
43 : enabled_(false),
44 websocket_(websocket),
45 updater_manager_(updater_manager),
46 dv_plugin_manager_(dv_plugin_manager) {
47 RegisterDataHandlers();
48 RegisterMessageHandlers();
49 auto channel_manager =
50 apollo::cyber::service_discovery::TopologyManager::Instance()
51 ->channel_manager();
52 auto topology_callback =
53 [this](const apollo::cyber::proto::ChangeMsg &change_msg) {
54 this->RefreshChannels(change_msg);
55 };
56 channel_manager->AddChangeListener(topology_callback);
57}
58
59void SocketManager::RegisterDataHandlers() {
60 enabled_ = GetProtoFromFile(FLAGS_data_handler_config_path,
61 &data_handler_base_conf_);
62 if (!enabled_) {
63 AERROR << "Unable to parse data handler configuration from file "
64 << FLAGS_data_handler_config_path;
65 }
66 for (auto &data_handler_iter :
67 dv_plugin_manager_->data_handler_conf_.data_handler_info()) {
68 if (data_handler_base_conf_.data_handler_info().find(
69 data_handler_iter.first) !=
70 data_handler_base_conf_.data_handler_info().end()) {
71 AERROR << "There are duplicate updater handlers between dv and plugins";
72 continue;
73 }
74 auto data_handler_info =
75 data_handler_base_conf_.mutable_data_handler_info();
76 (*data_handler_info)[data_handler_iter.first] = data_handler_iter.second;
77 }
78 AINFO << "data_handler_base_conf_: " << data_handler_base_conf_.DebugString();
79
80 // 遍历 然后register
81 // for (const auto& data_handler_iter :
82 // data_handler_base_conf_.data_handler_info()) {
83 // const std::string& data_name = data_handler_iter.first;
84 // const DataHandlerInfo& data_handler_info = data_handler_iter.second;
85 // RegisterDataHandler(data_handler_info);
86 // }
87}
88
89void SocketManager::RegisterMessageHandlers() {
92
93 websocket_->RegisterMessageHandler(
94 "subscribe",
95 [this](const Json &json, WebSocketHandler::Connection *conn) {
96 Json response;
97 response["action"] = "response";
98 response["data"]["info"] = {};
99 response["data"]["info"]["code"] = this->Subscribe(json) ? 0 : -1;
100 websocket_->SendData(conn, response.dump());
101 });
102
103 websocket_->RegisterMessageHandler(
104 "unsubscribe",
105 [this](const Json &json, WebSocketHandler::Connection *conn) {
106 Json response;
107 response["action"] = "response";
108 response["data"]["info"] = {};
109 response["data"]["info"]["code"] = this->UnSubscribe(json) ? 0 : -1;
110 websocket_->SendData(conn, response.dump());
111 });
112}
113
114bool SocketManager::GetDataUpdaterChannels(const std::string &updater_path,
115 std::vector<std::string> *channels) {
116 UpdaterBase *updater = updater_manager_->GetUpdater(updater_path);
117 UpdaterWithChannelsBase *updater_with_channels =
118 dynamic_cast<UpdaterWithChannelsBase *>(updater);
119 if (updater_with_channels == nullptr) {
120 return false;
121 }
122 updater_with_channels->GetChannelMsg(channels);
123 return true;
124}
125
126bool SocketManager::ModifyUpdaterChannels(const std::string &updater_path,
127 const std::string &channel_name,
128 const std::string &operation) {
129 UpdaterBase *updater = updater_manager_->GetUpdater(updater_path);
130 UpdaterWithChannelsBase *updater_with_channels =
131 dynamic_cast<UpdaterWithChannelsBase *>(updater);
132 if (updater_with_channels == nullptr) {
133 return false;
134 }
135 auto iter = std::find(updater_with_channels->channels_.begin(),
136 updater_with_channels->channels_.end(), channel_name);
137 if (operation == "join" && iter == updater_with_channels->channels_.end()) {
138 updater_with_channels->channels_.emplace_back(channel_name);
139 } else if (operation == "leave" &&
140 iter != updater_with_channels->channels_.end()) {
141 updater_with_channels->channels_.erase(iter);
142 }
143 return true;
144}
145
146bool SocketManager::Subscribe(const Json &json) {
147 const std::string url = json["data"]["info"]["websocketName"];
148 double time_interval_ms = 0;
149 JsonUtil::GetNumberByPath(json, "data.info.dataFrequencyMs",
150 &time_interval_ms);
151 std::string channel_name;
152 if (!JsonUtil::GetStringByPath(json, "data.info.channelName",
153 &channel_name)) {
154 channel_name = "";
155 }
156 Json subscribe_param = {};
157 std::vector<std::string> json_path = {"data", "info", "param"};
158 JsonUtil::GetJsonByPath(json, json_path, &subscribe_param);
159 return updater_manager_->Start(url, time_interval_ms, channel_name,
160 &subscribe_param);
161}
162
163bool SocketManager::UnSubscribe(const Json &json) {
164 const std::string url = json["data"]["info"]["websocketName"];
165 std::string channel_name;
166 if (!JsonUtil::GetStringByPath(json, "data.info.channelName",
167 &channel_name)) {
168 channel_name = "";
169 }
170 return updater_manager_->Stop(url, channel_name);
171}
172
173Json SocketManager::ClearDataHandlerChannelMsgs() {
174 Json response_data({});
175 Json data({});
176
177 if (enabled_) {
178 for (auto iter = data_handler_conf_.mutable_data_handler_info()->begin();
179 iter != data_handler_conf_.mutable_data_handler_info()->end();
180 iter++) {
181 if (iter->second.different_for_channels()) {
182 const std::string &data_type = (*iter).first;
183 (*data_handler_conf_.mutable_data_handler_info())[data_type]
184 .clear_channels();
185 }
186 }
187 complete_channel_count_.clear();
188 data_handler_channel_count_.clear();
189 }
190 data = JsonUtil::ProtoToTypedJson("data", data_handler_conf_);
191 data.erase("type");
192 response_data["info"] = data;
193 response_data["info"]["code"] = 0;
194 return response_data;
195}
196
197Json SocketManager::GetDataHandlerInfo() {
198 Json response_data({});
199 Json data({});
200 data_handler_conf_.Clear();
201 data_handler_channel_count_.clear();
202 complete_channel_count_.clear();
203
204 if (enabled_) {
205 for (auto iter =
206 data_handler_base_conf_.mutable_data_handler_info()->begin();
207 iter != data_handler_base_conf_.mutable_data_handler_info()->end();
208 iter++) {
209 const std::string &data_type = (*iter).first;
210 DataHandlerInfo updater_info;
211 updater_info.CopyFrom(iter->second);
212 if (data_type == FLAGS_cyber_channels_key) {
213 // For cyber channels
214 auto topology_manager =
215 apollo::cyber::service_discovery::TopologyManager::Instance();
216 auto channel_manager = topology_manager->channel_manager();
217
218 std::vector<apollo::cyber::proto::RoleAttributes> role_attributes;
219 channel_manager->GetWriters(&role_attributes);
220
221 for (const auto &role : role_attributes) {
222 if (!complete_channel_count_[role.channel_name()]) {
223 std::string proto_path;
224 apollo::cyber::message::ProtobufFactory::Instance()->GetProtoPath(
225 role.message_type(), proto_path);
226 if (proto_path.empty()) {
227 AWARN << "Cannot find proto location for message type "
228 << role.message_type();
229 continue;
230 }
231 auto channel_item = updater_info.add_channels();
232 channel_item->set_proto_path(proto_path);
233 channel_item->set_channel_name(role.channel_name());
234 channel_item->set_msg_type(role.message_type());
235 }
236 complete_channel_count_[role.channel_name()]++;
237 }
238 } else {
239 // For other channels
240 const std::string &updater_path = (*iter).second.data_name();
241 std::string proto_path;
242 apollo::cyber::message::ProtobufFactory::Instance()->GetProtoPath(
243 data_type, proto_path);
244 if (proto_path.empty()) {
245 AWARN << "Cannot find proto location for message type " << data_type;
246 continue;
247 }
248 updater_info.set_proto_path(proto_path);
249 if (iter->second.different_for_channels()) {
250 std::vector<std::string> channels;
251 if (!GetDataUpdaterChannels(updater_path, &channels)) {
252 continue;
253 }
254 for (auto iter = channels.begin(); iter != channels.end(); iter++) {
255 if (!data_handler_channel_count_[*iter]) {
256 auto channel_item = updater_info.add_channels();
257 channel_item->set_channel_name(*iter);
258 }
259 data_handler_channel_count_[*iter]++;
260 }
261 }
262 }
263 (*data_handler_conf_.mutable_data_handler_info())[data_type] =
264 updater_info;
265 }
266 }
267 data = JsonUtil::ProtoToTypedJson("data", data_handler_conf_);
268 data.erase("type");
269 response_data["info"] = data;
270 response_data["info"]["code"] = 0;
271 return response_data;
272}
273
274void SocketManager::BrocastDataHandlerConf(bool clear_channel_msg) {
275 Json response({});
276 response["data"] =
277 clear_channel_msg ? ClearDataHandlerChannelMsgs() : GetDataHandlerInfo();
278 response["action"] = "metadata";
279 websocket_->BroadcastData(response.dump());
280}
281
282bool SocketManager::UpdateUpdaterInfo(
283 const apollo::cyber::proto::ChangeMsg &change_msg,
284 DataHandlerInfo &updater_info) {
285 auto role_attr = change_msg.role_attr();
286 auto channel_item = updater_info.add_channels();
287 channel_item->set_channel_name(role_attr.channel_name());
289 change_msg.operate_type()) {
290 channel_item->set_msg_type(role_attr.message_type());
291 std::string proto_path;
292 apollo::cyber::message::ProtobufFactory::Instance()->GetProtoPath(
293 role_attr.message_type(), proto_path);
294 if (proto_path.empty()) {
295 AWARN << "Cannot find proto location for message type "
296 << role_attr.message_type();
297 return false;
298 }
299 channel_item->set_proto_path(proto_path);
300 }
301 return true;
302}
303
304bool SocketManager::UpdateCyberChannels(
305 const apollo::cyber::proto::ChangeMsg &change_msg,
306 DataHandlerInfo &updater_info) {
307 std::string channel_name = change_msg.role_attr().channel_name();
308
310 change_msg.operate_type()) {
311 // Used to extract the channel of the complete set.
312 if (!complete_channel_count_[channel_name]) {
313 if (!UpdateUpdaterInfo(change_msg, updater_info)) return false;
314 complete_channel_count_[channel_name]++;
315 return true;
316 }
317 complete_channel_count_[channel_name]++;
318 } else {
319 complete_channel_count_[channel_name]--;
320 if (complete_channel_count_[channel_name] == 0) {
321 if (!UpdateUpdaterInfo(change_msg, updater_info)) return false;
322 return true;
323 }
324 }
325 return false;
326}
327
328void SocketManager::RefreshDataHandlerChannels(
329 const apollo::cyber::proto::ChangeMsg &change_msg,
330 DataHandlerConf &data_handler_conf_diff, bool &flag) {
331 auto role_attr = change_msg.role_attr();
332 std::string message_type = role_attr.message_type();
333 std::string channel_name = role_attr.channel_name();
334
335 // Used to filter the channel of the current data packet and the channel in
336 // non-broadcast packet mode.
337 std::vector<std::string> records;
338 std::vector<std::string> other_record_node_name;
339 auto *record_player_factory = RecordPlayerFactory::Instance();
340 record_player_factory->GetAllRecords(&records);
341 const std::string current_record = record_player_factory->GetCurrentRecord();
342 for (auto iter = records.begin(); iter != records.end(); iter++) {
343 if (current_record.empty() || *iter != current_record) {
344 std::string other_node_name = "record_player_factory_" + *iter;
345 other_record_node_name.push_back(other_node_name);
346 }
347 }
348
349 std::string node_name = role_attr.node_name();
350 for (auto iter = data_handler_base_conf_.mutable_data_handler_info()->begin();
351 iter != data_handler_base_conf_.mutable_data_handler_info()->end();
352 iter++) {
353 const std::string &data_type = (*iter).first;
354 DataHandlerInfo updater_info;
355 updater_info.set_data_name(iter->second.data_name());
356 updater_info.set_different_for_channels(
357 iter->second.different_for_channels());
358
359 if (data_type == FLAGS_cyber_channels_key) {
360 // For cyber channels
361 flag = UpdateCyberChannels(change_msg, updater_info);
362 } else {
363 // For other channels
364 if (!iter->second.different_for_channels()) {
365 (*data_handler_conf_diff.mutable_data_handler_info())[data_type] =
366 updater_info;
367 continue;
368 }
369
370 int index = 0;
371 if (filter_info.find(data_type) != filter_info.end() &&
372 !filter_info[data_type].first.empty()) {
373 index = message_type.rfind(filter_info[data_type].first);
374 }
375 int index_channel = 0;
376 if (filter_info.find(data_type) != filter_info.end() &&
377 !filter_info[data_type].second.empty()) {
378 index_channel = channel_name.rfind(filter_info[data_type].second);
379 }
380
381 if (index != -1 && index_channel != -1 &&
382 (current_record.empty() ||
383 std::find(other_record_node_name.begin(),
384 other_record_node_name.end(),
385 node_name) == other_record_node_name.end())) {
387 change_msg.operate_type()) {
388 if (!data_handler_channel_count_[channel_name]) {
389 flag = true;
390 auto channel_item = updater_info.add_channels();
391 channel_item->set_channel_name(channel_name);
392 if (!ModifyUpdaterChannels(iter->second.data_name(), channel_name,
393 "join"))
394 continue;
395 }
396 data_handler_channel_count_[channel_name]++;
397 } else {
398 data_handler_channel_count_[channel_name]--;
399 if (data_handler_channel_count_[channel_name] == 0) {
400 flag = true;
401 auto channel_item = updater_info.add_channels();
402 channel_item->set_channel_name(channel_name);
403 if (!ModifyUpdaterChannels(iter->second.data_name(), channel_name,
404 "leave"))
405 continue;
406 }
407 }
408 }
409 }
410 (*data_handler_conf_diff.mutable_data_handler_info())[data_type] =
411 updater_info;
412 }
413}
414
415void SocketManager::RefreshChannels(
416 const apollo::cyber::proto::ChangeMsg &change_msg) {
417 // Just look at the writer's
419 return;
420 }
421
422 DataHandlerConf data_handler_conf_diff;
423 bool flag = false;
424
425 RefreshDataHandlerChannels(change_msg, data_handler_conf_diff, flag);
426
427 // If the channel is not used.
428 if (flag == false) {
429 return;
430 }
431
432 Json response({});
433 Json data({});
434 data = JsonUtil::ProtoToTypedJson("data", data_handler_conf_diff);
435 data.erase("type");
436 response["data"]["info"] = data;
437 response["data"]["info"]["code"] = 0;
438 response["action"] =
440 ? "join"
441 : "leave";
442 websocket_->BroadcastData(response.dump());
443}
444
445} // namespace dreamview
446} // namespace apollo
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 bool GetJsonByPath(const nlohmann::json &json, const std::vector< std::string > &paths, nlohmann::json *value)
Get the json from the given json and path.
Definition json_util.cc:73
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 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
A class that manages dreamview plus plug-ins.
void BrocastDataHandlerConf(bool clear_channel_msg=false)
Broadcast data handler conf for all connections
SocketManager(WebSocketHandler *websocket, UpdaterManager *updater_manager, DvPluginManager *dv_plugin_manager)
Constructor of SocketManager.
Management for all data updater.
bool Start(const std::string &path_name, const double &time_interval_ms, const std::string &channel_name="", nlohmann::json *subscribe_param=nullptr)
Start a updater implemetnent.
UpdaterBase * GetUpdater(const std::string &path_name)
Get registered updater
bool Stop(const std::string &path_name, const std::string &channel_name)
Stop updater publish data.
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.
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.
void RegisterConnectionReadyHandler(ConnectionReadyHandler handler)
Add a new handler for new connections.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
nlohmann::json Json
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
std::map< std::string, std::pair< std::string, std::string > > filter_info
class register implement
Definition arena_queue.h:37
SocketManager to manage all websocket
optional RoleAttributes role_attr
map< string, DataHandlerInfo > data_handler_info