OpenCPN Partial API docs
Loading...
Searching...
No Matches
plugin_api.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2022 by David Register *
3 * Copyright (C) 2022 Alec Leamas *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 **************************************************************************/
20
26#include <memory>
27#include <sstream>
28#include <vector>
29
30#include <wx/event.h>
31#include <wx/fileconf.h>
32#include <wx/jsonval.h>
33#include <wx/jsonreader.h>
34#include <wx/tokenzr.h>
35
36#include "model/base_platform.h"
37#include "model/comm_appmsg.h"
40#include "model/comm_drv_n2k.h"
44#include "ocpn_plugin.h"
45#include "model/comm_drv_factory.h"
46#include "model/comm_drv_n2k_net.h"
47#include "model/comm_drv_n2k_serial.h"
48using namespace std;
49
50vector<uint8_t> GetN2000Payload(NMEA2000Id id, ObservedEvt ev) {
51 auto msg = UnpackEvtPointer<Nmea2000Msg>(ev);
52 return msg->payload;
53}
54
56 auto msg = UnpackEvtPointer<Nmea2000Msg>(ev);
57 return msg->source->to_string();
58}
59
61 auto msg = UnpackEvtPointer<Nmea0183Msg>(ev);
62 return msg->payload;
63}
64
66 auto msg = UnpackEvtPointer<PluginMsg>(ev);
67 return msg->message;
68}
69
70std::shared_ptr<void> GetSignalkPayload(ObservedEvt ev) {
71 auto msg = UnpackEvtPointer<SignalkMsg>(ev);
72 wxJSONReader reader;
73 wxJSONValue data;
74 reader.Parse(wxString(msg->raw_message), &data);
75
76 wxJSONValue root(wxJSONTYPE_OBJECT);
77 root["Data"] = data;
78 root["ErrorCount"] = reader.GetErrorCount();
79 root["WarningCount"] = reader.GetWarningCount();
80
81 root["Errors"] = wxJSONValue(wxJSONTYPE_ARRAY);
82 for (size_t i = 0; i < reader.GetErrors().GetCount(); i++)
83 root["Errors"].Append(reader.GetErrors().Item(i));
84
85 root["Warnings"] = wxJSONValue(wxJSONTYPE_ARRAY);
86 for (size_t i = 0; i < reader.GetWarnings().GetCount(); i++)
87 root["Warnings"].Append(reader.GetWarnings().Item(i));
88
89 root["Context"] = msg->context;
90 root["ContextSelf"] = msg->context_self;
91
92 return static_pointer_cast<void>(std::make_shared<wxJSONValue>(root));
93}
94
95std::shared_ptr<PI_Notification> GetNotificationMsgPayload(NotificationMsgId id,
96 ObservedEvt ev) {
97 auto msg = UnpackEvtPointer<NotificationMsg>(ev);
98 auto note = msg->notification;
99 auto rv = std::make_shared<PI_Notification>(
100 (PI_NotificationSeverity)note->GetSeverity(), note->GetMessage(),
101 note->GetTimeoutStart(), note->GetTimeoutLeft(), note->GetGuid());
102 rv->action_verb = msg->action_verb;
103 return rv;
104}
105
106shared_ptr<ObservableListener> GetListener(NMEA2000Id id, wxEventType et,
107 wxEvtHandler* eh) {
108 return make_shared<ObservableListener>(Nmea2000Msg(id.id), eh, et);
109}
110
111std::shared_ptr<ObservableListener> GetListener(NMEA0183Id id, wxEventType et,
112 wxEvtHandler* eh) {
113 return make_shared<ObservableListener>(Nmea0183Msg(id.id), eh, et);
114}
115
116shared_ptr<ObservableListener> GetListener(SignalkId id, wxEventType et,
117 wxEvtHandler* eh) {
118 return make_shared<ObservableListener>(SignalkMsg(), eh, et);
119}
120
121shared_ptr<ObservableListener> GetListener(NavDataId id, wxEventType et,
122 wxEvtHandler* eh) {
123 return make_shared<ObservableListener>(BasicNavDataMsg(), eh, et);
124}
125
126std::shared_ptr<ObservableListener> GetListener(PluginMsgId id, wxEventType et,
127 wxEvtHandler* eh) {
128 return make_shared<ObservableListener>(PluginMsg(id.id, ""), eh, et);
129}
130
131std::shared_ptr<ObservableListener> GetListener(NotificationMsgId id,
132 wxEventType et,
133 wxEvtHandler* eh) {
134 return make_shared<ObservableListener>(NotificationMsg(), eh, et);
135}
136
138 auto msg = UnpackEvtPointer<BasicNavDataMsg>(ev);
139 PluginNavdata data;
140
141 data.lat = msg->pos.lat;
142 data.lon = msg->pos.lon;
143 data.sog = msg->sog;
144 data.cog = msg->cog;
145 data.var = msg->var;
146 data.hdt = msg->hdt;
147 data.time = msg->time;
148 return data;
149}
150
153std::vector<DriverHandle> GetActiveDrivers() {
154 std::vector<DriverHandle> result;
155
156 auto& registry = CommDriverRegistry::GetInstance();
157 const std::vector<DriverPtr>& drivers = registry.GetDrivers();
158
159 for (auto& driver : drivers) result.push_back(driver->Key());
160
161 return result;
162}
163
164const std::unordered_map<std::string, std::string> GetAttributes(
165 DriverHandle handle) {
166 auto& registry = CommDriverRegistry::GetInstance();
167 auto& drivers = registry.GetDrivers();
168 auto func = [handle](const DriverPtr d) { return d->Key() == handle; };
169 AbstractCommDriver* found = nullptr;
170 for (auto& d : drivers)
171 if (d->Key() == handle) found = d.get();
172 if (found)
173 return found->GetAttributes();
174 else
175 return {};
176}
177
179 DriverHandle handle, const std::shared_ptr<std::vector<uint8_t>>& payload) {
180 // Find the driver from the handle
181 auto& registry = CommDriverRegistry::GetInstance();
182 auto& drivers = registry.GetDrivers();
183 AbstractCommDriver* found = nullptr;
184 for (auto& d : drivers)
185 if (d->Key() == handle) found = d.get();
186 if (!found) {
188 }
189
190 // Determine protocol
191 std::unordered_map<std::string, std::string> attributes =
192 GetAttributes(handle);
193 auto protocol_it = attributes.find("protocol");
194 if (protocol_it == attributes.end()) return RESULT_COMM_INVALID_PARMS;
195 std::string protocol = protocol_it->second;
196
197 if (protocol == "nmea0183") {
198 auto d0183 = dynamic_cast<CommDriverN0183*>(found);
199
200 std::string msg(payload->begin(), payload->end());
201 std::string id = msg.substr(1, 5);
202 auto address = std::make_shared<NavAddr>();
203 auto msg_out = std::make_shared<Nmea0183Msg>(id, msg, address);
204 bool xmit_ok = d0183->SendMessage(msg_out, address);
206 } else if (protocol == "internal") {
207 std::string msg(payload->begin(), payload->end());
208 size_t space_pos = msg.find(" ");
209 if (space_pos == std::string::npos) return RESULT_COMM_INVALID_PARMS;
210 auto plugin_msg = std::make_shared<PluginMsg>(msg.substr(0, space_pos),
211 msg.substr(space_pos + 1));
212 NavMsgBus::GetInstance().Notify(static_pointer_cast<NavMsg>(plugin_msg));
214 } else {
216 }
217}
218
220 DriverHandle handle, int PGN, int destinationCANAddress, int priority,
221 const std::shared_ptr<std::vector<uint8_t>>& payload) {
222 uint64_t _PGN;
223 _PGN = PGN;
224
225 // Find the driver from the handle
226 auto& registry = CommDriverRegistry::GetInstance();
227 auto& drivers = registry.GetDrivers();
228
229 AbstractCommDriver* found(nullptr);
230 for (auto& d : drivers)
231 if (d->Key() == handle) found = d.get();
232 if (!found) {
234 }
235 auto dest_addr =
236 std::make_shared<const NavAddr2000>(found->iface, destinationCANAddress);
237 auto msg =
238 std::make_shared<const Nmea2000Msg>(_PGN, *payload, dest_addr, priority);
239 bool result = found->SendMessage(msg, dest_addr);
240
242}
243
245 std::vector<int>& pgn_list) {
246 if (!pgn_list.size()) return RESULT_COMM_INVALID_PARMS;
247
248 // Find the driver from the handle
249 auto& registry = CommDriverRegistry::GetInstance();
250 auto& drivers = registry.GetDrivers();
251 AbstractCommDriver* found(nullptr);
252 for (auto& d : drivers)
253 if (d->Key() == handle) found = d.get();
254
255 if (!found) {
257 }
258 auto dn2k = dynamic_cast<CommDriverN2K*>(found);
259
260 int nloop = 0;
261 for (size_t i = 0; i < pgn_list.size(); i++) {
262 int nTry = 5;
263 int iresult = -1;
264 nloop = 0;
265 while (nTry && iresult < 0) {
266 iresult = dn2k->SetTXPGN(pgn_list[i]);
267 nTry--;
268 nloop++;
269 }
270 if (iresult < 0) {
272 }
273 }
275}
276
278 return g_BasePlatform->GetPrivateDataDirPtr();
279}
280
281void ReloadConfigConnections() {
282 // Close and delete all active comm drivers
283 auto& registry = CommDriverRegistry::GetInstance();
284 registry.CloseAllDrivers();
285
286 // Reload config file connections parameters.
287 wxFileConfig* pConf = GetOCPNConfigObject();
288 if (pConf) {
289 TheConnectionParams().clear();
290 pConf->SetPath(_T ( "/Settings/NMEADataSource" ));
291
292 wxString connectionconfigs;
293 pConf->Read(_T( "DataConnections" ), &connectionconfigs);
294 if (!connectionconfigs.IsEmpty()) {
295 wxArrayString confs = wxStringTokenize(connectionconfigs, _T("|"));
296 for (size_t i = 0; i < confs.Count(); i++) {
297 ConnectionParams* prm = new ConnectionParams(confs[i]);
298 if (!prm->Valid) continue;
299 TheConnectionParams().push_back(prm);
300 }
301 }
302 }
303
304 // Reconnect enabled connections
305 for (auto* cp : TheConnectionParams()) {
306 if (cp->bEnabled) {
307 MakeCommDriver(cp);
308 cp->b_IsSetup = TRUE;
309 }
310 }
311}
312
318 const std::string& _message,
319 int _timeout_start, int _timeout_left,
320 std::string _guid) {
321 severity = _severity;
322 message = _message;
323 auto_timeout_start = _timeout_start;
324 auto_timeout_left = _timeout_left;
325 guid = _guid;
326}
327
328int GetActiveNotificationCount() {
329 auto& noteman = NotificationManager::GetInstance();
330 return noteman.GetNotificationCount();
331}
332
333PI_NotificationSeverity GetMaxActiveNotificationLevel() {
334 auto& noteman = NotificationManager::GetInstance();
335 return (PI_NotificationSeverity)noteman.GetMaxSeverity();
336}
337
338std::string RaiseNotification(const PI_NotificationSeverity _severity,
339 const std::string& _message, int timeout_secs) {
340 auto& noteman = NotificationManager::GetInstance();
341 auto notification = std::make_shared<Notification>(
342 (NotificationSeverity)_severity, _message, timeout_secs);
343 return noteman.AddNotification(notification);
344}
345
346bool AcknowledgeNotification(const std::string& guid) {
347 auto& noteman = NotificationManager::GetInstance();
348 return noteman.AcknowledgeNotification(guid);
349}
350
351std::vector<std::shared_ptr<PI_Notification>> GetActiveNotifications() {
352 auto& noteman = NotificationManager::GetInstance();
353 std::vector<std::shared_ptr<PI_Notification>> pi_notes;
354 for (auto note : noteman.GetNotifications()) {
355 auto pi_note = std::make_shared<PI_Notification>(
356 (PI_NotificationSeverity)note->GetSeverity(), note->GetMessage(),
357 note->GetTimeoutStart(), note->GetTimeoutLeft(), note->GetGuid());
358 pi_notes.push_back(pi_note);
359 }
360
361 return pi_notes;
362}
363
367PI_Comm_Status GetConnState(const std::string& iface, PI_Conn_Bus _bus) {
368 // Translate API bus to internal NavAddr::Bus
369 NavAddr::Bus ibus = NavAddr::Bus::Undef;
370 switch (_bus) {
371 case PI_Conn_Bus::N0183:
372 ibus = NavAddr::Bus::N0183;
373 break;
374
375 case PI_Conn_Bus::Signalk:
376 ibus = NavAddr::Bus::Signalk;
377 break;
378
379 case PI_Conn_Bus::N2000:
380 ibus = NavAddr::Bus::N2000;
381 break;
382
383 default:
384 break;
385 }
386
387 DriverStats stats;
388 if (ibus != NavAddr::Bus::Undef) {
389 auto& registry = CommDriverRegistry::GetInstance();
390 auto& drivers = registry.GetDrivers();
391 auto& found_driver = FindDriver(drivers, iface, ibus);
392 if (found_driver) {
393 auto stats_provider =
394 dynamic_cast<DriverStatsProvider*>(found_driver.get());
395 if (stats_provider) {
396 stats = stats_provider->GetDriverStats();
397 }
398 }
399 }
400
402 if (stats.available) {
403 if (stats.rx_count)
404 rv.state = PI_Comm_State::Ok;
405 else
406 rv.state = PI_Comm_State::NoData;
407 } else
408 rv.state = PI_Comm_State::Unavailable;
409
410 rv.rx_count = stats.rx_count;
411 rv.tx_count = stats.tx_count;
412 rv.error_count = stats.error_count;
413
414 return rv;
415}
Common interface for all drivers.
Definition comm_driver.h:58
const std::string iface
Physical device for 0183, else a unique string.
Definition comm_driver.h:88
wxString * GetPrivateDataDirPtr()
Legacy compatibility syntactic sugar for GetPrivateDataDir().
NMEA0183 drivers common part.
Driver interface providing driver statistics.
void Notify(std::shared_ptr< const NavMsg > message)
Accept message received by driver, make it available for upper layers.
A regular Nmea0183 message.
See: https://github.com/OpenCPN/OpenCPN/issues/2729#issuecomment-1179506343.
Custom event class for OpenCPN's notification system.
unsigned error_count
Number of detected errors since program start.
unsigned tx_count
Number of bytes sent since program start.
unsigned rx_count
Number of bytes received since program start.
PI_Notification(PI_NotificationSeverity _severity, const std::string &_message, int _timeout_start, int _timeout_left, std::string _guid)
Plugin Notification Framework support.
A plugin to plugin json message over the REST interface.
A parsed SignalK message over ipv4.
The JSON parser.
Definition jsonreader.h:50
const wxArrayString & GetWarnings() const
Return a reference to the warning message's array.
const wxArrayString & GetErrors() const
Return a reference to the error message's array.
int GetErrorCount() const
Return the size of the error message's array.
int GetWarningCount() const
Return the size of the warning message's array.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
Definition jsonval.h:84
NMEA0183 over IP driver.
NMEA0183 serial driver.
DriverPtr & FindDriver(const std::vector< DriverPtr > &drivers, const std::string &iface, const NavAddr::Bus _bus)
Search list of drivers for a driver with given interface string.
Driver registration container, a singleton.
Raw messages layer, supports sending and recieving navmsg messages.
Class NotificationManager.
PlugIn Object Definition/API.
CommDriverResult
Error return values
@ RESULT_COMM_INVALID_PARMS
Invalid parameters provided to operation.
@ RESULT_COMM_TX_ERROR
Error occurred during transmission.
@ RESULT_COMM_REGISTER_PGN_ERROR
Failed to register PGN parameters.
@ RESULT_COMM_NO_ERROR
Operation completed successfully.
@ RESULT_COMM_INVALID_HANDLE
Invalid or unknown driver handle specified.
PI_NotificationSeverity
Plugin Notification Framework support.
std::string DriverHandle
Plugin API supporting direct access to comm drivers for output purposes.
wxFileConfig * GetOCPNConfigObject(void)
Gets OpenCPN's configuration object.
PI_Comm_Status GetConnState(const std::string &iface, PI_Conn_Bus _bus)
Plugin polled Comm Status support.
std::string GetPluginMsgPayload(PluginMsgId id, ObservedEvt ev)
Retrieve the string in a plugin message, internal or received on the REST insterface.
std::string GetN0183Payload(NMEA0183Id id, ObservedEvt ev)
Return payload in a received n0183 message of type id in ev.
PluginNavdata GetEventNavdata(ObservedEvt ev)
Return BasicNavDataMsg decoded data available in ev.
std::shared_ptr< PI_Notification > GetNotificationMsgPayload(NotificationMsgId id, ObservedEvt ev)
Retrieve the Notification Event in a Notification message.
CommDriverResult WriteCommDriverN2K(DriverHandle handle, int PGN, int destinationCANAddress, int priority, const std::shared_ptr< std::vector< uint8_t > > &payload)
Send a PGN message to an NMEA2000 address.
shared_ptr< ObservableListener > GetListener(NMEA2000Id id, wxEventType et, wxEvtHandler *eh)
Gets listener for NMEA 2000 messages.
std::vector< DriverHandle > GetActiveDrivers()
Comm port plugin TX support methods
const std::unordered_map< std::string, std::string > GetAttributes(DriverHandle handle)
Query a specific driver for attributes.
std::string GetN2000Source(NMEA2000Id id, ObservedEvt ev)
Return source identifier (iface) of a received n2000 message of type id in ev.
vector< uint8_t > GetN2000Payload(NMEA2000Id id, ObservedEvt ev)
Return N2K payload for a received n2000 message of type id in ev.
std::shared_ptr< void > GetSignalkPayload(ObservedEvt ev)
Get SignalK status payload after receiving a message.
wxString * GetpPrivateApplicationDataLocation(void)
Gets private application data directory.
CommDriverResult WriteCommDriver(DriverHandle handle, const std::shared_ptr< std::vector< uint8_t > > &payload)
Send a non-NMEA2000 message.
CommDriverResult RegisterTXPGNs(DriverHandle handle, std::vector< int > &pgn_list)
Register PGNs that this application intends to transmit for some NMEA 2000 adapters like Actisense NG...
Driver statistics report.
unsigned tx_count
Number of bytes sent since program start.
unsigned rx_count
Number of bytes received since program start.
unsigned error_count
Number of detected errors since program start.
Identifier for NMEA 0183 sentence types.
Identifier for NMEA 2000 message types.
Navigation data message identifier.
Facade for NotificationMsg.
Facade for NavAddrPluginMsg.
Basic navigation data structure.
double lat
Latitude in decimal degrees.
Identifier for Signal K paths.