29#include "wx/jsonreader.h"
30#include "wx/jsonwriter.h"
33#include "std_filesystem.h"
35using Direction = NavmsgStatus::Direction;
36using State = NavmsgStatus::State;
37using Accepted = NavmsgStatus::Accepted;
39static const std::unordered_map<Accepted, std::string> StringByAccepted = {
40 {Accepted::kOk,
"Ok"},
41 {Accepted::kFilteredNoOutput,
"FilteredNoOutput"},
42 {Accepted::kFilteredDropped,
"FilteredDropped"},
43 {Accepted::kNone,
"None"}};
47 return StringByAccepted.at(a);
48 }
catch (std::out_of_range& e) {
49 std::cout <<
"Error: " << e.what() <<
" :" <<
static_cast<int>(a) <<
"\n";
50 assert(
false &&
"Bad Accepted state");
56 for (
auto& kv : StringByAccepted)
57 if (kv.second == s)
return kv.first;
58 return Accepted::kNone;
62static const std::unordered_map<const char*, Direction> dir_map = {
63 {
"input", Direction::kInput},
64 {
"handled", Direction::kHandled},
65 {
"output", Direction::kOutput},
66 {
"internal", Direction::kInternal},
67 {
"none", NavmsgStatus::Direction::kNone}};
69static const std::unordered_map<const char*, State> statemap = {
71 {
"checksum-err", State::kChecksumError},
72 {
"malformed", State::kMalformed},
73 {
"tx-error", State::kTxError}};
75static const std::unordered_map<const char*, Accepted> acceptmap = {
76 {
"Ok", Accepted::kOk},
77 {
"FilteredDropped", Accepted::kFilteredDropped},
78 {
"FilteredNoOutput", Accepted::kFilteredNoOutput},
79 {
"None", Accepted::kNone}};
81static NavmsgStatus::Direction StringToDirection(
const std::string s) {
84 if (s ==
"received")
return NavmsgStatus::Direction::kHandled;
86 for (
auto kv : dir_map)
87 if (kv.first == s) return kv.second;
88 return NavmsgStatus::Direction::kNone;
91static std::string DirectionToString(Direction direction) {
92 for (
auto kv : dir_map)
93 if (kv.second == direction) return kv.first;
94 assert(
false &&
"Illegal direction enumeration type (!)");
98static Accepted StringToAccepted(
const std::string s) {
99 for (
auto kv : acceptmap)
100 if (kv.first == s) return kv.second;
101 return Accepted::kNone;
104static std::string AcceptedToString(Accepted accept) {
105 for (
auto kv : acceptmap)
106 if (kv.second == accept) return kv.first;
107 assert(
false &&
"Illegal direction enumeration type (!)");
111static State StringToState(
const std::string s) {
112 for (
auto kv : statemap)
113 if (kv.first == s) return kv.second;
117static std::string StateToString(State state) {
118 for (
auto kv : statemap)
119 if (kv.second == state) return kv.first;
120 assert(
false &&
"Illegal direction enumeration type (!)");
125 for (
int i = 0; i < json_val.
Size(); i++) {
126 auto str = json_val[i].
AsString().ToStdString();
127 filter.buses.insert(NavAddr::StringToBus(str));
132 for (
int i = 0; i < json_val.
Size(); i++) {
133 auto str = json_val[i].
AsString().ToStdString();
134 filter.directions.insert(StringToDirection(str));
139 for (
int i = 0; i < json_val.
Size(); i++) {
140 auto str = json_val[i].
AsString().ToStdString();
141 filter.accepted.insert(StringToAccepted(str));
146 for (
int i = 0; i < json_val.
Size(); i++) {
147 auto str = json_val[i].
AsString().ToStdString();
148 filter.status.insert(StringToState(str));
154 auto val = json_val[
"blockedMsg"];
155 for (
int i = 0; i < val.Size(); i++)
156 filter.exclude_msg.insert(val[i].AsString().ToStdString());
157 }
else if (json_val.
HasMember(
"allowedMsg")) {
158 auto val = json_val[
"allowedMsg"];
159 for (
int i = 0; i < val.Size(); i++)
160 filter.include_msg.insert(val[i].AsString().ToStdString());
165 for (
int i = 0; i < json_val.
Size(); i++)
166 filter.interfaces.insert(json_val[i].AsString().ToStdString());
171 for (
int i = 0; i < json_val.
Size(); i++)
172 filter.pgns.insert(std::stoi(json_val[i].AsString().ToStdString()));
180 for (
int i = 0; i < json_val.
Size(); i++) {
181 filter.src_pgns.insert(std::stoi(json_val[i].AsString().ToStdString()));
189 std::vector<NavmsgFilter> filters;
191 for (
auto& entry : fs::directory_iterator(dir)) {
193 if (filter.m_is_valid)
194 filters.push_back(filter);
196 wxLogWarning(
"Illegal system filter: %s",
197 entry.path().string().c_str());
200 wxLogWarning(
"Bad system filter path: %s", dir.string().c_str());
206 fs::path dirpath(
g_BasePlatform->GetSharedDataDir().ToStdString());
210std::vector<NavmsgFilter> GetUserFilters() {
217 std::vector user_filters = GetUserFilters();
218 filters.insert(filters.end(), user_filters.begin(), user_filters.end());
223 const std::shared_ptr<const NavMsg>& msg) {
224 if (directions.size() > 0) {
225 if (directions.find(msg_status.direction) == directions.end())
return false;
227 if (status.size() > 0) {
228 if (status.find(msg_status.status) == status.end())
return false;
230 if (buses.size() > 0) {
231 if (buses.find(msg->bus) == buses.end())
return false;
233 if (include_msg.size() > 0) {
234 if (include_msg.find(msg->key()) == include_msg.end())
return false;
236 if (exclude_msg.size() > 0) {
237 if (exclude_msg.find(msg->key()) != exclude_msg.end())
return false;
239 if (interfaces.size() > 0) {
240 if (interfaces.find(msg->source->iface) == interfaces.end())
return false;
242 if (accepted.size() > 0) {
243 if (accepted.find(msg_status.accepted) == accepted.end())
return false;
245 auto n2k_msg = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
247 if (pgns.size() > 0) {
248 if (pgns.find(n2k_msg->PGN) == pgns.end())
return false;
250 if (src_pgns.size() > 0) {
251 auto src = std::static_pointer_cast<const NavAddr2000>(msg->source);
252 if (src && src_pgns.find(src->name) == src_pgns.end())
return false;
259 std::ifstream stream(path);
261 std::stringstream ss;
262 ss << stream.rdbuf();
269 int err_count = reader.
Parse(
string, &root);
271 wxLogWarning(
"Error parsing filter XML");
273 wxLogWarning(
"Parse error: %s", e.c_str());
277 filter.m_name = root[
"filter"][
"name"].
AsString();
278 filter.m_description = root[
"filter"][
"description"].
AsString();
279 if (root[
"filter"].HasMember(
"buses"))
280 ParseBuses(filter, root[
"filter"][
"buses"]);
281 if (root[
"filter"].HasMember(
"accepted"))
282 ParseAccepted(filter, root[
"filter"][
"accepted"]);
283 if (root[
"filter"].HasMember(
"status"))
284 ParseStatus(filter, root[
"filter"][
"status"]);
285 if (root[
"filter"].HasMember(
"directions"))
286 ParseDirections(filter, root[
"filter"][
"directions"]);
287 if (root[
"filter"].HasMember(
"msgFilter"))
288 ParseMsgFilter(filter, root[
"filter"][
"msgFilter"]);
289 if (root[
"filter"].HasMember(
"interfaces"))
290 ParseInterfaces(filter, root[
"filter"][
"interfaces"]);
291 if (root[
"filter"].HasMember(
"pgns"))
292 ParsePgn(filter, root[
"filter"][
"pgns"]);
293 if (root[
"filter"].HasMember(
"src_pgns"))
294 ParseSource(filter, root[
"filter"][
"src_pgns"]);
300 root[
"filter"][
"name"] = m_name;
301 root[
"filter"][
"description"] = m_description;
304 if (!buses.empty()) {
305 for (
auto b : buses) filter[
"buses"].Append(NavAddr::BusToString(b));
307 if (!directions.empty()) {
308 for (
auto d : directions) filter[
"directions"].Append(DirectionToString(d));
310 if (!accepted.empty()) {
311 for (
auto a : accepted) filter[
"accepted"].Append(AcceptedToString(a));
313 if (!status.empty()) {
314 for (
auto s : status) filter[
"status"].Append(StateToString(s));
316 if (!include_msg.empty()) {
317 for (
auto m : include_msg) filter[
"msgFilter"][
"allowedMsg"].Append(m);
318 }
else if (!exclude_msg.empty()) {
319 for (
auto m : exclude_msg) filter[
"msgFilter"][
"blockedMsg"].Append(m);
321 if (!interfaces.empty()) {
322 for (
auto i : interfaces) filter[
"interfaces"].Append(i);
325 for (
auto p : pgns) filter[
"pgns"].Append(p.to_string());
327 if (!src_pgns.empty()) {
328 for (
auto p : src_pgns) filter[
"src_pgns"].Append(p.to_string());
332 writer.
Write(root, ws);
333 return ws.ToStdString();
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.
const wxArrayString & GetErrors() const
Return a reference to the error message's array.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
int Size() const
Return the size of the array or map stored in this value.
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
wxString AsString() const
Return the stored value as a wxWidget's string.
The JSON document writer.
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
Data monitor filter definitions.