28#include "model/base_platform.h"
31#include "wx/jsonreader.h"
32#include "wx/jsonwriter.h"
35#include "std_filesystem.h"
37using Direction = NavmsgStatus::Direction;
38using State = NavmsgStatus::State;
39using Accepted = NavmsgStatus::Accepted;
41static const std::unordered_map<Accepted, std::string> StringByAccepted = {
42 {Accepted::kOk,
"Ok"},
43 {Accepted::kFilteredNoOutput,
"FilteredNoOutput"},
44 {Accepted::kFilteredDropped,
"FilteredDropped"},
45 {Accepted::kNone,
"None"}};
49 return StringByAccepted.at(a);
50 }
catch (std::out_of_range& e) {
51 std::cout <<
"Error: " << e.what() <<
" :" <<
static_cast<int>(a) <<
"\n";
52 assert(
false &&
"Bad Accepted state");
58 for (
auto& kv : StringByAccepted)
59 if (kv.second == s)
return kv.first;
60 return Accepted::kNone;
64static const std::unordered_map<const char*, Direction> dir_map = {
65 {
"input", Direction::kInput},
66 {
"received", Direction::kReceived},
67 {
"output", Direction::kOutput},
68 {
"internal", Direction::kInternal},
69 {
"none", NavmsgStatus::Direction::kNone}};
71static const std::unordered_map<const char*, State> statemap = {
73 {
"checksum-err", State::kChecksumError},
74 {
"malformed", State::kMalformed},
75 {
"tx-error", State::kTxError}};
77static const std::unordered_map<const char*, Accepted> acceptmap = {
78 {
"Ok", Accepted::kOk},
79 {
"FilteredDropped", Accepted::kFilteredDropped},
80 {
"FilteredNoOutput", Accepted::kFilteredNoOutput},
81 {
"None", Accepted::kNone}};
83static NavmsgStatus::Direction StringToDirection(
const std::string s) {
84 for (
auto kv : dir_map)
85 if (kv.first == s) return kv.second;
86 return NavmsgStatus::Direction::kNone;
89static std::string DirectionToString(Direction direction) {
90 for (
auto kv : dir_map)
91 if (kv.second == direction) return kv.first;
92 assert(
false &&
"Illegal direction enumeration type (!)");
96static Accepted StringToAccepted(
const std::string s) {
97 for (
auto kv : acceptmap)
98 if (kv.first == s) return kv.second;
99 return Accepted::kNone;
102static std::string AcceptedToString(Accepted accept) {
103 for (
auto kv : acceptmap)
104 if (kv.second == accept) return kv.first;
105 assert(
false &&
"Illegal direction enumeration type (!)");
109static State StringToState(
const std::string s) {
110 for (
auto kv : statemap)
111 if (kv.first == s) return kv.second;
115static std::string StateToString(State state) {
116 for (
auto kv : statemap)
117 if (kv.second == state) return kv.first;
118 assert(
false &&
"Illegal direction enumeration type (!)");
123 for (
int i = 0; i < json_val.
Size(); i++) {
124 auto str = json_val[i].
AsString().ToStdString();
125 filter.buses.insert(NavAddr::StringToBus(str));
130 for (
int i = 0; i < json_val.
Size(); i++) {
131 auto str = json_val[i].
AsString().ToStdString();
132 filter.directions.insert(StringToDirection(str));
137 for (
int i = 0; i < json_val.
Size(); i++) {
138 auto str = json_val[i].
AsString().ToStdString();
139 filter.accepted.insert(StringToAccepted(str));
144 for (
int i = 0; i < json_val.
Size(); i++) {
145 auto str = json_val[i].
AsString().ToStdString();
146 filter.status.insert(StringToState(str));
152 auto val = json_val[
"blockedMsg"];
153 for (
int i = 0; i < val.Size(); i++)
154 filter.exclude_msg.insert(val[i].AsString().ToStdString());
155 }
else if (json_val.
HasMember(
"allowedMsg")) {
156 auto val = json_val[
"allowedMsg"];
157 for (
int i = 0; i < val.Size(); i++)
158 filter.include_msg.insert(val[i].AsString().ToStdString());
163 for (
int i = 0; i < json_val.
Size(); i++)
164 filter.interfaces.insert(json_val[i].AsString().ToStdString());
169 for (
int i = 0; i < json_val.
Size(); i++)
170 filter.pgns.insert(std::stoi(json_val[i].AsString().ToStdString()));
178 for (
int i = 0; i < json_val.
Size(); i++) {
179 filter.src_pgns.insert(std::stoi(json_val[i].AsString().ToStdString()));
187 std::vector<NavmsgFilter> filters;
189 for (
auto& entry : fs::directory_iterator(dir)) {
191 if (filter.m_is_valid)
192 filters.push_back(filter);
194 wxLogWarning(
"Illegal system filter: %s",
195 entry.path().string().c_str());
198 wxLogWarning(
"Bad system filter path: %s", dir.string().c_str());
204 fs::path dirpath(g_BasePlatform->GetSharedDataDir().ToStdString());
208std::vector<NavmsgFilter> GetUserFilters() {
215 std::vector user_filters = GetUserFilters();
216 filters.insert(filters.end(), user_filters.begin(), user_filters.end());
221 const std::shared_ptr<const NavMsg>& msg) {
222 if (directions.size() > 0) {
223 if (directions.find(msg_status.direction) == directions.end())
return false;
225 if (status.size() > 0) {
226 if (status.find(msg_status.status) == status.end())
return false;
228 if (buses.size() > 0) {
229 if (buses.find(msg->bus) == buses.end())
return false;
231 if (include_msg.size() > 0) {
232 if (include_msg.find(msg->key()) == include_msg.end())
return false;
234 if (exclude_msg.size() > 0) {
235 if (exclude_msg.find(msg->key()) != exclude_msg.end())
return false;
237 if (interfaces.size() > 0) {
238 if (interfaces.find(msg->source->iface) == interfaces.end())
return false;
240 if (accepted.size() > 0) {
241 if (accepted.find(msg_status.accepted) == accepted.end())
return false;
243 auto n2k_msg = std::dynamic_pointer_cast<const Nmea2000Msg>(msg);
245 if (pgns.size() > 0) {
246 if (pgns.find(n2k_msg->PGN) == pgns.end())
return false;
248 if (src_pgns.size() > 0) {
249 auto src = std::static_pointer_cast<const NavAddr2000>(msg->source);
250 if (src && src_pgns.find(src->name) == src_pgns.end())
return false;
257 std::ifstream stream(path);
259 std::stringstream ss;
260 ss << stream.rdbuf();
267 int err_count = reader.
Parse(
string, &root);
269 wxLogWarning(
"Error parsing filter XML");
271 wxLogWarning(
"Parse error: %s", e.c_str());
275 filter.m_name = root[
"filter"][
"name"].
AsString();
276 filter.m_description = root[
"filter"][
"description"].
AsString();
277 if (root[
"filter"].HasMember(
"buses"))
278 ParseBuses(filter, root[
"filter"][
"buses"]);
279 if (root[
"filter"].HasMember(
"accepted"))
280 ParseAccepted(filter, root[
"filter"][
"accepted"]);
281 if (root[
"filter"].HasMember(
"status"))
282 ParseStatus(filter, root[
"filter"][
"status"]);
283 if (root[
"filter"].HasMember(
"directions"))
284 ParseDirections(filter, root[
"filter"][
"directions"]);
285 if (root[
"filter"].HasMember(
"msgFilter"))
286 ParseMsgFilter(filter, root[
"filter"][
"msgFilter"]);
287 if (root[
"filter"].HasMember(
"interfaces"))
288 ParseInterfaces(filter, root[
"filter"][
"interfaces"]);
289 if (root[
"filter"].HasMember(
"pgns"))
290 ParsePgn(filter, root[
"filter"][
"pgns"]);
291 if (root[
"filter"].HasMember(
"src_pgns"))
292 ParseSource(filter, root[
"filter"][
"src_pgns"]);
298 root[
"filter"][
"name"] = m_name;
299 root[
"filter"][
"description"] = m_description;
302 if (!buses.empty()) {
303 for (
auto b : buses) filter[
"buses"].Append(NavAddr::BusToString(b));
305 if (!directions.empty()) {
306 for (
auto d : directions) filter[
"directions"].Append(DirectionToString(d));
308 if (!accepted.empty()) {
309 for (
auto a : accepted) filter[
"accepted"].Append(AcceptedToString(a));
311 if (!status.empty()) {
312 for (
auto s : status) filter[
"status"].Append(StateToString(s));
314 if (!include_msg.empty()) {
315 for (
auto m : include_msg) filter[
"msgFilter"][
"allowedMsg"].Append(m);
316 }
else if (!exclude_msg.empty()) {
317 for (
auto m : exclude_msg) filter[
"msgFilter"][
"blockedMsg"].Append(m);
319 if (!interfaces.empty()) {
320 for (
auto i : interfaces) filter[
"interfaces"].Append(i);
323 for (
auto p : pgns) filter[
"pgns"].Append(p.to_string());
325 if (!src_pgns.empty()) {
326 for (
auto p : src_pgns) filter[
"src_pgns"].Append(p.to_string());
330 writer.
Write(root, ws);
331 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.