hamlib 0.1.3 → 0.1.5

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 CHANGED
@@ -284,6 +284,109 @@ rig.setAntenna(2); // Select antenna 2
284
284
  const antenna = rig.getAntenna();
285
285
  ```
286
286
 
287
+ ### ⚙️ Serial Port Configuration
288
+
289
+ #### `getSupportedSerialConfigs()`
290
+ Get available serial configuration options
291
+ ```javascript
292
+ const configs = rig.getSupportedSerialConfigs();
293
+ console.log('Data bits:', configs.serial.data_bits); // ['5', '6', '7', '8']
294
+ console.log('Stop bits:', configs.serial.stop_bits); // ['1', '2']
295
+ console.log('Parity:', configs.serial.serial_parity); // ['None', 'Even', 'Odd']
296
+ console.log('Handshake:', configs.serial.serial_handshake); // ['None', 'Hardware', 'Software']
297
+ console.log('PTT types:', configs.ptt_type); // ['RIG', 'DTR', 'RTS', 'PARALLEL', ...]
298
+ console.log('DCD types:', configs.dcd_type); // ['RIG', 'DSR', 'CTS', 'CD', ...]
299
+ ```
300
+
301
+ #### `setSerialConfig(param, value)` / `getSerialConfig(param)`
302
+ Configure serial port parameters
303
+ ```javascript
304
+ // Basic serial configuration (most common)
305
+ rig.setSerialConfig('data_bits', '8'); // 8 data bits
306
+ rig.setSerialConfig('stop_bits', '1'); // 1 stop bit
307
+ rig.setSerialConfig('serial_parity', 'None'); // No parity
308
+ rig.setSerialConfig('serial_handshake', 'None'); // No flow control
309
+
310
+ // Hardware flow control (if supported)
311
+ rig.setSerialConfig('serial_handshake', 'Hardware');
312
+
313
+ // Control line states
314
+ rig.setSerialConfig('rts_state', 'ON'); // Set RTS high
315
+ rig.setSerialConfig('dtr_state', 'OFF'); // Set DTR low
316
+
317
+ // Get current configuration
318
+ const dataBits = rig.getSerialConfig('data_bits');
319
+ const parity = rig.getSerialConfig('serial_parity');
320
+ ```
321
+
322
+ #### `setPttType(type)` / `getPttType()`
323
+ Configure PTT (Push-to-Talk) method
324
+ ```javascript
325
+ // Use CAT command for PTT (recommended)
326
+ rig.setPttType('RIG');
327
+
328
+ // Use DTR line for PTT (legacy interfaces)
329
+ rig.setPttType('DTR');
330
+
331
+ // Use RTS line for PTT (alternative)
332
+ rig.setPttType('RTS');
333
+
334
+ // Disable PTT control
335
+ rig.setPttType('NONE');
336
+
337
+ // Get current PTT type
338
+ const pttType = rig.getPttType();
339
+ console.log('PTT method:', pttType);
340
+ ```
341
+
342
+ #### `setDcdType(type)` / `getDcdType()`
343
+ Configure DCD (Data Carrier Detect) method
344
+ ```javascript
345
+ // Use CAT command for DCD (software squelch)
346
+ rig.setDcdType('RIG');
347
+
348
+ // Use DSR line for DCD (hardware squelch)
349
+ rig.setDcdType('DSR');
350
+
351
+ // Use CTS line for DCD (alternative)
352
+ rig.setDcdType('CTS');
353
+
354
+ // Get current DCD type
355
+ const dcdType = rig.getDcdType();
356
+ console.log('DCD method:', dcdType);
357
+ ```
358
+
359
+ #### Common Serial Configurations
360
+
361
+ **Yaesu Radios:**
362
+ ```javascript
363
+ rig.setSerialConfig('data_bits', '8');
364
+ rig.setSerialConfig('stop_bits', '1');
365
+ rig.setSerialConfig('serial_parity', 'None');
366
+ rig.setSerialConfig('serial_handshake', 'None');
367
+ rig.setPttType('RIG'); // Use CAT command
368
+ // Baud rate: 4800/9600 (set in constructor)
369
+ ```
370
+
371
+ **Kenwood Radios:**
372
+ ```javascript
373
+ rig.setSerialConfig('data_bits', '8');
374
+ rig.setSerialConfig('stop_bits', '2'); // Note: 2 stop bits
375
+ rig.setSerialConfig('serial_parity', 'None');
376
+ rig.setSerialConfig('serial_handshake', 'None');
377
+ rig.setPttType('RIG');
378
+ // Baud rate: 9600
379
+ ```
380
+
381
+ **Legacy Interface (DTR/RTS PTT):**
382
+ ```javascript
383
+ rig.setSerialConfig('data_bits', '8');
384
+ rig.setSerialConfig('stop_bits', '1');
385
+ rig.setSerialConfig('serial_parity', 'None');
386
+ rig.setPttType('DTR'); // Use DTR for PTT
387
+ rig.setDcdType('DSR'); // Use DSR for squelch
388
+ ```
389
+
287
390
  ## 🎯 Complete Example
288
391
 
289
392
  ```javascript
package/index.d.ts CHANGED
@@ -142,6 +142,47 @@ type VfoOperationType = 'CPY' | 'XCHG' | 'FROM_VFO' | 'TO_VFO' | 'MCL' | 'UP' |
142
142
  'DOWN' | 'BAND_UP' | 'BAND_DOWN' | 'LEFT' | 'RIGHT' |
143
143
  'TUNE' | 'TOGGLE';
144
144
 
145
+ /**
146
+ * Serial configuration parameter names
147
+ */
148
+ type SerialConfigParam = 'data_bits' | 'stop_bits' | 'serial_parity' | 'serial_handshake' |
149
+ 'rts_state' | 'dtr_state';
150
+
151
+ /**
152
+ * PTT (Push-to-Talk) types
153
+ */
154
+ type PttType = 'RIG' | 'DTR' | 'RTS' | 'PARALLEL' | 'CM108' | 'GPIO' | 'GPION' | 'NONE';
155
+
156
+ /**
157
+ * DCD (Data Carrier Detect) types
158
+ */
159
+ type DcdType = 'RIG' | 'DSR' | 'CTS' | 'CD' | 'PARALLEL' | 'CM108' | 'GPIO' | 'GPION' | 'NONE';
160
+
161
+ /**
162
+ * Serial configuration options interface
163
+ */
164
+ interface SerialConfigOptions {
165
+ /** Serial port basic parameters */
166
+ serial: {
167
+ /** Data bits options */
168
+ data_bits: string[];
169
+ /** Stop bits options */
170
+ stop_bits: string[];
171
+ /** Parity options */
172
+ serial_parity: string[];
173
+ /** Handshake options */
174
+ serial_handshake: string[];
175
+ /** RTS state options */
176
+ rts_state: string[];
177
+ /** DTR state options */
178
+ dtr_state: string[];
179
+ };
180
+ /** PTT type options */
181
+ ptt_type: string[];
182
+ /** DCD type options */
183
+ dcd_type: string[];
184
+ }
185
+
145
186
  /**
146
187
  * HamLib class - for controlling amateur radio devices
147
188
  */
@@ -444,6 +485,89 @@ declare class HamLib {
444
485
  * @returns Current antenna number
445
486
  */
446
487
  getAntenna(): number;
488
+
489
+ // Serial Port Configuration
490
+
491
+ /**
492
+ * Set serial port configuration parameter
493
+ * @param paramName Parameter name ('data_bits', 'stop_bits', 'serial_parity', 'serial_handshake', 'rts_state', 'dtr_state')
494
+ * @param paramValue Parameter value
495
+ * @example
496
+ * // Set data bits to 8
497
+ * hamlib.setSerialConfig('data_bits', '8');
498
+ *
499
+ * // Set parity to even
500
+ * hamlib.setSerialConfig('serial_parity', 'Even');
501
+ *
502
+ * // Set handshake to hardware
503
+ * hamlib.setSerialConfig('serial_handshake', 'Hardware');
504
+ */
505
+ setSerialConfig(paramName: SerialConfigParam, paramValue: string): void;
506
+
507
+ /**
508
+ * Get serial port configuration parameter
509
+ * @param paramName Parameter name to retrieve
510
+ * @returns Parameter value
511
+ * @example
512
+ * // Get current data bits setting
513
+ * const dataBits = hamlib.getSerialConfig('data_bits');
514
+ *
515
+ * // Get current parity setting
516
+ * const parity = hamlib.getSerialConfig('serial_parity');
517
+ */
518
+ getSerialConfig(paramName: SerialConfigParam): string;
519
+
520
+ /**
521
+ * Set PTT (Push-to-Talk) type
522
+ * @param pttType PTT type ('RIG', 'DTR', 'RTS', 'PARALLEL', 'CM108', 'GPIO', 'GPION', 'NONE')
523
+ * @example
524
+ * // Use DTR line for PTT
525
+ * hamlib.setPttType('DTR');
526
+ *
527
+ * // Use RTS line for PTT
528
+ * hamlib.setPttType('RTS');
529
+ *
530
+ * // Use CAT command for PTT
531
+ * hamlib.setPttType('RIG');
532
+ */
533
+ setPttType(pttType: PttType): void;
534
+
535
+ /**
536
+ * Get current PTT type
537
+ * @returns Current PTT type
538
+ */
539
+ getPttType(): string;
540
+
541
+ /**
542
+ * Set DCD (Data Carrier Detect) type
543
+ * @param dcdType DCD type ('RIG', 'DSR', 'CTS', 'CD', 'PARALLEL', 'CM108', 'GPIO', 'GPION', 'NONE')
544
+ * @example
545
+ * // Use DSR line for DCD
546
+ * hamlib.setDcdType('DSR');
547
+ *
548
+ * // Use CTS line for DCD
549
+ * hamlib.setDcdType('CTS');
550
+ *
551
+ * // Use CAT command for DCD
552
+ * hamlib.setDcdType('RIG');
553
+ */
554
+ setDcdType(dcdType: DcdType): void;
555
+
556
+ /**
557
+ * Get current DCD type
558
+ * @returns Current DCD type
559
+ */
560
+ getDcdType(): string;
561
+
562
+ /**
563
+ * Get supported serial configuration options
564
+ * @returns Object containing all supported configuration parameters and their possible values
565
+ * @example
566
+ * const configs = hamlib.getSupportedSerialConfigs();
567
+ * console.log('Supported data bits:', configs.serial.data_bits);
568
+ * console.log('Supported PTT types:', configs.ptt_type);
569
+ */
570
+ getSupportedSerialConfigs(): SerialConfigOptions;
447
571
  }
448
572
 
449
573
  /**
@@ -456,7 +580,7 @@ declare const nodeHamlib: {
456
580
  // Export types for use elsewhere
457
581
  export { ConnectionInfo, ModeInfo, SupportedRigInfo, VFO, RadioMode, MemoryChannelData,
458
582
  MemoryChannelInfo, SplitModeInfo, SplitStatusInfo, LevelType, FunctionType,
459
- ScanType, VfoOperationType, HamLib };
583
+ ScanType, VfoOperationType, SerialConfigParam, PttType, DcdType, SerialConfigOptions, HamLib };
460
584
 
461
585
  // Support both CommonJS and ES module exports
462
586
  export = nodeHamlib;
package/lib/index.js CHANGED
@@ -367,6 +367,103 @@ class HamLib {
367
367
  getAntenna() {
368
368
  return this._nativeInstance.getAntenna();
369
369
  }
370
+
371
+ // Serial Port Configuration
372
+
373
+ /**
374
+ * Set serial port configuration parameter
375
+ * @param {string} paramName - Parameter name ('data_bits', 'stop_bits', 'serial_parity', 'serial_handshake', 'rts_state', 'dtr_state')
376
+ * @param {string} paramValue - Parameter value
377
+ * @example
378
+ * // Set data bits to 8
379
+ * hamlib.setSerialConfig('data_bits', '8');
380
+ *
381
+ * // Set parity to even
382
+ * hamlib.setSerialConfig('serial_parity', 'Even');
383
+ *
384
+ * // Set handshake to hardware
385
+ * hamlib.setSerialConfig('serial_handshake', 'Hardware');
386
+ */
387
+ setSerialConfig(paramName, paramValue) {
388
+ return this._nativeInstance.setSerialConfig(paramName, paramValue);
389
+ }
390
+
391
+ /**
392
+ * Get serial port configuration parameter
393
+ * @param {string} paramName - Parameter name to retrieve
394
+ * @returns {string} Parameter value
395
+ * @example
396
+ * // Get current data bits setting
397
+ * const dataBits = hamlib.getSerialConfig('data_bits');
398
+ *
399
+ * // Get current parity setting
400
+ * const parity = hamlib.getSerialConfig('serial_parity');
401
+ */
402
+ getSerialConfig(paramName) {
403
+ return this._nativeInstance.getSerialConfig(paramName);
404
+ }
405
+
406
+ /**
407
+ * Set PTT (Push-to-Talk) type
408
+ * @param {string} pttType - PTT type ('RIG', 'DTR', 'RTS', 'PARALLEL', 'CM108', 'GPIO', 'GPION', 'NONE')
409
+ * @example
410
+ * // Use DTR line for PTT
411
+ * hamlib.setPttType('DTR');
412
+ *
413
+ * // Use RTS line for PTT
414
+ * hamlib.setPttType('RTS');
415
+ *
416
+ * // Use CAT command for PTT
417
+ * hamlib.setPttType('RIG');
418
+ */
419
+ setPttType(pttType) {
420
+ return this._nativeInstance.setPttType(pttType);
421
+ }
422
+
423
+ /**
424
+ * Get current PTT type
425
+ * @returns {string} Current PTT type
426
+ */
427
+ getPttType() {
428
+ return this._nativeInstance.getPttType();
429
+ }
430
+
431
+ /**
432
+ * Set DCD (Data Carrier Detect) type
433
+ * @param {string} dcdType - DCD type ('RIG', 'DSR', 'CTS', 'CD', 'PARALLEL', 'CM108', 'GPIO', 'GPION', 'NONE')
434
+ * @example
435
+ * // Use DSR line for DCD
436
+ * hamlib.setDcdType('DSR');
437
+ *
438
+ * // Use CTS line for DCD
439
+ * hamlib.setDcdType('CTS');
440
+ *
441
+ * // Use CAT command for DCD
442
+ * hamlib.setDcdType('RIG');
443
+ */
444
+ setDcdType(dcdType) {
445
+ return this._nativeInstance.setDcdType(dcdType);
446
+ }
447
+
448
+ /**
449
+ * Get current DCD type
450
+ * @returns {string} Current DCD type
451
+ */
452
+ getDcdType() {
453
+ return this._nativeInstance.getDcdType();
454
+ }
455
+
456
+ /**
457
+ * Get supported serial configuration options
458
+ * @returns {Object} Object containing all supported configuration parameters and their possible values
459
+ * @example
460
+ * const configs = hamlib.getSupportedSerialConfigs();
461
+ * console.log('Supported data bits:', configs.serial.data_bits);
462
+ * console.log('Supported PTT types:', configs.ptt_type);
463
+ */
464
+ getSupportedSerialConfigs() {
465
+ return this._nativeInstance.getSupportedSerialConfigs();
466
+ }
370
467
  }
371
468
 
372
469
  // Export for CommonJS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hamlib",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Node.js wrapper for hamlib radio control library",
5
5
  "main": "index.js",
6
6
  "module": "lib/index.mjs",
@@ -30,6 +30,7 @@
30
30
  "lib/",
31
31
  "prebuilds/",
32
32
  "src/",
33
+ "scripts/",
33
34
  "index.js",
34
35
  "index.d.ts",
35
36
  "binding.gyp",
Binary file
Binary file
Binary file
@@ -0,0 +1,262 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { execSync } = require('child_process');
4
+ const { getPlatformBinaryPath } = require('../lib/binary-loader');
5
+
6
+ /**
7
+ * Check if a prebuilt binary exists for the current platform
8
+ */
9
+ function checkPrebuiltBinary() {
10
+ try {
11
+ const binaryPath = getPlatformBinaryPath();
12
+ return fs.existsSync(binaryPath);
13
+ } catch (error) {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Check if we can build from source
20
+ */
21
+ function canBuildFromSource() {
22
+ try {
23
+ // Check if binding.gyp exists
24
+ const bindingGypPath = path.join(__dirname, '..', 'binding.gyp');
25
+ if (!fs.existsSync(bindingGypPath)) {
26
+ return false;
27
+ }
28
+
29
+ // Check if source files exist
30
+ const srcPath = path.join(__dirname, '..', 'src');
31
+ if (!fs.existsSync(srcPath)) {
32
+ return false;
33
+ }
34
+
35
+ // Check if node-gyp is available
36
+ try {
37
+ execSync('node-gyp --version', { stdio: 'ignore' });
38
+ return true;
39
+ } catch (error) {
40
+ return false;
41
+ }
42
+ } catch (error) {
43
+ return false;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Check if we're in a MinGW environment
49
+ */
50
+ function isMinGWEnvironment() {
51
+ return process.env.HAMLIB_ROOT === '/mingw64' ||
52
+ process.env.HAMLIB_ROOT === 'C:\\msys64\\mingw64' ||
53
+ process.env.MSYSTEM === 'MINGW64' ||
54
+ process.env.MINGW_PREFIX === '/mingw64' ||
55
+ process.env.MINGW_PREFIX === 'C:\\msys64\\mingw64';
56
+ }
57
+
58
+ /**
59
+ * Check if hamlib is available in the system
60
+ */
61
+ function checkHamlibAvailable() {
62
+ try {
63
+ if (isMinGWEnvironment()) {
64
+ // In MinGW environment, try to use pkg-config to check hamlib
65
+ try {
66
+ execSync('pkg-config --exists hamlib', { stdio: 'ignore' });
67
+ console.log('✓ Hamlib found via pkg-config');
68
+ return true;
69
+ } catch (pkgConfigError) {
70
+ // If pkg-config fails, try to check for specific files
71
+ // Note: In MSYS2, /mingw64 might be mapped differently for Node.js
72
+ console.log('pkg-config check failed, trying direct file checks...');
73
+
74
+ // Try common MSYS2 paths
75
+ const possiblePaths = [
76
+ '/mingw64/include/hamlib',
77
+ 'C:/msys64/mingw64/include/hamlib',
78
+ 'C:\\msys64\\mingw64\\include\\hamlib',
79
+ process.env.MINGW_PREFIX + '/include/hamlib',
80
+ process.env.HAMLIB_ROOT + '/include/hamlib'
81
+ ].filter(Boolean);
82
+
83
+ for (const includePath of possiblePaths) {
84
+ try {
85
+ if (fs.existsSync(includePath)) {
86
+ console.log(`✓ Hamlib headers found at: ${includePath}`);
87
+ return true;
88
+ }
89
+ } catch (e) {
90
+ // Continue to next path
91
+ }
92
+ }
93
+
94
+ // If all file checks fail, assume hamlib is available since we're in MinGW
95
+ // and the build process showed it was installed
96
+ console.log('Direct file checks failed, but assuming hamlib is available in MinGW environment');
97
+ return true;
98
+ }
99
+ } else {
100
+ // Check if hamlib is available in standard locations
101
+ const locations = [
102
+ '/usr/include/hamlib',
103
+ '/usr/local/include/hamlib',
104
+ '/opt/homebrew/include/hamlib'
105
+ ];
106
+ return locations.some(location => fs.existsSync(location));
107
+ }
108
+ } catch (error) {
109
+ console.log('Error checking hamlib availability:', error.message);
110
+ // In MinGW environment, be more lenient since paths might be mapped differently
111
+ return isMinGWEnvironment();
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Setup Windows dependencies if needed
117
+ */
118
+ async function setupWindowsDependencies() {
119
+ // Skip if we're in MinGW environment - dependencies should already be set up
120
+ if (isMinGWEnvironment()) {
121
+ console.log('✓ MinGW environment detected, skipping Windows dependency setup...');
122
+ return checkHamlibAvailable();
123
+ }
124
+
125
+ // Check if dependencies are already set up
126
+ if (process.env.HAMLIB_ROOT && fs.existsSync(process.env.HAMLIB_ROOT)) {
127
+ console.log('✓ Windows dependencies already set up, skipping...');
128
+ return true;
129
+ }
130
+
131
+ console.log('Setting up Windows dependencies...');
132
+
133
+ try {
134
+ // Call PowerShell script instead of Node.js script
135
+ const scriptPath = path.join(__dirname, 'setup-windows-deps.ps1');
136
+ const command = `powershell -ExecutionPolicy Bypass -File "${scriptPath}"`;
137
+
138
+ console.log(`Running: ${command}`);
139
+ execSync(command, { stdio: 'inherit' });
140
+
141
+ console.log('✓ Windows dependencies setup completed');
142
+ return true;
143
+ } catch (error) {
144
+ console.error('✗ Failed to setup Windows dependencies:', error.message);
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Try to build from source
151
+ */
152
+ async function buildFromSource() {
153
+ console.log('Building hamlib from source...');
154
+
155
+ try {
156
+ // Setup Windows dependencies first if on Windows and not in MinGW environment
157
+ if (process.platform === 'win32' && !isMinGWEnvironment()) {
158
+ const success = await setupWindowsDependencies();
159
+ if (!success) {
160
+ throw new Error('Windows dependencies setup failed');
161
+ }
162
+ }
163
+
164
+ // For MinGW environment, verify hamlib is available
165
+ if (isMinGWEnvironment()) {
166
+ if (!checkHamlibAvailable()) {
167
+ throw new Error('Hamlib not found in MinGW environment. Please install hamlib first.');
168
+ }
169
+ console.log('✓ Hamlib found in MinGW environment');
170
+ }
171
+
172
+ // Build with node-gyp
173
+ execSync('node-gyp configure', { stdio: 'inherit' });
174
+ execSync('node-gyp build', { stdio: 'inherit' });
175
+
176
+ console.log('✓ Built hamlib successfully');
177
+ return true;
178
+ } catch (error) {
179
+ console.error('✗ Failed to build hamlib from source:', error.message);
180
+ return false;
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Main installation logic
186
+ */
187
+ async function main() {
188
+ console.log('Installing node-hamlib...');
189
+
190
+ try {
191
+ // Try to find prebuilt binary first
192
+ const prebuiltPath = path.join(__dirname, '..', 'prebuilds');
193
+ const platform = process.platform;
194
+ const arch = process.arch;
195
+
196
+ let targetDir = '';
197
+ if (platform === 'win32' && arch === 'x64') {
198
+ targetDir = 'win32-x64';
199
+ } else if (platform === 'linux' && arch === 'x64') {
200
+ targetDir = 'linux-x64';
201
+ } else if (platform === 'linux' && arch === 'arm64') {
202
+ targetDir = 'linux-arm64';
203
+ } else if (platform === 'darwin' && arch === 'arm64') {
204
+ targetDir = 'darwin-arm64';
205
+ }
206
+
207
+ const prebuiltBinary = path.join(prebuiltPath, targetDir, 'hamlib.node');
208
+
209
+ if (fs.existsSync(prebuiltBinary)) {
210
+ console.log('✓ Found prebuilt binary');
211
+
212
+ // Copy to build directory
213
+ const buildDir = path.join(__dirname, '..', 'build', 'Release');
214
+ if (!fs.existsSync(buildDir)) {
215
+ fs.mkdirSync(buildDir, { recursive: true });
216
+ }
217
+
218
+ const targetPath = path.join(buildDir, 'hamlib.node');
219
+ fs.copyFileSync(prebuiltBinary, targetPath);
220
+
221
+ console.log('✓ Installation completed successfully');
222
+ return;
223
+ }
224
+
225
+ console.log('⚠ No prebuilt binary found for your platform');
226
+
227
+ // Build from source
228
+ const success = await buildFromSource();
229
+ if (!success) {
230
+ throw new Error('Failed to build from source');
231
+ }
232
+
233
+ console.log('✓ Installation completed successfully');
234
+
235
+ } catch (error) {
236
+ console.error('❌ Installation failed!');
237
+ console.error('This could be due to:');
238
+ console.error('1. No prebuilt binary available for your platform');
239
+ console.error('2. Missing system dependencies (libhamlib-dev)');
240
+ console.error('3. Missing build tools (node-gyp, compiler)');
241
+ console.error('');
242
+ console.error('To resolve this:');
243
+ console.error('System dependencies:');
244
+ console.error(' Linux: sudo apt-get install libhamlib-dev');
245
+ console.error(' macOS: brew install hamlib');
246
+ console.error(' Windows: Install hamlib via vcpkg or from source');
247
+ console.error('');
248
+ console.error('Build tools:');
249
+ console.error(' npm install -g node-gyp');
250
+ console.error(' # Follow node-gyp platform-specific setup instructions');
251
+
252
+ process.exit(1);
253
+ }
254
+ }
255
+
256
+ // Run only if this script is called directly
257
+ if (require.main === module) {
258
+ main().catch(error => {
259
+ console.error('Installation failed:', error);
260
+ process.exit(1);
261
+ });
262
+ }
package/src/hamlib.cpp CHANGED
@@ -2,6 +2,16 @@
2
2
  #include <string>
3
3
  #include <vector>
4
4
 
5
+ // Cross-platform compatibility for hamlib token types
6
+ // Linux versions use token_t, some others use hamlib_token_t
7
+ #ifndef HAMLIB_TOKEN_T
8
+ #ifdef __linux__
9
+ #define HAMLIB_TOKEN_T token_t
10
+ #else
11
+ #define HAMLIB_TOKEN_T hamlib_token_t
12
+ #endif
13
+ #endif
14
+
5
15
  // Structure to hold rig information for the callback
6
16
  struct RigListData {
7
17
  std::vector<Napi::Object> rigList;
@@ -1485,6 +1495,15 @@ Napi::Function NodeHamLib::GetClass(Napi::Env env) {
1485
1495
  // Antenna Selection
1486
1496
  NodeHamLib::InstanceMethod("setAntenna", & NodeHamLib::SetAntenna),
1487
1497
  NodeHamLib::InstanceMethod("getAntenna", & NodeHamLib::GetAntenna),
1498
+
1499
+ // Serial Port Configuration
1500
+ NodeHamLib::InstanceMethod("setSerialConfig", & NodeHamLib::SetSerialConfig),
1501
+ NodeHamLib::InstanceMethod("getSerialConfig", & NodeHamLib::GetSerialConfig),
1502
+ NodeHamLib::InstanceMethod("setPttType", & NodeHamLib::SetPttType),
1503
+ NodeHamLib::InstanceMethod("getPttType", & NodeHamLib::GetPttType),
1504
+ NodeHamLib::InstanceMethod("setDcdType", & NodeHamLib::SetDcdType),
1505
+ NodeHamLib::InstanceMethod("getDcdType", & NodeHamLib::GetDcdType),
1506
+ NodeHamLib::InstanceMethod("getSupportedSerialConfigs", & NodeHamLib::GetSupportedSerialConfigs),
1488
1507
 
1489
1508
  NodeHamLib::InstanceMethod("close", & NodeHamLib::Close),
1490
1509
  NodeHamLib::InstanceMethod("destroy", & NodeHamLib::Destroy),
@@ -1601,3 +1620,250 @@ Napi::Value NodeHamLib::GetSupportedRigs(const Napi::CallbackInfo& info) {
1601
1620
  return rigArray;
1602
1621
  }
1603
1622
 
1623
+ // Serial Port Configuration Methods
1624
+
1625
+ // Set serial configuration parameter (data_bits, stop_bits, parity, handshake, etc.)
1626
+ Napi::Value NodeHamLib::SetSerialConfig(const Napi::CallbackInfo& info) {
1627
+ Napi::Env env = info.Env();
1628
+
1629
+ if (!rig_is_open) {
1630
+ Napi::TypeError::New(env, "Rig is not open!").ThrowAsJavaScriptException();
1631
+ return env.Null();
1632
+ }
1633
+
1634
+ if (info.Length() < 2 || !info[0].IsString() || !info[1].IsString()) {
1635
+ Napi::TypeError::New(env, "Expected parameter name and value as strings").ThrowAsJavaScriptException();
1636
+ return env.Null();
1637
+ }
1638
+
1639
+ std::string paramName = info[0].As<Napi::String>().Utf8Value();
1640
+ std::string paramValue = info[1].As<Napi::String>().Utf8Value();
1641
+
1642
+ // Get configuration token from parameter name
1643
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, paramName.c_str());
1644
+ if (token == RIG_CONF_END) {
1645
+ Napi::Error::New(env, "Unknown configuration parameter").ThrowAsJavaScriptException();
1646
+ return env.Null();
1647
+ }
1648
+
1649
+ // Use rig_set_conf to set configuration parameter
1650
+ int retcode = rig_set_conf(my_rig, token, paramValue.c_str());
1651
+ if (retcode != RIG_OK) {
1652
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1653
+ return env.Null();
1654
+ }
1655
+
1656
+ return Napi::Number::New(env, retcode);
1657
+ }
1658
+
1659
+ // Get serial configuration parameter
1660
+ Napi::Value NodeHamLib::GetSerialConfig(const Napi::CallbackInfo& info) {
1661
+ Napi::Env env = info.Env();
1662
+
1663
+ if (!rig_is_open) {
1664
+ Napi::TypeError::New(env, "Rig is not open!").ThrowAsJavaScriptException();
1665
+ return env.Null();
1666
+ }
1667
+
1668
+ if (info.Length() < 1 || !info[0].IsString()) {
1669
+ Napi::TypeError::New(env, "Expected parameter name as string").ThrowAsJavaScriptException();
1670
+ return env.Null();
1671
+ }
1672
+
1673
+ std::string paramName = info[0].As<Napi::String>().Utf8Value();
1674
+ char value[256];
1675
+
1676
+ // Get configuration token from parameter name
1677
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, paramName.c_str());
1678
+ if (token == RIG_CONF_END) {
1679
+ Napi::Error::New(env, "Unknown configuration parameter").ThrowAsJavaScriptException();
1680
+ return env.Null();
1681
+ }
1682
+
1683
+ // Use rig_get_conf to get configuration parameter
1684
+ int retcode = rig_get_conf(my_rig, token, value);
1685
+ if (retcode != RIG_OK) {
1686
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1687
+ return env.Null();
1688
+ }
1689
+
1690
+ return Napi::String::New(env, value);
1691
+ }
1692
+
1693
+ // Set PTT type
1694
+ Napi::Value NodeHamLib::SetPttType(const Napi::CallbackInfo& info) {
1695
+ Napi::Env env = info.Env();
1696
+
1697
+ if (info.Length() < 1 || !info[0].IsString()) {
1698
+ Napi::TypeError::New(env, "Expected PTT type as string").ThrowAsJavaScriptException();
1699
+ return env.Null();
1700
+ }
1701
+
1702
+ std::string pttTypeStr = info[0].As<Napi::String>().Utf8Value();
1703
+
1704
+ // Get configuration token for ptt_type
1705
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, "ptt_type");
1706
+ if (token == RIG_CONF_END) {
1707
+ Napi::Error::New(env, "PTT type configuration not supported").ThrowAsJavaScriptException();
1708
+ return env.Null();
1709
+ }
1710
+
1711
+ // Set PTT type through configuration
1712
+ int retcode = rig_set_conf(my_rig, token, pttTypeStr.c_str());
1713
+ if (retcode != RIG_OK) {
1714
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1715
+ return env.Null();
1716
+ }
1717
+
1718
+ return Napi::Number::New(env, retcode);
1719
+ }
1720
+
1721
+ // Get PTT type
1722
+ Napi::Value NodeHamLib::GetPttType(const Napi::CallbackInfo& info) {
1723
+ Napi::Env env = info.Env();
1724
+
1725
+ char value[256];
1726
+
1727
+ // Get configuration token for ptt_type
1728
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, "ptt_type");
1729
+ if (token == RIG_CONF_END) {
1730
+ Napi::Error::New(env, "PTT type configuration not supported").ThrowAsJavaScriptException();
1731
+ return env.Null();
1732
+ }
1733
+
1734
+ // Get PTT type through configuration
1735
+ int retcode = rig_get_conf(my_rig, token, value);
1736
+ if (retcode != RIG_OK) {
1737
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1738
+ return env.Null();
1739
+ }
1740
+
1741
+ return Napi::String::New(env, value);
1742
+ }
1743
+
1744
+ // Set DCD type
1745
+ Napi::Value NodeHamLib::SetDcdType(const Napi::CallbackInfo& info) {
1746
+ Napi::Env env = info.Env();
1747
+
1748
+ if (info.Length() < 1 || !info[0].IsString()) {
1749
+ Napi::TypeError::New(env, "Expected DCD type as string").ThrowAsJavaScriptException();
1750
+ return env.Null();
1751
+ }
1752
+
1753
+ std::string dcdTypeStr = info[0].As<Napi::String>().Utf8Value();
1754
+
1755
+ // Get configuration token for dcd_type
1756
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, "dcd_type");
1757
+ if (token == RIG_CONF_END) {
1758
+ Napi::Error::New(env, "DCD type configuration not supported").ThrowAsJavaScriptException();
1759
+ return env.Null();
1760
+ }
1761
+
1762
+ // Set DCD type through configuration
1763
+ int retcode = rig_set_conf(my_rig, token, dcdTypeStr.c_str());
1764
+ if (retcode != RIG_OK) {
1765
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1766
+ return env.Null();
1767
+ }
1768
+
1769
+ return Napi::Number::New(env, retcode);
1770
+ }
1771
+
1772
+ // Get DCD type
1773
+ Napi::Value NodeHamLib::GetDcdType(const Napi::CallbackInfo& info) {
1774
+ Napi::Env env = info.Env();
1775
+
1776
+ char value[256];
1777
+
1778
+ // Get configuration token for dcd_type
1779
+ HAMLIB_TOKEN_T token = rig_token_lookup(my_rig, "dcd_type");
1780
+ if (token == RIG_CONF_END) {
1781
+ Napi::Error::New(env, "DCD type configuration not supported").ThrowAsJavaScriptException();
1782
+ return env.Null();
1783
+ }
1784
+
1785
+ // Get DCD type through configuration
1786
+ int retcode = rig_get_conf(my_rig, token, value);
1787
+ if (retcode != RIG_OK) {
1788
+ Napi::Error::New(env, rigerror(retcode)).ThrowAsJavaScriptException();
1789
+ return env.Null();
1790
+ }
1791
+
1792
+ return Napi::String::New(env, value);
1793
+ }
1794
+
1795
+ // Get supported serial configuration options
1796
+ Napi::Value NodeHamLib::GetSupportedSerialConfigs(const Napi::CallbackInfo& info) {
1797
+ Napi::Env env = info.Env();
1798
+
1799
+ // Return object with supported configuration parameters and their possible values
1800
+ Napi::Object configs = Napi::Object::New(env);
1801
+
1802
+ // Serial basic parameters
1803
+ Napi::Object serialParams = Napi::Object::New(env);
1804
+
1805
+ // Data bits options
1806
+ Napi::Array dataBitsOptions = Napi::Array::New(env, 4);
1807
+ dataBitsOptions[0u] = Napi::String::New(env, "5");
1808
+ dataBitsOptions[1u] = Napi::String::New(env, "6");
1809
+ dataBitsOptions[2u] = Napi::String::New(env, "7");
1810
+ dataBitsOptions[3u] = Napi::String::New(env, "8");
1811
+ serialParams.Set("data_bits", dataBitsOptions);
1812
+
1813
+ // Stop bits options
1814
+ Napi::Array stopBitsOptions = Napi::Array::New(env, 2);
1815
+ stopBitsOptions[0u] = Napi::String::New(env, "1");
1816
+ stopBitsOptions[1u] = Napi::String::New(env, "2");
1817
+ serialParams.Set("stop_bits", stopBitsOptions);
1818
+
1819
+ // Parity options
1820
+ Napi::Array parityOptions = Napi::Array::New(env, 3);
1821
+ parityOptions[0u] = Napi::String::New(env, "None");
1822
+ parityOptions[1u] = Napi::String::New(env, "Even");
1823
+ parityOptions[2u] = Napi::String::New(env, "Odd");
1824
+ serialParams.Set("serial_parity", parityOptions);
1825
+
1826
+ // Handshake options
1827
+ Napi::Array handshakeOptions = Napi::Array::New(env, 3);
1828
+ handshakeOptions[0u] = Napi::String::New(env, "None");
1829
+ handshakeOptions[1u] = Napi::String::New(env, "Hardware");
1830
+ handshakeOptions[2u] = Napi::String::New(env, "Software");
1831
+ serialParams.Set("serial_handshake", handshakeOptions);
1832
+
1833
+ // Control line state options
1834
+ Napi::Array stateOptions = Napi::Array::New(env, 2);
1835
+ stateOptions[0u] = Napi::String::New(env, "ON");
1836
+ stateOptions[1u] = Napi::String::New(env, "OFF");
1837
+ serialParams.Set("rts_state", stateOptions);
1838
+ serialParams.Set("dtr_state", stateOptions);
1839
+
1840
+ configs.Set("serial", serialParams);
1841
+
1842
+ // PTT type options
1843
+ Napi::Array pttTypeOptions = Napi::Array::New(env, 8);
1844
+ pttTypeOptions[0u] = Napi::String::New(env, "RIG");
1845
+ pttTypeOptions[1u] = Napi::String::New(env, "DTR");
1846
+ pttTypeOptions[2u] = Napi::String::New(env, "RTS");
1847
+ pttTypeOptions[3u] = Napi::String::New(env, "PARALLEL");
1848
+ pttTypeOptions[4u] = Napi::String::New(env, "CM108");
1849
+ pttTypeOptions[5u] = Napi::String::New(env, "GPIO");
1850
+ pttTypeOptions[6u] = Napi::String::New(env, "GPION");
1851
+ pttTypeOptions[7u] = Napi::String::New(env, "NONE");
1852
+ configs.Set("ptt_type", pttTypeOptions);
1853
+
1854
+ // DCD type options
1855
+ Napi::Array dcdTypeOptions = Napi::Array::New(env, 9);
1856
+ dcdTypeOptions[0u] = Napi::String::New(env, "RIG");
1857
+ dcdTypeOptions[1u] = Napi::String::New(env, "DSR");
1858
+ dcdTypeOptions[2u] = Napi::String::New(env, "CTS");
1859
+ dcdTypeOptions[3u] = Napi::String::New(env, "CD");
1860
+ dcdTypeOptions[4u] = Napi::String::New(env, "PARALLEL");
1861
+ dcdTypeOptions[5u] = Napi::String::New(env, "CM108");
1862
+ dcdTypeOptions[6u] = Napi::String::New(env, "GPIO");
1863
+ dcdTypeOptions[7u] = Napi::String::New(env, "GPION");
1864
+ dcdTypeOptions[8u] = Napi::String::New(env, "NONE");
1865
+ configs.Set("dcd_type", dcdTypeOptions);
1866
+
1867
+ return configs;
1868
+ }
1869
+
package/src/hamlib.h CHANGED
@@ -66,6 +66,15 @@ class NodeHamLib : public Napi::ObjectWrap<NodeHamLib> {
66
66
  Napi::Value SetAntenna(const Napi::CallbackInfo&);
67
67
  Napi::Value GetAntenna(const Napi::CallbackInfo&);
68
68
 
69
+ // Serial Port Configuration
70
+ Napi::Value SetSerialConfig(const Napi::CallbackInfo&);
71
+ Napi::Value GetSerialConfig(const Napi::CallbackInfo&);
72
+ Napi::Value SetPttType(const Napi::CallbackInfo&);
73
+ Napi::Value GetPttType(const Napi::CallbackInfo&);
74
+ Napi::Value SetDcdType(const Napi::CallbackInfo&);
75
+ Napi::Value GetDcdType(const Napi::CallbackInfo&);
76
+ Napi::Value GetSupportedSerialConfigs(const Napi::CallbackInfo&);
77
+
69
78
  // Static method to get supported rig models
70
79
  static Napi::Value GetSupportedRigs(const Napi::CallbackInfo&);
71
80