27#include "nlohmann/json.hpp"
32#include "std_filesystem.h"
34using Direction = NavmsgStatus::Direction;
35using State = NavmsgStatus::State;
36using Accepted = NavmsgStatus::Accepted;
38static const std::unordered_map<Accepted, std::string> StringByAccepted = {
39 {Accepted::kOk,
"Ok"},
40 {Accepted::kFilteredNoOutput,
"FilteredNoOutput"},
41 {Accepted::kFilteredDropped,
"FilteredDropped"},
42 {Accepted::kNone,
"None"}};
46 return StringByAccepted.at(a);
47 }
catch (std::out_of_range& e) {
48 std::cout <<
"Error: " << e.what() <<
" :" <<
static_cast<int>(a) <<
"\n";
49 assert(
false &&
"Bad Accepted state");
55 for (
auto& kv : StringByAccepted)
56 if (kv.second == s)
return kv.first;
57 return Accepted::kNone;
61static const std::unordered_map<const char*, Direction> dir_map = {
62 {
"input", Direction::kInput},
63 {
"handled", Direction::kHandled},
64 {
"output", Direction::kOutput},
65 {
"internal", Direction::kInternal},
66 {
"none", NavmsgStatus::Direction::kNone}};
68static const std::unordered_map<const char*, State> statemap = {
70 {
"checksum-err", State::kChecksumError},
71 {
"malformed", State::kMalformed},
72 {
"tx-error", State::kTxError}};
74static const std::unordered_map<const char*, Accepted> acceptmap = {
75 {
"Ok", Accepted::kOk},
76 {
"FilteredDropped", Accepted::kFilteredDropped},
77 {
"FilteredNoOutput", Accepted::kFilteredNoOutput},
78 {
"None", Accepted::kNone}};
80static NavmsgStatus::Direction StringToDirection(
const std::string s) {
83 if (s ==
"received")
return NavmsgStatus::Direction::kHandled;
85 for (
auto kv : dir_map)
86 if (kv.first == s) return kv.second;
87 return NavmsgStatus::Direction::kNone;
90static std::string DirectionToString(Direction direction) {
91 for (
auto kv : dir_map)
92 if (kv.second == direction) return kv.first;
93 assert(
false &&
"Illegal direction enumeration type (!)");
97static Accepted StringToAccepted(
const std::string s) {
98 for (
auto kv : acceptmap)
99 if (kv.first == s) return kv.second;
100 return Accepted::kNone;
103static std::string AcceptedToString(Accepted accept) {
104 for (
auto kv : acceptmap)
105 if (kv.second == accept) return kv.first;
106 assert(
false &&
"Illegal direction enumeration type (!)");
110static State StringToState(
const std::string s) {
111 for (
auto kv : statemap)
112 if (kv.first == s) return kv.second;
116static std::string StateToString(State state) {
117 for (
auto kv : statemap)
118 if (kv.second == state) return kv.first;
119 assert(
false &&
"Illegal direction enumeration type (!)");
123static void ParseBuses(
NavmsgFilter& filter,
const nlohmann::json& json_val) {
124 for (
const auto& value : json_val) {
125 auto str = value.get<std::string>();
126 filter.buses.insert(NavAddr::StringToBus(str));
131 const nlohmann::json& json_val) {
132 for (
const auto& value : json_val) {
133 auto str = value.get<std::string>();
134 filter.directions.insert(StringToDirection(str));
138static void ParseAccepted(
NavmsgFilter& filter, nlohmann::json json_val) {
139 for (
const auto& value : json_val) {
140 auto str = value.get<std::string>();
141 filter.accepted.insert(StringToAccepted(str));
145static void ParseStatus(
NavmsgFilter& filter, nlohmann::json json_val) {
146 for (
const auto& value : json_val) {
147 auto str = value.get<std::string>();
148 filter.status.insert(StringToState(str));
152static void ParseMsgFilter(
NavmsgFilter& filter, nlohmann::json json_val) {
153 if (json_val.contains(
"blockedMsg")) {
154 auto values = json_val[
"blockedMsg"];
155 for (
const auto& val : values)
156 filter.exclude_msg.insert(val.get<std::string>());
157 }
else if (json_val.contains(
"allowedMsg")) {
158 auto values = json_val[
"allowedMsg"];
159 for (
const auto& val : values)
160 filter.include_msg.insert(val.get<std::string>());
164static void ParseInterfaces(
NavmsgFilter& filter, nlohmann::json json_val) {
165 for (
const auto& value : json_val)
166 filter.interfaces.insert(value.get<std::string>());
169static void ParsePgn(
NavmsgFilter& filter, nlohmann::json json_val) {
171 for (
const auto& value : json_val)
172 filter.pgns.insert(std::stoi(value.get<std::string>()));
178static void ParseSource(
NavmsgFilter& filter, nlohmann::json json_val) {
180 for (
const auto& value : json_val)
181 for (unsigned i = 0; i < json_val.size(); i++) {
182 filter.src_pgns.insert(std::stoi(value.get<std::string>()));
190 std::vector<NavmsgFilter> filters;
192 for (
auto& entry : fs::directory_iterator(dir)) {
194 if (filter.m_is_valid)
195 filters.push_back(filter);
197 wxLogWarning(
"Illegal system filter: %s",
198 entry.path().string().c_str());
201 wxLogWarning(
"Bad system filter path: %s", dir.string().c_str());
207 fs::path dirpath(
g_BasePlatform->GetSharedDataDir().ToStdString());
211std::vector<NavmsgFilter> GetUserFilters() {
218 std::vector user_filters = GetUserFilters();
219 filters.insert(filters.end(), user_filters.begin(), user_filters.end());
224 const std::shared_ptr<const NavMsg>& msg) {
225 if (directions.size() > 0) {
226 if (directions.find(msg_status.direction) == directions.end())
return false;
228 if (status.size() > 0) {
229 if (status.find(msg_status.status) == status.end())
return false;
231 if (buses.size() > 0) {
232 if (buses.find(msg->bus) == buses.end())
return false;
234 if (include_msg.size() > 0) {
235 if (include_msg.find(msg->key()) == include_msg.end())
return false;
237 if (exclude_msg.size() > 0) {
238 if (exclude_msg.find(msg->key()) != exclude_msg.end())
return false;
240 if (interfaces.size() > 0) {
241 if (interfaces.find(msg->source->iface) == interfaces.end())
return false;
243 if (accepted.size() > 0) {
244 if (accepted.find(msg_status.accepted) == accepted.end())
return false;
246 auto n2k_msg = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
248 if (pgns.size() > 0) {
249 if (pgns.find(n2k_msg->PGN) == pgns.end())
return false;
251 if (src_pgns.size() > 0) {
252 auto src = std::static_pointer_cast<const NavAddr2000>(msg->source);
253 if (src && src_pgns.find(src->name) == src_pgns.end())
return false;
260 std::ifstream stream(path);
262 std::stringstream ss;
263 ss << stream.rdbuf();
270 root = nlohmann::json::parse(
string);
271 }
catch (nlohmann::json::exception& e) {
272 wxLogWarning(
"Error parsing filter XML: %s", e.what());
276 filter.m_name = root[
"filter"][
"name"].get<std::string>();
277 filter.m_description = root[
"filter"][
"description"].get<std::string>();
278 if (root[
"filter"].contains(
"buses"))
279 ParseBuses(filter, root[
"filter"][
"buses"]);
280 if (root[
"filter"].contains(
"accepted"))
281 ParseAccepted(filter, root[
"filter"][
"accepted"]);
282 if (root[
"filter"].contains(
"status"))
283 ParseStatus(filter, root[
"filter"][
"status"]);
284 if (root[
"filter"].contains(
"directions"))
285 ParseDirections(filter, root[
"filter"][
"directions"]);
286 if (root[
"filter"].contains(
"msgFilter"))
287 ParseMsgFilter(filter, root[
"filter"][
"msgFilter"]);
288 if (root[
"filter"].contains(
"interfaces"))
289 ParseInterfaces(filter, root[
"filter"][
"interfaces"]);
290 if (root[
"filter"].contains(
"pgns")) ParsePgn(filter, root[
"filter"][
"pgns"]);
291 if (root[
"filter"].contains(
"src_pgns"))
292 ParseSource(filter, root[
"filter"][
"src_pgns"]);
298 root[
"filter"][
"name"] = m_name;
299 root[
"filter"][
"description"] = m_description;
300 nlohmann::json& filter = root[
"filter"];
302 if (!buses.empty()) {
303 for (
auto b : buses) filter[
"buses"].push_back(NavAddr::BusToString(b));
305 if (!directions.empty()) {
306 for (
auto d : directions)
307 filter[
"directions"].push_back(DirectionToString(d));
309 if (!accepted.empty()) {
310 for (
auto a : accepted) filter[
"accepted"].push_back(AcceptedToString(a));
312 if (!status.empty()) {
313 for (
auto s : status) filter[
"status"].push_back(StateToString(s));
315 if (!include_msg.empty()) {
316 for (
auto m : include_msg) filter[
"msgFilter"][
"allowedMsg"].push_back(m);
317 }
else if (!exclude_msg.empty()) {
318 for (
auto m : exclude_msg) filter[
"msgFilter"][
"blockedMsg"].push_back(m);
320 if (!interfaces.empty()) {
321 for (
auto i : interfaces) filter[
"interfaces"].push_back(i);
324 for (
auto p : pgns) filter[
"pgns"].push_back(p.to_string());
326 if (!src_pgns.empty()) {
327 for (
auto p : src_pgns) filter[
"src_pgns"].push_back(p.to_string());
331 }
catch (nlohmann::json::exception& e) {
332 wxLogWarning(
"Error serializing filter %s: %s", m_name.c_str(), e.what());
bool Pass(NavmsgStatus status, const std::shared_ptr< const NavMsg > &msg)
Return true if message is not matched by filter.
static std::vector< NavmsgFilter > GetFilters(const fs::path &path)
Return list of pre-defined filters shipped with app, test hook.
static std::vector< NavmsgFilter > GetAllFilters()
Return list of all filters, system + user defined.
std::string to_string() const
Output parsable JSON string representation.
static NavmsgFilter Parse(const std::string &s)
Parse text as created by to_string().
static std::vector< NavmsgFilter > GetSystemFilters()
Return list of pre-defined filters shipped with application.
Representation of message status as determined by the multiplexer.
static Accepted StringToAccepted(const std::string &s)
Return Accepted value corresponding to argument s.
static std::string AcceptedToString(Accepted)
Return string representation of argument.
Data monitor filter definitions.