icom-wlan-node 0.5.1 → 0.6.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.
@@ -1,83 +1,56 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IcomScopeCommands = void 0;
4
+ const IcomCivFrame_1 = require("../rig/IcomCivFrame");
5
+ const IcomCivSpec_1 = require("../rig/IcomCivSpec");
4
6
  exports.IcomScopeCommands = {
5
7
  setScopeDataOutput(ctrAddr, rigAddr, enabled) {
6
- return Buffer.from([
7
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x11, enabled ? 0x01 : 0x00, 0xfd
8
- ]);
8
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_DOP, payload: [enabled ? 0x01 : 0x00] });
9
9
  },
10
10
  setScopeDisplay(ctrAddr, rigAddr, enabled) {
11
- return Buffer.from([
12
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x10, enabled ? 0x01 : 0x00, 0xfd
13
- ]);
11
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_STS, payload: [enabled ? 0x01 : 0x00] });
14
12
  },
15
13
  readScopeSpan(ctrAddr, rigAddr, receiver = 0) {
16
- return Buffer.from([
17
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x15, receiver & 0xff, 0xfd
18
- ]);
14
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_SPN, payload: [receiver & 0xff] });
19
15
  },
20
16
  setScopeSpan(ctrAddr, rigAddr, spanHz, receiver = 0) {
21
- const bytes = exports.IcomScopeCommands.encodeScopeSpanHz(spanHz);
22
- return Buffer.from([
23
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x15, receiver & 0xff, ...bytes, 0xfd
24
- ]);
17
+ // Hamlib maps public span to ICOM's +/- span value.
18
+ const bytes = exports.IcomScopeCommands.encodeScopeSpanHz(Math.round(spanHz / 2));
19
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_SPN, payload: [receiver & 0xff, ...bytes] });
25
20
  },
26
21
  readScopeMode(ctrAddr, rigAddr, receiver = 0) {
27
- return Buffer.from([
28
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x14, receiver & 0xff, 0xfd
29
- ]);
22
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_MOD, payload: [receiver & 0xff] });
30
23
  },
31
24
  setScopeMode(ctrAddr, rigAddr, mode, receiver = 0) {
32
- return Buffer.from([
33
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x14, receiver & 0xff, mode & 0xff, 0xfd
34
- ]);
25
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_MOD, payload: [receiver & 0xff, mode & 0xff] });
35
26
  },
36
27
  readScopeEdge(ctrAddr, rigAddr, receiver = 0) {
37
- return Buffer.from([
38
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x16, receiver & 0xff, 0xfd
39
- ]);
28
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_EDG, payload: [receiver & 0xff] });
40
29
  },
41
30
  setScopeEdge(ctrAddr, rigAddr, edgeSlot, receiver = 0) {
42
- return Buffer.from([
43
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x16, receiver & 0xff, edgeSlot & 0xff, 0xfd
44
- ]);
31
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_EDG, payload: [receiver & 0xff, edgeSlot & 0xff] });
45
32
  },
46
33
  readScopeFixedEdge(ctrAddr, rigAddr, rangeId, edgeSlot) {
47
- return Buffer.from([
48
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x1e, rangeId & 0xff, edgeSlot & 0xff, 0xfd
49
- ]);
34
+ return (0, IcomCivFrame_1.buildCivFrame)({ rigAddr, ctrlAddr: ctrAddr, cmd: IcomCivSpec_1.CIV.C_CTL_SCP, subcmd: IcomCivSpec_1.CIV.S_SCP_FEF, payload: [rangeId & 0xff, edgeSlot & 0xff] });
50
35
  },
51
36
  setScopeFixedEdge(ctrAddr, rigAddr, rangeId, edgeSlot, lowHz, highHz) {
52
- return Buffer.from([
53
- 0xfe, 0xfe, rigAddr & 0xff, ctrAddr & 0xff, 0x27, 0x1e,
54
- rangeId & 0xff,
55
- edgeSlot & 0xff,
56
- ...exports.IcomScopeCommands.encodeScopeFreqHz(lowHz),
57
- ...exports.IcomScopeCommands.encodeScopeFreqHz(highHz),
58
- 0xfd
59
- ]);
37
+ return (0, IcomCivFrame_1.buildCivFrame)({
38
+ rigAddr,
39
+ ctrlAddr: ctrAddr,
40
+ cmd: IcomCivSpec_1.CIV.C_CTL_SCP,
41
+ subcmd: IcomCivSpec_1.CIV.S_SCP_FEF,
42
+ payload: [
43
+ rangeId & 0xff,
44
+ edgeSlot & 0xff,
45
+ ...exports.IcomScopeCommands.encodeScopeFreqHz(lowHz),
46
+ ...exports.IcomScopeCommands.encodeScopeFreqHz(highHz),
47
+ ],
48
+ });
60
49
  },
61
50
  encodeScopeSpanHz(spanHz) {
62
- const safeSpanHz = Math.max(0, Math.round(spanHz));
63
- const out = Buffer.alloc(5);
64
- let remaining = safeSpanHz;
65
- for (let i = 0; i < out.length; i++) {
66
- const twoDigits = remaining % 100;
67
- out[i] = ((((twoDigits / 10) | 0) & 0x0f) << 4) | (twoDigits % 10);
68
- remaining = Math.floor(remaining / 100);
69
- }
70
- return out;
51
+ return (0, IcomCivFrame_1.encodeFrequencyBcdLE)(Math.max(0, Math.round(spanHz)), 5);
71
52
  },
72
53
  encodeScopeFreqHz(freqHz) {
73
- const safeFreqHz = Math.max(0, Math.round(freqHz));
74
- const out = Buffer.alloc(5);
75
- let remaining = safeFreqHz;
76
- for (let i = 0; i < out.length; i++) {
77
- const twoDigits = remaining % 100;
78
- out[i] = ((((twoDigits / 10) | 0) & 0x0f) << 4) | (twoDigits % 10);
79
- remaining = Math.floor(remaining / 100);
80
- }
81
- return out;
54
+ return (0, IcomCivFrame_1.encodeFrequencyBcdLE)(Math.max(0, Math.round(freqHz)), 5);
82
55
  }
83
56
  };
package/dist/types.d.ts CHANGED
@@ -8,8 +8,11 @@ export interface IcomCredentials {
8
8
  userName: string;
9
9
  password: string;
10
10
  }
11
+ export type IcomModelId = 'IC-705' | 'IC-905' | 'IC-7300' | 'IC-9700' | 'IC-7610' | 'IC-7760' | 'generic-modern-icom';
11
12
  export interface IcomRigOptions extends IcomCredentials {
12
13
  control: UdpAddress;
14
+ /** Radio model profile. Defaults to auto-detection from rig name or CI-V address. */
15
+ model?: IcomModelId | 'auto';
13
16
  }
14
17
  export interface CivCommand {
15
18
  bytes: Buffer;
@@ -32,6 +35,8 @@ export interface CapabilitiesInfo {
32
35
  civAddress?: number;
33
36
  audioName?: string;
34
37
  supportTX?: boolean;
38
+ modelId?: IcomModelId;
39
+ profileName?: string;
35
40
  }
36
41
  export interface IcomRigEvents {
37
42
  login: (res: LoginResult) => void;
@@ -71,9 +76,11 @@ export type ConnectorDataMode = keyof typeof CONNECTOR_MODE_MAP;
71
76
  export interface SetModeOptions {
72
77
  /**
73
78
  * Enable data mode (e.g., USB-D for digital modes)
74
- * Uses CI-V command 0x26 instead of 0x06
79
+ * Uses CI-V command 0x26 on modern targetable ICOM profiles.
75
80
  */
76
81
  dataMode?: boolean;
82
+ /** Optional IF filter preset. Modern DSP rigs commonly support 1, 2, or 3. */
83
+ filter?: 1 | 2 | 3;
77
84
  }
78
85
  /**
79
86
  * Options for query operations (frequency, meters, etc.)
@@ -183,8 +190,8 @@ export interface LevelReading {
183
190
  export interface SwrReading {
184
191
  /**
185
192
  * Raw BCD value (0-300+)
186
- * Actual SWR = raw / 100
187
- * Example: 120 = SWR 1.2, 250 = SWR 2.5
193
+ * Conversion is profile-calibrated from Hamlib curves.
194
+ * Example: raw 48 SWR 1.5, raw 120 SWR 3.0 on modern ICOM profiles.
188
195
  */
189
196
  raw: number;
190
197
  /**
@@ -193,7 +200,7 @@ export interface SwrReading {
193
200
  */
194
201
  swr: number;
195
202
  /**
196
- * Alert flag when SWR is too high (≥1.2)
203
+ * Alert flag when SWR is too high (≥3.0)
197
204
  * High SWR can damage transmitter
198
205
  */
199
206
  alert: boolean;
@@ -292,11 +299,13 @@ export interface OvfStatusReading {
292
299
  export interface PowerLevelReading {
293
300
  /**
294
301
  * Raw BCD value (0-255)
295
- * Calibration: 0143≈50%, 0213≈100%
302
+ * Calibration is model-specific.
296
303
  */
297
304
  raw: number;
298
- /** Percentage of maximum power (0-100%) */
305
+ /** Percentage of profile maximum power (0-100%) */
299
306
  percent: number;
307
+ /** Estimated RF output in watts when profile calibration is available */
308
+ watts?: number;
300
309
  }
301
310
  /**
302
311
  * COMP (voice compression) level reading (CI-V 0x15/0x14)
@@ -305,8 +314,10 @@ export interface PowerLevelReading {
305
314
  export interface CompLevelReading {
306
315
  /** Raw BCD value (0-255) */
307
316
  raw: number;
308
- /** Percentage of maximum compression (0-100%) */
317
+ /** Percentage of 30 dB compression scale (0-100%) */
309
318
  percent: number;
319
+ /** Estimated compression level in dB */
320
+ db?: number;
310
321
  }
311
322
  /**
312
323
  * Voltage reading (CI-V 0x15/0x15)
@@ -335,7 +346,7 @@ export interface CurrentReading {
335
346
  amps: number;
336
347
  }
337
348
  /**
338
- * Antenna tuner state (IC-705 CI-V 0x1A/0x00)
349
+ * Antenna tuner state (standard CI-V 0x1C/0x01)
339
350
  * 00=OFF, 01=ON, 02=TUNING
340
351
  */
341
352
  export type TunerState = 'OFF' | 'ON' | 'TUNING';
@@ -31,3 +31,16 @@ export declare class ConnectionAbortedError extends Error {
31
31
  context: Record<string, any> | undefined;
32
32
  };
33
33
  }
34
+ export interface UnsupportedCommandContext {
35
+ modelId?: string;
36
+ commandName: string;
37
+ civCommand?: number | string;
38
+ reason?: string;
39
+ }
40
+ export declare class UnsupportedCommandError extends Error {
41
+ readonly modelId?: string;
42
+ readonly commandName: string;
43
+ readonly civCommand?: number | string;
44
+ readonly reason?: string;
45
+ constructor(context: UnsupportedCommandContext);
46
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConnectionAbortedError = void 0;
3
+ exports.UnsupportedCommandError = exports.ConnectionAbortedError = void 0;
4
4
  exports.getDisconnectMessage = getDisconnectMessage;
5
5
  const types_1 = require("../types");
6
6
  /**
@@ -62,3 +62,19 @@ class ConnectionAbortedError extends Error {
62
62
  }
63
63
  }
64
64
  exports.ConnectionAbortedError = ConnectionAbortedError;
65
+ class UnsupportedCommandError extends Error {
66
+ constructor(context) {
67
+ const details = [
68
+ context.modelId ? `model=${context.modelId}` : undefined,
69
+ context.civCommand !== undefined ? `civ=${context.civCommand}` : undefined,
70
+ context.reason,
71
+ ].filter(Boolean).join(', ');
72
+ super(`Unsupported ICOM CI-V command '${context.commandName}'${details ? ` (${details})` : ''}`);
73
+ this.name = 'UnsupportedCommandError';
74
+ this.modelId = context.modelId;
75
+ this.commandName = context.commandName;
76
+ this.civCommand = context.civCommand;
77
+ this.reason = context.reason;
78
+ }
79
+ }
80
+ exports.UnsupportedCommandError = UnsupportedCommandError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icom-wlan-node",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Icom WLAN (CI‑V, audio) protocol implementation for Node.js/TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "license": "MIT",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "https://github.com/boybook/icom-wlan-node.git"
29
+ "url": "git+https://github.com/boybook/icom-wlan-node.git"
30
30
  },
31
31
  "files": [
32
32
  "dist"