hamlib 0.2.7 → 0.3.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 +77 -6
- package/binding.gyp +8 -2
- package/docs/build-hamlib-from-source.md +640 -0
- package/docs/prebuilt-bundling.md +347 -0
- package/index.d.ts +126 -6
- package/lib/index.js +162 -1
- package/package.json +5 -2
- package/prebuilds/darwin-arm64/libhamlib.4.dylib +0 -0
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/darwin-x64/libhamlib.4.dylib +0 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/prebuilds/linux-arm64/libhamlib.so +0 -0
- package/prebuilds/linux-arm64/libhamlib.so.4 +0 -0
- package/prebuilds/linux-arm64/libhamlib.so.4.0.7 +0 -0
- package/prebuilds/linux-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/libhamlib.so +0 -0
- package/prebuilds/linux-x64/libhamlib.so.4 +0 -0
- package/prebuilds/linux-x64/libhamlib.so.4.0.7 +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/prebuilds/win32-x64/hamlib_shim.dll +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/hamlib.cpp +291 -10
- package/src/hamlib.h +14 -0
- package/src/shim/hamlib_shim.c +135 -0
- package/src/shim/hamlib_shim.h +54 -0
package/lib/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const { EventEmitter } = require('events');
|
|
2
3
|
const nodeGypBuild = require('node-gyp-build');
|
|
3
4
|
// Ensure loader resolves from package root (contains prebuilds/ and build/)
|
|
4
5
|
const nativeModule = nodeGypBuild(path.join(__dirname, '..'));
|
|
@@ -9,7 +10,7 @@ const nativeModule = nodeGypBuild(path.join(__dirname, '..'));
|
|
|
9
10
|
* This is a wrapper around the native hamlib module that provides
|
|
10
11
|
* a consistent interface for controlling amateur radio devices.
|
|
11
12
|
*/
|
|
12
|
-
class HamLib {
|
|
13
|
+
class HamLib extends EventEmitter {
|
|
13
14
|
/**
|
|
14
15
|
* Create a new HamLib instance
|
|
15
16
|
* @param {number} model - Radio model number (run `rigctl -l` to find your device model)
|
|
@@ -18,7 +19,9 @@ class HamLib {
|
|
|
18
19
|
* - Network: 'localhost:4532' or '192.168.1.100:4532' (auto-switches to NETRIGCTL mode)
|
|
19
20
|
*/
|
|
20
21
|
constructor(model, port) {
|
|
22
|
+
super();
|
|
21
23
|
this._nativeInstance = new nativeModule.HamLib(model, port);
|
|
24
|
+
this._managedSpectrumRunning = false;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
/**
|
|
@@ -187,6 +190,9 @@ class HamLib {
|
|
|
187
190
|
* Connection can be re-established by calling open()
|
|
188
191
|
*/
|
|
189
192
|
async close() {
|
|
193
|
+
if (this._managedSpectrumRunning) {
|
|
194
|
+
await this.stopManagedSpectrum();
|
|
195
|
+
}
|
|
190
196
|
return this._nativeInstance.close();
|
|
191
197
|
}
|
|
192
198
|
|
|
@@ -195,6 +201,9 @@ class HamLib {
|
|
|
195
201
|
* Object reference should be deleted after calling this
|
|
196
202
|
*/
|
|
197
203
|
async destroy() {
|
|
204
|
+
if (this._managedSpectrumRunning) {
|
|
205
|
+
await this.stopManagedSpectrum();
|
|
206
|
+
}
|
|
198
207
|
return this._nativeInstance.destroy();
|
|
199
208
|
}
|
|
200
209
|
|
|
@@ -1151,6 +1160,158 @@ class HamLib {
|
|
|
1151
1160
|
return this._nativeInstance.sendRaw(data, replyMaxLen);
|
|
1152
1161
|
}
|
|
1153
1162
|
|
|
1163
|
+
/**
|
|
1164
|
+
* Get official Hamlib spectrum capability metadata from the backend.
|
|
1165
|
+
* @returns {Promise<Object>} Spectrum capability object.
|
|
1166
|
+
*/
|
|
1167
|
+
async getSpectrumCapabilities() {
|
|
1168
|
+
return this._nativeInstance.getSpectrumCapabilities();
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Summarize whether official Hamlib spectrum streaming is usable for this rig.
|
|
1173
|
+
* @returns {Promise<Object>} Product-oriented support summary.
|
|
1174
|
+
*/
|
|
1175
|
+
async getSpectrumSupportSummary() {
|
|
1176
|
+
const capabilities = await this.getSpectrumCapabilities();
|
|
1177
|
+
const supportedFunctions = this.getSupportedFunctions();
|
|
1178
|
+
const supportedLevels = this.getSupportedLevels();
|
|
1179
|
+
const hasSpectrumFunction = supportedFunctions.includes('SPECTRUM');
|
|
1180
|
+
const hasSpectrumHoldFunction = supportedFunctions.includes('SPECTRUM_HOLD');
|
|
1181
|
+
const hasTransceiveFunction = supportedFunctions.includes('TRANSCEIVE');
|
|
1182
|
+
const asyncDataSupported = capabilities.asyncDataSupported ?? hasSpectrumFunction;
|
|
1183
|
+
const configurableLevels = ['SPECTRUM_MODE', 'SPECTRUM_SPAN', 'SPECTRUM_SPEED', 'SPECTRUM_REF', 'SPECTRUM_AVG']
|
|
1184
|
+
.filter((name) => supportedLevels.includes(name));
|
|
1185
|
+
|
|
1186
|
+
return {
|
|
1187
|
+
supported: Boolean(hasSpectrumFunction),
|
|
1188
|
+
asyncDataSupported: Boolean(asyncDataSupported),
|
|
1189
|
+
hasSpectrumFunction,
|
|
1190
|
+
hasSpectrumHoldFunction,
|
|
1191
|
+
hasTransceiveFunction,
|
|
1192
|
+
configurableLevels,
|
|
1193
|
+
scopes: capabilities.scopes ?? [],
|
|
1194
|
+
modes: capabilities.modes ?? [],
|
|
1195
|
+
spans: capabilities.spans ?? [],
|
|
1196
|
+
avgModes: capabilities.avgModes ?? [],
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
/**
|
|
1201
|
+
* Apply official Hamlib spectrum settings using high-level level/function APIs.
|
|
1202
|
+
* Unsupported settings are skipped silently.
|
|
1203
|
+
* @param {Object} [config]
|
|
1204
|
+
*/
|
|
1205
|
+
async configureSpectrum(config = {}) {
|
|
1206
|
+
const summary = await this.getSpectrumSupportSummary();
|
|
1207
|
+
const applyLevel = async (name, value) => {
|
|
1208
|
+
if (value === undefined || !summary.configurableLevels.includes(name)) return;
|
|
1209
|
+
await this.setLevel(name, value);
|
|
1210
|
+
};
|
|
1211
|
+
|
|
1212
|
+
if (summary.hasSpectrumHoldFunction && config.hold !== undefined) {
|
|
1213
|
+
await this.setFunction('SPECTRUM_HOLD', Boolean(config.hold));
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
await applyLevel('SPECTRUM_MODE', config.mode);
|
|
1217
|
+
await applyLevel('SPECTRUM_SPAN', config.spanHz);
|
|
1218
|
+
await applyLevel('SPECTRUM_SPEED', config.speed);
|
|
1219
|
+
await applyLevel('SPECTRUM_REF', config.referenceLevel);
|
|
1220
|
+
await applyLevel('SPECTRUM_AVG', config.averageMode);
|
|
1221
|
+
|
|
1222
|
+
return summary;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* Start the official Hamlib spectrum callback stream.
|
|
1227
|
+
* @param {(line: Object) => void} [callback]
|
|
1228
|
+
* @returns {Promise<boolean>}
|
|
1229
|
+
*/
|
|
1230
|
+
async startSpectrumStream(callback) {
|
|
1231
|
+
const listener = typeof callback === 'function'
|
|
1232
|
+
? callback
|
|
1233
|
+
: (line) => this.emit('spectrumLine', line);
|
|
1234
|
+
return this._nativeInstance.startSpectrumStream(listener);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Stop the official Hamlib spectrum callback stream.
|
|
1239
|
+
* @returns {Promise<boolean>}
|
|
1240
|
+
*/
|
|
1241
|
+
async stopSpectrumStream() {
|
|
1242
|
+
return this._nativeInstance.stopSpectrumStream();
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* High-level managed spectrum startup for application use.
|
|
1247
|
+
* @param {Object} [config]
|
|
1248
|
+
*/
|
|
1249
|
+
async startManagedSpectrum(config = {}) {
|
|
1250
|
+
const summary = await this.getSpectrumSupportSummary();
|
|
1251
|
+
if (!summary.supported) {
|
|
1252
|
+
throw new Error('Official Hamlib spectrum streaming is not supported by this rig/backend');
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
if (this._managedSpectrumRunning) {
|
|
1256
|
+
return true;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
await this.startSpectrumStream((line) => this.emit('spectrumLine', line));
|
|
1260
|
+
|
|
1261
|
+
try {
|
|
1262
|
+
try {
|
|
1263
|
+
await this.setConf('async', '1');
|
|
1264
|
+
} catch (_) {
|
|
1265
|
+
try {
|
|
1266
|
+
await this.setConf('async', 'True');
|
|
1267
|
+
} catch (_) {
|
|
1268
|
+
// Not every backend accepts the config write even if async is supported.
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
await this.configureSpectrum({ hold: false, ...config });
|
|
1273
|
+
await this.setFunction('SPECTRUM', true);
|
|
1274
|
+
if (summary.hasTransceiveFunction) {
|
|
1275
|
+
await this.setFunction('TRANSCEIVE', true);
|
|
1276
|
+
}
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
try {
|
|
1279
|
+
await this.stopManagedSpectrum();
|
|
1280
|
+
} catch (_) {
|
|
1281
|
+
// Ignore cleanup failures and surface the original startup error.
|
|
1282
|
+
}
|
|
1283
|
+
throw error;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
this._managedSpectrumRunning = true;
|
|
1287
|
+
this.emit('spectrumStateChanged', { active: true });
|
|
1288
|
+
return true;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* High-level managed spectrum shutdown for application use.
|
|
1293
|
+
*/
|
|
1294
|
+
async stopManagedSpectrum() {
|
|
1295
|
+
try {
|
|
1296
|
+
const supportedFunctions = this.getSupportedFunctions();
|
|
1297
|
+
if (supportedFunctions.includes('TRANSCEIVE')) {
|
|
1298
|
+
await this.setFunction('TRANSCEIVE', false);
|
|
1299
|
+
}
|
|
1300
|
+
if (supportedFunctions.includes('SPECTRUM_HOLD')) {
|
|
1301
|
+
await this.setFunction('SPECTRUM_HOLD', false);
|
|
1302
|
+
}
|
|
1303
|
+
if (supportedFunctions.includes('SPECTRUM')) {
|
|
1304
|
+
await this.setFunction('SPECTRUM', false);
|
|
1305
|
+
}
|
|
1306
|
+
} finally {
|
|
1307
|
+
await this.stopSpectrumStream();
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
this._managedSpectrumRunning = false;
|
|
1311
|
+
this.emit('spectrumStateChanged', { active: false });
|
|
1312
|
+
return true;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1154
1315
|
/**
|
|
1155
1316
|
* Set a backend configuration parameter
|
|
1156
1317
|
* @param {string} name - Configuration token name
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hamlib",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Node.js
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Node.js bindings for Hamlib rig control with official spectrum streaming support",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
7
7
|
"types": "index.d.ts",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"lib/",
|
|
31
31
|
"prebuilds/",
|
|
32
32
|
"src/",
|
|
33
|
+
"docs/",
|
|
33
34
|
"index.js",
|
|
34
35
|
"index.d.ts",
|
|
35
36
|
"binding.gyp",
|
|
@@ -43,9 +44,11 @@
|
|
|
43
44
|
"rebuild": "node-gyp rebuild",
|
|
44
45
|
"clean": "node-gyp clean",
|
|
45
46
|
"test": "node test/test_loader.js",
|
|
47
|
+
"test:version": "node test/test_version.js",
|
|
46
48
|
"test:network": "node test/test_network.js",
|
|
47
49
|
"test:dummy": "node test/test_dummy_complete.js",
|
|
48
50
|
"test:serial": "node test/test_serial_config.js",
|
|
51
|
+
"test:spectrum": "node test/test_spectrum_stream.js",
|
|
49
52
|
"prebuild": "prebuildify --napi --strip",
|
|
50
53
|
"prepare": "",
|
|
51
54
|
"bundle": "node scripts/bundle-deps.js",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|