icom-wlan-node 0.5.1 → 0.6.0
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 +62 -22
- package/dist/index.d.ts +4 -1
- package/dist/index.js +15 -1
- package/dist/rig/IcomCivFrame.d.ts +13 -0
- package/dist/rig/IcomCivFrame.js +72 -0
- package/dist/rig/IcomCivSpec.d.ts +54 -0
- package/dist/rig/IcomCivSpec.js +57 -0
- package/dist/rig/IcomControl.d.ts +20 -7
- package/dist/rig/IcomControl.js +188 -139
- package/dist/rig/IcomProfiles.d.ts +61 -0
- package/dist/rig/IcomProfiles.js +255 -0
- package/dist/rig/IcomRigCommands.d.ts +13 -15
- package/dist/rig/IcomRigCommands.js +66 -86
- package/dist/scope/IcomScopeCommands.js +27 -54
- package/dist/types.d.ts +19 -8
- package/dist/utils/errors.d.ts +13 -0
- package/dist/utils/errors.js +17 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Icom WLAN (UDP) protocol implementation in Node.js + TypeScript, featuring:
|
|
4
4
|
|
|
5
|
+
CI-V profile support is Hamlib-aligned for modern ICOM radios: WLAN UDP packets carry standard CI-V frames, with model-specific profiles for IC-705, IC-905, IC-7300, IC-9700, IC-7610, and IC-7760.
|
|
6
|
+
|
|
5
7
|
- Control channel handshake (AreYouThere/AreYouReady), login (0x80/0x60), token confirm/renew (0x40)
|
|
6
8
|
- CI‑V over UDP encapsulation (open/close keep‑alive + CIV frame transport)
|
|
7
9
|
- Scope/spectrum data capture over CI‑V `0x27`, with automatic segment assembly into friendly frame events
|
|
@@ -35,7 +37,8 @@ import { IcomControl, AUDIO_RATE, DisconnectReason } from 'icom-wlan-node';
|
|
|
35
37
|
const rig = new IcomControl({
|
|
36
38
|
control: { ip: '192.168.1.50', port: 50001 },
|
|
37
39
|
userName: 'user',
|
|
38
|
-
password: 'pass'
|
|
40
|
+
password: 'pass',
|
|
41
|
+
model: 'auto' // or force a profile, e.g. 'IC-705'
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
rig.events.on('login', (res) => {
|
|
@@ -48,7 +51,7 @@ rig.events.on('status', (s) => {
|
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
rig.events.on('capabilities', (c) => {
|
|
51
|
-
console.log('CIV address:', c.civAddress, 'audio:', c.audioName);
|
|
54
|
+
console.log('CIV address:', c.civAddress, 'audio:', c.audioName, 'profile:', c.profileName);
|
|
52
55
|
});
|
|
53
56
|
|
|
54
57
|
rig.events.on('civ', (bytes) => {
|
|
@@ -87,6 +90,42 @@ rig.events.on('error', (err) => console.error('UDP error', err));
|
|
|
87
90
|
rig.sendCiv(Buffer.from([0xfe,0xfe,0xa4,0xe0,0x03,0xfd]));
|
|
88
91
|
```
|
|
89
92
|
|
|
93
|
+
### Main Rig Control Usage
|
|
94
|
+
|
|
95
|
+
Modern ICOM LAN/WLAN radios still transport standard serial CI‑V frames inside the UDP CIV payload. `icom-wlan-node` selects a model profile automatically from the radio name or CI‑V address, or you can force one with `model`.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const rig = new IcomControl({
|
|
99
|
+
control: { ip: '192.168.1.50', port: 50001 },
|
|
100
|
+
userName: 'icom',
|
|
101
|
+
password: 'icomicom',
|
|
102
|
+
model: 'auto' // 'IC-705', 'IC-905', 'IC-7300', 'IC-9700', 'IC-7610', 'IC-7760'
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await rig.connect();
|
|
106
|
+
|
|
107
|
+
// Frequency and mode are profile-aware:
|
|
108
|
+
// modern profiles use CI-V 0x25/0x26, legacy fallback uses 0x05/0x06.
|
|
109
|
+
await rig.setFrequency(14074000);
|
|
110
|
+
await rig.setMode('USB', { dataMode: true, filter: 1 }); // USB-D, filter 1
|
|
111
|
+
|
|
112
|
+
const freqHz = await rig.readOperatingFrequency();
|
|
113
|
+
const mode = await rig.readOperatingMode();
|
|
114
|
+
const tx = await rig.readPtt();
|
|
115
|
+
console.log({ freqHz, mode, state: tx ? 'TX' : 'RX' });
|
|
116
|
+
|
|
117
|
+
// Tuner uses Hamlib-aligned CI-V 0x1C/0x01.
|
|
118
|
+
const tuner = await rig.readTunerStatus();
|
|
119
|
+
await rig.setTunerEnabled(true);
|
|
120
|
+
|
|
121
|
+
// Meters use active-profile calibration tables.
|
|
122
|
+
const swr = await rig.readSWR();
|
|
123
|
+
const power = await rig.readPowerLevel();
|
|
124
|
+
console.log({ tuner, swr, watts: power?.watts, powerPercent: power?.percent });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Profile-specific behavior includes IC-905 6-byte frequency BCD above 5.85 GHz, model-specific scope fixed-edge ranges, and calibrated SWR/ALC/RF power/COMP/voltage/current meters. Private connector commands such as WLAN level or connector data mode are only enabled when the active profile declares the vendor extension; unsupported writes throw `UnsupportedCommandError`.
|
|
128
|
+
|
|
90
129
|
### PTT and Audio TX
|
|
91
130
|
|
|
92
131
|
```ts
|
|
@@ -136,7 +175,7 @@ await rig.disableScope();
|
|
|
136
175
|
|
|
137
176
|
## API Overview
|
|
138
177
|
|
|
139
|
-
- `new IcomControl(options)`
|
|
178
|
+
- `new IcomControl(options)` — `options.model` may be `'auto'` or a supported model profile such as `'IC-705'`, `'IC-905'`, `'IC-7300'`, `'IC-9700'`, `'IC-7610'`, or `'IC-7760'`
|
|
140
179
|
- `options.control`: `{ ip, port }` radio control UDP endpoint
|
|
141
180
|
- `options.userName`, `options.password`
|
|
142
181
|
- Events (`rig.events.on(...)`)
|
|
@@ -160,12 +199,12 @@ await rig.disableScope();
|
|
|
160
199
|
- **Scope / Spectrum**: `scope`, `enableScope()`, `disableScope()`, `waitForScopeFrame()`
|
|
161
200
|
- **Audio TX**: `setPtt(on: boolean)`, `sendAudioFloat32()`, `sendAudioPcm16()`
|
|
162
201
|
- **Rig Control**: `setFrequency()`, `setMode()`, `setConnectorDataMode()`, `setConnectorWLanLevel()`
|
|
163
|
-
- **Rig Query**: `readOperatingFrequency()`, `readOperatingMode()`, `readTransmitFrequency()`, `readTransceiverState()`, `readBandEdges()`
|
|
202
|
+
- **Rig Query**: `readOperatingFrequency()`, `readOperatingMode()`, `readTransmitFrequency()`, `readPtt()`, `readTransceiverState()`, `readBandEdges()`
|
|
164
203
|
- **Antenna Tuner**: `readTunerStatus()`, `setTunerEnabled()`, `startManualTune()`
|
|
165
204
|
- **Meters (RX)**: `readSquelchStatus()`, `readAudioSquelch()`, `readOvfStatus()`, `getLevelMeter()`
|
|
166
205
|
- **Meters (TX)**: `readSWR()`, `readALC()`, `readPowerLevel()`, `readCompLevel()`
|
|
167
206
|
- **Power Supply**: `readVoltage()`, `readCurrent()`
|
|
168
|
-
- **Audio Config**: `getConnectorWLanLevel()`
|
|
207
|
+
- **Audio Config**: `getUsbAfLevel()`, `setUsbAfLevel()`, `getConnectorWLanLevel()`
|
|
169
208
|
- **Connection Monitoring**: `getConnectionPhase()`, `getConnectionMetrics()`, `getConnectionState()`, `isAnySessionDisconnected()`, `configureMonitoring()`
|
|
170
209
|
|
|
171
210
|
### Connection Management & Auto-Reconnect
|
|
@@ -285,8 +324,8 @@ The library exposes common CI‑V operations as friendly methods. Addresses are
|
|
|
285
324
|
|
|
286
325
|
#### Rig Control
|
|
287
326
|
|
|
288
|
-
- `setFrequency(hz: number)` — Set operating frequency in Hz
|
|
289
|
-
- `setMode(mode: IcomMode | number, options?: { dataMode?: boolean })` — Set mode
|
|
327
|
+
- `setFrequency(hz: number)` — Set operating frequency in Hz; modern profiles use targetable CI-V `0x25`, and IC-905 uses 6-byte BCD above 5.85 GHz
|
|
328
|
+
- `setMode(mode: IcomMode | number, options?: { dataMode?: boolean; filter?: 1|2|3 })` — Set mode; modern profiles use CI-V `0x26` with VFO, data-mode and filter
|
|
290
329
|
- `setPtt(on: boolean)` — Key/unkey transmitter
|
|
291
330
|
|
|
292
331
|
**Supported Modes** (IcomMode string constants):
|
|
@@ -296,8 +335,9 @@ The library exposes common CI‑V operations as friendly methods. Addresses are
|
|
|
296
335
|
#### Rig Query
|
|
297
336
|
|
|
298
337
|
- `readOperatingFrequency(options?: QueryOptions) => Promise<number|null>`
|
|
299
|
-
- `readOperatingMode(options?: QueryOptions) => Promise<{ mode: number; filter?: number; modeName?: string; filterName?: string } | null>`
|
|
338
|
+
- `readOperatingMode(options?: QueryOptions) => Promise<{ mode: number; filter?: number; modeName?: string; filterName?: string; dataMode?: boolean } | null>`
|
|
300
339
|
- `readTransmitFrequency(options?: QueryOptions) => Promise<number|null>`
|
|
340
|
+
- `readPtt(options?: QueryOptions) => Promise<boolean|null>`
|
|
301
341
|
- `readTransceiverState(options?: QueryOptions) => Promise<'TX' | 'RX' | 'UNKNOWN' | null>`
|
|
302
342
|
- `readBandEdges(options?: QueryOptions) => Promise<Buffer|null>`
|
|
303
343
|
|
|
@@ -309,7 +349,7 @@ The library exposes common CI‑V operations as friendly methods. Addresses are
|
|
|
309
349
|
- `readScopeMode(options?: QueryOptions & { receiver?: 0 | 1 }) => Promise<IcomScopeModeInfo | null>` — Read current scope mode using CI‑V `0x27 0x14`
|
|
310
350
|
- `setScopeMode(mode: IcomScopeMode | 0 | 1 | 2 | 3, options?: { receiver?: 0 | 1 }) => Promise<void>` — Set current scope mode
|
|
311
351
|
- `readScopeSpan(options?: QueryOptions & { receiver?: 0 | 1 }) => Promise<{ receiver: 0 | 1; spanHz: number } | null>` — Read current scope span
|
|
312
|
-
- `setScopeSpan(spanHz: number, options?: { receiver?: 0 | 1 }) => Promise<void>` — Set scope span using CI‑V `0x27 0x15`
|
|
352
|
+
- `setScopeSpan(spanHz: number, options?: { receiver?: 0 | 1 }) => Promise<void>` — Set public scope span using CI‑V `0x27 0x15`; the wire value is `spanHz / 2` per Hamlib
|
|
313
353
|
- `readScopeEdge(options?: QueryOptions & { receiver?: 0 | 1 }) => Promise<IcomScopeEdgeInfo | null>` — Read active fixed-edge slot using CI‑V `0x27 0x16`
|
|
314
354
|
- `setScopeEdge(edgeSlot: number, options?: { receiver?: 0 | 1 }) => Promise<void>` — Select active fixed-edge slot
|
|
315
355
|
- `readScopeFixedEdge(rangeId: number, edgeSlot: number, options?: QueryOptions) => Promise<IcomScopeFixedEdgeInfo | null>` — Read fixed-edge frequencies using CI‑V `0x27 0x1E`
|
|
@@ -340,17 +380,17 @@ interface IcomScopeFrame {
|
|
|
340
380
|
|
|
341
381
|
Current implementation notes:
|
|
342
382
|
|
|
343
|
-
-
|
|
383
|
+
- Implements basic on/off controls, `0x27 0x15` span read/write, fixed-edge selection/ranges, and `0x27 00 00` scope data capture
|
|
344
384
|
- The parsing layer is decoupled from the UDP session layer and only depends on complete CI‑V frames
|
|
345
|
-
- Frequency
|
|
385
|
+
- Frequency and fixed-edge ranges are profile-aware; unsupported model-specific variants should be added in `src/rig/IcomProfiles.ts`
|
|
346
386
|
- LAN aggregate waterfall payload splitting is not implemented yet; standard segment input is supported
|
|
347
387
|
- The `scope` logic is designed to be reusable for future serial CI‑V or Hamlib CI‑V integration
|
|
348
388
|
|
|
349
389
|
#### Antenna Tuner (ATU)
|
|
350
390
|
|
|
351
|
-
- `readTunerStatus(options?: QueryOptions) => Promise<{ raw: number; state: 'OFF'|'ON'|'TUNING' } | null>` — Read tuner status (CI
|
|
352
|
-
- `setTunerEnabled(enabled: boolean) => Promise<void>` — Enable/disable internal tuner (CI‑V
|
|
353
|
-
- `startManualTune() => Promise<void>` — Trigger one manual tune cycle (CI‑V
|
|
391
|
+
- `readTunerStatus(options?: QueryOptions) => Promise<{ raw: number; state: 'OFF'|'ON'|'TUNING' } | null>` — Read tuner status (Hamlib-aligned CI-V `0x1C 0x01`)
|
|
392
|
+
- `setTunerEnabled(enabled: boolean) => Promise<void>` — Enable/disable internal tuner (Hamlib-aligned CI‑V `0x1C 0x01 0x00/0x01`)
|
|
393
|
+
- `startManualTune() => Promise<void>` — Trigger one manual tune cycle (Hamlib-aligned CI‑V `0x1C 0x01 0x02`)
|
|
354
394
|
|
|
355
395
|
#### Meters & Levels
|
|
356
396
|
|
|
@@ -363,20 +403,20 @@ Current implementation notes:
|
|
|
363
403
|
**Transmission Meters** (require PTT on):
|
|
364
404
|
- `readSWR(options?: QueryOptions) => Promise<{ raw: number; swr: number; alert: boolean } | null>` — SWR meter (CI-V 0x15/0x12)
|
|
365
405
|
- `readALC(options?: QueryOptions) => Promise<{ raw: number; percent: number; alert: boolean } | null>` — ALC meter (CI-V 0x15/0x13)
|
|
366
|
-
- `readPowerLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — Output power level (CI-V 0x15/0x11)
|
|
367
|
-
- `readCompLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` — Voice compression level (CI-V 0x15/0x14)
|
|
406
|
+
- `readPowerLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number; watts?: number } | null>` — Output power level (CI-V 0x15/0x11)
|
|
407
|
+
- `readCompLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number; db?: number } | null>` — Voice compression level (CI-V 0x15/0x14)
|
|
368
408
|
|
|
369
409
|
**Power Supply Monitoring**:
|
|
370
410
|
- `readVoltage(options?: QueryOptions) => Promise<{ raw: number; volts: number } | null>` — Supply voltage (CI-V 0x15/0x15)
|
|
371
411
|
- `readCurrent(options?: QueryOptions) => Promise<{ raw: number; amps: number } | null>` — Supply current draw (CI-V 0x15/0x16)
|
|
372
412
|
|
|
373
413
|
**Audio Configuration**:
|
|
374
|
-
- `
|
|
375
|
-
- `setConnectorWLanLevel(level: number)` —
|
|
414
|
+
- `getUsbAfLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` / `setUsbAfLevel(level: number)` — Hamlib-aligned USB AF level when the active profile declares it
|
|
415
|
+
- `getConnectorWLanLevel(options?: QueryOptions) => Promise<{ raw: number; percent: number } | null>` / `setConnectorWLanLevel(level: number)` — Private `icom-wlan-node` WLAN level extension; returns `null` or throws `UnsupportedCommandError` when the active profile does not declare it
|
|
376
416
|
|
|
377
417
|
#### Connector Settings
|
|
378
418
|
|
|
379
|
-
- `setConnectorDataMode(mode: ConnectorDataMode | number)` —
|
|
419
|
+
- `setConnectorDataMode(mode: ConnectorDataMode | number)` — Private connector routing extension; supported only on profiles that declare the vendor command
|
|
380
420
|
|
|
381
421
|
**Supported Connector Modes** (ConnectorDataMode string constants):
|
|
382
422
|
- `'MIC'` (0x00), `'ACC'` (0x01), `'USB'` (0x02), `'WLAN'` (0x03)
|
|
@@ -457,17 +497,17 @@ if (alc) {
|
|
|
457
497
|
|
|
458
498
|
const power = await rig.readPowerLevel({ timeout: 2000 });
|
|
459
499
|
if (power) {
|
|
460
|
-
console.log(`Power: ${power.percent.toFixed(1)}
|
|
500
|
+
console.log(`Power: ${power.percent.toFixed(1)}%${power.watts != null ? ` (${power.watts.toFixed(1)} W)` : ''}`);
|
|
461
501
|
}
|
|
462
502
|
|
|
463
503
|
const comp = await rig.readCompLevel({ timeout: 2000 });
|
|
464
504
|
if (comp) {
|
|
465
|
-
console.log(`COMP: ${comp.percent.toFixed(1)}
|
|
505
|
+
console.log(`COMP: ${comp.percent.toFixed(1)}%${comp.db != null ? ` (${comp.db.toFixed(1)} dB)` : ''}`);
|
|
466
506
|
}
|
|
467
507
|
|
|
468
508
|
await rig.setPtt(false);
|
|
469
509
|
|
|
470
|
-
// Configure WLAN connector
|
|
510
|
+
// Configure WLAN connector (private extension; profile-gated)
|
|
471
511
|
const wlanLevel = await rig.getConnectorWLanLevel({ timeout: 2000 });
|
|
472
512
|
if (wlanLevel) {
|
|
473
513
|
console.log(`WLAN Level: ${wlanLevel.percent.toFixed(1)}%`);
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export { IcomScopeCommands } from './scope/IcomScopeCommands';
|
|
|
5
5
|
export { MODE_MAP, CONNECTOR_MODE_MAP, DEFAULT_CONTROLLER_ADDR, METER_THRESHOLDS, METER_CALIBRATION, getModeCode, getConnectorModeCode, getModeString, getConnectorModeString, getFilterString, rawToPowerPercent, rawToVoltage, rawToCurrent } from './rig/IcomConstants';
|
|
6
6
|
export { parseTwoByteBcd, intToTwoByteBcd } from './utils/bcd';
|
|
7
7
|
export { IcomRigCommands } from './rig/IcomRigCommands';
|
|
8
|
+
export { CIV } from './rig/IcomCivSpec';
|
|
9
|
+
export { buildCivFrame, encodeFrequencyBcdLE, decodeFrequencyBcdLE, encodeBcdBE, decodeBcdBE } from './rig/IcomCivFrame';
|
|
10
|
+
export { ICOM_PROFILES, resolveIcomProfile, getProfileByModel, interpolateCalibration } from './rig/IcomProfiles';
|
|
8
11
|
export { AUDIO_RATE } from './rig/IcomAudio';
|
|
9
12
|
export { setupGlobalErrorHandlers, setupBasicErrorProtection, GlobalErrorHandlerOptions } from './utils/errorHandling';
|
|
10
|
-
export { ConnectionAbortedError, getDisconnectMessage } from './utils/errors';
|
|
13
|
+
export { ConnectionAbortedError, UnsupportedCommandError, getDisconnectMessage } from './utils/errors';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.getDisconnectMessage = exports.ConnectionAbortedError = exports.setupBasicErrorProtection = exports.setupGlobalErrorHandlers = exports.AUDIO_RATE = exports.IcomRigCommands = exports.intToTwoByteBcd = exports.parseTwoByteBcd = exports.rawToCurrent = exports.rawToVoltage = exports.rawToPowerPercent = exports.getFilterString = exports.getConnectorModeString = exports.getModeString = exports.getConnectorModeCode = exports.getModeCode = exports.METER_CALIBRATION = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = exports.IcomScopeCommands = exports.IcomScopeService = exports.IcomControl = void 0;
|
|
17
|
+
exports.getDisconnectMessage = exports.UnsupportedCommandError = exports.ConnectionAbortedError = exports.setupBasicErrorProtection = exports.setupGlobalErrorHandlers = exports.AUDIO_RATE = exports.interpolateCalibration = exports.getProfileByModel = exports.resolveIcomProfile = exports.ICOM_PROFILES = exports.decodeBcdBE = exports.encodeBcdBE = exports.decodeFrequencyBcdLE = exports.encodeFrequencyBcdLE = exports.buildCivFrame = exports.CIV = exports.IcomRigCommands = exports.intToTwoByteBcd = exports.parseTwoByteBcd = exports.rawToCurrent = exports.rawToVoltage = exports.rawToPowerPercent = exports.getFilterString = exports.getConnectorModeString = exports.getModeString = exports.getConnectorModeCode = exports.getModeCode = exports.METER_CALIBRATION = exports.METER_THRESHOLDS = exports.DEFAULT_CONTROLLER_ADDR = exports.CONNECTOR_MODE_MAP = exports.MODE_MAP = exports.IcomScopeCommands = exports.IcomScopeService = exports.IcomControl = void 0;
|
|
18
18
|
// Export types (includes ConnectionPhase, ConnectionMetrics, etc.)
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
// Export main class
|
|
@@ -46,6 +46,19 @@ Object.defineProperty(exports, "intToTwoByteBcd", { enumerable: true, get: funct
|
|
|
46
46
|
// Export low-level utilities (for advanced users)
|
|
47
47
|
var IcomRigCommands_1 = require("./rig/IcomRigCommands");
|
|
48
48
|
Object.defineProperty(exports, "IcomRigCommands", { enumerable: true, get: function () { return IcomRigCommands_1.IcomRigCommands; } });
|
|
49
|
+
var IcomCivSpec_1 = require("./rig/IcomCivSpec");
|
|
50
|
+
Object.defineProperty(exports, "CIV", { enumerable: true, get: function () { return IcomCivSpec_1.CIV; } });
|
|
51
|
+
var IcomCivFrame_1 = require("./rig/IcomCivFrame");
|
|
52
|
+
Object.defineProperty(exports, "buildCivFrame", { enumerable: true, get: function () { return IcomCivFrame_1.buildCivFrame; } });
|
|
53
|
+
Object.defineProperty(exports, "encodeFrequencyBcdLE", { enumerable: true, get: function () { return IcomCivFrame_1.encodeFrequencyBcdLE; } });
|
|
54
|
+
Object.defineProperty(exports, "decodeFrequencyBcdLE", { enumerable: true, get: function () { return IcomCivFrame_1.decodeFrequencyBcdLE; } });
|
|
55
|
+
Object.defineProperty(exports, "encodeBcdBE", { enumerable: true, get: function () { return IcomCivFrame_1.encodeBcdBE; } });
|
|
56
|
+
Object.defineProperty(exports, "decodeBcdBE", { enumerable: true, get: function () { return IcomCivFrame_1.decodeBcdBE; } });
|
|
57
|
+
var IcomProfiles_1 = require("./rig/IcomProfiles");
|
|
58
|
+
Object.defineProperty(exports, "ICOM_PROFILES", { enumerable: true, get: function () { return IcomProfiles_1.ICOM_PROFILES; } });
|
|
59
|
+
Object.defineProperty(exports, "resolveIcomProfile", { enumerable: true, get: function () { return IcomProfiles_1.resolveIcomProfile; } });
|
|
60
|
+
Object.defineProperty(exports, "getProfileByModel", { enumerable: true, get: function () { return IcomProfiles_1.getProfileByModel; } });
|
|
61
|
+
Object.defineProperty(exports, "interpolateCalibration", { enumerable: true, get: function () { return IcomProfiles_1.interpolateCalibration; } });
|
|
49
62
|
var IcomAudio_1 = require("./rig/IcomAudio");
|
|
50
63
|
Object.defineProperty(exports, "AUDIO_RATE", { enumerable: true, get: function () { return IcomAudio_1.AUDIO_RATE; } });
|
|
51
64
|
// Export error handling utilities (optional, for robustness)
|
|
@@ -55,4 +68,5 @@ Object.defineProperty(exports, "setupBasicErrorProtection", { enumerable: true,
|
|
|
55
68
|
// Export disconnect error utilities
|
|
56
69
|
var errors_1 = require("./utils/errors");
|
|
57
70
|
Object.defineProperty(exports, "ConnectionAbortedError", { enumerable: true, get: function () { return errors_1.ConnectionAbortedError; } });
|
|
71
|
+
Object.defineProperty(exports, "UnsupportedCommandError", { enumerable: true, get: function () { return errors_1.UnsupportedCommandError; } });
|
|
58
72
|
Object.defineProperty(exports, "getDisconnectMessage", { enumerable: true, get: function () { return errors_1.getDisconnectMessage; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CivFrameBuildOptions {
|
|
2
|
+
rigAddr: number;
|
|
3
|
+
ctrlAddr: number;
|
|
4
|
+
cmd: number;
|
|
5
|
+
subcmd?: number | number[];
|
|
6
|
+
payload?: Buffer | number[];
|
|
7
|
+
}
|
|
8
|
+
export declare function buildCivFrame(options: CivFrameBuildOptions): Buffer;
|
|
9
|
+
export declare function encodeFrequencyBcdLE(freqHz: number, byteLength?: number): Buffer;
|
|
10
|
+
export declare function decodeFrequencyBcdLE(bytes: Buffer | Uint8Array): number;
|
|
11
|
+
export declare function encodeBcdBE(value: number, byteLength: number): Buffer;
|
|
12
|
+
export declare function decodeBcdBE(bytes: Buffer | Uint8Array): number;
|
|
13
|
+
export declare function getCivPayload(frame: Buffer): Buffer | null;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildCivFrame = buildCivFrame;
|
|
4
|
+
exports.encodeFrequencyBcdLE = encodeFrequencyBcdLE;
|
|
5
|
+
exports.decodeFrequencyBcdLE = decodeFrequencyBcdLE;
|
|
6
|
+
exports.encodeBcdBE = encodeBcdBE;
|
|
7
|
+
exports.decodeBcdBE = decodeBcdBE;
|
|
8
|
+
exports.getCivPayload = getCivPayload;
|
|
9
|
+
const IcomCivSpec_1 = require("./IcomCivSpec");
|
|
10
|
+
function buildCivFrame(options) {
|
|
11
|
+
const subcmd = options.subcmd === undefined
|
|
12
|
+
? []
|
|
13
|
+
: Array.isArray(options.subcmd)
|
|
14
|
+
? options.subcmd
|
|
15
|
+
: [options.subcmd];
|
|
16
|
+
const payload = options.payload ? Array.from(options.payload) : [];
|
|
17
|
+
return Buffer.from([
|
|
18
|
+
IcomCivSpec_1.CIV.PR,
|
|
19
|
+
IcomCivSpec_1.CIV.PR,
|
|
20
|
+
options.rigAddr & 0xff,
|
|
21
|
+
options.ctrlAddr & 0xff,
|
|
22
|
+
options.cmd & 0xff,
|
|
23
|
+
...subcmd.map((v) => v & 0xff),
|
|
24
|
+
...payload.map((v) => v & 0xff),
|
|
25
|
+
IcomCivSpec_1.CIV.FI,
|
|
26
|
+
]);
|
|
27
|
+
}
|
|
28
|
+
function encodeFrequencyBcdLE(freqHz, byteLength = 5) {
|
|
29
|
+
const out = Buffer.alloc(byteLength);
|
|
30
|
+
let remaining = Math.max(0, Math.round(freqHz));
|
|
31
|
+
for (let i = 0; i < byteLength; i++) {
|
|
32
|
+
const twoDigits = remaining % 100;
|
|
33
|
+
out[i] = ((((twoDigits / 10) | 0) & 0x0f) << 4) | (twoDigits % 10);
|
|
34
|
+
remaining = Math.floor(remaining / 100);
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
function decodeFrequencyBcdLE(bytes) {
|
|
39
|
+
let hz = 0;
|
|
40
|
+
let multiplier = 1;
|
|
41
|
+
for (const byte of bytes) {
|
|
42
|
+
hz += (byte & 0x0f) * multiplier;
|
|
43
|
+
multiplier *= 10;
|
|
44
|
+
hz += ((byte >> 4) & 0x0f) * multiplier;
|
|
45
|
+
multiplier *= 10;
|
|
46
|
+
}
|
|
47
|
+
return hz;
|
|
48
|
+
}
|
|
49
|
+
function encodeBcdBE(value, byteLength) {
|
|
50
|
+
const out = Buffer.alloc(byteLength);
|
|
51
|
+
let remaining = Math.max(0, Math.floor(value));
|
|
52
|
+
for (let i = byteLength - 1; i >= 0; i--) {
|
|
53
|
+
const twoDigits = remaining % 100;
|
|
54
|
+
out[i] = ((((twoDigits / 10) | 0) & 0x0f) << 4) | (twoDigits % 10);
|
|
55
|
+
remaining = Math.floor(remaining / 100);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function decodeBcdBE(bytes) {
|
|
60
|
+
let value = 0;
|
|
61
|
+
for (const byte of bytes) {
|
|
62
|
+
value = value * 100 + (((byte >> 4) & 0x0f) * 10) + (byte & 0x0f);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
function getCivPayload(frame) {
|
|
67
|
+
if (frame.length < 6)
|
|
68
|
+
return null;
|
|
69
|
+
if (frame[0] !== IcomCivSpec_1.CIV.PR || frame[1] !== IcomCivSpec_1.CIV.PR || frame[frame.length - 1] !== IcomCivSpec_1.CIV.FI)
|
|
70
|
+
return null;
|
|
71
|
+
return frame.subarray(4, frame.length - 1);
|
|
72
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Hamlib-aligned CI-V command and subcommand constants. */
|
|
2
|
+
export declare const CIV: {
|
|
3
|
+
readonly PR: 254;
|
|
4
|
+
readonly FI: 253;
|
|
5
|
+
readonly ACK: 251;
|
|
6
|
+
readonly NAK: 250;
|
|
7
|
+
readonly CTRLID: 224;
|
|
8
|
+
readonly C_RD_BAND: 2;
|
|
9
|
+
readonly C_RD_FREQ: 3;
|
|
10
|
+
readonly C_RD_MODE: 4;
|
|
11
|
+
readonly C_SET_FREQ: 5;
|
|
12
|
+
readonly C_SET_MODE: 6;
|
|
13
|
+
readonly C_CTL_LVL: 20;
|
|
14
|
+
readonly C_RD_SQSM: 21;
|
|
15
|
+
readonly C_CTL_FUNC: 22;
|
|
16
|
+
readonly C_CTL_MEM: 26;
|
|
17
|
+
readonly C_CTL_PTT: 28;
|
|
18
|
+
readonly C_SEND_SEL_FREQ: 37;
|
|
19
|
+
readonly C_SEND_SEL_MODE: 38;
|
|
20
|
+
readonly C_CTL_SCP: 39;
|
|
21
|
+
readonly S_PTT: 0;
|
|
22
|
+
readonly S_ANT_TUN: 1;
|
|
23
|
+
readonly S_RD_TX_FREQ: 3;
|
|
24
|
+
readonly S_MEM_PARM: 5;
|
|
25
|
+
readonly S_MEM_DATA_MODE: 6;
|
|
26
|
+
readonly S_LVL_AF: 1;
|
|
27
|
+
readonly S_LVL_RF: 2;
|
|
28
|
+
readonly S_LVL_SQL: 3;
|
|
29
|
+
readonly S_LVL_NR: 6;
|
|
30
|
+
readonly S_LVL_RFPOWER: 10;
|
|
31
|
+
readonly S_LVL_MICGAIN: 11;
|
|
32
|
+
readonly S_LVL_COMP: 14;
|
|
33
|
+
readonly S_LVL_BKINDL: 15;
|
|
34
|
+
readonly S_LVL_NB: 18;
|
|
35
|
+
readonly S_LVL_DIGI: 19;
|
|
36
|
+
readonly S_SQL: 1;
|
|
37
|
+
readonly S_SML: 2;
|
|
38
|
+
readonly S_CSQL: 5;
|
|
39
|
+
readonly S_OVF: 7;
|
|
40
|
+
readonly S_RFML: 17;
|
|
41
|
+
readonly S_SWR: 18;
|
|
42
|
+
readonly S_ALC: 19;
|
|
43
|
+
readonly S_CMP: 20;
|
|
44
|
+
readonly S_VD: 21;
|
|
45
|
+
readonly S_ID: 22;
|
|
46
|
+
readonly S_SCP_DAT: 0;
|
|
47
|
+
readonly S_SCP_STS: 16;
|
|
48
|
+
readonly S_SCP_DOP: 17;
|
|
49
|
+
readonly S_SCP_MOD: 20;
|
|
50
|
+
readonly S_SCP_SPN: 21;
|
|
51
|
+
readonly S_SCP_EDG: 22;
|
|
52
|
+
readonly S_SCP_FEF: 30;
|
|
53
|
+
};
|
|
54
|
+
export declare const ICOM_MODE_FILTER_DEFAULT: 1;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ICOM_MODE_FILTER_DEFAULT = exports.CIV = void 0;
|
|
4
|
+
/** Hamlib-aligned CI-V command and subcommand constants. */
|
|
5
|
+
exports.CIV = {
|
|
6
|
+
PR: 0xfe,
|
|
7
|
+
FI: 0xfd,
|
|
8
|
+
ACK: 0xfb,
|
|
9
|
+
NAK: 0xfa,
|
|
10
|
+
CTRLID: 0xe0,
|
|
11
|
+
C_RD_BAND: 0x02,
|
|
12
|
+
C_RD_FREQ: 0x03,
|
|
13
|
+
C_RD_MODE: 0x04,
|
|
14
|
+
C_SET_FREQ: 0x05,
|
|
15
|
+
C_SET_MODE: 0x06,
|
|
16
|
+
C_CTL_LVL: 0x14,
|
|
17
|
+
C_RD_SQSM: 0x15,
|
|
18
|
+
C_CTL_FUNC: 0x16,
|
|
19
|
+
C_CTL_MEM: 0x1a,
|
|
20
|
+
C_CTL_PTT: 0x1c,
|
|
21
|
+
C_SEND_SEL_FREQ: 0x25,
|
|
22
|
+
C_SEND_SEL_MODE: 0x26,
|
|
23
|
+
C_CTL_SCP: 0x27,
|
|
24
|
+
S_PTT: 0x00,
|
|
25
|
+
S_ANT_TUN: 0x01,
|
|
26
|
+
S_RD_TX_FREQ: 0x03,
|
|
27
|
+
S_MEM_PARM: 0x05,
|
|
28
|
+
S_MEM_DATA_MODE: 0x06,
|
|
29
|
+
S_LVL_AF: 0x01,
|
|
30
|
+
S_LVL_RF: 0x02,
|
|
31
|
+
S_LVL_SQL: 0x03,
|
|
32
|
+
S_LVL_NR: 0x06,
|
|
33
|
+
S_LVL_RFPOWER: 0x0a,
|
|
34
|
+
S_LVL_MICGAIN: 0x0b,
|
|
35
|
+
S_LVL_COMP: 0x0e,
|
|
36
|
+
S_LVL_BKINDL: 0x0f,
|
|
37
|
+
S_LVL_NB: 0x12,
|
|
38
|
+
S_LVL_DIGI: 0x13,
|
|
39
|
+
S_SQL: 0x01,
|
|
40
|
+
S_SML: 0x02,
|
|
41
|
+
S_CSQL: 0x05,
|
|
42
|
+
S_OVF: 0x07,
|
|
43
|
+
S_RFML: 0x11,
|
|
44
|
+
S_SWR: 0x12,
|
|
45
|
+
S_ALC: 0x13,
|
|
46
|
+
S_CMP: 0x14,
|
|
47
|
+
S_VD: 0x15,
|
|
48
|
+
S_ID: 0x16,
|
|
49
|
+
S_SCP_DAT: 0x00,
|
|
50
|
+
S_SCP_STS: 0x10,
|
|
51
|
+
S_SCP_DOP: 0x11,
|
|
52
|
+
S_SCP_MOD: 0x14,
|
|
53
|
+
S_SCP_SPN: 0x15,
|
|
54
|
+
S_SCP_EDG: 0x16,
|
|
55
|
+
S_SCP_FEF: 0x1e,
|
|
56
|
+
};
|
|
57
|
+
exports.ICOM_MODE_FILTER_DEFAULT = 1;
|
|
@@ -2,6 +2,7 @@ import { IcomRigOptions, RigEventEmitter, IcomMode, ConnectorDataMode, SetModeOp
|
|
|
2
2
|
import { IcomCiv } from './IcomCiv';
|
|
3
3
|
import { IcomAudio } from './IcomAudio';
|
|
4
4
|
import { IcomScopeService } from '../scope/IcomScopeService';
|
|
5
|
+
import { IcomProfile } from './IcomProfiles';
|
|
5
6
|
export declare class IcomControl {
|
|
6
7
|
private ev;
|
|
7
8
|
private sess;
|
|
@@ -16,6 +17,8 @@ export declare class IcomControl {
|
|
|
16
17
|
private tokenTimer?;
|
|
17
18
|
private civAssembleBuf;
|
|
18
19
|
private meterTimer?;
|
|
20
|
+
private activeProfile;
|
|
21
|
+
private lastFilter;
|
|
19
22
|
private connectionSession;
|
|
20
23
|
private nextSessionId;
|
|
21
24
|
private abortHandlers;
|
|
@@ -23,6 +26,9 @@ export declare class IcomControl {
|
|
|
23
26
|
private monitorConfig;
|
|
24
27
|
constructor(options: IcomRigOptions);
|
|
25
28
|
get events(): RigEventEmitter;
|
|
29
|
+
get profile(): IcomProfile;
|
|
30
|
+
private resolveActiveProfile;
|
|
31
|
+
private getProfileModelId;
|
|
26
32
|
/**
|
|
27
33
|
* Transition to a new connection phase with logging
|
|
28
34
|
* @private
|
|
@@ -187,15 +193,14 @@ export declare class IcomControl {
|
|
|
187
193
|
filter?: number;
|
|
188
194
|
modeName?: string;
|
|
189
195
|
filterName?: string;
|
|
196
|
+
dataMode?: boolean;
|
|
190
197
|
} | null>;
|
|
191
198
|
/**
|
|
192
199
|
* Read current transmit frequency (when TX)
|
|
193
200
|
*/
|
|
194
201
|
readTransmitFrequency(options?: QueryOptions): Promise<number | null>;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
* Note: Java comments mark this as not recommended; use with caution.
|
|
198
|
-
*/
|
|
202
|
+
readPtt(options?: QueryOptions): Promise<boolean | null>;
|
|
203
|
+
/** Read transceiver state (TX/RX) using standard Hamlib-aligned PTT status. */
|
|
199
204
|
readTransceiverState(options?: QueryOptions): Promise<'TX' | 'RX' | 'UNKNOWN' | null>;
|
|
200
205
|
/**
|
|
201
206
|
* Read band edge data (0x02). Format may vary by rig; returns raw data bytes after command.
|
|
@@ -257,6 +262,8 @@ export declare class IcomControl {
|
|
|
257
262
|
* @param level - Audio level (0-255)
|
|
258
263
|
*/
|
|
259
264
|
setConnectorWLanLevel(level: number): Promise<void>;
|
|
265
|
+
getUsbAfLevel(options?: QueryOptions): Promise<WlanLevelReading | null>;
|
|
266
|
+
setUsbAfLevel(level: number): Promise<void>;
|
|
260
267
|
/**
|
|
261
268
|
* Set connector data routing mode
|
|
262
269
|
* @param mode - Data routing mode (MIC, ACC, USB, WLAN)
|
|
@@ -271,17 +278,17 @@ export declare class IcomControl {
|
|
|
271
278
|
* ==============================
|
|
272
279
|
*/
|
|
273
280
|
/**
|
|
274
|
-
* Read antenna tuner status (CI-V
|
|
281
|
+
* Read antenna tuner status (CI-V 0x1C/0x01)
|
|
275
282
|
* 00=OFF, 01=ON, 02=TUNING
|
|
276
283
|
*/
|
|
277
284
|
readTunerStatus(options?: QueryOptions): Promise<TunerStatusReading | null>;
|
|
278
285
|
/**
|
|
279
|
-
* Enable or disable internal antenna tuner (CI-V
|
|
286
|
+
* Enable or disable internal antenna tuner (CI-V 0x1C/0x01)
|
|
280
287
|
* @param enabled true to enable, false to disable
|
|
281
288
|
*/
|
|
282
289
|
setTunerEnabled(enabled: boolean): Promise<void>;
|
|
283
290
|
/**
|
|
284
|
-
* Start a manual tuning cycle (same as [TUNE] key) (CI-V
|
|
291
|
+
* Start a manual tuning cycle (same as [TUNE] key) (CI-V 0x1C/0x01/0x02)
|
|
285
292
|
*/
|
|
286
293
|
startManualTune(): Promise<void>;
|
|
287
294
|
/** Get AF (audio output) gain. Returns 0.0–1.0, or null on timeout. */
|
|
@@ -300,6 +307,10 @@ export declare class IcomControl {
|
|
|
300
307
|
getMicGain(options?: QueryOptions): Promise<LevelReading | null>;
|
|
301
308
|
/** Set microphone gain. Value 0.0–1.0. */
|
|
302
309
|
setMicGain(value: number): void;
|
|
310
|
+
/** Get break-in delay. Returns 0.0–1.0, or null on timeout. */
|
|
311
|
+
getBreakInDelay(options?: QueryOptions): Promise<LevelReading | null>;
|
|
312
|
+
/** Set break-in delay. Value 0.0–1.0. */
|
|
313
|
+
setBreakInDelay(value: number): void;
|
|
303
314
|
/** Get noise blanker level. 0.0 = off, >0.0 = on with strength. */
|
|
304
315
|
getNBLevel(options?: QueryOptions): Promise<LevelReading | null>;
|
|
305
316
|
/** Set noise blanker level. Value 0.0 (off) – 1.0. */
|
|
@@ -393,9 +404,11 @@ export declare class IcomControl {
|
|
|
393
404
|
* @returns Parsed BCD integer value, or null if invalid
|
|
394
405
|
*/
|
|
395
406
|
private static extractMeterData;
|
|
407
|
+
private static extractTrailingBcd;
|
|
396
408
|
private static matchCommand;
|
|
397
409
|
private static matchCommandFrame;
|
|
398
410
|
private waitForCiv;
|
|
411
|
+
static parseFrequencyReply(frame: Buffer, payloadOffsetAfterCommand: number, byteLength?: number): number | null;
|
|
399
412
|
static parseIcomFreqFromReply(frame: Buffer): number | null;
|
|
400
413
|
sendAudioFloat32(samples: Float32Array, addLeadingBuffer?: boolean): void;
|
|
401
414
|
sendAudioPcm16(samples: Int16Array): void;
|