@rhizomatics/signalk-bluetti-plugin 1.0.6-alpha → 1.0.7-alpha

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 (2) hide show
  1. package/index.js +35 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -169,6 +169,17 @@ module.exports = function (app) {
169
169
  return;
170
170
  }
171
171
 
172
+ // Validate any explicitly-configured encryption CSV paths up front.
173
+ for (const cfg of devices) {
174
+ if (cfg.encryptionCsvPath) {
175
+ const err = validateEncryptionCsvPath(cfg.encryptionCsvPath, cfg.name);
176
+ if (err) {
177
+ app.setPluginError(err);
178
+ return;
179
+ }
180
+ }
181
+ }
182
+
172
183
  // Build address → cfg lookup (normalise to lowercase, no colons)
173
184
  const normalise = (addr) => addr.toLowerCase().replace(/:/g, '');
174
185
  const pending = new Map(devices.map(cfg => [normalise(cfg.address), cfg]));
@@ -180,6 +191,9 @@ module.exports = function (app) {
180
191
  if (cfg) {
181
192
  pending.delete(normalise(address));
182
193
  app.setPluginStatus(`Found ${name} [${address}] — connecting …`);
194
+ // Noble cannot scan and connect simultaneously — stop scan first.
195
+ // The scanComplete handler will restart scanning for any remaining pending devices.
196
+ scanner.stopScan();
183
197
  startDevice(cfg, peripheral, name, deps);
184
198
  } else {
185
199
  log(`Discovered unconfigured Bluetti device: ${name} [${address}]`);
@@ -212,6 +226,27 @@ module.exports = function (app) {
212
226
  }
213
227
  }
214
228
 
229
+ function validateEncryptionCsvPath(csvPath, deviceName) {
230
+ try {
231
+ fs.accessSync(csvPath, fs.constants.R_OK);
232
+ } catch (_) {
233
+ return `[${deviceName}] Encryption CSV not found or not readable: ${csvPath}`;
234
+ }
235
+ let lines;
236
+ try {
237
+ lines = fs.readFileSync(csvPath, 'utf8').split('\n').map(l => l.trim()).filter(Boolean);
238
+ } catch (err) {
239
+ return `[${deviceName}] Could not read encryption CSV "${csvPath}": ${err.message}`;
240
+ }
241
+ if (lines[0] !== 'bluetti') {
242
+ return `[${deviceName}] Encryption CSV does not look like a Bluetti key file (expected first line "bluetti"): ${csvPath}`;
243
+ }
244
+ if (lines.length < 4) {
245
+ return `[${deviceName}] Encryption CSV is missing the key line (expected 4 lines): ${csvPath}`;
246
+ }
247
+ return null;
248
+ }
249
+
215
250
  function resolveRegisterMapPath(cfg) {
216
251
  const { builtinModel, csvPath } = cfg;
217
252
  if (!builtinModel || builtinModel === 'custom') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhizomatics/signalk-bluetti-plugin",
3
- "version": "1.0.6-alpha",
3
+ "version": "1.0.7-alpha",
4
4
  "signalk": {
5
5
  "displayName": "Bluetti Monitoring"
6
6
  },