OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_navmsg.h
Go to the documentation of this file.
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
25#ifndef _DRIVER_NAVMSG_H
26#define _DRIVER_NAVMSG_H
27
28#include <chrono>
29#include <memory>
30#include <sstream>
31#include <vector>
32#include <string>
33
34#ifdef _MSC_VER
35#include <winsock2.h>
36#else
37#include <netinet/in.h>
38#endif
39
40#include "observable.h"
41
42using NavmsgClock = std::chrono::system_clock;
43using NavmsgTimePoint = std::chrono::time_point<NavmsgClock>;
44
45struct N2kPGN {
46 uint64_t pgn;
47
48 N2kPGN(uint64_t _pgn) { pgn = _pgn; }
49
50 friend bool operator<(const N2kPGN& lhs, const N2kPGN& rhs) {
51 return lhs.pgn < rhs.pgn;
52 }
53
54 std::string to_string() const {
55 std::stringstream ss;
56 ss << pgn;
57 return ss.str();
58 }
59};
60
70struct N2kName {
71 N2kName() {};
72 N2kName(uint64_t name) { value.Name = name; }
73
74 friend bool operator<(const N2kName& lhs, const N2kName& rhs) {
75 return lhs.value.Name < rhs.value.Name;
76 }
77
78 std::string to_string() const {
79 std::stringstream ss;
80 ss << value.Name;
81 return ss.str();
82 }
83
84 static uint64_t Parse(const std::string& s) {
85 std::stringstream ss;
86 uint64_t id;
87 ss << s;
88 ss >> id;
89 return id;
90 }
91
92 uint32_t GetNumber() const;
93 uint16_t GetManufacturer() const;
94 uint8_t GetDevInstanceLow() const;
95 uint8_t GetDevInstanceHigh() const;
96 uint8_t GetDevFunc() const;
97 uint8_t GetDevClass() const;
98 uint8_t GetSysInstance() const;
99 uint8_t GetIndustryGroup() const;
101 typedef union {
102 uint64_t Name;
103 struct {
104 uint32_t UnicNumberAndManCode; // ManufacturerCode 11 bits , UniqueNumber
105 // 21 bits
106 unsigned char DeviceInstance;
107 unsigned char DeviceFunction;
108 unsigned char DeviceClass;
109 unsigned char IndustryGroupAndSystemInstance; // 4 bits each
110 };
112
114
115 void SetUniqueNumber(uint32_t _UniqueNumber) {
116 value.UnicNumberAndManCode =
117 (value.UnicNumberAndManCode & 0xffe00000) | (_UniqueNumber & 0x1fffff);
118 }
119 void SetManufacturerCode(uint16_t _ManufacturerCode) {
120 value.UnicNumberAndManCode =
121 (value.UnicNumberAndManCode & 0x1fffff) |
122 (((unsigned long)(_ManufacturerCode & 0x7ff)) << 21);
123 }
124 void SetDeviceInstance(unsigned char _DeviceInstance) {
125 value.DeviceInstance = _DeviceInstance;
126 }
127 void SetDeviceFunction(unsigned char _DeviceFunction) {
128 value.DeviceFunction = _DeviceFunction;
129 }
130 void SetDeviceClass(unsigned char _DeviceClass) {
131 value.DeviceClass = ((_DeviceClass & 0x7f) << 1);
132 }
133 void SetIndustryGroup(unsigned char _IndustryGroup) {
134 value.IndustryGroupAndSystemInstance =
135 (value.IndustryGroupAndSystemInstance & 0x0f) | (_IndustryGroup << 4) |
136 0x80;
137 }
138 void SetSystemInstance(unsigned char _SystemInstance) {
139 value.IndustryGroupAndSystemInstance =
140 (value.IndustryGroupAndSystemInstance & 0xf0) |
141 (_SystemInstance & 0x0f);
142 }
143
144 uint64_t GetName() const { return value.Name; }
145};
146
148class NavAddr {
149public:
150 enum class Bus {
151 N0183,
152 Signalk,
153 N2000,
154 Onenet,
155 Plugin,
156 TestBus,
157 AppMsg,
158 Undef
159 };
160
161 NavAddr(Bus b, const std::string& i) : bus(b), iface(i) {};
162 NavAddr() : bus(Bus::Undef), iface("") {};
163
164 virtual ~NavAddr() = default;
165
166 virtual std::string to_string() const {
167 return NavAddr::BusToString(bus) + " " + iface;
168 }
169 static std::string BusToString(Bus b);
170 static Bus StringToBus(const std::string& s);
171
172 Bus bus;
173 const std::string iface;
175};
176
177class NavAddr0183 : public NavAddr {
178public:
179 NavAddr0183(const std::string iface) : NavAddr(NavAddr::Bus::N0183, iface) {};
180
181 // An empty, illegal N0183 address
182 NavAddr0183() : NavAddr() {}
183
184 std::string to_string() const { return iface; }
185};
186
187class NavAddr2000 : public NavAddr {
188public:
189 NavAddr2000(const std::string& iface, const N2kName& _name)
190 : NavAddr(NavAddr::Bus::N2000, iface), name(_name) {};
191
192 NavAddr2000(const std::string& iface, unsigned char _address)
193 : NavAddr(NavAddr::Bus::N2000, iface), name(0), address(_address) {};
194
195 // An empty, illegal N2000 address
196 NavAddr2000() : NavAddr() {}
197
198 std::string to_string() const { return name.to_string(); }
199
200 const N2kName name;
201 unsigned char address;
202};
203
204class NavAddrPlugin : public NavAddr {
205public:
206 const std::string id;
207 NavAddrPlugin(const std::string& _id)
208 : NavAddr(NavAddr::Bus::Plugin, "Internal"), id(_id) {}
209};
210
211class NavAddrSignalK : public NavAddr {
212public:
213 NavAddrSignalK(std::string iface) : NavAddr(NavAddr::Bus::Signalk, iface) {};
214
215 std::string to_string() const { return NavAddr::to_string(); }
216};
217
218class NavAddrTest : public NavAddr {
219public:
220 NavAddrTest(std::string output_path)
221 : NavAddr(NavAddr::Bus::TestBus, "Test"), name(output_path) {};
222
223 const std::string name;
224};
225
227class NavMsg : public KeyProvider {
228public:
229 enum class State { kOk, kCannotParse, kBadChecksum, kFiltered };
230
231 NavMsg() = delete;
232 virtual ~NavMsg() = default;
233
235 static NavAddr::Bus GetBusByKey(const std::string& key);
236
238 virtual std::string key() const = 0;
239
241 virtual std::string to_string() const { return key(); }
242
247 virtual std::string to_vdr() const { return to_string(); }
248
250 std::string GetKey() const { return key(); }
251
252 const NavAddr::Bus bus;
253
254 const State state;
255
260 std::shared_ptr<const NavAddr> source;
261
262 const NavmsgTimePoint created_at;
263
264protected:
265 NavMsg(const NavAddr::Bus& _bus, std::shared_ptr<const NavAddr> src,
266 State _state)
267 : bus(_bus), state(_state), source(src), created_at(NavmsgClock::now()) {
268 };
269
270 NavMsg(const NavAddr::Bus& _bus, std::shared_ptr<const NavAddr> src)
271 : NavMsg(_bus, src, State::kOk) {};
272};
273
277class Nmea2000Msg : public NavMsg {
278public:
279 Nmea2000Msg(const uint64_t _pgn)
280 : NavMsg(NavAddr::Bus::N2000, std::make_shared<NavAddr>()), PGN(_pgn) {}
281
282 Nmea2000Msg(const uint64_t _pgn, std::shared_ptr<const NavAddr2000> src)
283 : NavMsg(NavAddr::Bus::N2000, src), PGN(_pgn) {}
284
285 Nmea2000Msg(const uint64_t _pgn, const std::vector<unsigned char>& _payload,
286 std::shared_ptr<const NavAddr2000> src)
287 : NavMsg(NavAddr::Bus::N2000, src), PGN(_pgn), payload(_payload) {}
288
289 Nmea2000Msg(const uint64_t _pgn, const std::vector<unsigned char>& _payload,
290 std::shared_ptr<const NavAddr2000> src, int _priority)
291 : NavMsg(NavAddr::Bus::N2000, src),
292 PGN(_pgn),
293 payload(_payload),
294 priority(_priority) {}
295
296 virtual ~Nmea2000Msg() = default;
297
298 std::string key() const override {
299 return std::string("n2000-") + PGN.to_string();
300 };
301
303 std::string to_string() const override;
304
305 std::string to_vdr() const override;
306
307 N2kPGN PGN; // For TX message, unparsed
308 std::vector<unsigned char> payload;
309 int priority;
310};
311
313class Nmea0183Msg : public NavMsg {
314public:
315 Nmea0183Msg(const std::string& id, const std::string& _payload,
316 std::shared_ptr<const NavAddr> src, State _state)
317 : NavMsg(NavAddr::Bus::N0183, src, _state),
318 talker(id.substr(0, 2)),
319 type(id.substr(2)),
320 payload(_payload) {}
321
322 Nmea0183Msg(const std::string& id, const std::string& _payload,
323 std::shared_ptr<const NavAddr> src)
324 : Nmea0183Msg(id, _payload, src, State::kOk) {};
325
327 : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
328
329 Nmea0183Msg(const std::string& id)
330 : Nmea0183Msg(id.size() <= 3 ? std::string("??") + id : id, "",
331 std::make_shared<const NavAddr>()) {}
332
333 Nmea0183Msg(const Nmea0183Msg& other, const std::string& t)
334 : NavMsg(NavAddr::Bus::N0183, other.source),
335 talker(other.talker),
336 type(t),
337 payload(other.payload) {}
338
339 virtual ~Nmea0183Msg() = default;
340
341 std::string key() const override {
342 return Nmea0183Msg::MessageKey(type.c_str());
343 };
344
345 std::string to_string() const override;
346
347 std::string to_vdr() const override;
348
350 static std::string MessageKey(const char* type) {
351 assert(type && strlen(type) != 0);
352 static const char* const prefix = "n0183-";
353 return std::string(prefix) + type;
354 }
355
356 const std::string talker;
357 const std::string type;
358 const std::string payload;
359};
360
362class PluginMsg : public NavMsg {
363public:
364 PluginMsg()
365 : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
366
367 PluginMsg(const std::string& _name, const std::string& _dest_host,
368 const std::string& msg)
369 : NavMsg(NavAddr::Bus::Plugin, std::make_shared<const NavAddr>(
370 NavAddr::Bus::Plugin, "Internal")),
371 name(_name),
372 message(msg),
373 dest_host(_dest_host) {}
374
375 PluginMsg(const std::string& _name, const std::string& msg)
376 : PluginMsg(_name, "localhost", msg) {}
377
378 virtual ~PluginMsg() = default;
379
380 std::string key() const { return std::string("plug.json-") + name; };
381
382 std::string to_string() const;
383
384 const std::string name;
385 const std::string message;
386 const std::string dest_host;
387};
388
390class SignalkMsg : public NavMsg {
391public:
392 SignalkMsg()
393 : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
394
395 SignalkMsg(std::string _context_self, std::string _context,
396 std::string _raw_message, std::string _iface)
397 : NavMsg(NavAddr::Bus::Signalk,
398 std::make_shared<const NavAddr>(NavAddr::Bus::Signalk, _iface)),
399 context_self(_context_self),
400 context(_context),
401 raw_message(_raw_message) {};
402
403 virtual ~SignalkMsg() = default;
404
405 std::string key() const { return std::string("signalK"); };
406
407 std::string to_string() const { return raw_message; }
408
409 struct in_addr dest;
410 struct in_addr src;
411 std::string context_self;
412 std::string context;
413 std::string raw_message;
414};
415
417class NullNavMsg : public NavMsg {
418public:
419 NullNavMsg()
420 : NavMsg(NavAddr::Bus::Undef, std::make_shared<const NavAddr>()) {}
421
422 virtual ~NullNavMsg() = default;
423
424 std::string key() const { return "navmsg-undef"; }
425};
426
427#endif // DRIVER_NAVMSG_H
Interface implemented by classes which listens.
Definition observable.h:64
Where messages are sent to or received from.
const std::string iface
Physical device for 0183, else a unique string.
Actual data sent between application and transport layer.
std::string GetKey() const
Alias for key().
virtual std::string to_vdr() const
Return message in unquoted format used by VDR plugin, see https://opencpn-manuals....
virtual std::string key() const =0
Return unique key used by observable to notify/listen.
std::shared_ptr< const NavAddr > source
Source address is set by drivers when receiving, unused and should be empty when sending.
virtual std::string to_string() const
Return printable string for logging etc without trailing nl.
static NavAddr::Bus GetBusByKey(const std::string &key)
Return bus corresponding to given key.
A regular Nmea0183 message.
const std::string type
For example 'GGA'.
std::string key() const override
Return unique key used by observable to notify/listen.
const std::string talker
For example 'GP'.
const std::string payload
Complete NMEA0183 sentence, also prefix.
std::string to_vdr() const override
Return message in unquoted format used by VDR plugin, see https://opencpn-manuals....
static std::string MessageKey(const char *type)
Return key which should be used to listen to given message type.
std::string to_string() const override
Return printable string for logging etc without trailing nl.
See: https://github.com/OpenCPN/OpenCPN/issues/2729#issuecomment-1179506343.
std::string key() const override
Return unique key used by observable to notify/listen.
std::string to_string() const override
Print "bus key id payload".
std::string to_vdr() const override
Return message in unquoted format used by VDR plugin, see https://opencpn-manuals....
An invalid message, error return value.
std::string key() const
Return unique key used by observable to notify/listen.
A plugin to plugin json message over the REST interface.
std::string to_string() const
Return printable string for logging etc without trailing nl.
std::string key() const
Return unique key used by observable to notify/listen.
const std::string dest_host
hostname, ip address or 'localhost'
Plugin ABI encapsulation.
A parsed SignalK message over ipv4.
std::string key() const
Return unique key used by observable to notify/listen.
std::string to_string() const
Return printable string for logging etc without trailing nl.
General observable implementation with several specializations.
N2k uses CAN which defines the basic properties of messages.
Definition comm_navmsg.h:70
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