OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_drv_loopback.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2025 Alec Leamas *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24// For compilers that support precompilation, includes "wx.h".
25#include <wx/wxprec.h>
26
27#ifndef WX_PRECOMP
28#include <wx/wx.h>
29#endif
30
31#include <algorithm>
32#include <cctype>
33#include <memory>
34#include <string>
35#include <vector>
36
37#include <wx/jsonreader.h>
38#include <wx/log.h>
39#include <wx/string.h>
40
41#include "model/comm_drv_loopback.h"
42#include "model/comm_navmsg.h"
43#include "model/ocpn_utils.h"
44
45using namespace std;
46
47using NavMsgPtr = shared_ptr<const NavMsg>;
48
49static string NextWord(std::string& line) {
50 if (line.empty()) return "";
51 size_t space_pos = line.find(" ");
52 if (space_pos == string::npos) space_pos = line.size();
53 string word(line.substr(0, space_pos));
54 line = ocpn::ltrim(line.substr(space_pos));
55 return word;
56}
57
58static unsigned HexNibbleValue(char c) {
59 c = tolower(c);
60 if (c >= '0' && c <= '9') return c - '0';
61 if (c >= 'a' && c <= 'f') return 10 + c - 'a';
62 return -1;
63}
64
65static unsigned char HexByteValue(const string& text) {
66 unsigned value;
67 if (text.size() == 1) {
68 value = HexNibbleValue(text[0]);
69 } else {
70 value = 16 * HexNibbleValue(text[0]) + HexNibbleValue(text[1]);
71 }
72 return static_cast<unsigned char>(value);
73}
74
75static NavMsgPtr Parse2000(const std::string& iface, const string& type,
76 const std::string& msg) {
77 vector<unsigned char> payload;
78 auto hexbytes = ocpn::split(msg, " ");
79 for (const auto& byte : hexbytes) payload.push_back(HexByteValue(byte));
80 uint64_t pgn;
81 try {
82 pgn = stoi(type);
83 } catch (invalid_argument&) {
84 return {nullptr};
85 }
86 return make_shared<Nmea2000Msg>(
87 pgn, payload, make_shared<NavAddr2000>(iface, N2kName(pgn)));
88}
89
90static NavMsgPtr Parse0183(const string& iface, const string& type,
91 const string& msg) {
92 return make_shared<Nmea0183Msg>(type, msg, make_shared<NavAddr0183>(iface));
93}
94
95static NavMsgPtr ParseSignalk(const string& iface, const string& type,
96 const string& msg) {
97 wxJSONValue root;
98 wxJSONReader reader;
99 int err_count = reader.Parse(msg, &root);
100 std::string context;
101 if (err_count == 0) {
102 if (root.HasMember("context")) context = root["context"].AsString();
103 }
104 return make_shared<SignalkMsg>(type, context, msg, iface);
105}
106
107NavMsgPtr LoopbackDriver::ParsePluginMessage(const string& msg) {
108 int space_count = count(msg.begin(), msg.end(), ' ');
109 if (space_count < 3) {
110 return {nullptr};
111 }
112 std::string msg_(msg);
113 auto protocol = ocpn::tolower(NextWord(msg_));
114 auto iface = NextWord(msg_);
115 auto type = NextWord(msg_);
116
117 if (protocol == "nmea2000") return Parse2000(iface, type, msg_);
118 if (protocol == "nmea0183") return Parse0183(iface, type, msg_);
119 if (protocol == "signalk") return ParseSignalk(iface, type, msg_);
120 return {nullptr};
121}
const std::string iface
Physical device for 0183, else a unique string.
Definition comm_driver.h:97
static std::shared_ptr< const NavMsg > ParsePluginMessage(const std::string &msg)
Parse a string as provided by plugin and convert to a navmsg.
The JSON parser.
Definition jsonreader.h:50
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
Definition jsonval.h:84
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
Definition jsonval.cpp:1298
wxString AsString() const
Return the stored value as a wxWidget's string.
Definition jsonval.cpp:872
Raw, undecoded messages definitions.
std::string tolower(const std::string &input)
Return copy of s with all characters converted to lower case.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
std::string ltrim(const std::string &arg)
Strip possibly leading space characters in s.
Miscellaneous utilities, many of which string related.
N2k uses CAN which defines the basic properties of messages.
Definition comm_navmsg.h:70