signalk-vessels-to-ais 1.2.0 → 1.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.
package/README.md CHANGED
@@ -9,6 +9,9 @@ User can configure:
9
9
  - Own data can be added to AIS sending
10
10
 
11
11
  New:
12
+ - v1.3.0, add: Navigational Status variations
13
+ - v1.2.2, fix: if own position is not available
14
+ - v1.2.1, fix: own vessel sending
12
15
  - v1.2.0, updated fetch method, no need for NODE_TLS_REJECT_UNAUTHORIZED=0 anymore
13
16
  - v1.1.5, updated vessels within selected timeframe are sent out, radius filtering around own vessel and tag-block option added
14
17
  - v1.1.4, small fix
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-bitwise */
1
2
  /*
2
3
  MIT License
3
4
 
@@ -22,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
23
  SOFTWARE.
23
24
  */
24
25
 
25
- const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
26
+ const fetchNew = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
26
27
  const https = require('https');
27
28
  const AisEncode = require('ggencoder').AisEncode;
28
29
  const moment = require('moment');
@@ -41,7 +42,6 @@ module.exports = function createPlugin(app) {
41
42
  let intervalRun;
42
43
  const setStatus = app.setPluginStatus || app.setProviderStatus;
43
44
 
44
- let position_update;
45
45
  let useTag;
46
46
 
47
47
  const httpsAgent = new https.Agent({
@@ -50,20 +50,19 @@ module.exports = function createPlugin(app) {
50
50
 
51
51
  let getParam;
52
52
 
53
- plugin.start = function (options, restartPlugin) {
54
- position_update = options.position_update * 60;
53
+ plugin.start = function (options) {
55
54
  useTag = options.useTag;
56
55
 
57
- positionUpdate = options.position_update;
56
+ positionUpdate = options.position_update * 60;
58
57
  distance = options.distance;
59
58
  sendOwn = options.sendOwn;
60
59
 
61
- let port = options.port || 3000;
62
- let portSec = options.portSec || 3443;
60
+ const port = options.port || 3000;
61
+ const portSec = options.portSec || 3443;
63
62
 
64
- url = 'https://localhost:' + portSec + '/signalk/v1/api/vessels';
63
+ url = `https://localhost:${portSec}/signalk/v1/api/vessels`;
65
64
  getParam = { method: 'GET', agent: httpsAgent };
66
- fetch(url, getParam)
65
+ fetchNew(url, getParam)
67
66
  .then((res) => {
68
67
  console.log(`${plugin.id}: SSL enabled, using https`);
69
68
  if (!res.ok) {
@@ -72,23 +71,23 @@ module.exports = function createPlugin(app) {
72
71
  }
73
72
  })
74
73
  .catch(() => {
75
- url = 'http://localhost:' + port + '/signalk/v1/api/vessels';
74
+ url = `http://localhost:${port}/signalk/v1/api/vessels`;
76
75
  getParam = { method: 'GET' };
77
- fetch(url, getParam)
76
+ fetchNew(url, getParam)
78
77
  .then((res) => {
79
78
  console.log(`${plugin.id}: SSL disabled, using http`);
80
79
  if (!res.ok) {
81
80
  console.error(`${plugin.id}: SSL disabled, but error accessing server. Check 'Allow Readonly Access' and enable it.`);
82
81
  setStatus("Error accessing server. Check 'Allow Readonly Access' and enable it");
83
82
  }
84
- })
83
+ });
85
84
  })
86
85
  .finally(() => {
87
- intervalRun = setInterval(readData, (positionUpdate * 60000), getParam);
86
+ // eslint-disable-next-line no-use-before-define
87
+ intervalRun = setInterval(readData, (positionUpdate * 1000), getParam);
88
88
  });
89
89
 
90
90
  app.debug('Plugin started');
91
-
92
91
  };
93
92
 
94
93
  //----------------------------------------------------------------------------
@@ -96,18 +95,32 @@ module.exports = function createPlugin(app) {
96
95
 
97
96
  const stateMapping = {
98
97
  motoring: 0,
98
+ 'UnderWayUsingEngine': 0,
99
+ 'under way using engine': 0,
100
+ 'underway using engine': 0,
99
101
  anchored: 1,
102
+ 'AtAnchor': 1,
103
+ 'at anchor': 1,
100
104
  'not under command': 2,
101
105
  'restricted manouverability': 3,
102
106
  'constrained by draft': 4,
107
+ 'constrained by her draught': 4,
103
108
  moored: 5,
109
+ 'Moored': 5,
104
110
  aground: 6,
105
111
  fishing: 7,
112
+ 'engaged in fishing': 7,
106
113
  sailing: 8,
114
+ 'UnderWaySailing': 8,
115
+ 'under way sailing': 8,
116
+ 'underway sailing': 8,
107
117
  'hazardous material high speed': 9,
108
118
  'hazardous material wing in ground': 10,
119
+ 'reserved for future use': 13,
109
120
  'ais-sart': 14,
110
121
  default: 15,
122
+ 'UnDefined': 15,
123
+ 'undefined': 15,
111
124
  };
112
125
 
113
126
  //----------------------------------------------------------------------------
@@ -131,15 +144,16 @@ module.exports = function createPlugin(app) {
131
144
  const sentence = enc.nmea;
132
145
  let taggString = '';
133
146
  if (useTag) {
134
- taggString = createTagBlock(aisTime)
135
- }
147
+ // eslint-disable-next-line no-use-before-define
148
+ taggString = createTagBlock(aisTime);
149
+ }
136
150
  if (sentence && sentence.length > 0) {
137
- app.debug(taggString+sentence);
138
- app.emit('nmea0183out', taggString+sentence);
151
+ app.debug(taggString + sentence);
152
+ app.emit('nmea0183out', taggString + sentence);
139
153
  }
140
154
  }
141
155
 
142
- const m_hex = [
156
+ const mHex = [
143
157
  '0',
144
158
  '1',
145
159
  '2',
@@ -155,60 +169,60 @@ module.exports = function createPlugin(app) {
155
169
  'C',
156
170
  'D',
157
171
  'E',
158
- 'F'
159
- ]
160
-
161
- function toHexString (v) {
162
- let msn = (v >> 4) & 0x0f
163
- let lsn = (v >> 0) & 0x0f
164
- return m_hex[msn] + m_hex[lsn]
172
+ 'F',
173
+ ];
174
+
175
+ function toHexString(v) {
176
+ const msn = (v >> 4) & 0x0f;
177
+ const lsn = (v >> 0) & 0x0f;
178
+ return mHex[msn] + mHex[lsn];
165
179
  }
166
180
 
167
- function createTagBlock (aisTime) {
168
- let tagBlock = ''
169
- tagBlock += 's:SK0001,'
170
- //tagBlock += 'c:' + aisTime + ','
171
- tagBlock += 'c:' + Date.now(aisTime) + ','
172
- tagBlock = tagBlock.slice(0, - 1)
173
- let tagBlockChecksum = 0
181
+ function createTagBlock(aisTime) {
182
+ let tagBlock = '';
183
+ tagBlock += 's:SK0001,';
184
+ // tagBlock += 'c:' + aisTime + ','
185
+ tagBlock += `c:${Date.now(aisTime)},`;
186
+ tagBlock = tagBlock.slice(0, -1);
187
+ let tagBlockChecksum = 0;
174
188
  for (let i = 0; i < tagBlock.length; i++) {
175
- tagBlockChecksum ^= tagBlock.charCodeAt(i)
189
+ tagBlockChecksum ^= tagBlock.charCodeAt(i);
176
190
  }
177
- return `\\${tagBlock}*` + toHexString(tagBlockChecksum) + `\\`
191
+ return `\\${tagBlock}*${toHexString(tagBlockChecksum)}\\`;
178
192
  }
179
193
 
180
194
  //----------------------------------------------------------------------------
181
195
  // Read and parse AIS data
182
196
 
197
+ // eslint-disable-next-line no-shadow
183
198
  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)
199
+ let i, mmsi, aisTime, aisDelay, shipName, lat, lon, sog, cog, rot;
200
+ let navStat, hdg, dst, callSign, imo, id, type;
201
+ let draftCur, length, beam, ais, encMsg3, encMsg5, encMsg18, encMsg240, encMsg241, own;
202
+ const ownLat = app.getSelfPath('navigation.position.value.latitude');
203
+ const ownLon = app.getSelfPath('navigation.position.value.longitude');
204
+ if (typeof ownLat !== "undefined" && typeof ownLon !== "undefined") {
205
+ fetchNew(url, getParam)
189
206
  .then((res) => res.json())
190
207
  .then((json) => {
191
208
  const jsonContent = JSON.parse(JSON.stringify(json));
192
209
  const numberAIS = Object.keys(jsonContent).length;
193
210
  for (i = 0; i < numberAIS; i++) {
194
211
  const jsonKey = Object.keys(jsonContent)[i];
195
-
212
+
196
213
  try {
197
214
  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
215
  } catch (error) {
204
216
  if (i === 0) {
205
- aisTime = new Date(Date.now()).toISOString();
206
- aisDelay = true;
217
+ aisTime = jsonContent[jsonKey].navigation.position.timestamp;
207
218
  } else {
208
219
  aisTime = null;
209
- aisDelay = false;
210
220
  }
211
221
  }
222
+
223
+ aisDelay = (parseFloat((moment(new Date(Date.now()))
224
+ .diff(aisTime) / 1000).toFixed(3))) < positionUpdate;
225
+
212
226
  try {
213
227
  mmsi = jsonContent[jsonKey].mmsi;
214
228
  } catch (error) { mmsi = null; }
@@ -267,7 +281,7 @@ module.exports = function createPlugin(app) {
267
281
  try {
268
282
  ais = jsonContent[jsonKey].sensors.ais.class.value;
269
283
  } catch (error) { ais = null; }
270
-
284
+
271
285
  if (shipName % 1 === 0) {
272
286
  shipName = '';
273
287
  }
@@ -280,7 +294,7 @@ module.exports = function createPlugin(app) {
280
294
  if (type % 1 === 0) {
281
295
  type = '';
282
296
  }
283
-
297
+
284
298
  if (i === 0) {
285
299
  own = true;
286
300
  if (sendOwn) {
@@ -291,13 +305,12 @@ module.exports = function createPlugin(app) {
291
305
  } else {
292
306
  own = false;
293
307
  }
294
-
295
- const a = { lat: ownLat, lon: ownLon }
296
- const b = { lat: lat, lon: lon }
297
- let dist = (haversine(a, b)/1000).toFixed(2);
298
-
308
+
309
+ const a = { lat: ownLat, lon: ownLon };
310
+ const b = { lat, lon };
311
+ const dist = (haversine(a, b) / 1000).toFixed(2);
312
+
299
313
  if (dist <= distance) {
300
-
301
314
  encMsg3 = {
302
315
  own,
303
316
  aistype: 3, // class A position report
@@ -311,7 +324,7 @@ module.exports = function createPlugin(app) {
311
324
  hdg,
312
325
  rot,
313
326
  };
314
-
327
+
315
328
  encMsg5 = {
316
329
  own,
317
330
  aistype: 5, // class A static
@@ -328,7 +341,7 @@ module.exports = function createPlugin(app) {
328
341
  dimC: beam,
329
342
  dimD: beam,
330
343
  };
331
-
344
+
332
345
  encMsg18 = {
333
346
  own,
334
347
  aistype: 18, // class B position report
@@ -341,7 +354,7 @@ module.exports = function createPlugin(app) {
341
354
  cog,
342
355
  hdg,
343
356
  };
344
-
357
+
345
358
  encMsg240 = {
346
359
  own,
347
360
  aistype: 24, // class B static
@@ -350,7 +363,7 @@ module.exports = function createPlugin(app) {
350
363
  mmsi,
351
364
  shipname: shipName,
352
365
  };
353
-
366
+
354
367
  encMsg241 = {
355
368
  own,
356
369
  aistype: 24, // class B static
@@ -364,9 +377,10 @@ module.exports = function createPlugin(app) {
364
377
  dimC: beam,
365
378
  dimD: beam,
366
379
  };
367
-
380
+
368
381
  if (aisDelay && (ais === 'A' || ais === 'B')) {
369
- app.debug("Distance range: " + distance + "km, AIS target distance: " + dist + "km" + ", Class " + ais + " Vessel" + ", MMSI:" + mmsi)
382
+ // eslint-disable-next-line no-useless-concat
383
+ app.debug(`Distance range: ${distance}km, AIS target distance: ${dist}km` + `, Class ${ais} Vessel` + `, MMSI:${mmsi}`);
370
384
  if (ais === 'A') {
371
385
  app.debug(`class A, ${i}, time: ${aisTime}`);
372
386
  aisOut(encMsg3, aisTime);
@@ -378,22 +392,17 @@ module.exports = function createPlugin(app) {
378
392
  aisOut(encMsg240, aisTime);
379
393
  aisOut(encMsg241, aisTime);
380
394
  }
381
- app.debug("--------------------------------------------------------");
382
-
395
+ app.debug('--------------------------------------------------------');
383
396
  }
384
397
  }
385
398
  }
386
399
  const dateobj = new Date(Date.now());
387
400
  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}`);
401
+ setStatus(`AIS NMEA message sent: ${date}`);
394
402
  })
395
403
  .catch((err) => console.error(err));
396
- };
404
+ }
405
+ }
397
406
 
398
407
  //----------------------------------------------------------------------------
399
408
 
@@ -413,22 +422,22 @@ module.exports = function createPlugin(app) {
413
422
  port: {
414
423
  type: 'number',
415
424
  title: 'HTTP port',
416
- default: 3000
425
+ default: 3000,
417
426
  },
418
427
  portSec: {
419
428
  type: 'number',
420
429
  title: 'HTTPS port',
421
- default: 3443
430
+ default: 3443,
422
431
  },
423
432
  sendOwn: {
424
433
  type: 'boolean',
425
434
  title: 'Send own AIS data, VDO',
426
- default: true
435
+ default: true,
427
436
  },
428
437
  useTag: {
429
438
  type: 'boolean',
430
439
  title: 'Add Tag-block',
431
- default: false
440
+ default: false,
432
441
  },
433
442
  distance: {
434
443
  type: 'integer',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-vessels-to-ais",
3
- "version": "1.2.0",
3
+ "version": "1.3.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": {
package/.eslintrc.js DELETED
@@ -1,24 +0,0 @@
1
- module.exports = {
2
- env: {
3
- commonjs: true,
4
- es2021: true,
5
- node: true,
6
- browser: true,
7
- jquery: true,
8
- },
9
- extends: [
10
- 'airbnb-base',
11
- ],
12
- parserOptions: {
13
- ecmaVersion: 12,
14
- },
15
- rules: {
16
- 'linebreak-style': 0,
17
- 'no-console': 0,
18
- 'func-names': 0,
19
- 'prefer-destructuring': 0,
20
- 'one-var-declaration-per-line': 0,
21
- 'one-var': 0,
22
- 'no-plusplus': 0,
23
- },
24
- };