Control amateur radio transceivers from Node.js using the Hamlib library.
- 300+ Supported Radios - Yaesu, Icom, Kenwood, Elecraft, FlexRadio, and more
- Full Async/Promise API - Non-blocking operations with async/await support
- Comprehensive Serial Control - 13 parameters for complete serial port configuration
- Multiple Connections - Serial ports, network (rigctld), direct control
- Official Spectrum Streaming - Wraps Hamlib's official spectrum callback API with Promise helpers and typed events
- TypeScript Ready - Complete type definitions included
- Cross-platform - Windows, Linux, macOS
npm install hamlibThe package will automatically use precompiled binaries if available for your platform, otherwise it will build from source.
For faster installation or offline environments, you can manually install precompiled binaries:
- Download Prebuilds: Go to Releases and download
hamlib-prebuilds.zip - Extract: Unzip to your project's
node_modules/hamlib/prebuilds/directory - Install: Run
npm install hamlib --ignore-scripts
Supported Prebuilt Platforms:
- ✅ Linux x64
- ✅ Linux ARM64
- ✅ macOS ARM64 (Apple Silicon)
- ✅ Windows x64
const { HamLib } = require('hamlib');
async function main() {
// Create rig instance (model 1035 = FT-991A)
const rig = new HamLib(1035, '/dev/ttyUSB0');
await rig.open();
// Basic operations
await rig.setFrequency(144390000); // 144.39 MHz
await rig.setMode('FM');
const freq = await rig.getFrequency();
const mode = await rig.getMode();
console.log(`${freq/1000000} MHz ${mode.mode}`);
await rig.close();
}
main().catch(console.error);// Find your radio model
const rigs = HamLib.getSupportedRigs();
const ft991a = rigs.find(r => r.modelName === 'FT-991A');
// Create connection
const rig = new HamLib(1035, '/dev/ttyUSB0'); // Serial
const rig = new HamLib(1035, 'localhost:4532'); // Network (rigctld)
await rig.open();
await rig.close();// Frequency
await rig.setFrequency(14074000); // 14.074 MHz
const freq = await rig.getFrequency();
// Mode
await rig.setMode('USB');
const mode = await rig.getMode();
// VFO
await rig.setVfo('VFO-A');
const vfo = await rig.getVfo();
// PTT
await rig.setPtt(true); // Transmit
const isTransmitting = await rig.getPtt();
// Signal
const strength = await rig.getStrength();// Store channel
await rig.setMemoryChannel(1, {
frequency: 144390000,
mode: 'FM',
description: 'Local Repeater'
});
// Recall channel
const channel = await rig.getMemoryChannel(1);
await rig.selectMemoryChannel(1);// RIT/XIT offsets
await rig.setRit(100); // +100 Hz RIT
await rig.setXit(-50); // -50 Hz XIT
await rig.clearRitXit(); // Clear both
// Scanning
await rig.startScan('VFO'); // Start VFO scan
await rig.stopScan(); // Stop scan
// Levels (0.0-1.0)
await rig.setLevel('AF', 0.7); // Audio 70%
await rig.setLevel('RFPOWER', 0.5); // TX power 50%
const audioLevel = await rig.getLevel('AF');
// Functions
await rig.setFunction('NB', true); // Noise blanker on
const voxEnabled = await rig.getFunction('VOX');
// Split operation
await rig.setSplit(true); // Enable split
await rig.setSplitFreq(144340000); // TX frequency
// VFO operations
await rig.vfoOperation('CPY'); // Copy VFO A to B
await rig.vfoOperation('TOGGLE'); // Toggle VFO A/Bconst reply = await rig.sendRaw(
Buffer.from([0xfe, 0xfe, 0xa4, 0xe0, 0x03, 0xfd]),
64,
Buffer.from([0xfd])
);Notes:
sendRaw()is request/response oriented.- Continuous spectrum streaming now uses Hamlib's official spectrum callback APIs instead of a raw serial byte subscription.
- For Icom rigs, start managed spectrum only after
open(). The built-in helper now follows the validated sequence: register callback, best-effort enable async, configure spectrum, enableSPECTRUM, then enableTRANSCEIVE.
const { HamLib } = require('hamlib');
async function monitorSpectrum() {
const rig = new HamLib(3085, '/dev/tty.usbmodem11201');
await rig.setSerialConfig('rate', '9600');
await rig.setSerialConfig('data_bits', '8');
await rig.setSerialConfig('stop_bits', '1');
await rig.setSerialConfig('serial_parity', 'None');
await rig.open();
const support = await rig.getSpectrumSupportSummary();
if (!support.supported) {
throw new Error('Official Hamlib spectrum streaming is not supported by this rig/backend');
}
rig.on('spectrumLine', (line) => {
console.log({
centerFreq: line.centerFreq,
spanHz: line.spanHz,
bins: line.dataLength,
});
});
await rig.startManagedSpectrum({
hold: false,
spanHz: 10000,
});
await new Promise((resolve) => setTimeout(resolve, 15000));
await rig.stopManagedSpectrum();
await rig.close();
}Spectrum API summary:
getSpectrumCapabilities()returns conservative backend metadata exposed by the native addon.getSpectrumSupportSummary()returns a product-oriented summary of whether official spectrum streaming is usable on the current rig/backend.configureSpectrum()applies supportedSPECTRUM_*levels and optionalSPECTRUM_HOLD.getSpectrumDisplayState()returns a normalized display state withmode/span/fixed edges/edge slot.configureSpectrumDisplay()applies a normalized display config and reads back the resulting state.getSpectrumEdgeSlot()/setSpectrumEdgeSlot()expose backend edge-slot control when available.getSpectrumFixedEdges()/setSpectrumFixedEdges()expose direct fixed-range control usingSPECTRUM_EDGE_LOW/HIGH.startSpectrumStream(callback?)registers the official Hamlib spectrum callback only.stopSpectrumStream()unregisters the official spectrum callback.startManagedSpectrum(config?)runs the validated startup sequence for Icom/Hamlib async spectrum.stopManagedSpectrum()runs the symmetric shutdown sequence and unregisters the callback.
Fixed-range example:
await rig.configureSpectrumDisplay({
mode: 'fixed',
edgeSlot: 1,
edgeLowHz: 14074000,
edgeHighHz: 14077000,
});
const displayState = await rig.getSpectrumDisplayState();
console.log(displayState);Emitted events:
spectrumLinecarries a singleSpectrumLineobject with frequency edges, mode, and raw bin payload.spectrumStateChangedemits{ active: boolean }when managed spectrum starts or stops.spectrumErroris reserved for asynchronous streaming failures.
// Power control
await rig.setPowerstat(1); // Power on (0=off, 1=on, 2=standby)
const powerStatus = await rig.getPowerstat();
// Carrier detection
const carrierDetected = await rig.getDcd(); // Signal present?
// Tuning steps
await rig.setTuningStep(12500); // 12.5 kHz steps
const step = await rig.getTuningStep();// Set repeater shift
await rig.setRepeaterShift('PLUS'); // '+', '-', or 'NONE'
const shift = await rig.getRepeaterShift();
// Set offset frequency
await rig.setRepeaterOffset(600000); // 600 kHz for 2m
const offset = await rig.getRepeaterOffset();Node-hamlib provides comprehensive serial port configuration with 13 parameters covering all aspects of serial communication from basic data format to advanced timing control and device-specific features.
Important: Serial configuration must be done before calling rig.open().
// Create rig instance
const rig = new HamLib(1035, '/dev/ttyUSB0');
// Configure serial parameters BEFORE opening connection
await rig.setSerialConfig('rate', '115200'); // Baud rate: 150 to 4000000 bps
await rig.setSerialConfig('data_bits', '8'); // Data bits: 5, 6, 7, 8
await rig.setSerialConfig('serial_parity', 'None'); // Parity: None, Even, Odd, Mark, Space
await rig.setSerialConfig('timeout', '1000'); // Timeout in milliseconds
await rig.setSerialConfig('write_delay', '10'); // Inter-byte delay (ms)
// PTT/DCD configuration (also before opening)
await rig.setPttType('DTR'); // PTT: RIG, DTR, RTS, NONE, etc.
await rig.setDcdType('RIG'); // DCD: RIG, DSR, CTS, NONE, etc.
// Now open the connection with configured settings
await rig.open();
// Read current settings (can be done anytime)
const rate = await rig.getSerialConfig('rate');
const parity = await rig.getSerialConfig('serial_parity');| Category | Parameter | Description | Supported Values |
|---|---|---|---|
| Basic Serial | data_bits |
Number of data bits | 5, 6, 7, 8 |
stop_bits |
Number of stop bits | 1, 2 |
|
serial_parity |
Parity checking | None, Even, Odd, Mark, Space |
|
serial_handshake |
Flow control | None, Hardware, Software |
|
| Control Signals | rts_state |
RTS line state | ON, OFF, UNSET |
dtr_state |
DTR line state | ON, OFF, UNSET |
|
| Communication | rate |
Baud rate (bps) | 150 to 4000000 |
timeout |
I/O timeout (ms) | Any non-negative integer | |
retry |
Max retry count | Any non-negative integer | |
| Timing | write_delay |
Inter-byte delay (ms) | Any non-negative integer |
post_write_delay |
Inter-command delay (ms) | Any non-negative integer | |
| Advanced | flushx |
MicroHam flush mode | true, false |
const { HamLib } = require('hamlib');
async function repeaterOperation() {
const rig = new HamLib(1035, '/dev/ttyUSB0');
try {
await rig.open();
// Set up for 2m repeater
await rig.setFrequency(145500000); // 145.500 MHz
await rig.setMode('FM');
await rig.setRepeaterShift('MINUS'); // Negative offset
await rig.setRepeaterOffset(600000); // 600 kHz offset
await rig.setTuningStep(12500); // 12.5 kHz steps
await rig.setLevel('RFPOWER', 0.5); // 50% power
// Save to memory
await rig.setMemoryChannel(1, {
frequency: 145500000,
mode: 'FM',
description: 'W1AW Repeater'
});
console.log('Setup complete for repeater operation');
} catch (error) {
console.error('Error:', error.message);
} finally {
await rig.close();
}
}
repeaterOperation();Over 300 radio models supported, including:
| Manufacturer | Popular Models |
|---|---|
| Yaesu | FT-991A, FT-891, FT-857D, FT-817ND |
| Icom | IC-7300, IC-9700, IC-705, IC-7610 |
| Kenwood | TS-2000, TS-590SG, TS-890S |
| Elecraft | K3, K4, KX3, KX2 |
| FlexRadio | 6300, 6400, 6500, 6600, 6700 |
Find your radio model:
const rigs = HamLib.getSupportedRigs();
console.log(rigs.find(r => r.modelName.includes('FT-991')));# Linux/macOS
const rig = new HamLib(1035, '/dev/ttyUSB0');
# Windows
const rig = new HamLib(1035, 'COM3');# Start rigctld daemon
rigctld -m 1035 -r /dev/ttyUSB0 -t 4532
# Connect from Node.js
const rig = new HamLib(1035, 'localhost:4532');sudo usermod -a -G dialout $USER
# Log out and log back in# Linux
ls /dev/tty*
# macOS
ls /dev/cu.*
# Test connection
rigctl -m 1035 -r /dev/ttyUSB0 fLGPL - see COPYING file for details.