@ya-modbus/device-profiler 0.4.1-refactor-scope-driver-packages.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/CHANGELOG.md +21 -0
- package/LICENSE +674 -0
- package/README.md +69 -0
- package/dist/bin/profile.d.ts +9 -0
- package/dist/bin/profile.d.ts.map +1 -0
- package/dist/bin/profile.js +10 -0
- package/dist/bin/profile.js.map +1 -0
- package/dist/src/cli.d.ts +27 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +45 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/console-formatter.d.ts +20 -0
- package/dist/src/console-formatter.d.ts.map +1 -0
- package/dist/src/console-formatter.js +36 -0
- package/dist/src/console-formatter.js.map +1 -0
- package/dist/src/constants.d.ts +18 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +18 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/error-classifier.d.ts +24 -0
- package/dist/src/error-classifier.d.ts.map +1 -0
- package/dist/src/error-classifier.js +43 -0
- package/dist/src/error-classifier.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/program.d.ts +7 -0
- package/dist/src/program.d.ts.map +1 -0
- package/dist/src/program.js +75 -0
- package/dist/src/program.js.map +1 -0
- package/dist/src/read-tester.d.ts +40 -0
- package/dist/src/read-tester.d.ts.map +1 -0
- package/dist/src/read-tester.js +52 -0
- package/dist/src/read-tester.js.map +1 -0
- package/dist/src/register-scanner.d.ts +51 -0
- package/dist/src/register-scanner.d.ts.map +1 -0
- package/dist/src/register-scanner.js +68 -0
- package/dist/src/register-scanner.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @ya-modbus/device-profiler
|
|
2
|
+
|
|
3
|
+
Device profiler for discovering Modbus register maps through automated scanning.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Scans holding registers (FC03) and input registers (FC04)
|
|
8
|
+
- Batch reading with automatic fallback on errors
|
|
9
|
+
- Real-time progress display
|
|
10
|
+
- Timing measurement for each read operation
|
|
11
|
+
- Error classification (timeout, CRC, Modbus exceptions)
|
|
12
|
+
- Summary table of discovered registers
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @ya-modbus/device-profiler
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### CLI
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
ya-modbus-profile --port /dev/ttyUSB0 --slave-id 1 --baud 9600
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
|
|
30
|
+
- `--port` - Serial port or TCP host:port
|
|
31
|
+
- `--slave-id` - Modbus slave ID
|
|
32
|
+
- `--baud` - Baud rate for RTU (default: 9600)
|
|
33
|
+
- `--start` - Start register address (default: 0)
|
|
34
|
+
- `--end` - End register address (default: 100)
|
|
35
|
+
- `--batch` - Batch size for reads (default: 10)
|
|
36
|
+
|
|
37
|
+
### Programmatic
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { scanRegisters, RegisterType } from '@ya-modbus/device-profiler'
|
|
41
|
+
|
|
42
|
+
await scanRegisters({
|
|
43
|
+
transport,
|
|
44
|
+
type: RegisterType.Holding,
|
|
45
|
+
startAddress: 0,
|
|
46
|
+
endAddress: 100,
|
|
47
|
+
batchSize: 10,
|
|
48
|
+
onProgress: (current, total) => {
|
|
49
|
+
console.log(`${current}/${total}`)
|
|
50
|
+
},
|
|
51
|
+
onResult: (result) => {
|
|
52
|
+
console.log(result)
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
|
|
59
|
+
The scanner produces a summary showing:
|
|
60
|
+
|
|
61
|
+
- Register address
|
|
62
|
+
- Register type (holding/input)
|
|
63
|
+
- Read success/failure
|
|
64
|
+
- Response time
|
|
65
|
+
- Error details (if any)
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
GPL-3.0-or-later
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../bin/profile.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point
|
|
4
|
+
*
|
|
5
|
+
* This file is the executable entry point that parses command-line arguments.
|
|
6
|
+
* The actual CLI implementation is in src/program.ts
|
|
7
|
+
*/
|
|
8
|
+
import { program } from '../src/program.js';
|
|
9
|
+
program.parse();
|
|
10
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../bin/profile.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,OAAO,CAAC,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI orchestrator for register scanning
|
|
3
|
+
*/
|
|
4
|
+
import type { Transport } from '@ya-modbus/driver-types';
|
|
5
|
+
import { RegisterType } from './read-tester.js';
|
|
6
|
+
/**
|
|
7
|
+
* Options for running a profile scan
|
|
8
|
+
*/
|
|
9
|
+
export interface ProfileScanOptions {
|
|
10
|
+
/** Modbus transport */
|
|
11
|
+
transport: Transport;
|
|
12
|
+
/** Register type to scan */
|
|
13
|
+
type: RegisterType;
|
|
14
|
+
/** Starting register address */
|
|
15
|
+
startAddress: number;
|
|
16
|
+
/** Ending register address (inclusive) */
|
|
17
|
+
endAddress: number;
|
|
18
|
+
/** Maximum registers to read in a single batch (default: 10) */
|
|
19
|
+
batchSize?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run a register profile scan with console output
|
|
23
|
+
*
|
|
24
|
+
* @param options - Scan configuration
|
|
25
|
+
*/
|
|
26
|
+
export declare function runProfileScan(options: ProfileScanOptions): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAIxD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAG/C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,SAAS,EAAE,SAAS,CAAA;IACpB,4BAA4B;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkC/E"}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI orchestrator for register scanning
|
|
3
|
+
*/
|
|
4
|
+
import { formatProgress, formatSummary } from './console-formatter.js';
|
|
5
|
+
import { PROGRESS_UPDATE_INTERVAL_MS } from './constants.js';
|
|
6
|
+
import { scanRegisters } from './register-scanner.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run a register profile scan with console output
|
|
9
|
+
*
|
|
10
|
+
* @param options - Scan configuration
|
|
11
|
+
*/
|
|
12
|
+
export async function runProfileScan(options) {
|
|
13
|
+
const { transport, type, startAddress, endAddress, batchSize } = options;
|
|
14
|
+
const results = [];
|
|
15
|
+
try {
|
|
16
|
+
console.log(`Scanning ${type} registers from ${startAddress} to ${endAddress}...`);
|
|
17
|
+
console.log();
|
|
18
|
+
let lastProgressUpdate = 0;
|
|
19
|
+
await scanRegisters({
|
|
20
|
+
transport,
|
|
21
|
+
type,
|
|
22
|
+
startAddress,
|
|
23
|
+
endAddress,
|
|
24
|
+
...(batchSize !== undefined && { batchSize }),
|
|
25
|
+
onProgress: (current, total) => {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
if (now - lastProgressUpdate >= PROGRESS_UPDATE_INTERVAL_MS || current === total) {
|
|
28
|
+
process.stdout.write(`\r${formatProgress(current, total)}`);
|
|
29
|
+
lastProgressUpdate = now;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
onResult: (result) => {
|
|
33
|
+
results.push(result);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
console.log('\n');
|
|
37
|
+
console.log('Scan complete!');
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(formatSummary(results));
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
await transport.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AAE5D,OAAO,EAAE,aAAa,EAAmB,MAAM,uBAAuB,CAAA;AAkBtE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA2B;IAC9D,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IACxE,MAAM,OAAO,GAAiB,EAAE,CAAA;IAEhC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,mBAAmB,YAAY,OAAO,UAAU,KAAK,CAAC,CAAA;QAClF,OAAO,CAAC,GAAG,EAAE,CAAA;QAEb,IAAI,kBAAkB,GAAG,CAAC,CAAA;QAC1B,MAAM,aAAa,CAAC;YAClB,SAAS;YACT,IAAI;YACJ,YAAY;YACZ,UAAU;YACV,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;YAC7C,UAAU,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;gBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBACtB,IAAI,GAAG,GAAG,kBAAkB,IAAI,2BAA2B,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;oBACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;oBAC3D,kBAAkB,GAAG,GAAG,CAAA;gBAC1B,CAAC;YACH,CAAC;YACD,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;gBACnB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACtB,CAAC;SACF,CAAC,CAAA;QAEF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC7B,OAAO,CAAC,GAAG,EAAE,CAAA;QACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAA;IACrC,CAAC;YAAS,CAAC;QACT,MAAM,SAAS,CAAC,KAAK,EAAE,CAAA;IACzB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console output formatting for register scanning
|
|
3
|
+
*/
|
|
4
|
+
import type { ScanResult } from './register-scanner.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format progress message
|
|
7
|
+
*
|
|
8
|
+
* @param current - Current count
|
|
9
|
+
* @param total - Total count
|
|
10
|
+
* @returns Formatted progress string
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatProgress(current: number, total: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format summary table of scan results
|
|
15
|
+
*
|
|
16
|
+
* @param results - Scan results
|
|
17
|
+
* @returns Formatted table string
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatSummary(results: ScanResult[]): string;
|
|
20
|
+
//# sourceMappingURL=console-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-formatter.d.ts","sourceRoot":"","sources":["../../src/console-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAiB3D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console output formatting for register scanning
|
|
3
|
+
*/
|
|
4
|
+
import Table from 'cli-table3';
|
|
5
|
+
/**
|
|
6
|
+
* Format progress message
|
|
7
|
+
*
|
|
8
|
+
* @param current - Current count
|
|
9
|
+
* @param total - Total count
|
|
10
|
+
* @returns Formatted progress string
|
|
11
|
+
*/
|
|
12
|
+
export function formatProgress(current, total) {
|
|
13
|
+
const percentage = total > 0 ? Math.round((current / total) * 100) : 0;
|
|
14
|
+
return `Progress: ${current}/${total} (${percentage}%)`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Format summary table of scan results
|
|
18
|
+
*
|
|
19
|
+
* @param results - Scan results
|
|
20
|
+
* @returns Formatted table string
|
|
21
|
+
*/
|
|
22
|
+
export function formatSummary(results) {
|
|
23
|
+
const table = new Table({
|
|
24
|
+
head: ['Address', 'Type', 'Status', 'Value', 'Timing (ms)', 'Error'],
|
|
25
|
+
style: { head: [] },
|
|
26
|
+
});
|
|
27
|
+
for (const result of results) {
|
|
28
|
+
const value = result.success && result.value ? result.value.toString('hex').toUpperCase() : '-';
|
|
29
|
+
const status = result.success ? 'OK' : 'FAIL';
|
|
30
|
+
const error = result.error ?? '-';
|
|
31
|
+
const timing = result.timing.toFixed(1);
|
|
32
|
+
table.push([result.address.toString(), result.type, status, value, timing, error]);
|
|
33
|
+
}
|
|
34
|
+
return table.toString();
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=console-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-formatter.js","sourceRoot":"","sources":["../../src/console-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,YAAY,CAAA;AAI9B;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAAa;IAC3D,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACtE,OAAO,aAAa,OAAO,IAAI,KAAK,KAAK,UAAU,IAAI,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAqB;IACjD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC;QACpE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;KACpB,CAAC,CAAA;IAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;QAE/F,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAA;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAEvC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;IACpF,CAAC;IAED,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for Modbus device profiling
|
|
3
|
+
*/
|
|
4
|
+
/** Minimum valid TCP port number */
|
|
5
|
+
export declare const MIN_PORT = 1;
|
|
6
|
+
/** Maximum valid TCP port number */
|
|
7
|
+
export declare const MAX_PORT = 65535;
|
|
8
|
+
/** Minimum valid Modbus slave ID */
|
|
9
|
+
export declare const MIN_SLAVE_ID = 1;
|
|
10
|
+
/** Maximum valid Modbus slave ID */
|
|
11
|
+
export declare const MAX_SLAVE_ID = 247;
|
|
12
|
+
/** Default batch size for register reads */
|
|
13
|
+
export declare const DEFAULT_BATCH_SIZE = 10;
|
|
14
|
+
/** Number of bytes per Modbus register */
|
|
15
|
+
export declare const BYTES_PER_REGISTER = 2;
|
|
16
|
+
/** Minimum interval between progress updates in milliseconds */
|
|
17
|
+
export declare const PROGRESS_UPDATE_INTERVAL_MS = 100;
|
|
18
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oCAAoC;AACpC,eAAO,MAAM,QAAQ,IAAI,CAAA;AAEzB,oCAAoC;AACpC,eAAO,MAAM,QAAQ,QAAQ,CAAA;AAE7B,oCAAoC;AACpC,eAAO,MAAM,YAAY,IAAI,CAAA;AAE7B,oCAAoC;AACpC,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC,gEAAgE;AAChE,eAAO,MAAM,2BAA2B,MAAM,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for Modbus device profiling
|
|
3
|
+
*/
|
|
4
|
+
/** Minimum valid TCP port number */
|
|
5
|
+
export const MIN_PORT = 1;
|
|
6
|
+
/** Maximum valid TCP port number */
|
|
7
|
+
export const MAX_PORT = 65535;
|
|
8
|
+
/** Minimum valid Modbus slave ID */
|
|
9
|
+
export const MIN_SLAVE_ID = 1;
|
|
10
|
+
/** Maximum valid Modbus slave ID */
|
|
11
|
+
export const MAX_SLAVE_ID = 247;
|
|
12
|
+
/** Default batch size for register reads */
|
|
13
|
+
export const DEFAULT_BATCH_SIZE = 10;
|
|
14
|
+
/** Number of bytes per Modbus register */
|
|
15
|
+
export const BYTES_PER_REGISTER = 2;
|
|
16
|
+
/** Minimum interval between progress updates in milliseconds */
|
|
17
|
+
export const PROGRESS_UPDATE_INTERVAL_MS = 100;
|
|
18
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oCAAoC;AACpC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAA;AAEzB,oCAAoC;AACpC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAA;AAE7B,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAA;AAE7B,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAA;AAE/B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAEpC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAEnC,gEAAgE;AAChE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classification for Modbus operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Modbus error types
|
|
6
|
+
*/
|
|
7
|
+
export declare enum ErrorType {
|
|
8
|
+
/** Operation timed out */
|
|
9
|
+
Timeout = "timeout",
|
|
10
|
+
/** CRC or checksum validation failed */
|
|
11
|
+
CRC = "crc",
|
|
12
|
+
/** Modbus exception code returned by device */
|
|
13
|
+
ModbusException = "modbus_exception",
|
|
14
|
+
/** Unknown or unclassified error */
|
|
15
|
+
Unknown = "unknown"
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Classify a Modbus error by examining its message and properties
|
|
19
|
+
*
|
|
20
|
+
* @param error - Error to classify
|
|
21
|
+
* @returns Error classification
|
|
22
|
+
*/
|
|
23
|
+
export declare function classifyError(error: Error): ErrorType;
|
|
24
|
+
//# sourceMappingURL=error-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-classifier.d.ts","sourceRoot":"","sources":["../../src/error-classifier.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,oBAAY,SAAS;IACnB,0BAA0B;IAC1B,OAAO,YAAY;IACnB,wCAAwC;IACxC,GAAG,QAAQ;IACX,+CAA+C;IAC/C,eAAe,qBAAqB;IACpC,oCAAoC;IACpC,OAAO,YAAY;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAwBrD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classification for Modbus operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Modbus error types
|
|
6
|
+
*/
|
|
7
|
+
export var ErrorType;
|
|
8
|
+
(function (ErrorType) {
|
|
9
|
+
/** Operation timed out */
|
|
10
|
+
ErrorType["Timeout"] = "timeout";
|
|
11
|
+
/** CRC or checksum validation failed */
|
|
12
|
+
ErrorType["CRC"] = "crc";
|
|
13
|
+
/** Modbus exception code returned by device */
|
|
14
|
+
ErrorType["ModbusException"] = "modbus_exception";
|
|
15
|
+
/** Unknown or unclassified error */
|
|
16
|
+
ErrorType["Unknown"] = "unknown";
|
|
17
|
+
})(ErrorType || (ErrorType = {}));
|
|
18
|
+
/**
|
|
19
|
+
* Classify a Modbus error by examining its message and properties
|
|
20
|
+
*
|
|
21
|
+
* @param error - Error to classify
|
|
22
|
+
* @returns Error classification
|
|
23
|
+
*/
|
|
24
|
+
export function classifyError(error) {
|
|
25
|
+
const message = error.message?.toLowerCase() ?? '';
|
|
26
|
+
const code = error.code;
|
|
27
|
+
// Check for timeout
|
|
28
|
+
if (message.includes('timeout') || message.includes('timed out') || code === 'ETIMEDOUT') {
|
|
29
|
+
return ErrorType.Timeout;
|
|
30
|
+
}
|
|
31
|
+
// Check for CRC/checksum errors
|
|
32
|
+
if (message.includes('crc') || message.includes('checksum')) {
|
|
33
|
+
return ErrorType.CRC;
|
|
34
|
+
}
|
|
35
|
+
// Check for Modbus exceptions
|
|
36
|
+
if (/modbus\s+exception/i.test(message) ||
|
|
37
|
+
/exception\s+code\s+0x[0-9a-f]+/i.test(message) ||
|
|
38
|
+
/exception\s+\d+/.test(message)) {
|
|
39
|
+
return ErrorType.ModbusException;
|
|
40
|
+
}
|
|
41
|
+
return ErrorType.Unknown;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=error-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-classifier.js","sourceRoot":"","sources":["../../src/error-classifier.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAN,IAAY,SASX;AATD,WAAY,SAAS;IACnB,0BAA0B;IAC1B,gCAAmB,CAAA;IACnB,wCAAwC;IACxC,wBAAW,CAAA;IACX,+CAA+C;IAC/C,iDAAoC,CAAA;IACpC,oCAAoC;IACpC,gCAAmB,CAAA;AACrB,CAAC,EATW,SAAS,KAAT,SAAS,QASpB;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAY;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;IAClD,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAA;IAElD,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzF,OAAO,SAAS,CAAC,OAAO,CAAA;IAC1B,CAAC;IAED,gCAAgC;IAChC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC,GAAG,CAAA;IACtB,CAAC;IAED,8BAA8B;IAC9B,IACE,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QACnC,iCAAiC,CAAC,IAAI,CAAC,OAAO,CAAC;QAC/C,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAC/B,CAAC;QACD,OAAO,SAAS,CAAC,eAAe,CAAA;IAClC,CAAC;IAED,OAAO,SAAS,CAAC,OAAO,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ya-modbus/device-profiler - Device profiler for discovering Modbus register maps
|
|
3
|
+
*/
|
|
4
|
+
export { classifyError, ErrorType } from './error-classifier.js';
|
|
5
|
+
export { formatProgress, formatSummary } from './console-formatter.js';
|
|
6
|
+
export { testRead, RegisterType, type ReadTestResult } from './read-tester.js';
|
|
7
|
+
export { scanRegisters, type ScanOptions, type ScanResult } from './register-scanner.js';
|
|
8
|
+
export { BYTES_PER_REGISTER, DEFAULT_BATCH_SIZE, MAX_PORT, MAX_SLAVE_ID, MIN_PORT, MIN_SLAVE_ID, PROGRESS_UPDATE_INTERVAL_MS, } from './constants.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACxF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ya-modbus/device-profiler - Device profiler for discovering Modbus register maps
|
|
3
|
+
*/
|
|
4
|
+
export { classifyError, ErrorType } from './error-classifier.js';
|
|
5
|
+
export { formatProgress, formatSummary } from './console-formatter.js';
|
|
6
|
+
export { testRead, RegisterType } from './read-tester.js';
|
|
7
|
+
export { scanRegisters } from './register-scanner.js';
|
|
8
|
+
export { BYTES_PER_REGISTER, DEFAULT_BATCH_SIZE, MAX_PORT, MAX_SLAVE_ID, MIN_PORT, MIN_SLAVE_ID, PROGRESS_UPDATE_INTERVAL_MS, } from './constants.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAuB,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAqC,MAAM,uBAAuB,CAAA;AACxF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/program.ts"],"names":[],"mappings":";AAEA;;GAEG;AAIH,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAsB3C,eAAO,MAAM,OAAO,SAAgB,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI program for device profiler
|
|
4
|
+
*/
|
|
5
|
+
import { createTransport } from '@ya-modbus/transport';
|
|
6
|
+
import { Command, Option } from 'commander';
|
|
7
|
+
import { runProfileScan } from './cli.js';
|
|
8
|
+
import { MAX_PORT, MIN_PORT } from './constants.js';
|
|
9
|
+
import { RegisterType } from './read-tester.js';
|
|
10
|
+
const parseNumber = (value) => parseInt(value, 10);
|
|
11
|
+
export const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('ya-modbus-profile')
|
|
14
|
+
.description('Profile Modbus devices by scanning register ranges')
|
|
15
|
+
.version('0.1.0')
|
|
16
|
+
.requiredOption('--port <port>', 'Serial port (e.g., /dev/ttyUSB0) or TCP host:port')
|
|
17
|
+
.requiredOption('--slave-id <id>', 'Modbus slave ID (1-247)', parseNumber)
|
|
18
|
+
.option('--type <type>', 'Register type: holding or input', 'holding')
|
|
19
|
+
.option('--start <address>', 'Start register address', parseNumber, 0)
|
|
20
|
+
.option('--end <address>', 'End register address', parseNumber, 100)
|
|
21
|
+
.option('--batch <size>', 'Batch size for reads', parseNumber, 10)
|
|
22
|
+
.option('--baud <rate>', 'Baud rate for RTU', parseNumber, 9600)
|
|
23
|
+
.addOption(new Option('--parity <parity>', 'Parity for RTU')
|
|
24
|
+
.choices(['none', 'even', 'odd'])
|
|
25
|
+
.default('none'))
|
|
26
|
+
.option('--data-bits <bits>', 'Data bits for RTU', parseNumber, 8)
|
|
27
|
+
.option('--stop-bits <bits>', 'Stop bits for RTU', parseNumber, 1)
|
|
28
|
+
.option('--timeout <ms>', 'Response timeout in milliseconds', parseNumber, 1000)
|
|
29
|
+
.action(async (options) => {
|
|
30
|
+
try {
|
|
31
|
+
const registerType = options.type === 'input' ? RegisterType.Input : RegisterType.Holding;
|
|
32
|
+
let transport;
|
|
33
|
+
if (options.port.includes(':')) {
|
|
34
|
+
const parts = options.port.split(':');
|
|
35
|
+
const host = parts[0];
|
|
36
|
+
const portStr = parts[1];
|
|
37
|
+
if (!host || !portStr) {
|
|
38
|
+
throw new Error('Invalid TCP address format. Expected host:port');
|
|
39
|
+
}
|
|
40
|
+
const port = parseInt(portStr, 10);
|
|
41
|
+
if (isNaN(port) || port < MIN_PORT || port > MAX_PORT) {
|
|
42
|
+
throw new Error(`Invalid port number: ${portStr}. Must be between ${MIN_PORT} and ${MAX_PORT}`);
|
|
43
|
+
}
|
|
44
|
+
transport = await createTransport({
|
|
45
|
+
host,
|
|
46
|
+
port,
|
|
47
|
+
slaveId: options.slaveId,
|
|
48
|
+
timeout: options.timeout,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
transport = await createTransport({
|
|
53
|
+
port: options.port,
|
|
54
|
+
baudRate: options.baud,
|
|
55
|
+
dataBits: options.dataBits,
|
|
56
|
+
parity: options.parity,
|
|
57
|
+
stopBits: options.stopBits,
|
|
58
|
+
slaveId: options.slaveId,
|
|
59
|
+
timeout: options.timeout,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
await runProfileScan({
|
|
63
|
+
transport,
|
|
64
|
+
type: registerType,
|
|
65
|
+
startAddress: options.start,
|
|
66
|
+
endAddress: options.end,
|
|
67
|
+
batchSize: options.batch,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/program.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read testing utilities for Modbus registers
|
|
3
|
+
*/
|
|
4
|
+
import type { Transport } from '@ya-modbus/driver-types';
|
|
5
|
+
import { ErrorType } from './error-classifier.js';
|
|
6
|
+
/**
|
|
7
|
+
* Modbus register type
|
|
8
|
+
*/
|
|
9
|
+
export declare enum RegisterType {
|
|
10
|
+
/** Holding registers (FC03) */
|
|
11
|
+
Holding = "holding",
|
|
12
|
+
/** Input registers (FC04) */
|
|
13
|
+
Input = "input"
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Result of a register read test
|
|
17
|
+
*/
|
|
18
|
+
export interface ReadTestResult {
|
|
19
|
+
/** Whether the read was successful */
|
|
20
|
+
success: boolean;
|
|
21
|
+
/** Register data if successful */
|
|
22
|
+
data?: Buffer;
|
|
23
|
+
/** Time taken for the read operation in milliseconds */
|
|
24
|
+
timing: number;
|
|
25
|
+
/** Error message if failed */
|
|
26
|
+
error?: string;
|
|
27
|
+
/** Classified error type if failed */
|
|
28
|
+
errorType?: ErrorType;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Test reading a register with timing measurement
|
|
32
|
+
*
|
|
33
|
+
* @param transport - Modbus transport
|
|
34
|
+
* @param type - Register type (holding or input)
|
|
35
|
+
* @param address - Starting register address
|
|
36
|
+
* @param count - Number of registers to read
|
|
37
|
+
* @returns Read test result with timing information
|
|
38
|
+
*/
|
|
39
|
+
export declare function testRead(transport: Transport, type: RegisterType, address: number, count: number): Promise<ReadTestResult>;
|
|
40
|
+
//# sourceMappingURL=read-tester.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-tester.d.ts","sourceRoot":"","sources":["../../src/read-tester.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,EAAiB,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEhE;;GAEG;AACH,oBAAY,YAAY;IACtB,+BAA+B;IAC/B,OAAO,YAAY;IACnB,6BAA6B;IAC7B,KAAK,UAAU;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CA6BzB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read testing utilities for Modbus registers
|
|
3
|
+
*/
|
|
4
|
+
import { classifyError } from './error-classifier.js';
|
|
5
|
+
/**
|
|
6
|
+
* Modbus register type
|
|
7
|
+
*/
|
|
8
|
+
export var RegisterType;
|
|
9
|
+
(function (RegisterType) {
|
|
10
|
+
/** Holding registers (FC03) */
|
|
11
|
+
RegisterType["Holding"] = "holding";
|
|
12
|
+
/** Input registers (FC04) */
|
|
13
|
+
RegisterType["Input"] = "input";
|
|
14
|
+
})(RegisterType || (RegisterType = {}));
|
|
15
|
+
/**
|
|
16
|
+
* Test reading a register with timing measurement
|
|
17
|
+
*
|
|
18
|
+
* @param transport - Modbus transport
|
|
19
|
+
* @param type - Register type (holding or input)
|
|
20
|
+
* @param address - Starting register address
|
|
21
|
+
* @param count - Number of registers to read
|
|
22
|
+
* @returns Read test result with timing information
|
|
23
|
+
*/
|
|
24
|
+
export async function testRead(transport, type, address, count) {
|
|
25
|
+
const startTime = performance.now();
|
|
26
|
+
try {
|
|
27
|
+
let data;
|
|
28
|
+
if (type === RegisterType.Holding) {
|
|
29
|
+
data = await transport.readHoldingRegisters(address, count);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
data = await transport.readInputRegisters(address, count);
|
|
33
|
+
}
|
|
34
|
+
const timing = performance.now() - startTime;
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
data,
|
|
38
|
+
timing,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const timing = performance.now() - startTime;
|
|
43
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
timing,
|
|
47
|
+
error: error.message,
|
|
48
|
+
errorType: classifyError(error),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=read-tester.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-tester.js","sourceRoot":"","sources":["../../src/read-tester.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,aAAa,EAAa,MAAM,uBAAuB,CAAA;AAEhE;;GAEG;AACH,MAAM,CAAN,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,+BAA+B;IAC/B,mCAAmB,CAAA;IACnB,6BAA6B;IAC7B,+BAAe,CAAA;AACjB,CAAC,EALW,YAAY,KAAZ,YAAY,QAKvB;AAkBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAoB,EACpB,IAAkB,EAClB,OAAe,EACf,KAAa;IAEb,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;IAEnC,IAAI,CAAC;QACH,IAAI,IAAY,CAAA;QAChB,IAAI,IAAI,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,GAAG,MAAM,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC7D,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC3D,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;QAE5C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,MAAM;SACP,CAAA;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;QAC5C,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QAEjE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM;YACN,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC;SAChC,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register scanner with batch reading and automatic fallback
|
|
3
|
+
*/
|
|
4
|
+
import type { Transport } from '@ya-modbus/driver-types';
|
|
5
|
+
import type { ErrorType } from './error-classifier.js';
|
|
6
|
+
import { RegisterType } from './read-tester.js';
|
|
7
|
+
/**
|
|
8
|
+
* Result of scanning a single register
|
|
9
|
+
*/
|
|
10
|
+
export interface ScanResult {
|
|
11
|
+
/** Register address */
|
|
12
|
+
address: number;
|
|
13
|
+
/** Register type */
|
|
14
|
+
type: RegisterType;
|
|
15
|
+
/** Whether the read was successful */
|
|
16
|
+
success: boolean;
|
|
17
|
+
/** Register value if successful (2 bytes) */
|
|
18
|
+
value?: Buffer;
|
|
19
|
+
/** Time taken for the read operation in milliseconds */
|
|
20
|
+
timing: number;
|
|
21
|
+
/** Error message if failed */
|
|
22
|
+
error?: string;
|
|
23
|
+
/** Classified error type if failed */
|
|
24
|
+
errorType?: ErrorType;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Options for register scanning
|
|
28
|
+
*/
|
|
29
|
+
export interface ScanOptions {
|
|
30
|
+
/** Modbus transport */
|
|
31
|
+
transport: Transport;
|
|
32
|
+
/** Register type to scan */
|
|
33
|
+
type: RegisterType;
|
|
34
|
+
/** Starting register address */
|
|
35
|
+
startAddress: number;
|
|
36
|
+
/** Ending register address (inclusive) */
|
|
37
|
+
endAddress: number;
|
|
38
|
+
/** Maximum registers to read in a single batch (default: 10) */
|
|
39
|
+
batchSize?: number;
|
|
40
|
+
/** Callback for progress updates */
|
|
41
|
+
onProgress?: (current: number, total: number) => void;
|
|
42
|
+
/** Callback for each register result */
|
|
43
|
+
onResult?: (result: ScanResult) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Scan a range of registers with batch reads and automatic fallback
|
|
47
|
+
*
|
|
48
|
+
* @param options - Scan configuration
|
|
49
|
+
*/
|
|
50
|
+
export declare function scanRegisters(options: ScanOptions): Promise<void>;
|
|
51
|
+
//# sourceMappingURL=register-scanner.d.ts.map
|