forked from norbert-walter/esp32-nmea2000-obp60
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GwApi.h
280 lines (272 loc) · 9.74 KB
/
GwApi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#ifndef _GWAPI_H
#define _GWAPI_H
#include "GwMessage.h"
#include "N2kMsg.h"
#include "NMEA0183Msg.h"
#include "GWConfig.h"
#include "GwBoatData.h"
#include "GwXDRMappings.h"
#include <map>
class GwApi;
typedef void (*GwUserTaskFunction)(GwApi *);
//API to be used for additional tasks
class GwApi{
public:
class BoatValue{
const String name;
String format;
bool formatSet=false;
public:
double value=0;
bool valid=false;
int source=-1;
bool changed=false; //will be set by getBoatDataValues
BoatValue(){}
BoatValue(const String &n):name(n){
}
void setFormat(const String &format){
if (formatSet) return;
this->format=format;
formatSet=true;
}
const String & getName() const{
return name;
}
const String & getFormat() const{
return format;
}
};
/**
* an interface for the data exchange between tasks
* the core part will not handle this data at all but
* this interface ensures that there is a correct locking of the
* data to correctly handle multi threading
* The user code should not use this intterface directly
* but instead it should use the static functions
* apiGetXXX(GwApi *,...)
* apiSetXXX(GwApi *,...)
* that will be created by the macro DECLARE_TASK_INTERFACE
*/
class TaskInterfaces
{
public:
class Base
{
public:
virtual ~Base()
{
}
};
using Ptr = std::shared_ptr<Base>;
protected:
virtual bool iset(const String &file, const String &name, Ptr v) = 0;
virtual Ptr iget(const String &name, int &result) = 0;
virtual bool iclaim(const String &name, const String &task)=0;
public:
template <typename T>
bool set(const T &v){
return false;
}
template <typename T>
T get(int &res){
res=-1;
return T();
}
template <typename T>
bool claim(const String &task){
return false;
}
};
class Status{
public:
bool wifiApOn=false;
bool wifiClientOn=false;
bool wifiClientConnected=false;
String wifiApIp;
String systemName; //is also AP SSID
String wifiApPass;
String wifiClientIp;
String wifiClientSSID;
unsigned long usbRx=0;
unsigned long usbTx=0;
unsigned long serRx=0;
unsigned long serTx=0;
unsigned long ser2Rx=0;
unsigned long ser2Tx=0;
unsigned long tcpSerRx=0;
unsigned long tcpSerTx=0;
int tcpClients=0;
unsigned long tcpClRx=0;
unsigned long tcpClTx=0;
bool tcpClientConnected=false;
unsigned long n2kRx=0;
unsigned long n2kTx=0;
void empty(){
wifiApOn=false;
wifiClientOn=false;
wifiClientConnected=false;
wifiApIp=String();
systemName=String(); //is also AP SSID
wifiApPass=String();
wifiClientIp=String();
wifiClientSSID=String();
usbRx=0;
usbTx=0;
serRx=0;
serTx=0;
ser2Rx=0;
ser2Tx=0;
tcpSerRx=0;
tcpSerTx=0;
tcpClients=0;
tcpClRx=0;
tcpClTx=0;
tcpClientConnected=false;
n2kRx=0;
n2kTx=0;
}
};
/**
* thread safe methods - can directly be called from a user task
*/
virtual GwRequestQueue *getQueue()=0;
virtual void sendN2kMessage(const tN2kMsg &msg, bool convert=true)=0;
/**
* deprecated - sourceId will be ignored
*/
virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, int sourceId,bool convert=true)=0;
virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, bool convert=true)=0;
virtual int getSourceId()=0;
/**
* the returned config data must only be read in a user task
* writing to it is not thread safe and could lead to crashes
*/
virtual GwConfigHandler *getConfig()=0;
virtual GwLog *getLogger()=0;
virtual const char* getTalkerId()=0;
/**
* get a set of boat data values
* the provided list of BoatValue must be initialized with
* empty boatValues (see exampleTask source code)
* the method will fill the valid flag, the value and the format string of
* each boat value
* just make sure to have the list being of appropriate size (numValues)
*/
virtual void getBoatDataValues(int numValues,BoatValue **list)=0;
/**
* fill the status information
*/
virtual void getStatus(Status &status)=0;
/**
* access to counters for a task
* thread safe
* use the value returned from addCounter for the other operations
*/
virtual int addCounter(const String &){return -1;}
virtual void increment(int idx,const String &name,bool failed=false){}
virtual void reset(int idx){}
virtual void remove(int idx){}
virtual TaskInterfaces * taskInterfaces()=0;
/**
* only allowed during init methods
*/
virtual bool addXdrMapping(const GwXDRMappingDef &)=0;
virtual void addCapability(const String &name, const String &value)=0;
/**
* add a user task
* this allows you decide based on defines/config if a user task really should be added
* so this is the preferred solution over DECLARE_USERTASK
* The name should be similar to the function name of the user task (although not mandatory)
*/
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000)=0;
/**
* set a value that is used for calibration in config values
* for cfg types calset, calvalue
* @param name: the config name this value is used for
* @param value: the current value
*/
virtual void setCalibrationValue(const String &name, double value);
/**
* not thread safe methods
* accessing boat data must only be executed from within the main thread
* you need to use the request pattern as shown in GwExampleTask.cpp
*/
virtual GwBoatData *getBoatData()=0;
virtual ~GwApi(){}
};
/**
* a simple generic function to create runtime errors if some necessary values are not defined
*/
template<typename... T>
static void checkDef(T... args){};
#ifndef DECLARE_USERTASK
#define DECLARE_USERTASK(task)
#endif
#ifndef DECLARE_USERTASK_PARAM
#define DECLARE_USERTASK_PARAM(task,...)
#endif
#ifndef DECLARE_INITFUNCTION
#define DECLARE_INITFUNCTION(task)
#endif
#ifndef DECLARE_CAPABILITY
#define DECLARE_CAPABILITY(name,value)
#endif
#ifndef DECLARE_STRING_CAPABILITY
#define DECLARE_STRING_CAPABILITY(name,value)
#endif
/**
* macro to declare an interface that a task provides to other tasks
* this macro must be used in an File I<taskname>.h or GwI<taskname>.h
* the first parameter must be the name of the task that should be able
* to write this data (the same name as being used in DECLARE_TASK).
* The second parameter must be a type (class) that inherits from
* GwApi::TaskInterfaces::Base.
* This class must provide copy constructors and empty constructors.
* The attributes should only be simple values or structs but no pointers.
* example:
* class TestTaskApi: public GwApi::TaskInterfaces::Base{
* public:
* int ival1=0;
* int ival2=99;
* String sval="unset";
* };
* DECLARE_TASKIF(testTask,TestTaskApi);
* The macro will generate 2 static funtions:
*
* bool apiSetTestTaskApi(GwApi *api, const TestTaskApi &v);
* TestTaskApi apiGetTestTaskApi(GwApi *api, int &result);
*
* The setter will return true on success.
* It is intended to be used by the task that did declare the api.
* The getter will set the result to -1 if no data is available, otherwise
* it will return the update count (so you can check if there was a change
* compared to the last call).
* It is intended to be used by any task.
* Be aware that all the apis share a common namespace - so be sure to somehow
* make your API names unique.
*
*
*/
#define DECLARE_TASKIF_IMPL(type) \
template<> \
inline bool GwApi::TaskInterfaces::set(const type & v) {\
return iset(__FILE__,#type,GwApi::TaskInterfaces::Ptr(new type(v))); \
}\
template<> \
inline type GwApi::TaskInterfaces::get<type>(int &result) {\
auto ptr=iget(#type,result); \
if (!ptr) {\
result=-1; \
return type(); \
}\
type *tp=(type*)ptr.get(); \
return type(*tp); \
}\
template<> \
inline bool GwApi::TaskInterfaces::claim<type>(const String &task) {\
return iclaim(#type,task);\
}\
#ifndef DECLARE_TASKIF
#define DECLARE_TASKIF(type) DECLARE_TASKIF_IMPL(type)
#endif
#endif