OpenCPN Partial API docs
plugin_api.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Project: OpenCPN
4  * Purpose: Implement communications defined in ocpn_plugin.h
5  * Author: David Register, Alec Leamas
6  *
7  ***************************************************************************
8  * Copyright (C) 2022 by David Register, Alec Leamas *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the *
22  * Free Software Foundation, Inc., *
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24  **************************************************************************/
25 
28 #include <memory>
29 #include <sstream>
30 #include <vector>
31 
32 #include <wx/event.h>
33 #include <wx/jsonval.h>
34 #include <wx/jsonreader.h>
35 
36 #include "model/base_platform.h"
37 #include "model/comm_appmsg.h"
38 #include "model/comm_drv_n0183_net.h"
40 #include "model/comm_drv_n2k.h"
41 #include "model/comm_drv_registry.h"
42 #include "model/comm_navmsg_bus.h"
43 
44 #include "ocpn_plugin.h"
45 using namespace std;
46 
47 vector<uint8_t> GetN2000Payload(NMEA2000Id id, ObservedEvt ev) {
48  auto msg = UnpackEvtPointer<Nmea2000Msg>(ev);
49  return msg->payload;
50 }
51 
52 std::string GetN2000Source(NMEA2000Id id, ObservedEvt ev) {
53  auto msg = UnpackEvtPointer<Nmea2000Msg>(ev);
54  return msg->source->to_string();
55 }
56 
57 std::string GetN0183Payload(NMEA0183Id id, ObservedEvt ev) {
58  auto msg = UnpackEvtPointer<Nmea0183Msg>(ev);
59  return msg->payload;
60 }
61 
62 std::string GetPluginMsgPayload(PluginMsgId id, ObservedEvt ev) {
63  auto msg = UnpackEvtPointer<PluginMsg>(ev);
64  return msg->message;
65 }
66 
67 
68 std::shared_ptr<void> GetSignalkPayload(ObservedEvt ev) {
69  auto msg = UnpackEvtPointer<SignalkMsg>(ev);
70  wxJSONReader reader;
71  wxJSONValue data;
72  reader.Parse(wxString(msg->raw_message), &data);
73 
74  wxJSONValue root(wxJSONTYPE_OBJECT);
75  root["Data"] = data;
76  root["ErrorCount"] = reader.GetErrorCount();
77  root["WarningCount"] = reader.GetWarningCount();
78 
79  root["Errors"] = wxJSONValue(wxJSONTYPE_ARRAY);
80  for (size_t i = 0; i < reader.GetErrors().GetCount(); i++)
81  root["Errors"].Append(reader.GetErrors().Item(i));
82 
83  root["Warnings"] = wxJSONValue(wxJSONTYPE_ARRAY);
84  for (size_t i = 0; i < reader.GetWarnings().GetCount(); i++)
85  root["Warnings"].Append(reader.GetWarnings().Item(i));
86 
87  root["Context"] = msg->context;
88  root["ContextSelf"] = msg->context_self;
89 
90  return static_pointer_cast<void>(std::make_shared<wxJSONValue>(root));
91 }
92 
93 shared_ptr<ObservableListener> GetListener(NMEA2000Id id, wxEventType et,
94  wxEvtHandler* eh) {
95  return make_shared<ObservableListener>(Nmea2000Msg(id.id), eh,
96  et);
97 }
98 
99 std::shared_ptr<ObservableListener> GetListener(NMEA0183Id id, wxEventType et,
100  wxEvtHandler* eh) {
101  return make_shared<ObservableListener>(Nmea0183Msg(id.id), eh, et);
102 }
103 
104 shared_ptr<ObservableListener> GetListener(SignalkId id, wxEventType et,
105  wxEvtHandler* eh) {
106  return make_shared<ObservableListener>(SignalkMsg(), eh, et);
107 }
108 
109 shared_ptr<ObservableListener> GetListener(NavDataId id, wxEventType et,
110  wxEvtHandler* eh) {
111  return make_shared<ObservableListener>(BasicNavDataMsg(), eh, et);
112 }
113 
114 std::shared_ptr<ObservableListener> GetListener(PluginMsgId id, wxEventType et,
115  wxEvtHandler* eh) {
116  return make_shared<ObservableListener>(PluginMsg(id.id, ""), eh, et);
117 }
118 
119 
121  auto msg = UnpackEvtPointer<BasicNavDataMsg>(ev);
122  PluginNavdata data;
123 
124  data.lat = msg->pos.lat;
125  data.lon = msg->pos.lon;
126  data.sog = msg->sog;
127  data.cog = msg->cog;
128  data.var = msg->var;
129  data.hdt = msg->hdt;
130  data.time = msg->time;
131  return data;
132 }
133 
136 std::vector<DriverHandle> GetActiveDrivers() {
137  std::vector<DriverHandle> result;
138 
139  auto& registry = CommDriverRegistry::GetInstance();
140  const std::vector<std::shared_ptr<AbstractCommDriver>>& drivers =
141  registry.GetDrivers();
142 
143  for (auto& driver : drivers) result.push_back(driver->Key());
144 
145  return result;
146 }
147 
148 const std::unordered_map<std::string, std::string> GetAttributes(
149  DriverHandle handle) {
150  auto& registry = CommDriverRegistry::GetInstance();
151  auto drivers = registry.GetDrivers();
152  auto func = [handle](const DriverPtr d) { return d->Key() == handle; };
153  auto found = std::find_if(drivers.begin(), drivers.end(), func);
154 
155  std::unordered_map<std::string, std::string> rv;
156  if (found == drivers.end()) {
157  return rv;
158  }
159  return found->get()->GetAttributes();
160 }
161 
162 CommDriverResult WriteCommDriver(
163  DriverHandle handle, const std::shared_ptr<std::vector<uint8_t>>& payload) {
164  // Find the driver from the handle
165  auto& registry = CommDriverRegistry::GetInstance();
166  auto drivers = registry.GetDrivers();
167  auto func = [handle](const DriverPtr d) { return d->Key() == handle; };
168  auto found = std::find_if(drivers.begin(), drivers.end(), func);
169 
170  if (found == drivers.end()) {
171  return RESULT_COMM_INVALID_HANDLE;
172  }
173  auto driver = *found;
174 
175  // Determine protocol
176  std::unordered_map<std::string, std::string> attributes =
177  GetAttributes(handle);
178  auto protocol_it = attributes.find("protocol");
179  if (protocol_it == attributes.end()) return RESULT_COMM_INVALID_PARMS;
180  std::string protocol = protocol_it->second;
181 
182  if (protocol == "nmea0183") {
183  auto d0183 = std::dynamic_pointer_cast<CommDriverN0183>(driver);
184 
185  std::string msg(payload->begin(), payload->end());
186  std::string id = msg.substr(1, 5);
187  auto address = std::make_shared<NavAddr0183>(d0183->iface);
188  auto msg_out = std::make_shared<Nmea0183Msg>( id, msg, address);
189  bool xmit_ok = d0183->SendMessage(msg_out, address);
190  return xmit_ok ? RESULT_COMM_NO_ERROR : RESULT_COMM_TX_ERROR;
191  } else
192  return RESULT_COMM_INVALID_PARMS;
193 }
194 
196  DriverHandle handle, int PGN, int destinationCANAddress, int priority,
197  const std::shared_ptr<std::vector<uint8_t>>& payload) {
198  uint64_t _PGN;
199  _PGN = PGN;
200 
201  // Find the driver from the handle
202  auto& registry = CommDriverRegistry::GetInstance();
203  auto drivers = registry.GetDrivers();
204  auto func = [handle](const DriverPtr d) { return d->Key() == handle; };
205  auto found = std::find_if(drivers.begin(), drivers.end(), func);
206 
207  if (found == drivers.end()) {
208  return RESULT_COMM_INVALID_HANDLE;
209  }
210  auto driver = *found;
211  auto dest_addr = std::make_shared<const NavAddr2000>(driver->iface,
212  destinationCANAddress);
213  auto msg = std::make_shared<const Nmea2000Msg>(_PGN, *payload, dest_addr,
214  priority);
215  bool result = driver->SendMessage(msg, dest_addr);
216 
217  return RESULT_COMM_NO_ERROR;
218 }
219 
221  std::vector<int>& pgn_list) {
222  if (!pgn_list.size()) return RESULT_COMM_INVALID_PARMS;
223 
224  // Find the driver from the handle
225  auto& registry = CommDriverRegistry::GetInstance();
226  auto drivers = registry.GetDrivers();
227  auto func = [handle](const DriverPtr d) { return d->Key() == handle; };
228  auto driver = std::find_if(drivers.begin(), drivers.end(), func);
229 
230  if (driver == drivers.end()) {
231  return RESULT_COMM_INVALID_HANDLE;
232  }
233  auto dn2k = std::dynamic_pointer_cast<CommDriverN2K>(*driver);
234 
235  int nloop = 0;
236  for (size_t i = 0; i < pgn_list.size(); i++) {
237  int nTry = 5;
238  int iresult = -1;
239  nloop = 0;
240  while (nTry && iresult < 0) {
241  iresult = dn2k->SetTXPGN(pgn_list[i]);
242  nTry--;
243  nloop++;
244  }
245  if (iresult < 0) {
246  return RESULT_COMM_REGISTER_PGN_ERROR;
247  }
248  }
249  return RESULT_COMM_NO_ERROR;
250 }
251 
252 wxString* GetpPrivateApplicationDataLocation(void) {
253  return g_BasePlatform->GetPrivateDataDirPtr();
254 }
wxString * GetPrivateDataDirPtr()
Legacy compatibility syntactic sugar for GetPrivateDataDir().
A regular Nmea0183 message.
Definition: comm_navmsg.h:250
See: https://github.com/OpenCPN/OpenCPN/issues/2729#issuecomment-1179506343.
Definition: comm_navmsg.h:220
Adds a std::shared<void> element to wxCommandEvent.
Definition: ocpn_plugin.h:1652
A plugin to plugin json message over the REST interface.
Definition: comm_navmsg.h:292
A parsed SignalK message over ipv4.
Definition: comm_navmsg.h:319
NMEA0183 serial driver.
CommDriverResult
Error return values
Definition: ocpn_plugin.h:1796
std::string DriverHandle
Plugin API supporting direct access to comm drivers for output purposes.
Definition: ocpn_plugin.h:1792
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.
Definition: plugin_api.cpp:195
const std::unordered_map< std::string, std::string > GetAttributes(DriverHandle handle)
Query a specific driver for attributes
Definition: plugin_api.cpp:148
std::string GetN0183Payload(NMEA0183Id id, ObservedEvt ev)
Return payload in a received n0183 message of type id in ev.
Definition: plugin_api.cpp:57
std::shared_ptr< void > GetSignalkPayload(ObservedEvt ev)
Get SignalK status payload after receiving a message.
Definition: plugin_api.cpp:68
PluginNavdata GetEventNavdata(ObservedEvt ev)
Return BasicNavDataMsg decoded data available in ev.
Definition: plugin_api.cpp:120
vector< uint8_t > GetN2000Payload(NMEA2000Id id, ObservedEvt ev)
Return N2K payload for a received n2000 message of type id in ev.
Definition: plugin_api.cpp:47
std::string GetN2000Source(NMEA2000Id id, ObservedEvt ev)
Return source identifier (iface) of a received n2000 message of type id in ev.
Definition: plugin_api.cpp:52
std::vector< DriverHandle > GetActiveDrivers()
Comm port plugin TX support methods
Definition: plugin_api.cpp:136
CommDriverResult RegisterTXPGNs(DriverHandle handle, std::vector< int > &pgn_list)
Special NMEA2000 requirements NMEA2000 bus protocol device management requires that devices writing o...
Definition: plugin_api.cpp:220
Facade for NavAddr0183.
Definition: ocpn_plugin.h:1684
Facade for NavAddr2000.
Definition: ocpn_plugin.h:1675
Facade for BasicNavDataMsg.
Definition: ocpn_plugin.h:1747
Facade for NavAddrPluginMsg.
Definition: ocpn_plugin.h:1858
Available decoded data for plugins.
Definition: ocpn_plugin.h:1756
Facade for NavAddrSignalK.
Definition: ocpn_plugin.h:1693