signalk-vessels-to-ais 1.1.5 → 1.2.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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/index.js +220 -213
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -9,6 +9,7 @@ User can configure:
9
9
  - Own data can be added to AIS sending
10
10
 
11
11
  New:
12
+ - v1.2.0, updated fetch method, no need for NODE_TLS_REJECT_UNAUTHORIZED=0 anymore
12
13
  - v1.1.5, updated vessels within selected timeframe are sent out, radius filtering around own vessel and tag-block option added
13
14
  - v1.1.4, small fix
14
15
  - v1.1.3, add: own vessel data and sending interval modified
package/index.js CHANGED
@@ -23,6 +23,7 @@ SOFTWARE.
23
23
  */
24
24
 
25
25
  const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
26
+ const https = require('https');
26
27
  const AisEncode = require('ggencoder').AisEncode;
27
28
  const moment = require('moment');
28
29
  const haversine = require('haversine-distance');
@@ -38,22 +39,31 @@ module.exports = function createPlugin(app) {
38
39
  let sendOwn;
39
40
  let url;
40
41
  let intervalRun;
41
- let readInfo;
42
42
  const setStatus = app.setPluginStatus || app.setProviderStatus;
43
43
 
44
44
  let position_update;
45
45
  let useTag;
46
46
 
47
+ const httpsAgent = new https.Agent({
48
+ rejectUnauthorized: false,
49
+ });
50
+
51
+ let getParam;
52
+
47
53
  plugin.start = function (options, restartPlugin) {
48
54
  position_update = options.position_update * 60;
49
55
  useTag = options.useTag;
50
56
 
57
+ positionUpdate = options.position_update;
58
+ distance = options.distance;
59
+ sendOwn = options.sendOwn;
60
+
51
61
  let port = options.port || 3000;
52
62
  let portSec = options.portSec || 3443;
53
63
 
54
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
55
64
  url = 'https://localhost:' + portSec + '/signalk/v1/api/vessels';
56
- fetch(url, { method: 'GET' })
65
+ getParam = { method: 'GET', agent: httpsAgent };
66
+ fetch(url, getParam)
57
67
  .then((res) => {
58
68
  console.log(`${plugin.id}: SSL enabled, using https`);
59
69
  if (!res.ok) {
@@ -63,7 +73,8 @@ module.exports = function createPlugin(app) {
63
73
  })
64
74
  .catch(() => {
65
75
  url = 'http://localhost:' + port + '/signalk/v1/api/vessels';
66
- fetch(url, { method: 'GET' })
76
+ getParam = { method: 'GET' };
77
+ fetch(url, getParam)
67
78
  .then((res) => {
68
79
  console.log(`${plugin.id}: SSL disabled, using http`);
69
80
  if (!res.ok) {
@@ -71,17 +82,13 @@ module.exports = function createPlugin(app) {
71
82
  setStatus("Error accessing server. Check 'Allow Readonly Access' and enable it");
72
83
  }
73
84
  })
74
- .catch(() => {
75
- });
85
+ })
86
+ .finally(() => {
87
+ intervalRun = setInterval(readData, (positionUpdate * 60000), getParam);
76
88
  });
77
89
 
78
- positionUpdate = options.position_update;
79
- distance = options.distance;
80
- sendOwn = options.sendOwn;
81
-
82
90
  app.debug('Plugin started');
83
91
 
84
- intervalRun = setInterval(readInfo, (positionUpdate * 60000));
85
92
  };
86
93
 
87
94
  //----------------------------------------------------------------------------
@@ -173,219 +180,219 @@ module.exports = function createPlugin(app) {
173
180
  //----------------------------------------------------------------------------
174
181
  // Read and parse AIS data
175
182
 
176
- readInfo = function readData(options) {
177
- let i, mmsi, aisTime, aisDelay, shipName, lat, lon, sog, cog, rot, navStat, hdg, dst, callSign, imo, id, type;
178
- let draftCur, length, beam, ais, encMsg3, encMsg5, encMsg18, encMsg240, encMsg241, own;
179
- let ownLat = app.getSelfPath('navigation.position.value.latitude');
180
- let ownLon = app.getSelfPath('navigation.position.value.longitude');
181
- fetch(url, { method: 'GET' })
182
- .then((res) => res.json())
183
- .then((json) => {
184
- const jsonContent = JSON.parse(JSON.stringify(json));
185
- const numberAIS = Object.keys(jsonContent).length;
186
- for (i = 0; i < numberAIS; i++) {
187
- const jsonKey = Object.keys(jsonContent)[i];
188
-
189
- try {
190
- aisTime = jsonContent[jsonKey].sensors.ais.class.timestamp;
191
- if ((parseFloat((moment(new Date(Date.now())).diff(aisTime)/1000).toFixed(3))) < position_update) {
192
- aisDelay = true;
193
- } else {
194
- aisDelay = false;
183
+ function readData(getParam) {
184
+ let i, mmsi, aisTime, aisDelay, shipName, lat, lon, sog, cog, rot, navStat, hdg, dst, callSign, imo, id, type;
185
+ let draftCur, length, beam, ais, encMsg3, encMsg5, encMsg18, encMsg240, encMsg241, own;
186
+ let ownLat = app.getSelfPath('navigation.position.value.latitude');
187
+ let ownLon = app.getSelfPath('navigation.position.value.longitude');
188
+ fetch(url, getParam)
189
+ .then((res) => res.json())
190
+ .then((json) => {
191
+ const jsonContent = JSON.parse(JSON.stringify(json));
192
+ const numberAIS = Object.keys(jsonContent).length;
193
+ for (i = 0; i < numberAIS; i++) {
194
+ const jsonKey = Object.keys(jsonContent)[i];
195
+
196
+ try {
197
+ aisTime = jsonContent[jsonKey].sensors.ais.class.timestamp;
198
+ if ((parseFloat((moment(new Date(Date.now())).diff(aisTime)/1000).toFixed(3))) < position_update) {
199
+ aisDelay = true;
200
+ } else {
201
+ aisDelay = false;
202
+ }
203
+ } catch (error) {
204
+ if (i === 0) {
205
+ aisTime = new Date(Date.now()).toISOString();
206
+ aisDelay = true;
207
+ } else {
208
+ aisTime = null;
209
+ aisDelay = false;
210
+ }
195
211
  }
196
- } catch (error) {
197
- if (i === 0) {
198
- aisTime = new Date(Date.now()).toISOString();
199
- aisDelay = true;
200
- } else {
201
- aisTime = null;
202
- aisDelay = false;
212
+ try {
213
+ mmsi = jsonContent[jsonKey].mmsi;
214
+ } catch (error) { mmsi = null; }
215
+ try {
216
+ shipName = jsonContent[jsonKey].name;
217
+ } catch (error) { shipName = ''; }
218
+ try {
219
+ lat = jsonContent[jsonKey].navigation.position.value.latitude;
220
+ } catch (error) { lat = null; }
221
+ try {
222
+ lon = jsonContent[jsonKey].navigation.position.value.longitude;
223
+ } catch (error) { lon = null; }
224
+ try {
225
+ sog = msToKnots(jsonContent[jsonKey].navigation.speedOverGround.value);
226
+ } catch (error) { sog = null; }
227
+ try {
228
+ cog = radToDegrees(jsonContent[jsonKey].navigation.courseOverGroundTrue.value);
229
+ } catch (error) { cog = null; }
230
+ try {
231
+ rot = radToDegrees(jsonContent[jsonKey].navigation.rateOfTurn.value);
232
+ } catch (error) { rot = null; }
233
+ try {
234
+ navStat = stateMapping[jsonContent[jsonKey].navigation.state.value];
235
+ } catch (error) { navStat = ''; }
236
+ try {
237
+ hdg = radToDegrees(jsonContent[jsonKey].navigation.headingTrue.value);
238
+ } catch (error) { hdg = null; }
239
+ try {
240
+ dst = jsonContent[jsonKey].navigation.destination.commonName.value;
241
+ } catch (error) { dst = ''; }
242
+ try {
243
+ if (i === 0) {
244
+ callSign = jsonContent[jsonKey].communication.callsignVhf;
245
+ } else {
246
+ callSign = jsonContent[jsonKey].communication.value.callsignVhf;
247
+ }
248
+ } catch (error) { callSign = ''; }
249
+ try {
250
+ imo = (jsonContent[jsonKey].registrations.value.imo).substring(4, 20);
251
+ } catch (error) { imo = null; }
252
+ try {
253
+ id = jsonContent[jsonKey].design.aisShipType.value.id;
254
+ } catch (error) { id = null; }
255
+ try {
256
+ type = jsonContent[jsonKey].design.aisShipType.value.name;
257
+ } catch (error) { type = ''; }
258
+ try {
259
+ draftCur = (jsonContent[jsonKey].design.draft.value.current) / 10;
260
+ } catch (error) { draftCur = null; }
261
+ try {
262
+ length = jsonContent[jsonKey].design.length.value.overall;
263
+ } catch (error) { length = null; }
264
+ try {
265
+ beam = (jsonContent[jsonKey].design.beam.value) / 2;
266
+ } catch (error) { beam = null; }
267
+ try {
268
+ ais = jsonContent[jsonKey].sensors.ais.class.value;
269
+ } catch (error) { ais = null; }
270
+
271
+ if (shipName % 1 === 0) {
272
+ shipName = '';
203
273
  }
204
- }
205
- try {
206
- mmsi = jsonContent[jsonKey].mmsi;
207
- } catch (error) { mmsi = null; }
208
- try {
209
- shipName = jsonContent[jsonKey].name;
210
- } catch (error) { shipName = ''; }
211
- try {
212
- lat = jsonContent[jsonKey].navigation.position.value.latitude;
213
- } catch (error) { lat = null; }
214
- try {
215
- lon = jsonContent[jsonKey].navigation.position.value.longitude;
216
- } catch (error) { lon = null; }
217
- try {
218
- sog = msToKnots(jsonContent[jsonKey].navigation.speedOverGround.value);
219
- } catch (error) { sog = null; }
220
- try {
221
- cog = radToDegrees(jsonContent[jsonKey].navigation.courseOverGroundTrue.value);
222
- } catch (error) { cog = null; }
223
- try {
224
- rot = radToDegrees(jsonContent[jsonKey].navigation.rateOfTurn.value);
225
- } catch (error) { rot = null; }
226
- try {
227
- navStat = stateMapping[jsonContent[jsonKey].navigation.state.value];
228
- } catch (error) { navStat = ''; }
229
- try {
230
- hdg = radToDegrees(jsonContent[jsonKey].navigation.headingTrue.value);
231
- } catch (error) { hdg = null; }
232
- try {
233
- dst = jsonContent[jsonKey].navigation.destination.commonName.value;
234
- } catch (error) { dst = ''; }
235
- try {
236
- if (i === 0) {
237
- callSign = jsonContent[jsonKey].communication.callsignVhf;
238
- } else {
239
- callSign = jsonContent[jsonKey].communication.value.callsignVhf;
274
+ if (dst % 1 === 0) {
275
+ dst = '';
240
276
  }
241
- } catch (error) { callSign = ''; }
242
- try {
243
- imo = (jsonContent[jsonKey].registrations.value.imo).substring(4, 20);
244
- } catch (error) { imo = null; }
245
- try {
246
- id = jsonContent[jsonKey].design.aisShipType.value.id;
247
- } catch (error) { id = null; }
248
- try {
249
- type = jsonContent[jsonKey].design.aisShipType.value.name;
250
- } catch (error) { type = ''; }
251
- try {
252
- draftCur = (jsonContent[jsonKey].design.draft.value.current) / 10;
253
- } catch (error) { draftCur = null; }
254
- try {
255
- length = jsonContent[jsonKey].design.length.value.overall;
256
- } catch (error) { length = null; }
257
- try {
258
- beam = (jsonContent[jsonKey].design.beam.value) / 2;
259
- } catch (error) { beam = null; }
260
- try {
261
- ais = jsonContent[jsonKey].sensors.ais.class.value;
262
- } catch (error) { ais = null; }
263
-
264
- if (shipName % 1 === 0) {
265
- shipName = '';
266
- }
267
- if (dst % 1 === 0) {
268
- dst = '';
269
- }
270
- if (callSign % 1 === 0) {
271
- callSign = '';
272
- }
273
- if (type % 1 === 0) {
274
- type = '';
275
- }
276
-
277
- if (i === 0) {
278
- own = true;
279
- if (sendOwn) {
280
- ais = 'A';
281
- } else {
282
- ais = '';
277
+ if (callSign % 1 === 0) {
278
+ callSign = '';
279
+ }
280
+ if (type % 1 === 0) {
281
+ type = '';
283
282
  }
284
- } else {
285
- own = false;
286
- }
287
-
288
- const a = { lat: ownLat, lon: ownLon }
289
- const b = { lat: lat, lon: lon }
290
- let dist = (haversine(a, b)/1000).toFixed(2);
291
-
292
- if (dist <= distance) {
293
-
294
- encMsg3 = {
295
- own,
296
- aistype: 3, // class A position report
297
- repeat: 0,
298
- mmsi,
299
- navstatus: navStat,
300
- sog,
301
- lon,
302
- lat,
303
- cog,
304
- hdg,
305
- rot,
306
- };
307
-
308
- encMsg5 = {
309
- own,
310
- aistype: 5, // class A static
311
- repeat: 0,
312
- mmsi,
313
- imo,
314
- cargo: id,
315
- callsign: callSign,
316
- shipname: shipName,
317
- draught: draftCur,
318
- destination: dst,
319
- dimA: 0,
320
- dimB: length,
321
- dimC: beam,
322
- dimD: beam,
323
- };
324
283
 
325
- encMsg18 = {
326
- own,
327
- aistype: 18, // class B position report
328
- repeat: 0,
329
- mmsi,
330
- sog,
331
- accuracy: 0,
332
- lon,
333
- lat,
334
- cog,
335
- hdg,
336
- };
284
+ if (i === 0) {
285
+ own = true;
286
+ if (sendOwn) {
287
+ ais = 'A';
288
+ } else {
289
+ ais = '';
290
+ }
291
+ } else {
292
+ own = false;
293
+ }
337
294
 
338
- encMsg240 = {
339
- own,
340
- aistype: 24, // class B static
341
- repeat: 0,
342
- part: 0,
343
- mmsi,
344
- shipname: shipName,
345
- };
295
+ const a = { lat: ownLat, lon: ownLon }
296
+ const b = { lat: lat, lon: lon }
297
+ let dist = (haversine(a, b)/1000).toFixed(2);
346
298
 
347
- encMsg241 = {
348
- own,
349
- aistype: 24, // class B static
350
- repeat: 0,
351
- part: 1,
352
- mmsi,
353
- cargo: id,
354
- callsign: callSign,
355
- dimA: 0,
356
- dimB: length,
357
- dimC: beam,
358
- dimD: beam,
359
- };
299
+ if (dist <= distance) {
300
+
301
+ encMsg3 = {
302
+ own,
303
+ aistype: 3, // class A position report
304
+ repeat: 0,
305
+ mmsi,
306
+ navstatus: navStat,
307
+ sog,
308
+ lon,
309
+ lat,
310
+ cog,
311
+ hdg,
312
+ rot,
313
+ };
314
+
315
+ encMsg5 = {
316
+ own,
317
+ aistype: 5, // class A static
318
+ repeat: 0,
319
+ mmsi,
320
+ imo,
321
+ cargo: id,
322
+ callsign: callSign,
323
+ shipname: shipName,
324
+ draught: draftCur,
325
+ destination: dst,
326
+ dimA: 0,
327
+ dimB: length,
328
+ dimC: beam,
329
+ dimD: beam,
330
+ };
331
+
332
+ encMsg18 = {
333
+ own,
334
+ aistype: 18, // class B position report
335
+ repeat: 0,
336
+ mmsi,
337
+ sog,
338
+ accuracy: 0,
339
+ lon,
340
+ lat,
341
+ cog,
342
+ hdg,
343
+ };
344
+
345
+ encMsg240 = {
346
+ own,
347
+ aistype: 24, // class B static
348
+ repeat: 0,
349
+ part: 0,
350
+ mmsi,
351
+ shipname: shipName,
352
+ };
353
+
354
+ encMsg241 = {
355
+ own,
356
+ aistype: 24, // class B static
357
+ repeat: 0,
358
+ part: 1,
359
+ mmsi,
360
+ cargo: id,
361
+ callsign: callSign,
362
+ dimA: 0,
363
+ dimB: length,
364
+ dimC: beam,
365
+ dimD: beam,
366
+ };
367
+
368
+ if (aisDelay && (ais === 'A' || ais === 'B')) {
369
+ app.debug("Distance range: " + distance + "km, AIS target distance: " + dist + "km" + ", Class " + ais + " Vessel" + ", MMSI:" + mmsi)
370
+ if (ais === 'A') {
371
+ app.debug(`class A, ${i}, time: ${aisTime}`);
372
+ aisOut(encMsg3, aisTime);
373
+ aisOut(encMsg5, aisTime);
374
+ }
375
+ if (ais === 'B') {
376
+ app.debug(`class B, ${i}, time: ${aisTime}`);
377
+ aisOut(encMsg18, aisTime);
378
+ aisOut(encMsg240, aisTime);
379
+ aisOut(encMsg241, aisTime);
380
+ }
381
+ app.debug("--------------------------------------------------------");
360
382
 
361
- if (aisDelay && (ais === 'A' || ais === 'B')) {
362
- app.debug("Distance range: " + distance + "km, AIS target distance: " + dist + "km" + ", Class " + ais + " Vessel" + ", MMSI:" + mmsi)
363
- if (ais === 'A') {
364
- app.debug(`class A, ${i}, time: ${aisTime}`);
365
- aisOut(encMsg3, aisTime);
366
- aisOut(encMsg5, aisTime);
367
383
  }
368
- if (ais === 'B') {
369
- app.debug(`class B, ${i}, time: ${aisTime}`);
370
- aisOut(encMsg18, aisTime);
371
- aisOut(encMsg240, aisTime);
372
- aisOut(encMsg241, aisTime);
373
- }
374
- app.debug("--------------------------------------------------------");
375
-
376
384
  }
377
385
  }
378
- }
379
- const dateobj = new Date(Date.now());
380
- const date = dateobj.toISOString();
381
- app.handleMessage(plugin.id, {
382
- context: `vessels.${app.selfId}`,
383
- updates: [
384
- ],
385
- });
386
- setStatus(`Number of AIS targets sent: ${numberAIS - 1} (${date})`);
387
- })
388
- .catch((err) => console.error(err));
386
+ const dateobj = new Date(Date.now());
387
+ const date = dateobj.toISOString();
388
+ app.handleMessage(plugin.id, {
389
+ context: `vessels.${app.selfId}`,
390
+ updates: [
391
+ ],
392
+ });
393
+ setStatus(`AIS NMEA message send: ${date}`);
394
+ })
395
+ .catch((err) => console.error(err));
389
396
  };
390
397
 
391
398
  //----------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-vessels-to-ais",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "SignalK server plugin to convert other vessel data to NMEA0183 AIS format and forward it out to 3rd party applications",
5
5
  "main": "index.js",
6
6
  "scripts": {