@noforeignland/signalk-to-noforeignland 1.1.0-beta.3 → 1.2.0-beta.1
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 +24 -9
- package/package.json +38 -7
- package/.github/workflows/publish.yml +0 -40
- package/CHANGELOG.md +0 -116
- package/PROJECT_STRUCTURE.md +0 -357
- package/cleanup-old-plugin.js +0 -80
- package/doc/beta_install_cerbo.md +0 -116
- package/doc/beta_install_rpi.md +0 -64
- package/doc/dev +0 -0
- package/index.js +0 -304
- package/lib/ConfigManager.js +0 -216
- package/lib/DataPathEmitter.js +0 -93
- package/lib/DirectoryUtils.js +0 -38
- package/lib/HealthMonitor.js +0 -91
- package/lib/PluginCleanup.js +0 -161
- package/lib/TrackLogger.js +0 -306
- package/lib/TrackMigration.js +0 -110
- package/lib/TrackSender.js +0 -257
package/cleanup-old-plugin.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Cleanup script for old plugin versions
|
|
5
|
-
* This runs as a standalone script during npm postinstall
|
|
6
|
-
* NOT a class - just a simple executable script
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
// Detect SignalK directory (standard ~/.signalk or Victron Cerbo /data/conf/signalk)
|
|
13
|
-
function getSignalKDir() {
|
|
14
|
-
const victronPath = '/data/conf/signalk';
|
|
15
|
-
const homePath = path.join(process.env.HOME || '', '.signalk');
|
|
16
|
-
|
|
17
|
-
// Check Victron path first
|
|
18
|
-
if (fs.existsSync(victronPath)) {
|
|
19
|
-
return victronPath;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return homePath;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const signalkDir = getSignalKDir();
|
|
26
|
-
console.log(`Using SignalK directory: ${signalkDir}`);
|
|
27
|
-
|
|
28
|
-
// 1. Migration (only for signalk-to-noforeignland config)
|
|
29
|
-
try {
|
|
30
|
-
const configPath = path.join(signalkDir, 'plugin-config-data');
|
|
31
|
-
const oldConfig = path.join(configPath, 'signalk-to-noforeignland.json');
|
|
32
|
-
const newConfig = path.join(configPath, '@noforeignland-signalk-to-noforeignland.json');
|
|
33
|
-
|
|
34
|
-
if (fs.existsSync(oldConfig) && !fs.existsSync(newConfig)) {
|
|
35
|
-
fs.copyFileSync(oldConfig, newConfig);
|
|
36
|
-
fs.copyFileSync(oldConfig, `${oldConfig}.backup`);
|
|
37
|
-
console.log('✓ Configuration migrated');
|
|
38
|
-
}
|
|
39
|
-
} catch (e) {
|
|
40
|
-
console.warn('Could not migrate config:', e.message);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 2. Uninstall old plugins (with delay so npm can finish)
|
|
44
|
-
setTimeout(() => {
|
|
45
|
-
try {
|
|
46
|
-
const oldPlugins = [
|
|
47
|
-
{ dir: path.join(signalkDir, 'node_modules', 'signalk-to-noforeignland'), name: 'signalk-to-noforeignland' },
|
|
48
|
-
{ dir: path.join(signalkDir, 'node_modules', 'signalk-to-nfl'), name: 'signalk-to-nfl' }
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
let removedAny = false;
|
|
52
|
-
const failedPlugins = [];
|
|
53
|
-
|
|
54
|
-
for (const plugin of oldPlugins) {
|
|
55
|
-
if (fs.existsSync(plugin.dir)) {
|
|
56
|
-
try {
|
|
57
|
-
console.log(`Removing old plugin "${plugin.name}"...`);
|
|
58
|
-
// Direct deletion is safer than npm uninstall during installation
|
|
59
|
-
fs.rmSync(plugin.dir, { recursive: true, force: true });
|
|
60
|
-
console.log(`✓ Old plugin "${plugin.name}" removed`);
|
|
61
|
-
removedAny = true;
|
|
62
|
-
} catch (e) {
|
|
63
|
-
console.warn(`Could not remove "${plugin.name}":`, e.message);
|
|
64
|
-
failedPlugins.push(plugin.name);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (failedPlugins.length > 0) {
|
|
70
|
-
const uninstallCmd = failedPlugins.join(' ');
|
|
71
|
-
console.warn(`Please run manually: npm uninstall ${uninstallCmd}`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!removedAny && failedPlugins.length === 0) {
|
|
75
|
-
console.log('No old plugins found - already clean!');
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.warn('Error during cleanup:', e.message);
|
|
79
|
-
}
|
|
80
|
-
}, 2000); // Wait 2 seconds for npm to finish
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
How-to install the latest beta or dev tree (unstable) on your device?
|
|
2
|
-
|
|
3
|
-
This guide assumes you have a default install with default folders.
|
|
4
|
-
This is written for a Victron Cerbo GX jump to the section you need want to go to.
|
|
5
|
-
It is recommended to enable the Debug Log for this plugin in Server -> Plugin Config before updating.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# Pre-requirements
|
|
9
|
-
On the Cerbo GUI enable SSH access and set a afmin password
|
|
10
|
-
Windows User: Download putty (for ssh) and Winscp (for secure fie copy)
|
|
11
|
-
|
|
12
|
-
## On GUI v1:
|
|
13
|
-
1. Click "Menu" (bottom right)
|
|
14
|
-
2. Settings > General
|
|
15
|
-
3. Set root password
|
|
16
|
-
4. Enable "SSH on LAN"
|
|
17
|
-
|
|
18
|
-
## On GUI v2:
|
|
19
|
-
1. Settings -> General
|
|
20
|
-
2. Set root password
|
|
21
|
-
3. Enable "SSH on LAN"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Backup old data
|
|
25
|
-
|
|
26
|
-
## BEST + SLOW: Full signalk copy to local computer
|
|
27
|
-
1. Connect your Cerbo with WinSCP
|
|
28
|
-
2. Copy the folder "/data/conf/signalk" to your local PC
|
|
29
|
-
|
|
30
|
-
## Alternative Cerbo has a SD Card connected:
|
|
31
|
-
1. ssh to the Cerbo
|
|
32
|
-
```
|
|
33
|
-
df -h
|
|
34
|
-
# showns for me that /dev/mmcblk0p1 has 29GB free and is mounted to /run/media/mmcblk0p1
|
|
35
|
-
# This is a SD card that is manually inserted.
|
|
36
|
-
|
|
37
|
-
mount
|
|
38
|
-
# confirms this for me with output:
|
|
39
|
-
# /dev/mmcblk0p1 on /run/media/mmcblk0p1 type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
|
|
40
|
-
|
|
41
|
-
cp -r /data/conf/signalk /run/media/mmcblk0p1/signalk-backup
|
|
42
|
-
# copies the files for you, it will take some time, as the CPU and IO are not the fastest
|
|
43
|
-
|
|
44
|
-
ls –la /run/media/mmcblk0p1/signalk-backup
|
|
45
|
-
# Verify that folder and files exist.
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# npmjs beta on Cerbo
|
|
50
|
-
|
|
51
|
-
## Install latest beta
|
|
52
|
-
1. SSH to the Cerbo:
|
|
53
|
-
```
|
|
54
|
-
cd /data/conf/signalk
|
|
55
|
-
|
|
56
|
-
npm i @noforeignland/signalk-to-noforeignland@beta
|
|
57
|
-
|
|
58
|
-
# reset owner properly, else package belongs to root
|
|
59
|
-
chown -R signalk:signalk /data/conf/signalk/*
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
2. Restart Server & Check logs
|
|
64
|
-
```
|
|
65
|
-
svc -t /service/signalk-server
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
## Install specific beta version f.e. 1.0.1-beta.5
|
|
70
|
-
1. SSH to the Cerbo:
|
|
71
|
-
```
|
|
72
|
-
cd /data/conf/signalk
|
|
73
|
-
|
|
74
|
-
# Here use the beta version you want to install
|
|
75
|
-
npm i @noforeignland/signalk-to-noforeignland@1.0.1-beta.5
|
|
76
|
-
|
|
77
|
-
# reset owner properly, else package belongs to root
|
|
78
|
-
chown -R signalk:signalk /data/conf/signalk/*
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
2. Restart Server & Check logs
|
|
82
|
-
```
|
|
83
|
-
svc -t /service/signalk-server
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
----------------------------------------
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# dev tree (unstable) install - NOT RECOMMENDED
|
|
91
|
-
|
|
92
|
-
1. Backup as above
|
|
93
|
-
|
|
94
|
-
2. Get new files from repo (main for latest)
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
cd ~
|
|
98
|
-
mkdir dev
|
|
99
|
-
cd dev
|
|
100
|
-
wget https://github.com/noforeignland/nfl-signalk/archive/refs/heads/main.zip
|
|
101
|
-
unzip main.zip
|
|
102
|
-
cd nfl-signalk-main/
|
|
103
|
-
npm pack
|
|
104
|
-
|
|
105
|
-
cd /data/conf/signalk
|
|
106
|
-
npm install ~/dev/nfl-signalk-main/<your_npm_pack.tgz>
|
|
107
|
-
|
|
108
|
-
# reset owner properly, else package belongs to root
|
|
109
|
-
chown -R signalk:signalk /data/conf/signalk/*
|
|
110
|
-
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
3. Restart Server & Check logs
|
|
114
|
-
```
|
|
115
|
-
svc -t /service/signalk-server
|
|
116
|
-
```
|
package/doc/beta_install_rpi.md
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
How-to install the latest beta or dev tree (unstable) on your device?
|
|
2
|
-
|
|
3
|
-
This guide assumes you have a default install with default folders.
|
|
4
|
-
This is written for a RPI, jump to the section you need want to go to.
|
|
5
|
-
It is recommended to enable the Debug Log for this plugin in Server -> Plugin Config before updating.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# Backup old data
|
|
9
|
-
```
|
|
10
|
-
cp -a ~/.signalk ~/signalk-backup
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
# npmjs beta on RPI
|
|
14
|
-
|
|
15
|
-
## Install latest beta
|
|
16
|
-
```
|
|
17
|
-
cd ~.signalk
|
|
18
|
-
|
|
19
|
-
npm i @noforeignland/signalk-to-noforeignland@beta
|
|
20
|
-
|
|
21
|
-
sudo systemctl restart signalk.service && sudo journalctl -u signalk.service -f
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Install a specific beta
|
|
25
|
-
```
|
|
26
|
-
cd ~.signalk
|
|
27
|
-
|
|
28
|
-
# Here use the beta version you want to install
|
|
29
|
-
npm i @noforeignland/signalk-to-noforeignland@1.0.1-beta.5
|
|
30
|
-
|
|
31
|
-
sudo systemctl restart signalk.service && sudo journalctl -u signalk.service -f
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
--------------------------
|
|
35
|
-
|
|
36
|
-
# dev tree (unstable) - NOT RECOMMENDED
|
|
37
|
-
1. Backup old data
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
cd ~
|
|
41
|
-
cp -a .signalk/ signalk-backup
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
2. Get new files from repo (main for latest)
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
cd ~
|
|
48
|
-
mkdir dev
|
|
49
|
-
cd dev
|
|
50
|
-
wget https://github.com/noforeignland/nfl-signalk/archive/refs/heads/main.zip
|
|
51
|
-
unzip main.zip
|
|
52
|
-
cd nfl-signalk-main/
|
|
53
|
-
npm pack
|
|
54
|
-
|
|
55
|
-
cd ~/.signalk
|
|
56
|
-
npm install ~/dev/nfl-signalk-main/<your_npm_pack.tgz>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
3. Restart Server & Check logs
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
sudo systemctl restart signalk.service && sudo journalctl -u signalk.service -f
|
|
63
|
-
```
|
|
64
|
-
|
package/doc/dev
DELETED
|
File without changes
|
package/index.js
DELETED
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
const CronJob = require('cron').CronJob;
|
|
2
|
-
|
|
3
|
-
// Import all modules
|
|
4
|
-
const ConfigManager = require('./lib/ConfigManager');
|
|
5
|
-
const PluginCleanup = require('./lib/PluginCleanup');
|
|
6
|
-
const TrackMigration = require('./lib/TrackMigration');
|
|
7
|
-
const TrackLogger = require('./lib/TrackLogger');
|
|
8
|
-
const TrackSender = require('./lib/TrackSender');
|
|
9
|
-
const HealthMonitor = require('./lib/HealthMonitor');
|
|
10
|
-
const DataPathEmitter = require('./lib/DataPathEmitter');
|
|
11
|
-
const DirectoryUtils = require('./lib/DirectoryUtils');
|
|
12
|
-
|
|
13
|
-
class SignalkToNoforeignland {
|
|
14
|
-
constructor(app) {
|
|
15
|
-
this.app = app;
|
|
16
|
-
this.pluginId = 'signalk-to-noforeignland';
|
|
17
|
-
this.pluginName = 'Signal K to Noforeignland';
|
|
18
|
-
|
|
19
|
-
// Runtime state
|
|
20
|
-
this.options = {};
|
|
21
|
-
this.upSince = null;
|
|
22
|
-
this.cron = null;
|
|
23
|
-
this.lastSuccessfulTransfer = null;
|
|
24
|
-
|
|
25
|
-
// Module instances
|
|
26
|
-
this.configManager = new ConfigManager(app);
|
|
27
|
-
this.pluginCleanup = new PluginCleanup(app);
|
|
28
|
-
this.dataPathEmitter = new DataPathEmitter(app, this.pluginId);
|
|
29
|
-
this.trackLogger = null;
|
|
30
|
-
this.trackSender = null;
|
|
31
|
-
this.healthMonitor = null;
|
|
32
|
-
this.trackMigration = null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get plugin schema
|
|
37
|
-
*/
|
|
38
|
-
getSchema() {
|
|
39
|
-
return ConfigManager.getSchema(this.pluginName);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get plugin object for SignalK
|
|
44
|
-
*/
|
|
45
|
-
getPluginObject() {
|
|
46
|
-
return {
|
|
47
|
-
id: this.pluginId,
|
|
48
|
-
name: this.pluginName,
|
|
49
|
-
description: 'SignalK track logger to noforeignland.com',
|
|
50
|
-
schema: this.getSchema(),
|
|
51
|
-
start: this.start.bind(this),
|
|
52
|
-
stop: this.stop.bind(this)
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Start the plugin
|
|
58
|
-
*/
|
|
59
|
-
async start(options = {}, restartPlugin) {
|
|
60
|
-
try {
|
|
61
|
-
// 1. Migrate old config structure if needed
|
|
62
|
-
const { options: migratedOptions, migrated } = await this.configManager.migrateOldConfig(options);
|
|
63
|
-
options = migratedOptions;
|
|
64
|
-
|
|
65
|
-
// 2. Flatten config and apply defaults
|
|
66
|
-
this.options = this.configManager.flattenConfig(options);
|
|
67
|
-
|
|
68
|
-
// 3. Validate API key
|
|
69
|
-
try {
|
|
70
|
-
this.configManager.validateApiKey(this.options);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
this.app.debug(err.message);
|
|
73
|
-
this.setPluginError(err.message);
|
|
74
|
-
this.stop();
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// 4. Resolve track directory path
|
|
79
|
-
const dataDirPath = this.app.getDataDirPath();
|
|
80
|
-
this.options.trackDir = this.configManager.resolveTrackDir(this.options, dataDirPath);
|
|
81
|
-
|
|
82
|
-
// 5. Create track directory
|
|
83
|
-
try {
|
|
84
|
-
DirectoryUtils.createDir(this.options.trackDir, this.app);
|
|
85
|
-
} catch (err) {
|
|
86
|
-
this.setPluginError(err.message);
|
|
87
|
-
this.stop();
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// 6. Cleanup old plugin versions (with callback handling)
|
|
92
|
-
this.pluginCleanup.cleanup()
|
|
93
|
-
.then((result) => {
|
|
94
|
-
if (result === 'all_removed') {
|
|
95
|
-
this.app.debug('Old plugins successfully cleaned up');
|
|
96
|
-
// Update status if plugin started successfully
|
|
97
|
-
if (this.options.boatApiKey) {
|
|
98
|
-
this.setPluginStatus('Started (old plugins cleaned up)');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
.catch(err => {
|
|
103
|
-
this.app.debug('Error in cleanupOldPlugin:', err.message);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// 7. Migrate old track files
|
|
107
|
-
this.trackMigration = new TrackMigration(this.app, this.options.trackDir);
|
|
108
|
-
await this.trackMigration.migrate();
|
|
109
|
-
|
|
110
|
-
// 8. Initialize modules
|
|
111
|
-
this.trackLogger = new TrackLogger(this.app, this.options, this.options.trackDir);
|
|
112
|
-
this.trackSender = new TrackSender(this.app, this.options, this.options.trackDir);
|
|
113
|
-
this.healthMonitor = new HealthMonitor(this.app, this.options);
|
|
114
|
-
|
|
115
|
-
// 9. Update startup time and randomize CRON
|
|
116
|
-
this.upSince = new Date().getTime();
|
|
117
|
-
this.options = this.configManager.randomizeCron(this.options);
|
|
118
|
-
|
|
119
|
-
this.app.debug('Setting CRON to', this.options.apiCron);
|
|
120
|
-
this.app.debug('trackFrequency is set to', this.options.trackFrequency, 'seconds');
|
|
121
|
-
this.app.debug('track logger started, now logging to', this.options.trackDir);
|
|
122
|
-
|
|
123
|
-
// 10. Start logging
|
|
124
|
-
this.trackLogger.startLogging((lastPosition) => {
|
|
125
|
-
this.handleSavePoint(lastPosition);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// 11. Start CRON job for sending data
|
|
129
|
-
this.cron = new CronJob(this.options.apiCron, this.interval.bind(this));
|
|
130
|
-
this.cron.start();
|
|
131
|
-
|
|
132
|
-
// 12. Start health monitoring
|
|
133
|
-
this.healthMonitor.start(
|
|
134
|
-
() => this.trackLogger.getLastPositionReceived(),
|
|
135
|
-
() => this.trackLogger.getAutoSelectedSource(),
|
|
136
|
-
(errorMsg) => this.setPluginError(errorMsg),
|
|
137
|
-
() => this.handleHealthy()
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
// 13. Set plugin status
|
|
141
|
-
this.setPluginStatus(`Started${migrated ? ' (config migrated)' : ''}`);
|
|
142
|
-
|
|
143
|
-
} catch (err) {
|
|
144
|
-
this.app.debug('Error during plugin start:', err.message);
|
|
145
|
-
this.setPluginError(`Failed to start: ${err.message}`);
|
|
146
|
-
this.stop();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Handle savepoint event
|
|
152
|
-
*/
|
|
153
|
-
handleSavePoint(lastPosition) {
|
|
154
|
-
const now = new Date();
|
|
155
|
-
this.dataPathEmitter.emitSavepoint();
|
|
156
|
-
|
|
157
|
-
// Update plugin status
|
|
158
|
-
const activeSource = this.options.filterSource || this.trackLogger.getAutoSelectedSource() || '';
|
|
159
|
-
const sourcePrefix = activeSource ? `${activeSource} | ` : '';
|
|
160
|
-
const saveTime = now.toISOString();
|
|
161
|
-
const transferTime = this.lastSuccessfulTransfer
|
|
162
|
-
? this.lastSuccessfulTransfer.toISOString()
|
|
163
|
-
: 'None since start';
|
|
164
|
-
|
|
165
|
-
this.setPluginStatus(`Save: ${saveTime} | Transfer: ${transferTime} | ${sourcePrefix}`);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Handle healthy status from health monitor
|
|
170
|
-
*/
|
|
171
|
-
handleHealthy() {
|
|
172
|
-
// Clear error if position health is OK
|
|
173
|
-
if (this.dataPathEmitter.getError()) {
|
|
174
|
-
const lastPosition = this.trackLogger.getLastPosition();
|
|
175
|
-
const activeSource = this.options.filterSource || this.trackLogger.getAutoSelectedSource() || '';
|
|
176
|
-
const sourcePrefix = activeSource ? `${activeSource} | ` : '';
|
|
177
|
-
const saveTime = lastPosition
|
|
178
|
-
? new Date(lastPosition.currentTime).toISOString()
|
|
179
|
-
: 'None since start';
|
|
180
|
-
const transferTime = this.lastSuccessfulTransfer
|
|
181
|
-
? this.lastSuccessfulTransfer.toISOString()
|
|
182
|
-
: 'None since start';
|
|
183
|
-
|
|
184
|
-
this.setPluginStatus(`Save: ${saveTime} | Transfer: ${transferTime} | ${sourcePrefix}`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* CRON interval - check and send data
|
|
190
|
-
*/
|
|
191
|
-
async interval() {
|
|
192
|
-
try {
|
|
193
|
-
// Check if boat is moving
|
|
194
|
-
const lastPosition = this.trackLogger.getLastPosition();
|
|
195
|
-
const boatMoving = this.trackSender.isBoatMoving(lastPosition, this.upSince);
|
|
196
|
-
if (!boatMoving) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Check if we have track data
|
|
201
|
-
const hasTrack = await this.trackSender.hasTrackData();
|
|
202
|
-
if (!hasTrack) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Test internet connection
|
|
207
|
-
const hasInternet = await this.trackSender.testInternet();
|
|
208
|
-
if (!hasInternet) {
|
|
209
|
-
const errorMsg = 'No internet connection detected. Unable to send tracking data to NFL. DNS lookups failed - check your internet connection.';
|
|
210
|
-
this.app.debug(errorMsg);
|
|
211
|
-
this.setPluginError(errorMsg);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Send track data
|
|
216
|
-
const success = await this.trackSender.sendTrack();
|
|
217
|
-
|
|
218
|
-
if (success) {
|
|
219
|
-
this.lastSuccessfulTransfer = new Date();
|
|
220
|
-
this.dataPathEmitter.emitApiTransfer(this.lastSuccessfulTransfer);
|
|
221
|
-
|
|
222
|
-
// Update status
|
|
223
|
-
const activeSource = this.options.filterSource || this.trackLogger.getAutoSelectedSource() || '';
|
|
224
|
-
const sourcePrefix = activeSource ? `${activeSource} | ` : '';
|
|
225
|
-
const saveTime = lastPosition
|
|
226
|
-
? new Date(lastPosition.currentTime).toISOString()
|
|
227
|
-
: 'None since start';
|
|
228
|
-
const transferTime = this.lastSuccessfulTransfer.toISOString();
|
|
229
|
-
|
|
230
|
-
this.setPluginStatus(`Save: ${saveTime} | Transfer: ${transferTime} | ${sourcePrefix}`);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
} catch (err) {
|
|
234
|
-
this.app.debug('Error during send interval:', err.message);
|
|
235
|
-
this.setPluginError(`Failed to send track - ${err.message}`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Stop the plugin
|
|
241
|
-
*/
|
|
242
|
-
stop() {
|
|
243
|
-
this.app.debug('plugin stopped');
|
|
244
|
-
|
|
245
|
-
// Stop CRON job
|
|
246
|
-
if (this.cron) {
|
|
247
|
-
this.cron.stop();
|
|
248
|
-
this.cron = undefined;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Stop track logger
|
|
252
|
-
if (this.trackLogger) {
|
|
253
|
-
this.trackLogger.stop();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Stop health monitor
|
|
257
|
-
if (this.healthMonitor) {
|
|
258
|
-
this.healthMonitor.stop();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
this.app.setPluginStatus('Plugin stopped');
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Set plugin status and update data paths
|
|
266
|
-
*/
|
|
267
|
-
setPluginStatus(status) {
|
|
268
|
-
this.dataPathEmitter.clearError();
|
|
269
|
-
this.app.setPluginStatus(status);
|
|
270
|
-
|
|
271
|
-
const lastPosition = this.trackLogger ? this.trackLogger.getLastPosition() : null;
|
|
272
|
-
const autoSelectedSource = this.trackLogger ? this.trackLogger.getAutoSelectedSource() : null;
|
|
273
|
-
|
|
274
|
-
this.dataPathEmitter.updateStatusPaths(
|
|
275
|
-
this.options,
|
|
276
|
-
lastPosition,
|
|
277
|
-
this.lastSuccessfulTransfer,
|
|
278
|
-
autoSelectedSource
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Set plugin error and update data paths
|
|
284
|
-
*/
|
|
285
|
-
setPluginError(error) {
|
|
286
|
-
this.dataPathEmitter.setError(error);
|
|
287
|
-
this.app.setPluginError(error);
|
|
288
|
-
|
|
289
|
-
const lastPosition = this.trackLogger ? this.trackLogger.getLastPosition() : null;
|
|
290
|
-
const autoSelectedSource = this.trackLogger ? this.trackLogger.getAutoSelectedSource() : null;
|
|
291
|
-
|
|
292
|
-
this.dataPathEmitter.updateStatusPaths(
|
|
293
|
-
this.options,
|
|
294
|
-
lastPosition,
|
|
295
|
-
this.lastSuccessfulTransfer,
|
|
296
|
-
autoSelectedSource
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
module.exports = function (app) {
|
|
302
|
-
const instance = new SignalkToNoforeignland(app);
|
|
303
|
-
return instance.getPluginObject();
|
|
304
|
-
};
|