@irsdk-node/native 5.2.2 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,61 +1,71 @@
1
- #include "./irsdk_defines.h"
2
1
  #include "./irsdk_node.h"
2
+ #include "./irsdk/irsdk_defines.h"
3
3
  #include "./logger.h"
4
4
  #include <cstdio>
5
- #include <napi.h>
6
5
  #include <napi-inl.h>
6
+ #include <napi.h>
7
7
  #include <string.h>
8
8
 
9
- static const char *K_IRSDK_CLASS_EXPORT_NAME = "iRacingSdkNode";
9
+ using namespace irsdk_node;
10
+
11
+ static const char* K_IRSDK_CLASS_EXPORT_NAME = "iRacingSdkNode";
10
12
 
11
13
  // ---------------------------
12
14
  // Constructors
13
15
  // ---------------------------
14
16
  Napi::Object iRacingSdkNode::Init(Napi::Env aEnv, Napi::Object aExports)
15
17
  {
16
- Napi::Function func = DefineClass(aEnv, K_IRSDK_CLASS_EXPORT_NAME, {
17
- // Properties
18
- InstanceAccessor<&iRacingSdkNode::_napi_prop_getCurrSessionDataVer>("currDataVersion"),
19
- InstanceAccessor<&iRacingSdkNode::_napi_prop_getEnableLogging, &iRacingSdkNode::_napi_prop_setEnableLogging>("enableLogging"),
20
- InstanceAccessor<&iRacingSdkNode::_napi_prop_getLogLevel, &iRacingSdkNode::_napi_prop_setLogLevel>("logLevel"),
21
- InstanceAccessor<&iRacingSdkNode::_napi_prop_getIsMocked>("isMocked"),
22
-
23
- // Methods
24
- // Control
25
- InstanceMethod("startSDK", &iRacingSdkNode::_napi_startSdk),
26
- InstanceMethod("stopSDK", &iRacingSdkNode::_napi_stopSdk),
27
- InstanceMethod("waitForData", &iRacingSdkNode::_napi_waitForData),
28
- InstanceMethod("broadcast", &iRacingSdkNode::_napi_broadcastMessage),
29
- // Getters
30
- InstanceMethod("isRunning", &iRacingSdkNode::_napi_isRunning),
31
- InstanceMethod("getSessionVersionNum", &iRacingSdkNode::_napi_getSessionVersionNum),
32
- InstanceMethod("getSessionConnectionID", &iRacingSdkNode::_napi_getSessionConnectionID),
33
- InstanceMethod("getSessionData", &iRacingSdkNode::_napi_getSessionData),
34
- InstanceMethod("getTelemetryData", &iRacingSdkNode::_napi_getTelemetryData),
35
- InstanceMethod("getTelemetryVariable", &iRacingSdkNode::GetTelemetryVar),
36
- // Helpers
37
- InstanceMethod("__getTelemetryTypes", &iRacingSdkNode::_napi_getTelemetryTypes)
38
- });
39
-
40
- Napi::FunctionReference *constructor = new Napi::FunctionReference();
41
- *constructor = Napi::Persistent(func);
42
- aEnv.SetInstanceData(constructor);
43
-
44
- aExports.Set(K_IRSDK_CLASS_EXPORT_NAME, func);
45
- return aExports;
46
- }
47
-
48
- iRacingSdkNode::iRacingSdkNode(const Napi::CallbackInfo &aInfo)
49
- : Napi::ObjectWrap<iRacingSdkNode>(aInfo),
50
- _data(NULL),
51
- _bufLineLen(0),
52
- _sessionStatusID(0),
53
- _lastSessionCt(-1),
54
- _sessionData(NULL),
55
- _logger(irsdk_node::LogLevel_None)
56
- {
57
- printf("Initializing iRacingSdkNode\n");
58
- }
18
+ Napi::Function func = DefineClass(
19
+ aEnv,
20
+ K_IRSDK_CLASS_EXPORT_NAME,
21
+ { // Properties
22
+ InstanceAccessor<&iRacingSdkNode::_napi_prop_getCurrSessionDataVer>("currDataVersion"),
23
+ InstanceAccessor(
24
+ "enableLogging",
25
+ &iRacingSdkNode::_napi_prop_getEnableLogging,
26
+ &iRacingSdkNode::_napi_prop_setEnableLogging
27
+ ),
28
+ InstanceAccessor(
29
+ "logLevel",
30
+ &iRacingSdkNode::_napi_prop_getLogLevel,
31
+ &iRacingSdkNode::_napi_prop_setLogLevel
32
+ ),
33
+ InstanceAccessor<&iRacingSdkNode::_napi_prop_getIsMocked>("isMocked"),
34
+
35
+ // Methods
36
+ // Control
37
+ InstanceMethod("startSDK", &iRacingSdkNode::_napi_startSdk),
38
+ InstanceMethod("stopSDK", &iRacingSdkNode::_napi_stopSdk),
39
+ InstanceMethod("waitForData", &iRacingSdkNode::_napi_waitForData),
40
+ InstanceMethod("broadcast", &iRacingSdkNode::_napi_broadcastMessage),
41
+ // Getters
42
+ InstanceMethod("isRunning", &iRacingSdkNode::_napi_isRunning),
43
+ InstanceMethod("getSessionVersionNum", &iRacingSdkNode::_napi_getSessionVersionNum),
44
+ InstanceMethod("getSessionConnectionID", &iRacingSdkNode::_napi_getSessionConnectionID),
45
+ InstanceMethod("getSessionData", &iRacingSdkNode::_napi_getSessionData),
46
+ InstanceMethod("getTelemetryData", &iRacingSdkNode::_napi_getTelemetryData),
47
+ InstanceMethod("getTelemetryVariable", &iRacingSdkNode::_napi_getTelemetryVar),
48
+ // Helpers
49
+ InstanceMethod("__getTelemetryTypes", &iRacingSdkNode::_napi_getTelemetryTypes) }
50
+ );
51
+
52
+ Napi::FunctionReference* constructor = new Napi::FunctionReference();
53
+ *constructor = Napi::Persistent(func);
54
+ aEnv.SetInstanceData(constructor);
55
+
56
+ aExports.Set(K_IRSDK_CLASS_EXPORT_NAME, func);
57
+ return aExports;
58
+ }
59
+
60
+ iRacingSdkNode::iRacingSdkNode(const Napi::CallbackInfo& aInfo)
61
+ : Napi::ObjectWrap<iRacingSdkNode>(aInfo)
62
+ , _data(NULL)
63
+ , _bufLineLen(0)
64
+ , _sessionStatusID(0)
65
+ , _lastSessionCt(-1)
66
+ , _sessionData(NULL)
67
+ , _logger(irsdk_node::LogLevel_None)
68
+ { }
59
69
 
60
70
  // Internal implementation ----------------------------------------------------
61
71
 
@@ -64,108 +74,91 @@ iRacingSdkNode::iRacingSdkNode(const Napi::CallbackInfo &aInfo)
64
74
 
65
75
  bool iRacingSdkNode::startup()
66
76
  {
67
- _logger.debug("StartSdk: Attempting to connect to SDK");
77
+ _logger.debug("StartSdk: Attempting to connect to SDK");
68
78
 
69
- if (!irsdk_isConnected())
70
- {
71
- _logger.debug("iRacing SDK not connected, connecting\n");
72
- bool result = irsdk_startup();
73
- _logger.info("Attempted SDK startup (result: %i)\n", result);
79
+ if (!irsdk_isConnected()) {
80
+ _logger.debug("iRacing SDK not connected, connecting\n");
81
+ bool result = irsdk_startup();
82
+ _logger.info("Attempted SDK startup (result: %i)\n", result);
74
83
 
75
- return result;
76
- }
84
+ return result;
85
+ }
77
86
 
78
- return true;
87
+ return true;
79
88
  }
80
89
 
81
90
  void iRacingSdkNode::shutdown()
82
91
  {
83
- _logger.info("Running irsdk-node shutdown");
84
- irsdk_shutdown();
85
- _resetData();
92
+ _logger.info("Running irsdk-node shutdown");
93
+ irsdk_shutdown();
94
+ _resetData();
86
95
  }
87
96
 
88
- bool iRacingSdkNode::isConnected() const
89
- {
90
- return _data != NULL && irsdk_isConnected();
91
- }
97
+ bool iRacingSdkNode::isConnected() const { return _data != NULL && irsdk_isConnected(); }
92
98
 
93
- int iRacingSdkNode::getSessionInfoStrCount()
94
- {
95
- return irsdk_getSessionInfoStrUpdate();
96
- }
99
+ int iRacingSdkNode::getSessionInfoStrCount() { return irsdk_getSessionInfoStrUpdate(); }
97
100
 
98
- bool iRacingSdkNode::wasSessionStrUpdated()
99
- {
100
- return _lastSessionCt != getSessionInfoStrCount();
101
- }
101
+ bool iRacingSdkNode::wasSessionStrUpdated() { return _lastSessionCt != getSessionInfoStrCount(); }
102
102
 
103
103
  bool iRacingSdkNode::waitForData(int aTimeoutMs)
104
104
  {
105
- // Wait for new data or for a session to start
106
- if (irsdk_waitForDataReady(aTimeoutMs, _data) && irsdk_getHeader())
107
- {
108
- _logger.debug("Got data from iRacing SDK\n");
109
- const irsdk_header *header = irsdk_getHeader();
110
-
111
- // New connection or data changed length
112
- if (!_data || _bufLineLen != header->bufLen)
113
- {
114
- _logger.debug("Connection started / data changed length\n");
115
-
116
- // Reset memory to hold incoming data
117
- if (_data) delete[] _data;
118
- _bufLineLen = header->bufLen;
119
- _data = new char[_bufLineLen];
120
-
121
- // Increment connection and reset info string and buffer length
122
- _sessionStatusID++;
123
- _lastSessionCt = -1;
124
-
125
- // Try to fill in the new data
126
- if (irsdk_getNewData(_data))
127
- {
128
- _logger.debug("New data retrieved successfully\n");
129
- return true;
130
- }
131
- } else if (_data)
132
- {
133
- _logger.debug("Data already available, ready for processing\n");
134
- return true;
135
- }
136
- } else if (!isConnected())
137
- {
138
- _logger.debug("Session ended. Cleaning up.\n");
139
- _resetData();
140
- }
141
-
142
- _logger.debug("No data available.\n");
143
- return false;
144
- }
105
+ // Wait for new data or for a session to start
106
+ if (irsdk_waitForDataReady(aTimeoutMs, _data) && irsdk_getHeader()) {
107
+ _logger.debug("Got data from iRacing SDK\n");
108
+ const irsdk_header* header = irsdk_getHeader();
109
+
110
+ // New connection or data changed length
111
+ if (!_data || _bufLineLen != header->bufLen) {
112
+ _logger.debug("Connection started / data changed length\n");
145
113
 
114
+ // Reset memory to hold incoming data
115
+ if (_data)
116
+ delete[] _data;
117
+ _bufLineLen = header->bufLen;
118
+ _data = new char[_bufLineLen];
146
119
 
147
- const char *iRacingSdkNode::getSessionStr()
120
+ // Increment connection and reset info string and buffer length
121
+ _sessionStatusID++;
122
+ _lastSessionCt = -1;
123
+
124
+ // Try to fill in the new data
125
+ if (irsdk_getNewData(_data)) {
126
+ _logger.debug("New data retrieved successfully\n");
127
+ return true;
128
+ }
129
+ } else if (_data) {
130
+ _logger.debug("Data already available, ready for processing\n");
131
+ return true;
132
+ }
133
+ } else if (!isConnected()) {
134
+ _logger.debug("Session ended. Cleaning up.\n");
135
+ _resetData();
136
+ }
137
+
138
+ _logger.debug("No data available.\n");
139
+ return false;
140
+ }
141
+
142
+ const char* iRacingSdkNode::getSessionStr()
148
143
  {
149
- if (!isConnected())
150
- return NULL;
151
-
152
- // If there is no session data cached or the session string is out of date,
153
- // fetch the latest and update the cached session count.
154
- if (!_sessionData || wasSessionStrUpdated())
155
- {
156
- _logger.debug("Invalid session data, fetching latest\n");
157
-
158
- int latestUpdate = getSessionInfoStrCount();
159
- _logger.info("Session data has been updated (prev: %d, new: %d)\n", _lastSessionCt, latestUpdate);
160
-
161
- _lastSessionCt = latestUpdate;
162
- _sessionData = irsdk_getSessionInfoStr();
163
- } else
164
- {
165
- _logger.debug("Session data is valid, re-using cached\n");
166
- }
167
-
168
- return _sessionData;
144
+ if (!isConnected())
145
+ return NULL;
146
+
147
+ // If there is no session data cached or the session string is out of date,
148
+ // fetch the latest and update the cached session count.
149
+ if (!_sessionData || wasSessionStrUpdated()) {
150
+ _logger.debug("Invalid session data, fetching latest\n");
151
+
152
+ int latestUpdate = getSessionInfoStrCount();
153
+ _logger.info("Session data has been updated (prev: %d, new: %d)\n", _lastSessionCt, latestUpdate);
154
+
155
+ _lastSessionCt = latestUpdate;
156
+ _sessionData = irsdk_getSessionInfoStr();
157
+ } else {
158
+ _logger.debug("Session data is valid, re-using cached\n");
159
+ }
160
+
161
+ return _sessionData;
169
162
  }
170
163
 
171
164
  // Private API
@@ -173,14 +166,15 @@ const char *iRacingSdkNode::getSessionStr()
173
166
 
174
167
  void iRacingSdkNode::_resetData()
175
168
  {
176
- _logger.debug("Resetting cached data...\n");
169
+ _logger.debug("Resetting cached data...\n");
177
170
 
178
- if (_data) delete[] _data;
179
- _data = NULL;
180
- _sessionData = NULL;
181
- _lastSessionCt = -1;
171
+ if (_data)
172
+ delete[] _data;
173
+ _data = NULL;
174
+ _sessionData = NULL;
175
+ _lastSessionCt = -1;
182
176
 
183
- _logger.debug("Finished resetting cached data\n");
177
+ _logger.debug("Finished resetting cached data\n");
184
178
  }
185
179
 
186
180
  // Node API -------------------------------------------------------------------
@@ -188,346 +182,339 @@ void iRacingSdkNode::_resetData()
188
182
  // Property implementations
189
183
  // -------------------------
190
184
 
191
- Napi::Value iRacingSdkNode::_napi_prop_getCurrSessionDataVer(const Napi::CallbackInfo &aInfo)
185
+ Napi::Value iRacingSdkNode::_napi_prop_getCurrSessionDataVer(const Napi::CallbackInfo& aInfo)
192
186
  {
193
- return Napi::Number::New(aInfo.Env(), this->_lastSessionCt);
187
+ return Napi::Number::New(aInfo.Env(), _lastSessionCt);
194
188
  }
195
189
 
196
- Napi::Value iRacingSdkNode::_napi_prop_getEnableLogging(const Napi::CallbackInfo &aInfo)
190
+ Napi::Value iRacingSdkNode::_napi_prop_getEnableLogging(const Napi::CallbackInfo& aInfo)
197
191
  {
198
- bool enabled = this->_logger.logLevel > irsdk_node::LogLevel_None;
199
- return Napi::Boolean::New(aInfo.Env(), enabled);
192
+ bool enabled = _logger.logLevel > irsdk_node::LogLevel_None;
193
+ return Napi::Boolean::New(aInfo.Env(), enabled);
200
194
  }
201
195
 
202
- void iRacingSdkNode::_napi_prop_setEnableLogging(const Napi::CallbackInfo &aInfo, const Napi::Value &aValue)
196
+ void iRacingSdkNode::_napi_prop_setEnableLogging(const Napi::CallbackInfo& aInfo, const Napi::Value& aValue)
203
197
  {
204
- Napi::Boolean enable;
205
- if (!aValue.IsBoolean())
206
- {
207
- enable = Napi::Boolean::New(aInfo.Env(), false);
208
- } else
209
- {
210
- enable = aValue.As<Napi::Boolean>();
211
- }
212
-
213
- this->_logger.logLevel = enable ? irsdk_node::LogLevel_Error : irsdk_node::LogLevel_None;
214
- this->_logger.warn("DEPRECATION WARNING: .enableLogging is deprecated, please use .logLevel instead\n");
198
+ Napi::Boolean enable;
199
+ if (!aValue.IsBoolean()) {
200
+ enable = Napi::Boolean::New(aInfo.Env(), false);
201
+ } else {
202
+ enable = aValue.As<Napi::Boolean>();
203
+ }
204
+
205
+ _logger.logLevel = enable ? irsdk_node::LogLevel_Error : irsdk_node::LogLevel_None;
206
+ _logger.warn("DEPRECATION WARNING: .enableLogging is deprecated, please use .logLevel instead\n");
215
207
  }
216
208
 
217
- Napi::Value iRacingSdkNode::_napi_prop_getLogLevel(const Napi::CallbackInfo &aInfo)
209
+ Napi::Value iRacingSdkNode::_napi_prop_getLogLevel(const Napi::CallbackInfo& aInfo)
218
210
  {
219
- return Napi::Number::New(aInfo.Env(), this->_logger.logLevel);
211
+ return Napi::Number::New(aInfo.Env(), _logger.logLevel);
220
212
  }
221
213
 
222
- void iRacingSdkNode::_napi_prop_setLogLevel(const Napi::CallbackInfo &aInfo, const Napi::Value &aValue)
214
+ void iRacingSdkNode::_napi_prop_setLogLevel(const Napi::CallbackInfo& aInfo, const Napi::Value& aValue)
223
215
  {
224
- if (!aValue.IsNumber())
225
- {
226
- this->_logger.warn(".logLevel must be given a number (or the LogLevel enum)\n");
227
- return;
228
- }
229
-
230
- irsdk_node::LogLevel level = static_cast<irsdk_node::LogLevel>(aValue.As<Napi::Number>().Int32Value());
231
- if (level < irsdk_node::LogLevel_None || level > irsdk_node::LogLevel_Debug)
232
- {
233
- this->_logger.warn("logLevel given an invalid value\n");
234
- return;
235
- }
236
-
237
- this->_logger.logLevel = level;
238
- this->_logger.info("Log level changed to %s\n", irsdk_node::Logger::GetLabelForLevel(level));
216
+ if (!aValue.IsNumber()) {
217
+ _logger.warn(".logLevel must be given a number (or the LogLevel enum)\n");
218
+ return;
219
+ }
220
+
221
+ irsdk_node::LogLevel level = static_cast<irsdk_node::LogLevel>(aValue.As<Napi::Number>().Int32Value());
222
+ if (level < irsdk_node::LogLevel_None || level > irsdk_node::LogLevel_Debug) {
223
+ _logger.warn("logLevel given an invalid value\n");
224
+ return;
225
+ }
226
+
227
+ _logger.logLevel = level;
228
+ _logger.info("Log level changed to %s\n", irsdk_node::Logger::GetLabelForLevel(level));
239
229
  }
240
230
 
241
- Napi::Value iRacingSdkNode::_napi_prop_getIsMocked(const Napi::CallbackInfo &aInfo)
231
+ Napi::Value iRacingSdkNode::_napi_prop_getIsMocked(const Napi::CallbackInfo& aInfo)
242
232
  {
243
- return Napi::Boolean::New(aInfo.Env(), false);
233
+ return Napi::Boolean::New(aInfo.Env(), false);
244
234
  }
245
235
 
246
-
247
236
  // Instance implementations
248
237
  // ---------------------------
249
238
 
250
239
  // SDK Control
251
- Napi::Value iRacingSdkNode::_napi_startSdk(const Napi::CallbackInfo &aInfo)
240
+ Napi::Value iRacingSdkNode::_napi_startSdk(const Napi::CallbackInfo& aInfo)
252
241
  {
253
- return Napi::Boolean::New(aInfo.Env(), startup());
242
+ return Napi::Boolean::New(aInfo.Env(), startup());
254
243
  }
255
244
 
256
- Napi::Value iRacingSdkNode::_napi_stopSdk(const Napi::CallbackInfo &aInfo)
245
+ Napi::Value iRacingSdkNode::_napi_stopSdk(const Napi::CallbackInfo& aInfo)
257
246
  {
258
- shutdown();
259
- return Napi::Boolean::New(aInfo.Env(), true);
247
+ shutdown();
248
+ return Napi::Boolean::New(aInfo.Env(), true);
260
249
  }
261
250
 
262
- Napi::Value iRacingSdkNode::_napi_waitForData(const Napi::CallbackInfo &aInfo)
251
+ Napi::Value iRacingSdkNode::_napi_waitForData(const Napi::CallbackInfo& aInfo)
263
252
  {
264
- int timeout = aInfo.Length() <= 0 || !aInfo[0].IsNumber()
265
- ? K_DEFAULT_TIMEOUT_MS
266
- : aInfo[0].As<Napi::Number>().Int32Value();
253
+ int timeout
254
+ = aInfo.Length() <= 0 || !aInfo[0].IsNumber() ? K_DEFAULT_TIMEOUT_MS : aInfo[0].As<Napi::Number>().Int32Value();
267
255
 
268
- if (timeout < 16) timeout = 16;
256
+ if (timeout < 16)
257
+ timeout = 16;
269
258
 
270
- return Napi::Boolean::New(aInfo.Env(), waitForData(timeout));
259
+ return Napi::Boolean::New(aInfo.Env(), waitForData(timeout));
271
260
  }
272
261
 
273
- Napi::Value iRacingSdkNode::_napi_broadcastMessage(const Napi::CallbackInfo &aInfo)
262
+ Napi::Value iRacingSdkNode::_napi_broadcastMessage(const Napi::CallbackInfo& aInfo)
274
263
  {
275
- auto env = aInfo.Env();
276
-
277
- // Determine message type
278
- if (aInfo.Length() <= 2 || !aInfo[0].IsNumber())
279
- {
280
- return Napi::Boolean::New(env, false);
281
- }
282
-
283
- if (aInfo.Length() == 4 && !aInfo[2].IsNumber())
284
- {
285
- return Napi::Boolean::New(env, false);
286
- }
287
-
288
- Napi::Number msgEnumIndex = aInfo[0].As<Napi::Number>();
289
- irsdk_BroadcastMsg msgType = static_cast<irsdk_BroadcastMsg>(msgEnumIndex.Int32Value());
290
-
291
- // Args
292
- Napi::Number arg1 = aInfo[1].As<Napi::Number>();
293
- Napi::Number arg2 = aInfo[2].As<Napi::Number>();
294
- Napi::Number arg3 = aInfo[3].As<Napi::Number>();
295
-
296
- irsdk_ChatCommandMode chatCommand = irsdk_ChatCommand_Cancel;
297
-
298
-
299
- // Handle each message independently.
300
- //
301
- // This could be consolidated, but then it becomes way too difficult to easily
302
- // grep what each messages expected API is, as some are not necessarily what
303
- switch (msgType)
304
- {
305
- // BroadcastCamSwitchPos: car position, group, camera
306
- // BroadcastCamSwitchNum: driver #, group, camera
307
- case irsdk_BroadcastCamSwitchPos:
308
- case irsdk_BroadcastCamSwitchNum:
309
- // First arg can be irsdk_csMode enum.
310
- // Any value above -1 equates to focusing on a specific driver.
311
- irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.Int32Value(), arg3.Int32Value());
312
- break;
313
-
314
- // irsdk_CameraState, unused, unused
315
- case irsdk_BroadcastCamSetState:
316
- irsdk_broadcastMsg(msgType, static_cast<irsdk_CameraState>(arg1.Int32Value()), 0);
317
- break;
318
-
319
- // speed, slowMotion, unused
320
- case irsdk_BroadcastReplaySetPlaySpeed:
321
- // Speed (arg1) should be multiples of 2 (0, 1, 2, 4, 8, 16), can be negative
322
- // Slow mo (arg2) should be 1 | 0
323
- irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.ToBoolean().Value());
324
- break;
325
-
326
- // irsdk_RpyPosMode, Frame Number (high, low)
327
- case irsdk_BroadcastReplaySetPlayPosition:
328
- irsdk_broadcastMsg(msgType, static_cast<irsdk_RpyPosMode>(arg1.Int32Value()), arg2.Int32Value());
329
- break;
330
-
331
- // irsdk_RpySrchMode, unused, unused
332
- case irsdk_BroadcastReplaySearch:
333
- irsdk_broadcastMsg(msgType, static_cast<irsdk_RpySrchMode>(arg1.Int32Value()), 0, 0);
334
- break;
335
-
336
- // irsdk_RpyStateMode, unused, unused
337
- case irsdk_BroadcastReplaySetState:
338
- irsdk_broadcastMsg(msgType, static_cast<irsdk_RpyStateMode>(arg1.Int32Value()), 0);
339
- break;
340
-
341
- // irsdk_ReloadTexturesMode, carIdx, unused
342
- case irsdk_BroadcastReloadTextures:
343
- irsdk_broadcastMsg(msgType, static_cast<irsdk_ReloadTexturesMode>(arg1.Int32Value()), arg2.Int32Value(), 0);
344
- break;
345
-
346
- // irsdk_ChatCommandMode, subCommand, unused
347
- case irsdk_BroadcastChatComand:
348
- chatCommand = static_cast<irsdk_ChatCommandMode>(arg1.Int32Value());
349
- if (chatCommand != irsdk_ChatCommand_Macro)
350
- {
351
- irsdk_broadcastMsg(msgType, chatCommand, 0);
352
- break;
353
- }
354
-
355
- // If the chat command is to use a macro, parse the macro id (1 - 15) (2nd arg)
356
- irsdk_broadcastMsg(msgType, chatCommand, arg2.Int32Value(), 0);
357
- break;
358
-
359
- // irsdk_PitCommandMode, parameter
360
- case irsdk_BroadcastPitCommand:
361
- irsdk_broadcastMsg(msgType, static_cast<irsdk_PitCommandMode>(arg1.Int32Value()), arg2.Int32Value());
362
- break;
363
-
364
- // irsdk_TelemCommandMode, unused, unused
365
- case irsdk_BroadcastTelemCommand:
366
- irsdk_broadcastMsg(msgType, static_cast<irsdk_TelemCommandMode>(arg1.Int32Value()), 0, 0);
367
- break;
368
-
369
- // irsdk_FFBCommandMode, value (float, high, low)
370
- case irsdk_BroadcastFFBCommand:
371
- irsdk_broadcastMsg(msgType, static_cast<irsdk_FFBCommandMode>(arg1.Int32Value()), arg2.FloatValue());
372
- break;
373
-
374
- // This does a search and not a direct jump, so it may take a while
375
- // sessionNum, sessionTimeMS (high, low)
376
- case irsdk_BroadcastReplaySearchSessionTime:
377
- irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.Int32Value());
378
- break;
379
-
380
- // irsdk_VideoCaptureMode, unused, unused
381
- case irsdk_BroadcastVideoCapture:
382
- irsdk_broadcastMsg(msgType, static_cast<irsdk_VideoCaptureMode>(arg1.Int32Value()), 0);
383
- break;
384
-
385
- // Unused + out-of-bounds
386
- default:
387
- this->_logger.error("Attempted to broadcast an unsupported message.\n");
388
- return Napi::Boolean::New(env, false);
389
- }
390
-
391
- return Napi::Boolean::New(env, true);
264
+ auto env = aInfo.Env();
265
+
266
+ // Determine message type
267
+ if (aInfo.Length() <= 2 || !aInfo[0].IsNumber()) {
268
+ return Napi::Boolean::New(env, false);
269
+ }
270
+
271
+ if (aInfo.Length() == 4 && !aInfo[2].IsNumber()) {
272
+ return Napi::Boolean::New(env, false);
273
+ }
274
+
275
+ Napi::Number msgEnumIndex = aInfo[0].As<Napi::Number>();
276
+ irsdk_BroadcastMsg msgType = static_cast<irsdk_BroadcastMsg>(msgEnumIndex.Int32Value());
277
+
278
+ // Args
279
+ Napi::Number arg1 = aInfo[1].As<Napi::Number>();
280
+ Napi::Number arg2 = aInfo[2].As<Napi::Number>();
281
+ Napi::Number arg3 = aInfo[3].As<Napi::Number>();
282
+
283
+ irsdk_ChatCommandMode chatCommand = irsdk_ChatCommand_Cancel;
284
+
285
+ // Handle each message independently.
286
+ //
287
+ // This could be consolidated, but then it becomes way too difficult to easily
288
+ // grep what each messages expected API is, as some are not necessarily what
289
+ switch (msgType) {
290
+ // BroadcastCamSwitchPos: car position, group, camera
291
+ // BroadcastCamSwitchNum: driver #, group, camera
292
+ case irsdk_BroadcastCamSwitchPos:
293
+ case irsdk_BroadcastCamSwitchNum:
294
+ // First arg can be irsdk_csMode enum.
295
+ // Any value above -1 equates to focusing on a specific driver.
296
+ irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.Int32Value(), arg3.Int32Value());
297
+ break;
298
+
299
+ // irsdk_CameraState, unused, unused
300
+ case irsdk_BroadcastCamSetState:
301
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_CameraState>(arg1.Int32Value()), 0);
302
+ break;
303
+
304
+ // speed, slowMotion, unused
305
+ case irsdk_BroadcastReplaySetPlaySpeed:
306
+ // Speed (arg1) should be multiples of 2 (0, 1, 2, 4, 8, 16), can be negative
307
+ // Slow mo (arg2) should be 1 | 0
308
+ irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.ToBoolean().Value());
309
+ break;
310
+
311
+ // irsdk_RpyPosMode, Frame Number (high, low)
312
+ case irsdk_BroadcastReplaySetPlayPosition:
313
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_RpyPosMode>(arg1.Int32Value()), arg2.Int32Value());
314
+ break;
315
+
316
+ // irsdk_RpySrchMode, unused, unused
317
+ case irsdk_BroadcastReplaySearch:
318
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_RpySrchMode>(arg1.Int32Value()), 0, 0);
319
+ break;
320
+
321
+ // irsdk_RpyStateMode, unused, unused
322
+ case irsdk_BroadcastReplaySetState:
323
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_RpyStateMode>(arg1.Int32Value()), 0);
324
+ break;
325
+
326
+ // irsdk_ReloadTexturesMode, carIdx, unused
327
+ case irsdk_BroadcastReloadTextures:
328
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_ReloadTexturesMode>(arg1.Int32Value()), arg2.Int32Value(), 0);
329
+ break;
330
+
331
+ // irsdk_ChatCommandMode, subCommand, unused
332
+ case irsdk_BroadcastChatComand:
333
+ chatCommand = static_cast<irsdk_ChatCommandMode>(arg1.Int32Value());
334
+ if (chatCommand != irsdk_ChatCommand_Macro) {
335
+ irsdk_broadcastMsg(msgType, chatCommand, 0);
336
+ break;
337
+ }
338
+
339
+ // If the chat command is to use a macro, parse the macro id (1 - 15) (2nd arg)
340
+ irsdk_broadcastMsg(msgType, chatCommand, arg2.Int32Value(), 0);
341
+ break;
342
+
343
+ // irsdk_PitCommandMode, parameter
344
+ case irsdk_BroadcastPitCommand:
345
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_PitCommandMode>(arg1.Int32Value()), arg2.Int32Value());
346
+ break;
347
+
348
+ // irsdk_TelemCommandMode, unused, unused
349
+ case irsdk_BroadcastTelemCommand:
350
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_TelemCommandMode>(arg1.Int32Value()), 0, 0);
351
+ break;
352
+
353
+ // irsdk_FFBCommandMode, value (float, high, low)
354
+ case irsdk_BroadcastFFBCommand:
355
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_FFBCommandMode>(arg1.Int32Value()), arg2.FloatValue());
356
+ break;
357
+
358
+ // This does a search and not a direct jump, so it may take a while
359
+ // sessionNum, sessionTimeMS (high, low)
360
+ case irsdk_BroadcastReplaySearchSessionTime:
361
+ irsdk_broadcastMsg(msgType, arg1.Int32Value(), arg2.Int32Value());
362
+ break;
363
+
364
+ // irsdk_VideoCaptureMode, unused, unused
365
+ case irsdk_BroadcastVideoCapture:
366
+ irsdk_broadcastMsg(msgType, static_cast<irsdk_VideoCaptureMode>(arg1.Int32Value()), 0);
367
+ break;
368
+
369
+ // Unused + out-of-bounds
370
+ default:
371
+ _logger.error("Attempted to broadcast an unsupported message.\n");
372
+ return Napi::Boolean::New(env, false);
373
+ }
374
+
375
+ return Napi::Boolean::New(env, true);
392
376
  }
393
377
 
394
378
  // SDK State Getters
395
- Napi::Value iRacingSdkNode::_napi_isRunning(const Napi::CallbackInfo &aInfo)
379
+ Napi::Value iRacingSdkNode::_napi_isRunning(const Napi::CallbackInfo& aInfo)
396
380
  {
397
- return Napi::Boolean::New(aInfo.Env(), isConnected());
381
+ return Napi::Boolean::New(aInfo.Env(), isConnected());
398
382
  }
399
383
 
400
- Napi::Value iRacingSdkNode::_napi_getSessionVersionNum(const Napi::CallbackInfo &aInfo)
384
+ Napi::Value iRacingSdkNode::_napi_getSessionVersionNum(const Napi::CallbackInfo& aInfo)
401
385
  {
402
- return Napi::Number::New(aInfo.Env(), getSessionInfoStrCount());
386
+ return Napi::Number::New(aInfo.Env(), getSessionInfoStrCount());
403
387
  }
404
388
 
405
- Napi::Value iRacingSdkNode::_napi_getSessionConnectionID(const Napi::CallbackInfo &aInfo)
389
+ Napi::Value iRacingSdkNode::_napi_getSessionConnectionID(const Napi::CallbackInfo& aInfo)
406
390
  {
407
- return Napi::Number::New(aInfo.Env(), this->_sessionStatusID);
391
+ return Napi::Number::New(aInfo.Env(), _sessionStatusID);
408
392
  }
409
393
 
410
- Napi::Value iRacingSdkNode::_napi_getSessionData(const Napi::CallbackInfo &aInfo)
394
+ Napi::Value iRacingSdkNode::_napi_getSessionData(const Napi::CallbackInfo& aInfo)
411
395
  {
412
- auto session = getSessionStr();
396
+ auto session = getSessionStr();
413
397
 
414
- if (session == NULL)
415
- return Napi::String::New(aInfo.Env(), "");
398
+ if (session == NULL)
399
+ return Napi::String::New(aInfo.Env(), "");
416
400
 
417
- return Napi::String::New(aInfo.Env(), session);
401
+ return Napi::String::New(aInfo.Env(), session);
418
402
  }
419
403
 
420
- Napi::Value iRacingSdkNode::GetTelemetryVar(const Napi::CallbackInfo &aInfo)
404
+ Napi::Value iRacingSdkNode::_napi_getTelemetryVar(const Napi::CallbackInfo& aInfo)
421
405
  {
422
- Napi::Env env = aInfo.Env();
423
-
424
- int varIndex;
425
- if (aInfo.Length() <= 0)
426
- {
427
- varIndex = 0;
428
- } else if (!aInfo[0].IsNumber())
429
- {
430
- if (aInfo[0].IsString())
431
- {
432
- const char *name = aInfo[0].As<Napi::String>().Utf8Value().c_str();
433
- return this->GetTelemetryVar(env, name);
434
- }
435
- varIndex = 0;
436
- }
437
-
438
- return this->GetTelemetryVarByIndex(env, varIndex);
406
+ Napi::Env env = aInfo.Env();
407
+
408
+ // If given malformed input, return null
409
+ if (aInfo.Length() <= 0) {
410
+ return env.Null();
411
+ }
412
+
413
+ auto arg = aInfo[0];
414
+
415
+ // When given a number, it should just be converted to an int and used as
416
+ // the index.
417
+ if (arg.IsNumber()) {
418
+ return _getTelemetryVarByIndex(env, arg.ToNumber().Int32Value());
419
+ }
420
+
421
+ // If given a string, we are searching by name. Convert to a c string so we
422
+ // can use it for lookup.
423
+ if (arg.IsString()) {
424
+ auto nameNapiStr = arg.ToString().Utf8Value();
425
+ auto nameCStr = nameNapiStr.c_str();
426
+ return _getTelemetryVarByName(env, nameCStr);
427
+ }
428
+
429
+ // All other inputs are invalid, return null.
430
+ return env.Null();
439
431
  }
440
432
 
441
- Napi::Value iRacingSdkNode::_napi_getTelemetryData(const Napi::CallbackInfo &aInfo)
433
+ Napi::Value iRacingSdkNode::_napi_getTelemetryData(const Napi::CallbackInfo& aInfo)
442
434
  {
443
- const irsdk_header *header = irsdk_getHeader();
444
- auto env = aInfo.Env();
445
- auto telemVars = Napi::Object::New(env);
446
-
447
- int count = header->numVars;
448
- for (int i = 0; i < count; i++)
449
- {
450
- auto telemVariable = this->GetTelemetryVarByIndex(env, i);
451
- if (telemVariable.IsObject() && telemVariable.Has("name"))
452
- {
453
- telemVars.Set(telemVariable.Get("name"), telemVariable);
454
- }
455
- }
456
-
457
- return telemVars;
435
+ const irsdk_header* header = irsdk_getHeader();
436
+ auto env = aInfo.Env();
437
+ auto telemVars = Napi::Object::New(env);
438
+
439
+ int count = header->numVars;
440
+ for (int i = 0; i < count; i++) {
441
+ auto telemVariable = _getTelemetryVarByIndex(env, i);
442
+ if (telemVariable.IsObject() && telemVariable.Has("name")) {
443
+ telemVars.Set(telemVariable.Get("name"), telemVariable);
444
+ }
445
+ }
446
+
447
+ return telemVars;
458
448
  }
459
449
 
460
- // Helpers
461
- Napi::Value iRacingSdkNode::_napi_getTelemetryTypes(const Napi::CallbackInfo &aInfo)
450
+ Napi::Value iRacingSdkNode::_napi_getTelemetryTypes(const Napi::CallbackInfo& aInfo)
462
451
  {
463
- auto env = aInfo.Env();
464
- auto result = Napi::Object::New(env);
465
-
466
- const int count = irsdk_getHeader()->numVars;
467
- const irsdk_varHeader *varHeader;
468
- for (int i = 0; i < count; i++)
469
- {
470
- varHeader = irsdk_getVarHeaderEntry(i);
471
- result.Set(varHeader->name, Napi::Number::New(env, varHeader->type));
472
- }
473
-
474
- return result;
452
+ auto env = aInfo.Env();
453
+ auto result = Napi::Object::New(env);
454
+
455
+ const int count = irsdk_getHeader()->numVars;
456
+ const irsdk_varHeader* varHeader;
457
+ for (int i = 0; i < count; i++) {
458
+ varHeader = irsdk_getVarHeaderEntry(i);
459
+ result.Set(varHeader->name, Napi::Number::New(env, varHeader->type));
460
+ }
461
+
462
+ return result;
475
463
  }
476
464
 
477
- // ---------------------------
478
- // Helper functions
479
- // ---------------------------
480
- bool iRacingSdkNode::GetTelemetryBool(int aEntry, int aIndex)
465
+ // Helpers ---------------------------------------------------------------------
466
+ bool iRacingSdkNode::_getTelemetryBool(int aEntry, int aIndex)
481
467
  {
482
- const irsdk_varHeader *headerVar = irsdk_getVarHeaderEntry(aEntry);
483
- return *(reinterpret_cast<bool const *>(_data + headerVar->offset) + aIndex);
468
+ const irsdk_varHeader* headerVar = irsdk_getVarHeaderEntry(aEntry);
469
+ return *(reinterpret_cast<bool const*>(_data + headerVar->offset) + aIndex);
484
470
  }
485
471
 
486
- int iRacingSdkNode::GetTelemetryInt(int aEntry, int aIndex)
472
+ int iRacingSdkNode::_getTelemetryInt(int aEntry, int aIndex)
487
473
  {
488
- // Each int is 4 bytes
489
- const irsdk_varHeader *headerVar = irsdk_getVarHeaderEntry(aEntry);
490
- return *(reinterpret_cast<int const *>(_data + headerVar->offset) + aIndex * 4);
474
+ // Each int is 4 bytes
475
+ const irsdk_varHeader* headerVar = irsdk_getVarHeaderEntry(aEntry);
476
+ return *(reinterpret_cast<int const*>(_data + headerVar->offset) + aIndex * 4);
491
477
  }
492
478
 
493
- float iRacingSdkNode::GetTelemetryFloat(int aEntry, int aIndex)
479
+ float iRacingSdkNode::_getTelemetryFloat(int aEntry, int aIndex)
494
480
  {
495
- // Each float is 4 bytes
496
- const irsdk_varHeader *headerVar = irsdk_getVarHeaderEntry(aEntry);
497
- return *(reinterpret_cast<float const *>(_data + headerVar->offset) + aIndex * 4);
481
+ // Each float is 4 bytes
482
+ const irsdk_varHeader* headerVar = irsdk_getVarHeaderEntry(aEntry);
483
+ return *(reinterpret_cast<float const*>(_data + headerVar->offset) + aIndex * 4);
498
484
  }
499
485
 
500
- double iRacingSdkNode::GetTelemetryDouble(int aEntry, int aIndex)
486
+ double iRacingSdkNode::_getTelemetryDouble(int aEntry, int aIndex)
501
487
  {
502
- // Each double is 8 bytes
503
- const irsdk_varHeader *headerVar = irsdk_getVarHeaderEntry(aEntry);
504
- return *(reinterpret_cast<double const *>(_data + headerVar->offset) + aIndex * 8);
488
+ // Each double is 8 bytes
489
+ const irsdk_varHeader* headerVar = irsdk_getVarHeaderEntry(aEntry);
490
+ return *(reinterpret_cast<double const*>(_data + headerVar->offset) + aIndex * 8);
505
491
  }
506
492
 
507
- Napi::Object iRacingSdkNode::GetTelemetryVarByIndex(const Napi::Env aEnv, int aIndex)
493
+ // TODO: This should return null if the var is not found.
494
+ Napi::Object iRacingSdkNode::_getTelemetryVarByName(const Napi::Env aEnv, const char* aVarName)
508
495
  {
509
- auto headerVar = irsdk_getVarHeaderEntry(aIndex);
510
- auto telemVar = Napi::Object::New(aEnv);
511
-
512
- // Create entry object
513
- telemVar.Set("countAsTime", headerVar->countAsTime);
514
- telemVar.Set("length", headerVar->count);
515
- telemVar.Set("name", headerVar->name);
516
- telemVar.Set("description", headerVar->desc);
517
- telemVar.Set("unit", headerVar->unit);
518
- telemVar.Set("varType", headerVar->type);
519
-
520
- int dataSize = headerVar->count * irsdk_VarTypeBytes[headerVar->type];
521
- auto entryVal = Napi::ArrayBuffer::New(aEnv, dataSize);
522
- memcpy(entryVal.Data(), this->_data + headerVar->offset, dataSize);
523
-
524
- telemVar.Set("value", entryVal);
525
- return telemVar;
496
+ int varIndex = irsdk_varNameToIndex(aVarName);
497
+ return _getTelemetryVarByIndex(aEnv, varIndex);
526
498
  }
527
499
 
528
- Napi::Object iRacingSdkNode::GetTelemetryVar(const Napi::Env aEnv, const char *aVarName)
500
+ // TODO: This should return null if the var is not found.
501
+ Napi::Object iRacingSdkNode::_getTelemetryVarByIndex(const Napi::Env aEnv, int aIndex)
529
502
  {
530
- int varIndex = irsdk_varNameToIndex(aVarName);
531
- return this->GetTelemetryVarByIndex(aEnv, varIndex);
532
- }
503
+ auto headerVar = irsdk_getVarHeaderEntry(aIndex);
504
+ auto telemVar = Napi::Object::New(aEnv);
533
505
 
506
+ // Create entry object
507
+ telemVar.Set("countAsTime", headerVar->countAsTime);
508
+ telemVar.Set("length", headerVar->count);
509
+ telemVar.Set("name", headerVar->name);
510
+ telemVar.Set("description", headerVar->desc);
511
+ telemVar.Set("unit", headerVar->unit);
512
+ telemVar.Set("varType", headerVar->type);
513
+
514
+ int dataSize = headerVar->count * irsdk_VarTypeBytes[headerVar->type];
515
+ auto entryVal = Napi::ArrayBuffer::New(aEnv, dataSize);
516
+ memcpy(entryVal.Data(), _data + headerVar->offset, dataSize);
517
+
518
+ telemVar.Set("value", entryVal);
519
+ return telemVar;
520
+ }