@signalk/freeboard-sk 2.2.0 → 2.2.2
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 +12 -0
- package/package.json +18 -20
- package/plugin/alarms/alarms.js +2 -3
- package/plugin/anchor/anchor-api.js +102 -0
- package/plugin/index.js +13 -11
- package/plugin/lib/fetch.js +48 -2
- package/plugin/lib/noaa.js +58 -62
- package/plugin/lib/openweather.js +54 -57
- package/plugin/lib/types.js +8 -8
- package/plugin/weather.js +7 -9
- package/public/3rdpartylicenses.txt +3 -6
- package/public/760.128eba7bc7bf35a5.js +1 -0
- package/public/assets/help/index.html +4 -2
- package/public/index.html +6 -5
- package/public/main.b1d3ce26b87acfb4.js +1 -0
- package/public/polyfills.61cfd308b28d8fe0.js +1 -0
- package/public/{runtime.2004f5e0f40621fc.js → runtime.d3c37bb0c0c8df86.js} +1 -1
- package/public/styles.b53caac129c3f7a0.css +1 -0
- package/public/598.58a90802ad6bb7ff.js +0 -1
- package/public/main.5ff254cefee77641.js +0 -1
- package/public/polyfills.12ddee7e4cb46a02.js +0 -1
- package/public/styles.7ebc2b506afc0008.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# CHANGELOG: Freeboard
|
|
2
2
|
|
|
3
|
+
### v2.2.2
|
|
4
|
+
|
|
5
|
+
- **Fixed**: Update Anchor Watch to use `signalk-anchor-alarm` REST API to resolve incorrect state being displayed.
|
|
6
|
+
- **Fixed**: Switching to fixed location did not update map until a delta update had been parsed.
|
|
7
|
+
|
|
8
|
+
### v2.2.1
|
|
9
|
+
|
|
10
|
+
- **Fixed**: Issue where waypoint was not centered on the screen when the center waypoint button was clicked from the entry in the waypoint list.
|
|
11
|
+
|
|
12
|
+
- **Fixed**: Issue where invalid fixed location postion was being written to settings.
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
### v2.2.0
|
|
4
16
|
|
|
5
17
|
- **Added**: Ability to center a vessel in the Vessels List.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalk/freeboard-sk",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Openlayers chart plotter implementation for Signal K",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"signalk-webapp",
|
|
@@ -20,9 +20,7 @@
|
|
|
20
20
|
"build": "ng build",
|
|
21
21
|
"test": "ng test",
|
|
22
22
|
"format": "prettier --ignore-path .gitignore --write \"src/**/*.+(ts|html)\"",
|
|
23
|
-
"format:projects": "prettier --ignore-path .gitignore --write \"projects/**/*.+(ts|html)\"",
|
|
24
23
|
"format:helper": "prettier --ignore-path .gitignore --write \"helper/**/*.+(ts|html)\"",
|
|
25
|
-
"e2e": "ng e2e",
|
|
26
24
|
"build:helper": "tsc -p tsconfig-helper.json",
|
|
27
25
|
"build:web": "ng build -c production --output-hashing all",
|
|
28
26
|
"build:all": "npm run build:helper && npm run build:web",
|
|
@@ -44,19 +42,19 @@
|
|
|
44
42
|
"tslib": "^2.0.0"
|
|
45
43
|
},
|
|
46
44
|
"devDependencies": {
|
|
47
|
-
"@angular-devkit/build-angular": "^
|
|
48
|
-
"@angular/animations": "^
|
|
49
|
-
"@angular/cdk": "^
|
|
50
|
-
"@angular/cli": "^
|
|
51
|
-
"@angular/common": "^
|
|
52
|
-
"@angular/compiler": "^
|
|
53
|
-
"@angular/compiler-cli": "^
|
|
54
|
-
"@angular/core": "^
|
|
55
|
-
"@angular/forms": "^
|
|
56
|
-
"@angular/language-service": "^
|
|
57
|
-
"@angular/material": "^
|
|
58
|
-
"@angular/platform-browser": "^
|
|
59
|
-
"@angular/platform-browser-dynamic": "^
|
|
45
|
+
"@angular-devkit/build-angular": "^16.2.0",
|
|
46
|
+
"@angular/animations": "^16.2.0",
|
|
47
|
+
"@angular/cdk": "^16.2.0",
|
|
48
|
+
"@angular/cli": "^16.2.0",
|
|
49
|
+
"@angular/common": "^16.2.0",
|
|
50
|
+
"@angular/compiler": "^16.2.0",
|
|
51
|
+
"@angular/compiler-cli": "^16.2.0",
|
|
52
|
+
"@angular/core": "^16.2.0",
|
|
53
|
+
"@angular/forms": "^16.2.0",
|
|
54
|
+
"@angular/language-service": "^16.2.0",
|
|
55
|
+
"@angular/material": "^16.2.0",
|
|
56
|
+
"@angular/platform-browser": "^16.2.0",
|
|
57
|
+
"@angular/platform-browser-dynamic": "^16.2.0",
|
|
60
58
|
"@kolkov/angular-editor": "^2.1.0",
|
|
61
59
|
"@signalk/server-api": "^2.0.0",
|
|
62
60
|
"@types/arcgis-rest-api": "^10.4.5",
|
|
@@ -78,7 +76,7 @@
|
|
|
78
76
|
"karma-coverage-istanbul-reporter": "~3.0.2",
|
|
79
77
|
"karma-jasmine": "~4.0.0",
|
|
80
78
|
"karma-jasmine-html-reporter": "^1.5.0",
|
|
81
|
-
"ng-packagr": "^
|
|
79
|
+
"ng-packagr": "^16.2.0",
|
|
82
80
|
"ngeohash": "^0.6.3",
|
|
83
81
|
"ol": "^7.4.0",
|
|
84
82
|
"pmtiles": "^2.7.0",
|
|
@@ -91,7 +89,7 @@
|
|
|
91
89
|
"signalk-worker-angular": "^1.1.4",
|
|
92
90
|
"simplify-ts": "^1.0.2",
|
|
93
91
|
"ts-node": "~7.0.0",
|
|
94
|
-
"typescript": "~4.
|
|
95
|
-
"zone.js": "~0.
|
|
92
|
+
"typescript": "~4.9.5",
|
|
93
|
+
"zone.js": "~0.13.1"
|
|
96
94
|
}
|
|
97
|
-
}
|
|
95
|
+
}
|
package/plugin/alarms/alarms.js
CHANGED
|
@@ -77,7 +77,6 @@ const initAlarmEndpoints = () => {
|
|
|
77
77
|
});
|
|
78
78
|
};
|
|
79
79
|
const handlePutAlarmState = (context, path, value) => {
|
|
80
|
-
var _a, _b;
|
|
81
80
|
server.debug(context);
|
|
82
81
|
server.debug(path);
|
|
83
82
|
server.debug(JSON.stringify(value));
|
|
@@ -95,7 +94,7 @@ const handlePutAlarmState = (context, path, value) => {
|
|
|
95
94
|
server.debug(JSON.stringify(alarmType));
|
|
96
95
|
let noti;
|
|
97
96
|
if (value) {
|
|
98
|
-
noti = new types_1.Notification(alarmType, buildAlarmMessage(value.message, alarmType),
|
|
97
|
+
noti = new types_1.Notification(alarmType, buildAlarmMessage(value.message, alarmType), value.state ?? null, value.method ?? null);
|
|
99
98
|
}
|
|
100
99
|
else {
|
|
101
100
|
noti = {
|
|
@@ -123,7 +122,7 @@ const buildAlarmMessage = (message, alarmType) => {
|
|
|
123
122
|
if (['mob', 'sinking'].includes(alarmType)) {
|
|
124
123
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
124
|
const pos = server.getSelfPath('navigation.position');
|
|
126
|
-
msgAttrib = pos ? JSON.stringify(pos
|
|
125
|
+
msgAttrib = pos ? JSON.stringify(pos?.value) : '';
|
|
127
126
|
}
|
|
128
127
|
return `${message}\n\r${msgAttrib}`;
|
|
129
128
|
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initAnchorApi = void 0;
|
|
4
|
+
const fetch_1 = require("../lib/fetch");
|
|
5
|
+
let server;
|
|
6
|
+
let hostPath;
|
|
7
|
+
const apiBasePath = '/signalk/v2/api/vessels/self/navigation/anchor';
|
|
8
|
+
const anchorPlugin = {
|
|
9
|
+
has: false,
|
|
10
|
+
enabled: false,
|
|
11
|
+
version: ''
|
|
12
|
+
};
|
|
13
|
+
let pluginPath;
|
|
14
|
+
const msgPluginNotFound = 'signalk-anchor-alarm is not installed!';
|
|
15
|
+
const initAnchorApi = async (app) => {
|
|
16
|
+
server = app;
|
|
17
|
+
server.debug(`** initAnchorApi() **`);
|
|
18
|
+
// detect signalk-anchor-alarm plugin
|
|
19
|
+
let port = 3000;
|
|
20
|
+
if (typeof server.config?.getExternalPort === 'function') {
|
|
21
|
+
server.debug('*** getExternalPort()', server.config.getExternalPort());
|
|
22
|
+
port = server.config.getExternalPort();
|
|
23
|
+
}
|
|
24
|
+
hostPath = `${server.config.ssl ? 'https' : 'http'}://localhost:${port}`;
|
|
25
|
+
const url = `${hostPath}/plugins`;
|
|
26
|
+
const r = await (0, fetch_1.fetch)(url);
|
|
27
|
+
r.forEach((plugin) => {
|
|
28
|
+
if (plugin.id === 'anchoralarm') {
|
|
29
|
+
pluginPath = `/plugins/${plugin.id}`;
|
|
30
|
+
anchorPlugin.has = true;
|
|
31
|
+
anchorPlugin.version = plugin.version;
|
|
32
|
+
anchorPlugin.enabled = plugin.data.enabled;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
server.debug('*** Anchor Alarm Plugin detected:', anchorPlugin.has);
|
|
36
|
+
server.debug('*** Anchor Alarm Plugin enabled:', anchorPlugin.enabled);
|
|
37
|
+
server.debug('*** Anchor Alarm Plugin API Path', `${hostPath}${pluginPath}`);
|
|
38
|
+
if (anchorPlugin.has) {
|
|
39
|
+
initApiEndpoints();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.initAnchorApi = initAnchorApi;
|
|
43
|
+
const initApiEndpoints = () => {
|
|
44
|
+
server.debug(`** Registering Anchor API endpoint(s) **`);
|
|
45
|
+
server.post(`${apiBasePath}/drop`, async (req, res) => {
|
|
46
|
+
server.debug(`** POST ${apiBasePath}/drop`);
|
|
47
|
+
if (!anchorPlugin.has) {
|
|
48
|
+
res.status(400).json({
|
|
49
|
+
state: 'COMPLETED',
|
|
50
|
+
statusCode: 400,
|
|
51
|
+
message: msgPluginNotFound
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const r = await (0, fetch_1.post)(`${hostPath}${pluginPath}/dropAnchor`, '{}');
|
|
57
|
+
res.status(r.statusCode).json(r);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
res.status(e.statusCode).json(e);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
server.post(`${apiBasePath}/raise`, async (req, res) => {
|
|
64
|
+
server.debug(`** POST ${apiBasePath}/raise`);
|
|
65
|
+
if (!anchorPlugin.has) {
|
|
66
|
+
res.status(400).json({
|
|
67
|
+
state: 'COMPLETED',
|
|
68
|
+
statusCode: 400,
|
|
69
|
+
message: msgPluginNotFound
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const r = await (0, fetch_1.post)(`${hostPath}${pluginPath}/raiseAnchor`, '{}');
|
|
75
|
+
res.status(r.statusCode).json(r);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
res.status(e.statusCode).json(e);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
server.post(`${apiBasePath}/radius`, async (req, res) => {
|
|
82
|
+
server.debug(`** POST ${apiBasePath}/radius`);
|
|
83
|
+
if (!anchorPlugin.has) {
|
|
84
|
+
res.status(400).json({
|
|
85
|
+
state: 'COMPLETED',
|
|
86
|
+
statusCode: 400,
|
|
87
|
+
message: msgPluginNotFound
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const val = req.body.value && typeof req.body.value === 'number'
|
|
93
|
+
? { radius: req.body.value }
|
|
94
|
+
: {};
|
|
95
|
+
const r = await (0, fetch_1.post)(`${hostPath}${pluginPath}/setRadius`, JSON.stringify(val));
|
|
96
|
+
res.status(r.statusCode).json(r);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
res.status(e.statusCode).json(e);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
};
|
package/plugin/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const alarms_1 = require("./alarms/alarms");
|
|
4
|
+
const anchor_api_1 = require("./anchor/anchor-api");
|
|
4
5
|
const weather_1 = require("./weather");
|
|
5
6
|
const pypilot_1 = require("./pypilot");
|
|
6
7
|
const openapi = require("./openApi.json");
|
|
@@ -122,32 +123,31 @@ module.exports = (server) => {
|
|
|
122
123
|
};
|
|
123
124
|
// ************************************
|
|
124
125
|
const doStartup = (options) => {
|
|
125
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
126
126
|
try {
|
|
127
127
|
server.debug(`${plugin.name} starting.......`);
|
|
128
128
|
if (typeof options !== 'undefined') {
|
|
129
129
|
settings = options;
|
|
130
130
|
}
|
|
131
|
-
settings.weather =
|
|
131
|
+
settings.weather = options.weather ?? {
|
|
132
132
|
enable: false,
|
|
133
133
|
apiKey: '',
|
|
134
134
|
service: 'openweather'
|
|
135
135
|
};
|
|
136
|
-
settings.weather.enable =
|
|
137
|
-
settings.weather.apiKey =
|
|
138
|
-
settings.weather.service =
|
|
139
|
-
settings.alarms =
|
|
136
|
+
settings.weather.enable = options.weather.enable ?? false;
|
|
137
|
+
settings.weather.apiKey = options.weather.apiKey ?? '';
|
|
138
|
+
settings.weather.service = options.weather.service ?? 'openweather';
|
|
139
|
+
settings.alarms = options.alarms ?? {
|
|
140
140
|
enable: true
|
|
141
141
|
};
|
|
142
|
-
settings.alarms.enable =
|
|
143
|
-
settings.pypilot =
|
|
142
|
+
settings.alarms.enable = options.alarms.enable ?? true;
|
|
143
|
+
settings.pypilot = options.pypilot ?? {
|
|
144
144
|
enable: false,
|
|
145
145
|
host: 'localhost',
|
|
146
146
|
port: 8000
|
|
147
147
|
};
|
|
148
|
-
settings.pypilot.enable =
|
|
149
|
-
settings.pypilot.host =
|
|
150
|
-
settings.pypilot.port =
|
|
148
|
+
settings.pypilot.enable = options.pypilot.enable ?? false;
|
|
149
|
+
settings.pypilot.host = options.pypilot.host ?? 'localhost';
|
|
150
|
+
settings.pypilot.port = options.pypilot.port ?? 8000;
|
|
151
151
|
server.debug(`Applied config: ${JSON.stringify(settings)}`);
|
|
152
152
|
if (settings.alarms.enable) {
|
|
153
153
|
(0, alarms_1.initAlarms)(server, plugin.id);
|
|
@@ -163,6 +163,8 @@ module.exports = (server) => {
|
|
|
163
163
|
if (settings.pypilot.enable) {
|
|
164
164
|
(0, pypilot_1.initPyPilot)(server, plugin.id, settings.pypilot);
|
|
165
165
|
}
|
|
166
|
+
// Anchor API facade
|
|
167
|
+
(0, anchor_api_1.initAnchorApi)(server);
|
|
166
168
|
server.setPluginStatus(msg);
|
|
167
169
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
170
|
}
|
package/plugin/lib/fetch.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetch = void 0;
|
|
3
|
+
exports.post = exports.fetch = void 0;
|
|
4
4
|
const https = require("https");
|
|
5
5
|
const url = require("url");
|
|
6
|
+
const http = require("http");
|
|
7
|
+
// HTTP GET
|
|
6
8
|
const fetch = (href) => {
|
|
7
9
|
const opt = url.parse(href);
|
|
8
10
|
opt.headers = { 'User-Agent': 'Mozilla/5.0' };
|
|
11
|
+
const req = href.indexOf('https') !== -1 ? https : http;
|
|
9
12
|
return new Promise((resolve, reject) => {
|
|
10
|
-
|
|
13
|
+
req
|
|
11
14
|
.get(opt, (res) => {
|
|
12
15
|
let data = '';
|
|
13
16
|
res.on('data', (chunk) => {
|
|
@@ -29,3 +32,46 @@ const fetch = (href) => {
|
|
|
29
32
|
});
|
|
30
33
|
};
|
|
31
34
|
exports.fetch = fetch;
|
|
35
|
+
// HTTP POST
|
|
36
|
+
const post = (href, data) => {
|
|
37
|
+
const opt = url.parse(href);
|
|
38
|
+
(opt.method = 'POST'),
|
|
39
|
+
(opt.headers = {
|
|
40
|
+
'Content-Type': 'application/json'
|
|
41
|
+
});
|
|
42
|
+
const req = href.indexOf('https') !== -1 ? https : http;
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const postReq = req
|
|
45
|
+
.request(opt, (res) => {
|
|
46
|
+
let resText = '';
|
|
47
|
+
res.on('data', (chunk) => {
|
|
48
|
+
resText += chunk;
|
|
49
|
+
});
|
|
50
|
+
res.on('end', () => {
|
|
51
|
+
if (Math.floor(res.statusCode / 100) === 2) {
|
|
52
|
+
resolve({
|
|
53
|
+
statusCode: res.statusCode,
|
|
54
|
+
state: 'COMPLETED'
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
reject({
|
|
59
|
+
statusCode: res.statusCode,
|
|
60
|
+
state: 'FAILED',
|
|
61
|
+
message: resText
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
})
|
|
66
|
+
.on('error', (error) => {
|
|
67
|
+
reject({
|
|
68
|
+
statusCode: 400,
|
|
69
|
+
state: 'FAILED',
|
|
70
|
+
message: error.message
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
postReq.write(data);
|
|
74
|
+
postReq.end();
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
exports.post = post;
|
package/plugin/lib/noaa.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// NOAA
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.NOAA = void 0;
|
|
5
|
-
const tslib_1 = require("tslib");
|
|
6
5
|
const fetch_1 = require("./fetch");
|
|
7
6
|
var CARDINAL_POINTS;
|
|
8
7
|
(function (CARDINAL_POINTS) {
|
|
@@ -24,55 +23,8 @@ var CARDINAL_POINTS;
|
|
|
24
23
|
CARDINAL_POINTS[CARDINAL_POINTS["NNW"] = 337.5] = "NNW";
|
|
25
24
|
})(CARDINAL_POINTS || (CARDINAL_POINTS = {}));
|
|
26
25
|
class NOAA {
|
|
26
|
+
settings;
|
|
27
27
|
constructor(config) {
|
|
28
|
-
this.fetchData = (position) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
var _a, _b, _c, _d, _e, _f;
|
|
30
|
-
const url = this.getUrl(position);
|
|
31
|
-
try {
|
|
32
|
-
//console.log(`url`, url)
|
|
33
|
-
const response = yield (0, fetch_1.fetch)(url);
|
|
34
|
-
let forecasts = [];
|
|
35
|
-
let observations = [];
|
|
36
|
-
// observations
|
|
37
|
-
if ((_a = response === null || response === void 0 ? void 0 : response.properties) === null || _a === void 0 ? void 0 : _a.observationStations) {
|
|
38
|
-
const stations = yield (0, fetch_1.fetch)(response.properties.observationStations);
|
|
39
|
-
observations = yield (0, fetch_1.fetch)(`${stations.features[0].id}/observations/latest`);
|
|
40
|
-
//console.log(`observations`, observations)
|
|
41
|
-
}
|
|
42
|
-
// forecasts
|
|
43
|
-
if ((_b = response === null || response === void 0 ? void 0 : response.properties) === null || _b === void 0 ? void 0 : _b.forecastHourly) {
|
|
44
|
-
forecasts = yield (0, fetch_1.fetch)(response.properties.forecastHourly);
|
|
45
|
-
//console.log(`forecasts`, forecasts)
|
|
46
|
-
}
|
|
47
|
-
// warnings
|
|
48
|
-
const warnings = yield (0, fetch_1.fetch)(`https://api.weather.gov/alerts/active?point=${position.latitude.toFixed(4)},${position.longitude.toFixed(4)}`);
|
|
49
|
-
//console.log(`warnings`, warnings)
|
|
50
|
-
return this.parseResponse({
|
|
51
|
-
position: position,
|
|
52
|
-
forecasts: (_d = (_c = forecasts === null || forecasts === void 0 ? void 0 : forecasts.properties) === null || _c === void 0 ? void 0 : _c.periods) !== null && _d !== void 0 ? _d : [],
|
|
53
|
-
observations: (_e = observations === null || observations === void 0 ? void 0 : observations.properties) !== null && _e !== void 0 ? _e : null,
|
|
54
|
-
warnings: (_f = warnings === null || warnings === void 0 ? void 0 : warnings.features) !== null && _f !== void 0 ? _f : []
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
this.parseResponse = (wData) => {
|
|
62
|
-
return {
|
|
63
|
-
self: {
|
|
64
|
-
id: 'self',
|
|
65
|
-
name: 'Weather data relative to supplied position.',
|
|
66
|
-
position: {
|
|
67
|
-
latitude: wData.latitude,
|
|
68
|
-
longitude: wData.longitude
|
|
69
|
-
},
|
|
70
|
-
observations: this.parseNoaaObservations(wData.observations),
|
|
71
|
-
forecasts: this.parseNoaaForecasts(wData.forecasts),
|
|
72
|
-
warnings: this.parseNoaaWarnings(wData.warnings)
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
28
|
this.settings = config;
|
|
77
29
|
}
|
|
78
30
|
getUrl(position) {
|
|
@@ -84,14 +36,60 @@ class NOAA {
|
|
|
84
36
|
return `${api}/${position.latitude.toFixed(4)},${position.longitude.toFixed(4)}`;
|
|
85
37
|
}
|
|
86
38
|
}
|
|
39
|
+
fetchData = async (position) => {
|
|
40
|
+
const url = this.getUrl(position);
|
|
41
|
+
try {
|
|
42
|
+
//console.log(`url`, url)
|
|
43
|
+
const response = await (0, fetch_1.fetch)(url);
|
|
44
|
+
let forecasts = [];
|
|
45
|
+
let observations = [];
|
|
46
|
+
// observations
|
|
47
|
+
if (response?.properties?.observationStations) {
|
|
48
|
+
const stations = await (0, fetch_1.fetch)(response.properties.observationStations);
|
|
49
|
+
observations = await (0, fetch_1.fetch)(`${stations.features[0].id}/observations/latest`);
|
|
50
|
+
//console.log(`observations`, observations)
|
|
51
|
+
}
|
|
52
|
+
// forecasts
|
|
53
|
+
if (response?.properties?.forecastHourly) {
|
|
54
|
+
forecasts = await (0, fetch_1.fetch)(response.properties.forecastHourly);
|
|
55
|
+
//console.log(`forecasts`, forecasts)
|
|
56
|
+
}
|
|
57
|
+
// warnings
|
|
58
|
+
const warnings = await (0, fetch_1.fetch)(`https://api.weather.gov/alerts/active?point=${position.latitude.toFixed(4)},${position.longitude.toFixed(4)}`);
|
|
59
|
+
//console.log(`warnings`, warnings)
|
|
60
|
+
return this.parseResponse({
|
|
61
|
+
position: position,
|
|
62
|
+
forecasts: forecasts?.properties?.periods ?? [],
|
|
63
|
+
observations: observations?.properties ?? null,
|
|
64
|
+
warnings: warnings?.features ?? []
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
parseResponse = (wData) => {
|
|
72
|
+
return {
|
|
73
|
+
self: {
|
|
74
|
+
id: 'self',
|
|
75
|
+
name: 'Weather data relative to supplied position.',
|
|
76
|
+
position: {
|
|
77
|
+
latitude: wData.latitude,
|
|
78
|
+
longitude: wData.longitude
|
|
79
|
+
},
|
|
80
|
+
observations: this.parseNoaaObservations(wData.observations),
|
|
81
|
+
forecasts: this.parseNoaaForecasts(wData.forecasts),
|
|
82
|
+
warnings: this.parseNoaaWarnings(wData.warnings)
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
};
|
|
87
86
|
parseNoaaObservations(wData) {
|
|
88
|
-
var _a, _b;
|
|
89
87
|
const data = [];
|
|
90
88
|
const obs = {};
|
|
91
89
|
let v;
|
|
92
90
|
if (wData) {
|
|
93
|
-
obs.timestamp =
|
|
94
|
-
obs.description =
|
|
91
|
+
obs.timestamp = wData.timestamp ?? null;
|
|
92
|
+
obs.description = wData.textDescription ?? null;
|
|
95
93
|
v = wData.visibility.value
|
|
96
94
|
? wData.visibility.unitCode === 'wmoUnit:m'
|
|
97
95
|
? wData.visibility.value
|
|
@@ -176,10 +174,9 @@ class NOAA {
|
|
|
176
174
|
const data = [];
|
|
177
175
|
if (forecasts && Array.isArray(forecasts)) {
|
|
178
176
|
forecasts.forEach((f) => {
|
|
179
|
-
var _a, _b, _c;
|
|
180
177
|
const forecast = {};
|
|
181
|
-
forecast.timestamp =
|
|
182
|
-
forecast.description =
|
|
178
|
+
forecast.timestamp = f.startTime ?? null;
|
|
179
|
+
forecast.description = f.shortForecast ?? null;
|
|
183
180
|
forecast.temperature = {};
|
|
184
181
|
forecast.temperature.air = {
|
|
185
182
|
value: typeof f.temperature !== 'undefined'
|
|
@@ -189,7 +186,7 @@ class NOAA {
|
|
|
189
186
|
};
|
|
190
187
|
forecast.wind = {};
|
|
191
188
|
forecast.wind.speed = {
|
|
192
|
-
value:
|
|
189
|
+
value: parseInt(f.windSpeed.split(' ')[0]) / 2.237 ?? null,
|
|
193
190
|
units: 'm/s'
|
|
194
191
|
};
|
|
195
192
|
const wd = f.windDirection
|
|
@@ -208,13 +205,12 @@ class NOAA {
|
|
|
208
205
|
const data = [];
|
|
209
206
|
if (alerts && Array.isArray(alerts)) {
|
|
210
207
|
alerts.forEach((alert) => {
|
|
211
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
212
208
|
const warn = {
|
|
213
|
-
startTime:
|
|
214
|
-
endTime:
|
|
215
|
-
details:
|
|
216
|
-
source:
|
|
217
|
-
type:
|
|
209
|
+
startTime: alert?.properties?.effective ?? null,
|
|
210
|
+
endTime: alert?.properties?.ends ?? null,
|
|
211
|
+
details: alert?.properties?.description ?? null,
|
|
212
|
+
source: alert?.properties?.senderName ?? null,
|
|
213
|
+
type: alert?.properties?.messageType ?? null
|
|
218
214
|
};
|
|
219
215
|
data.push(warn);
|
|
220
216
|
});
|