
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
Node.js bindings for Hamlib rig control with official spectrum streaming support
Control amateur radio transceivers from Node.js using the Hamlib library.
npm install hamlib
The 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:
hamlib-prebuilds.zipnode_modules/hamlib/prebuilds/ directorynpm install hamlib --ignore-scriptsSupported Prebuilt Platforms:
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('VFOA');
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, true);
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', 0); // 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/B
const reply = await rig.sendRaw(
Buffer.from([0xfe, 0xfe, 0xa4, 0xe0, 0x03, 0xfd]),
64,
Buffer.from([0xfd])
);
Notes:
sendRaw() is request/response oriented.HamLib class stays a bridge. High-level spectrum helpers live under the hamlib/spectrum subpath.const { HamLib } = require('hamlib');
const { SpectrumController } = require('hamlib/spectrum');
async function monitorSpectrum() {
const rig = new HamLib(3085, '/dev/tty.usbmodem11201');
const spectrum = new SpectrumController(rig);
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 spectrum.getSpectrumSupportSummary();
if (!support.supported) {
throw new Error('Official Hamlib spectrum streaming is not supported by this rig/backend');
}
spectrum.on('spectrumLine', (line) => {
console.log({
centerFreq: line.centerFreq,
spanHz: line.spanHz,
bins: line.dataLength,
});
});
await spectrum.startManagedSpectrum({
hold: false,
spanHz: 10000,
pumpIntervalMs: 200,
});
await new Promise((resolve) => setTimeout(resolve, 15000));
await spectrum.stopManagedSpectrum();
await rig.close();
}
Spectrum API summary:
HamLib.getSpectrumCapabilities() returns conservative backend metadata exposed by the native addon.HamLib.startSpectrumStream(callback?) registers the official Hamlib spectrum callback only.HamLib.stopSpectrumStream() unregisters the official spectrum callback.SpectrumController.getSpectrumSupportSummary() returns a product-oriented summary of whether official spectrum streaming is usable on the current rig/backend.SpectrumController.configureSpectrum() applies supported SPECTRUM_* levels and optional SPECTRUM_HOLD.SpectrumController.getSpectrumDisplayState() returns a normalized display state with mode/span/fixed edges/edge slot.SpectrumController.configureSpectrumDisplay() applies a normalized display config and reads back the resulting state.SpectrumController.getSpectrumEdgeSlot() / SpectrumController.setSpectrumEdgeSlot() expose backend edge-slot control when available.SpectrumController.getSpectrumFixedEdges() / SpectrumController.setSpectrumFixedEdges() expose direct fixed-range control using SPECTRUM_EDGE_LOW/HIGH.SpectrumController.startManagedSpectrum(config?) runs the validated startup sequence for Icom/Hamlib async spectrum.
pumpIntervalMs controls a lightweight helper-side CAT pump. Default 200; set 0 or false to disable.SpectrumController.stopManagedSpectrum() runs the symmetric shutdown sequence and unregisters the callback.Fixed-range example:
await spectrum.configureSpectrumDisplay({
mode: 'fixed',
edgeSlot: 1,
edgeLowHz: 14074000,
edgeHighHz: 14077000,
});
const displayState = await spectrum.getSpectrumDisplayState();
console.log(displayState);
Emitted events:
HamLib emits spectrumLine when startSpectrumStream() is used without an explicit callback.SpectrumController emits spectrumLine for managed spectrum data.SpectrumController emits spectrumStateChanged when managed spectrum starts or stops.SpectrumController emits spectrumError when managed startup fails asynchronously.// 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 f
LGPL - see COPYING file for details.
FAQs
Node.js bindings for Hamlib rig control with official spectrum streaming support
The npm package hamlib receives a total of 928 weekly downloads. As such, hamlib popularity was classified as not popular.
We found that hamlib demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.