OpenCPN Partial API docs
comm_navmsg.h
1  /**************************************************************************
2  * Copyright (C) 2022 - 2024 by David Register, 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, write to the *
16  * Free Software Foundation, Inc., *
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18  **************************************************************************/
19 
22 #ifndef _DRIVER_NAVMSG_H
23 #define _DRIVER_NAVMSG_H
24 
25 #include <memory>
26 #include <sstream>
27 #include <vector>
28 #include <string>
29 
30 #ifdef _MSC_VER
31 #include <winsock2.h>
32 #else
33 #include <netinet/in.h>
34 #endif
35 
36 #include "observable.h"
37 
38 struct N2kPGN {
39  uint64_t pgn;
40 
41  N2kPGN(uint64_t _pgn) { pgn = _pgn; }
42 
43  std::string to_string() const {
44  std::stringstream ss;
45  ss << pgn;
46  return ss.str();
47  }
48 };
49 
59 struct N2kName {
60  N2kName(){};
61  N2kName(uint64_t name) { value.Name = name; }
62 
63  std::string to_string() const {
64  std::stringstream ss;
65  ss << value.Name;
66  return ss.str();
67  }
68 
69  static uint64_t Parse(const std::string& s) {
70  std::stringstream ss;
71  uint64_t id;
72  ss << s;
73  ss >> id;
74  return id;
75  }
76 
77  uint32_t GetNumber() const;
78  uint16_t GetManufacturer() const;
79  uint8_t GetDevInstanceLow() const;
80  uint8_t GetDevInstanceHigh() const;
81  uint8_t GetDevFunc() const;
82  uint8_t GetDevClass() const;
83  uint8_t GetSysInstance() const;
84  uint8_t GetIndustryGroup() const;
86  typedef union {
87  uint64_t Name;
88  struct {
89  uint32_t UnicNumberAndManCode; // ManufacturerCode 11 bits , UniqueNumber
90  // 21 bits
91  unsigned char DeviceInstance;
92  unsigned char DeviceFunction;
93  unsigned char DeviceClass;
94  unsigned char IndustryGroupAndSystemInstance; // 4 bits each
95  };
97 
99 
100  void SetUniqueNumber(uint32_t _UniqueNumber) {
101  value.UnicNumberAndManCode =
102  (value.UnicNumberAndManCode & 0xffe00000) | (_UniqueNumber & 0x1fffff);
103  }
104  void SetManufacturerCode(uint16_t _ManufacturerCode) {
105  value.UnicNumberAndManCode =
106  (value.UnicNumberAndManCode & 0x1fffff) |
107  (((unsigned long)(_ManufacturerCode & 0x7ff)) << 21);
108  }
109  void SetDeviceInstance(unsigned char _DeviceInstance) {
110  value.DeviceInstance = _DeviceInstance;
111  }
112  void SetDeviceFunction(unsigned char _DeviceFunction) {
113  value.DeviceFunction = _DeviceFunction;
114  }
115  void SetDeviceClass(unsigned char _DeviceClass) {
116  value.DeviceClass = ((_DeviceClass & 0x7f) << 1);
117  }
118  void SetIndustryGroup(unsigned char _IndustryGroup) {
119  value.IndustryGroupAndSystemInstance =
120  (value.IndustryGroupAndSystemInstance & 0x0f) | (_IndustryGroup << 4) |
121  0x80;
122  }
123  void SetSystemInstance(unsigned char _SystemInstance) {
124  value.IndustryGroupAndSystemInstance =
125  (value.IndustryGroupAndSystemInstance & 0xf0) |
126  (_SystemInstance & 0x0f);
127  }
128 
129  uint64_t GetName() const { return value.Name; }
130 };
131 
133 class NavAddr {
134 public:
135  enum class Bus { N0183, Signalk, N2000, Onenet, Plugin, TestBus, Undef };
136 
137  NavAddr(Bus b, const std::string& i) : bus(b), iface(i){};
138  NavAddr() : bus(Bus::Undef), iface(""){};
139 
140  std::string to_string() const {
141  return NavAddr::BusToString(bus) + " " + iface;
142  }
143  static std::string BusToString(Bus b);
144  static Bus StringToBus(const std::string& s);
145 
146  Bus bus;
147  const std::string iface;
149 };
150 
151 class NavAddr0183 : public NavAddr {
152 public:
153  NavAddr0183(const std::string iface) : NavAddr(NavAddr::Bus::N0183, iface){};
154 
155  std::string to_string() const { return iface; }
156 };
157 
158 class NavAddr2000 : public NavAddr {
159 public:
160  NavAddr2000(const std::string& iface, const N2kName& _name)
161  : NavAddr(NavAddr::Bus::N2000, iface), name(_name){};
162 
163  NavAddr2000(const std::string& iface, unsigned char _address)
164  : NavAddr(NavAddr::Bus::N2000, iface), name(0), address(_address){};
165 
166  std::string to_string() const { return name.to_string(); }
167 
168  const N2kName name;
169  unsigned char address;
170 };
171 
172 class NavAddrPlugin : public NavAddr {
173 public:
174  const std::string id;
175  NavAddrPlugin(const std::string& _id)
176  : NavAddr(NavAddr::Bus::Plugin, "Plugin"), id(_id) {}
177 };
178 
179 
180 class NavAddrSignalK : public NavAddr {
181 public:
182  NavAddrSignalK(std::string iface) : NavAddr(NavAddr::Bus::Signalk, iface){};
183 
184  std::string to_string() const { return NavAddr::to_string(); }
185 };
186 
187 class NavAddrTest : public NavAddr {
188 public:
189  NavAddrTest(std::string output_path)
190  : NavAddr(NavAddr::Bus::TestBus, "Test"), name(output_path){};
191 
192  const std::string name;
193 };
194 
196 class NavMsg : public KeyProvider {
197 public:
198  NavMsg() = delete;
199 
200  virtual std::string key() const = 0;
201 
202  virtual std::string to_string() const {
203  return NavAddr::BusToString(bus) + " " + key();
204  }
205 
206  std::string GetKey() const { return key(); }
207 
208  const NavAddr::Bus bus;
209 
210  std::shared_ptr<const NavAddr> source;
211 
212 protected:
213  NavMsg(const NavAddr::Bus& _bus, std::shared_ptr<const NavAddr> src)
214  : bus(_bus), source(src){};
215 };
216 
220 class Nmea2000Msg : public NavMsg {
221 public:
222  Nmea2000Msg(const uint64_t _pgn)
223  : NavMsg(NavAddr::Bus::N2000, std::make_shared<NavAddr>()), PGN(_pgn) {}
224 
225  Nmea2000Msg(const uint64_t _pgn, std::shared_ptr<const NavAddr> src)
226  : NavMsg(NavAddr::Bus::N2000, src), PGN(_pgn) {}
227 
228  Nmea2000Msg(const uint64_t _pgn, const std::vector<unsigned char>& _payload,
229  std::shared_ptr<const NavAddr> src)
230  : NavMsg(NavAddr::Bus::N2000, src), PGN(_pgn), payload(_payload) {}
231 
232  Nmea2000Msg(const uint64_t _pgn, const std::vector<unsigned char>& _payload,
233  std::shared_ptr<const NavAddr> src, int _priority)
234  : NavMsg(NavAddr::Bus::N2000, src), PGN(_pgn), payload(_payload),
235  priority(_priority) {}
236 
237  virtual ~Nmea2000Msg() = default;
238 
239  std::string key() const { return std::string("n2000-") + PGN.to_string(); };
240 
242  std::string to_string() const;
243 
244  N2kPGN PGN; // For TX message, unparsed
245  std::vector<unsigned char> payload;
246  int priority;
247 };
248 
250 class Nmea0183Msg : public NavMsg {
251 public:
252  Nmea0183Msg(const std::string& id, const std::string& _payload,
253  std::shared_ptr<const NavAddr> src)
254  : NavMsg(NavAddr::Bus::N0183, src),
255  talker(id.substr(0, 2)),
256  type(id.substr(2)),
257  payload(_payload) {}
258 
259  Nmea0183Msg()
260  : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
261 
262  Nmea0183Msg(const std::string& id)
263  : Nmea0183Msg(id.size() <= 3 ? std::string("??") + id : id, "",
264  std::make_shared<const NavAddr>()) {}
265 
266  Nmea0183Msg(const Nmea0183Msg& other, const std::string& t)
267  : NavMsg(NavAddr::Bus::N0183, other.source),
268  talker(other.talker),
269  type(t),
270  payload(other.payload) {}
271 
272  virtual ~Nmea0183Msg() = default;
273 
274  std::string key() const { return Nmea0183Msg::MessageKey(type.c_str()); };
275 
276  std::string to_string() const {
277  return NavMsg::to_string() + " " + talker + type + " " + payload;
278  }
279 
281  static std::string MessageKey(const char* type = "ALL") {
282  static const char* const prefix = "n0183-";
283  return std::string(prefix) + type;
284  }
285 
286  const std::string talker;
287  const std::string type;
288  const std::string payload;
289 };
290 
292 class PluginMsg : public NavMsg {
293 public:
294  PluginMsg()
295  : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
296 
297  PluginMsg(const std::string& _name, const std::string& _dest_host,
298  const std::string& msg)
299  : NavMsg(NavAddr::Bus::Plugin,
300  std::make_shared<const NavAddr>(NavAddr::Bus::Plugin, "")),
301  name(_name),
302  message(msg),
303  dest_host(_dest_host) {}
304 
305  PluginMsg(const std::string& _name, const std::string& msg)
306  : PluginMsg(_name, "localhost", msg) {}
307 
308  virtual ~PluginMsg() = default;
309 
310  const std::string name;
311  const std::string message;
312  const std::string dest_host;
313 
314  std::string key() const { return std::string("plug.json-") + name; };
315 };
316 
317 
319 class SignalkMsg : public NavMsg {
320 public:
321  SignalkMsg()
322  : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
323 
324  SignalkMsg(std::string _context_self, std::string _context,
325  std::string _raw_message, std::string _iface)
326  : NavMsg(NavAddr::Bus::Signalk,
327  std::make_shared<const NavAddr>(NavAddr::Bus::Signalk, _iface)),
328  context_self(_context_self),
329  context(_context),
330  raw_message(_raw_message){};
331 
332  virtual ~SignalkMsg() = default;
333 
334  struct in_addr dest;
335  struct in_addr src;
336  std::string context_self;
337  std::string context;
338  std::string raw_message;
339 
340  std::string key() const { return std::string("signalK"); };
341 };
342 
344 class NullNavMsg : public NavMsg {
345 public:
346  NullNavMsg()
347  : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
348 
349  virtual ~NullNavMsg() = default;
350 
351  std::string key() const { return "navmsg-undef"; }
352 };
353 
354 #endif // DRIVER_NAVMSG_H
Interface implemented by classes which listens.
Definition: observable.h:55
Where messages are sent to or received from.
Definition: comm_navmsg.h:133
const std::string iface
Physical device for 0183, else a unique string.
Definition: comm_navmsg.h:147
Actual data sent between application and transport layer.
Definition: comm_navmsg.h:196
A regular Nmea0183 message.
Definition: comm_navmsg.h:250
const std::string type
For example 'GGA'.
Definition: comm_navmsg.h:287
const std::string talker
For example 'GP'.
Definition: comm_navmsg.h:286
const std::string payload
Complete NMEA0183 sentence, also prefix.
Definition: comm_navmsg.h:288
static std::string MessageKey(const char *type="ALL")
Return key which should be used to listen to given message type.
Definition: comm_navmsg.h:281
See: https://github.com/OpenCPN/OpenCPN/issues/2729#issuecomment-1179506343.
Definition: comm_navmsg.h:220
std::string to_string() const
Print "bus key id payload".
Definition: comm_navmsg.cpp:79
An invalid message, error return value.
Definition: comm_navmsg.h:344
A plugin to plugin json message over the REST interface.
Definition: comm_navmsg.h:292
const std::string dest_host
hostname, ip address or 'localhost'
Definition: comm_navmsg.h:312
Plugin ABI encapsulation.
A parsed SignalK message over ipv4.
Definition: comm_navmsg.h:319
N2k uses CAN which defines the basic properties of messages.
Definition: comm_navmsg.h:59
uint32_t GetNumber() const
21 bits
uint16_t GetManufacturer() const
9 bits
uint8_t GetDevClass() const
7 bits
uint8_t GetDevFunc() const
8 bits
uint8_t GetIndustryGroup() const
4 bits
uint8_t GetDevInstanceHigh() const
5 bits
uint8_t GetDevInstanceLow() const
3 bits
uint8_t GetSysInstance() const
4 bits