@signalk/freeboard-sk 2.7.0 → 2.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG: Freeboard
2
2
 
3
+ ### v2.8.0
4
+
5
+ - **Added**: Option to display laylines when destination is active. (#149)
6
+ - **Added**: Support for Signal K server "Features" API.
7
+ - **Updated**: Measure function displays both segment details and total distance. (#153)
8
+ - **Updated**: Clearing an alarm sets alarm state to normal rather than `null`.
9
+ - **Fixed**: Inverted label color not correctly applied after feature update.
10
+
11
+ ### v2.7.1
12
+
13
+ - **Added**: Set a default waypoint name when adding a waypoint at vessel position. (#146)
14
+
3
15
  ### v2.7.0
4
16
 
5
17
  - **Added**: OpenWeather OneCall v3.0 support. _(v2.5 is deprecated April 2024)_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalk/freeboard-sk",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Openlayers chart plotter implementation for Signal K",
5
5
  "keywords": [
6
6
  "signalk-webapp",
@@ -87,6 +87,7 @@
87
87
  "proj4": "2.6.2",
88
88
  "protractor": "~7.0.0",
89
89
  "rxjs": "~6.6.3",
90
+ "semver": "^7.6.0",
90
91
  "signalk-client-angular": "^2.0.3",
91
92
  "signalk-worker-angular": "^1.1.4",
92
93
  "simplify-ts": "^1.0.2",
@@ -97,4 +98,4 @@
97
98
  "xml2js": "^0.6.2",
98
99
  "zone.js": "~0.14.4"
99
100
  }
100
- }
101
+ }
@@ -16,6 +16,7 @@ const STANDARD_ALARMS = [
16
16
  ];
17
17
  let server;
18
18
  let pluginId;
19
+ const ALARM_API_PATH = '/signalk/v1/api/alarms';
19
20
  const initAlarms = (app, id) => {
20
21
  server = app;
21
22
  pluginId = id;
@@ -32,8 +33,8 @@ const initAlarms = (app, id) => {
32
33
  exports.initAlarms = initAlarms;
33
34
  const initAlarmEndpoints = () => {
34
35
  server.debug(`** Registering Alarm Action API endpoint(s) **`);
35
- server.put('/signalk/v2/api/notifications/:alarmType', (req, res, next) => {
36
- server.debug(`** PUT /signalk/v2/api/notifications/${req.params.alarmType}`);
36
+ server.post(`${ALARM_API_PATH}/:alarmType`, (req, res, next) => {
37
+ server.debug(`** POST ${ALARM_API_PATH}/${req.params.alarmType}`);
37
38
  if (!STANDARD_ALARMS.includes(req.params.alarmType)) {
38
39
  next();
39
40
  return;
@@ -57,14 +58,59 @@ const initAlarmEndpoints = () => {
57
58
  });
58
59
  }
59
60
  });
60
- server.delete('/signalk/v2/api/notifications/:alarmType', (req, res, next) => {
61
- server.debug(`** DELETE /signalk/v2/api/notifications/${req.params.alarmType}`);
61
+ server.post(`${ALARM_API_PATH}/:alarmType/silence`, (req, res) => {
62
+ server.debug(`** POST ${req.path}`);
63
+ if (!STANDARD_ALARMS.includes(req.params.alarmType)) {
64
+ res.status(200).json({
65
+ state: 'COMPLETED',
66
+ statusCode: 200,
67
+ message: `Unsupported Alarm (${req.params.alarmType}).`
68
+ });
69
+ return;
70
+ }
71
+ try {
72
+ const al = server.getSelfPath(`notifications.${req.params.alarmType}`);
73
+ if (al && al.value) {
74
+ server.debug('Alarm value....');
75
+ if (al.value.method && al.value.method.includes('sound')) {
76
+ server.debug('Alarm has sound... silence!!!');
77
+ al.value.method = al.value.method.filter((i) => i !== 'sound');
78
+ const r = handlePutAlarmState('vessels.self', `notifications.${req.params.alarmType}`, al.value);
79
+ res.status(200).json(r);
80
+ }
81
+ else {
82
+ server.debug('Alarm has no sound... no action required.');
83
+ res.status(200).json({
84
+ state: 'COMPLETED',
85
+ statusCode: 200,
86
+ message: `Alarm (${req.params.alarmType}) is already silent.`
87
+ });
88
+ }
89
+ }
90
+ else {
91
+ throw new Error(`Alarm (${req.params.alarmType}) has no value or was not found!`);
92
+ }
93
+ }
94
+ catch (e) {
95
+ res.status(400).json({
96
+ state: 'FAILED',
97
+ statusCode: 400,
98
+ message: e.message
99
+ });
100
+ }
101
+ });
102
+ server.delete(`${ALARM_API_PATH}/:alarmType`, (req, res, next) => {
103
+ server.debug(`** DELETE ${ALARM_API_PATH}/${req.params.alarmType}`);
62
104
  if (!STANDARD_ALARMS.includes(req.params.alarmType)) {
63
105
  next();
64
106
  return;
65
107
  }
66
108
  try {
67
- const r = handlePutAlarmState('vessels.self', `notifications.${req.params.alarmType}`, null);
109
+ const r = handlePutAlarmState('vessels.self', `notifications.${req.params.alarmType}`, {
110
+ message: '',
111
+ method: [],
112
+ state: server_api_1.ALARM_STATE.normal
113
+ });
68
114
  res.status(200).json(r);
69
115
  }
70
116
  catch (e) {
@@ -94,16 +140,16 @@ const handlePutAlarmState = (context, path, value) => {
94
140
  server.debug(JSON.stringify(alarmType));
95
141
  let noti;
96
142
  if (value) {
97
- const alm = buildAlarmMessage(value.message);
143
+ const alm = value.state === server_api_1.ALARM_STATE.normal ? null : buildAlarmData();
98
144
  noti = {
99
145
  path: `notifications.${alarmType}`,
100
146
  value: {
101
147
  state: value.state ?? null,
102
148
  method: value.method ?? null,
103
- message: alm.message
149
+ message: value.message
104
150
  }
105
151
  };
106
- if (alm.data) {
152
+ if (alm && alm.data) {
107
153
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
108
154
  noti.value.data = alm.data;
109
155
  }
@@ -129,10 +175,9 @@ const handlePutAlarmState = (context, path, value) => {
129
175
  };
130
176
  }
131
177
  };
132
- const buildAlarmMessage = (message) => {
178
+ const buildAlarmData = () => {
133
179
  const pos = server.getSelfPath('navigation.position');
134
180
  return {
135
- message: message,
136
181
  data: {
137
182
  position: pos ? pos.value : null
138
183
  }
@@ -143,5 +188,5 @@ const emitNotification = (msg) => {
143
188
  const delta = {
144
189
  updates: [{ values: [msg] }]
145
190
  };
146
- server.handleMessage(pluginId, delta);
191
+ server.handleMessage(pluginId, delta, server_api_1.SKVersion.v2);
147
192
  };
package/plugin/index.js CHANGED
@@ -7,19 +7,6 @@ const openapi = require("./openApi.json");
7
7
  const defaultPollInterval = 60;
8
8
  const CONFIG_SCHEMA = {
9
9
  properties: {
10
- alarms: {
11
- type: 'object',
12
- title: 'Standard Alarms.',
13
- description: 'Standard Alarms request handler (MOB, etc.)',
14
- properties: {
15
- enable: {
16
- type: 'boolean',
17
- default: true,
18
- title: 'Enable Standard Alarms',
19
- description: ' '
20
- }
21
- }
22
- },
23
10
  weather: {
24
11
  type: 'object',
25
12
  title: 'Weather API.',
@@ -34,8 +21,8 @@ const CONFIG_SCHEMA = {
34
21
  apiVersion: {
35
22
  type: 'number',
36
23
  title: 'API Version',
37
- default: 2,
38
- enum: [2, 3],
24
+ default: 3,
25
+ enum: [3, 2],
39
26
  description: 'Note: v2 API not supported after April 2024!'
40
27
  },
41
28
  apiKey: {
@@ -108,7 +95,7 @@ module.exports = (server) => {
108
95
  },
109
96
  weather: {
110
97
  enable: false,
111
- apiVersion: 2,
98
+ apiVersion: 3,
112
99
  apiKey: '',
113
100
  pollInterval: defaultPollInterval
114
101
  },
@@ -145,19 +132,19 @@ module.exports = (server) => {
145
132
  }
146
133
  settings.weather = options.weather ?? {
147
134
  enable: false,
148
- apiVersion: 2,
135
+ apiVersion: 3,
149
136
  apiKey: '',
150
137
  pollInterval: defaultPollInterval
151
138
  };
152
139
  settings.weather.enable = options.weather.enable ?? false;
153
- settings.weather.apiVersion = options.weather.apiVersion ?? 2;
140
+ settings.weather.apiVersion = options.weather.apiVersion ?? 3;
154
141
  settings.weather.apiKey = options.weather.apiKey ?? '';
155
142
  settings.weather.pollInterval =
156
143
  options.weather.pollInterval ?? defaultPollInterval;
157
144
  settings.alarms = options.alarms ?? {
158
145
  enable: true
159
146
  };
160
- settings.alarms.enable = options.alarms.enable ?? true;
147
+ settings.alarms.enable = true;
161
148
  settings.pypilot = options.pypilot ?? {
162
149
  enable: false,
163
150
  host: 'localhost',
@@ -16,14 +16,10 @@
16
16
  },
17
17
  "servers": [
18
18
  {
19
- "url": "/signalk/v2/api"
19
+ "url": "/"
20
20
  }
21
21
  ],
22
22
  "tags": [
23
- {
24
- "name": "Alarms",
25
- "description": "Raise and clear Signal K alarms."
26
- },
27
23
  {
28
24
  "name": "OpenWeather",
29
25
  "description": "Weather data from OpenWeather service."
@@ -470,7 +466,7 @@
470
466
  },
471
467
  "security": [{ "cookieAuth": [] }, { "bearerAuth": [] }],
472
468
  "paths": {
473
- "/meteo/{id}": {
469
+ "/signalk/v2/api/meteo/{id}": {
474
470
  "parameters": [
475
471
  {
476
472
  "$ref": "#/components/parameters/StationIdParam"
@@ -493,7 +489,7 @@
493
489
  }
494
490
  }
495
491
  },
496
- "/meteo/{id}/observations": {
492
+ "/signalk/v2/api/meteo/{id}/observations": {
497
493
  "parameters": [
498
494
  {
499
495
  "$ref": "#/components/parameters/StationIdParam"
@@ -519,7 +515,7 @@
519
515
  }
520
516
  }
521
517
  },
522
- "/meteo/{id}/observations/{entryId}": {
518
+ "/signalk/v2/api/meteo/{id}/observations/{entryId}": {
523
519
  "parameters": [
524
520
  {
525
521
  "$ref": "#/components/parameters/StationIdParam"
@@ -545,7 +541,7 @@
545
541
  }
546
542
  }
547
543
  },
548
- "/meteo/{id}/forecasts": {
544
+ "/signalk/v2/api/meteo/{id}/forecasts": {
549
545
  "parameters": [
550
546
  {
551
547
  "$ref": "#/components/parameters/StationIdParam"
@@ -571,7 +567,7 @@
571
567
  }
572
568
  }
573
569
  },
574
- "/meteo/{id}/forecasts/{entryId}": {
570
+ "/signalk/v2/api/meteo/{id}/forecasts/{entryId}": {
575
571
  "parameters": [
576
572
  {
577
573
  "$ref": "#/components/parameters/StationIdParam"
@@ -597,7 +593,7 @@
597
593
  }
598
594
  }
599
595
  },
600
- "/meteo/{id}/warnings": {
596
+ "/signalk/v2/api/meteo/{id}/warnings": {
601
597
  "parameters": [
602
598
  {
603
599
  "$ref": "#/components/parameters/StationIdParam"
@@ -623,7 +619,7 @@
623
619
  }
624
620
  }
625
621
  },
626
- "/meteo/{id}/warnings/{entryId}": {
622
+ "/signalk/v2/api/meteo/{id}/warnings/{entryId}": {
627
623
  "parameters": [
628
624
  {
629
625
  "$ref": "#/components/parameters/StationIdParam"
@@ -648,31 +644,6 @@
648
644
  }
649
645
  }
650
646
  }
651
- },
652
- "/notifications/{alarmType}": {
653
- "parameters": [
654
- {
655
- "$ref": "#/components/parameters/AlarmTypeParam"
656
- }
657
- ],
658
- "put": {
659
- "tags": ["Alarms"],
660
- "summary": "Raise alarm.",
661
- "responses": {
662
- "default": {
663
- "$ref": "#/components/responses/200OKResponse"
664
- }
665
- }
666
- },
667
- "delete": {
668
- "tags": ["Alarms"],
669
- "summary": "Clear alarm.",
670
- "responses": {
671
- "default": {
672
- "$ref": "#/components/responses/200OKResponse"
673
- }
674
- }
675
- }
676
647
  }
677
648
  }
678
649
  }
@@ -57,13 +57,13 @@ class OpenWeather {
57
57
  },
58
58
  outside: {
59
59
  uvIndex: current.uvi ?? null,
60
- cloudCover: current.clouds ?? null,
60
+ cloudCover: current.clouds / 100 ?? null,
61
61
  horizontalVisibility: current.visibility ?? null,
62
62
  temperature: current.temp ?? null,
63
63
  feelsLikeTemperature: current.feels_like ?? null,
64
64
  dewPointTemperature: current.dew_point ?? null,
65
65
  pressure: current.pressure ? current.pressure * 100 : null,
66
- absoluteHumidity: current.humidity ?? null,
66
+ absoluteHumidity: current.humidity / 100 ?? null,
67
67
  precipitationType: current.rain && typeof current.rain['1h'] !== 'undefined'
68
68
  ? 'rain'
69
69
  : current.snow && typeof current.snow['1h'] !== 'undefined'
@@ -119,10 +119,10 @@ class OpenWeather {
119
119
  }
120
120
  forecast.outside.dewPointTemperature = f.dew_point ?? null;
121
121
  forecast.outside.uvIndex = f.uvi ?? null;
122
- forecast.outside.cloudCover = f.clouds ?? null;
122
+ forecast.outside.cloudCover = f.clouds / 100 ?? null;
123
123
  forecast.outside.pressure =
124
124
  typeof f.pressure !== 'undefined' ? f.pressure * 100 : null;
125
- forecast.outside.absoluteHumidity = f.humidity ?? null;
125
+ forecast.outside.absoluteHumidity = f.humidity / 100 ?? null;
126
126
  forecast.wind.speedTrue = f.wind_speed ?? null;
127
127
  forecast.wind.directionTrue =
128
128
  typeof f.wind_deg !== 'undefined'
@@ -457,7 +457,7 @@ const buildObservationMetas = (pathRoot) => {
457
457
  path: `${pathRoot}.outside.cloudCover`,
458
458
  value: {
459
459
  description: 'Cloud clover.',
460
- units: '%'
460
+ units: 'ratio'
461
461
  }
462
462
  });
463
463
  metas.push({
@@ -517,14 +517,14 @@ const buildObservationMetas = (pathRoot) => {
517
517
  path: `${pathRoot}.outside.relativeHumidity`,
518
518
  value: {
519
519
  description: 'Relative humidity.',
520
- units: '%'
520
+ units: 'ratio'
521
521
  }
522
522
  });
523
523
  metas.push({
524
524
  path: `${pathRoot}.outside.absoluteHumidity`,
525
525
  value: {
526
526
  description: 'Absolute humidity.',
527
- units: '%'
527
+ units: 'ratio'
528
528
  }
529
529
  });
530
530
  metas.push({