dsc-itv2-client 1.0.7
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 +342 -0
- package/package.json +46 -0
- package/src/ITV2Client.js +502 -0
- package/src/constants.js +106 -0
- package/src/event-handler.js +323 -0
- package/src/examples/README.md +287 -0
- package/src/examples/arm-disarm-example.js +152 -0
- package/src/examples/basic-monitoring.js +82 -0
- package/src/examples/interactive-cli.js +1033 -0
- package/src/index.js +17 -0
- package/src/itv2-crypto.js +310 -0
- package/src/itv2-session.js +1069 -0
- package/src/response-parsers.js +185 -0
- package/src/utils.js +240 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arm/Disarm Control Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to arm and disarm partitions
|
|
5
|
+
* using the ITV2Client library.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ITV2Client } from '../index.js';
|
|
9
|
+
import readline from 'readline';
|
|
10
|
+
|
|
11
|
+
// Configuration
|
|
12
|
+
const config = {
|
|
13
|
+
integrationId: process.env.INTEGRATION_ID || '123123123123',
|
|
14
|
+
accessCode: process.env.ACCESS_CODE || '12345678',
|
|
15
|
+
masterCode: process.env.MASTER_CODE || '5555',
|
|
16
|
+
port: parseInt(process.env.UDP_PORT || '3073'),
|
|
17
|
+
logLevel: process.env.LOG_LEVEL || 'minimal' // 'silent', 'minimal', 'verbose'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const client = new ITV2Client(config);
|
|
21
|
+
let sessionEstablished = false;
|
|
22
|
+
|
|
23
|
+
// Create readline interface
|
|
24
|
+
const rl = readline.createInterface({
|
|
25
|
+
input: process.stdin,
|
|
26
|
+
output: process.stdout,
|
|
27
|
+
prompt: '> '
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Session events
|
|
31
|
+
client.on('listening', (address) => {
|
|
32
|
+
console.log(`Listening on ${address.address}:${address.port}`);
|
|
33
|
+
console.log('Waiting for panel connection...\n');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
client.on('session:established', () => {
|
|
37
|
+
sessionEstablished = true;
|
|
38
|
+
console.log('ā
Session established!\n');
|
|
39
|
+
console.log('Commands:');
|
|
40
|
+
console.log(' stay [partition] [code] - Arm in STAY mode');
|
|
41
|
+
console.log(' away [partition] [code] - Arm in AWAY mode');
|
|
42
|
+
console.log(' disarm [partition] [code] - Disarm partition');
|
|
43
|
+
console.log(' status - Show current status');
|
|
44
|
+
console.log(' quit - Exit\n');
|
|
45
|
+
rl.prompt();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Zone events
|
|
49
|
+
client.on('zone:open', (zone) => {
|
|
50
|
+
console.log(`\nšŖ Zone ${zone} opened`);
|
|
51
|
+
if (sessionEstablished) rl.prompt();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
client.on('zone:closed', (zone) => {
|
|
55
|
+
console.log(`\nš Zone ${zone} closed`);
|
|
56
|
+
if (sessionEstablished) rl.prompt();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Partition events (these would be emitted when the panel confirms arming/disarming)
|
|
60
|
+
client.on('partition:armed', (partition, mode) => {
|
|
61
|
+
console.log(`\nš”ļø Partition ${partition} ARMED (mode: ${mode})`);
|
|
62
|
+
if (sessionEstablished) rl.prompt();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
client.on('partition:disarmed', (partition) => {
|
|
66
|
+
console.log(`\nš Partition ${partition} DISARMED`);
|
|
67
|
+
if (sessionEstablished) rl.prompt();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Command errors
|
|
71
|
+
client.on('command:error', (error) => {
|
|
72
|
+
console.log(`\nā ļø Command error: ${error.message}`);
|
|
73
|
+
if (sessionEstablished) rl.prompt();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Handle user commands
|
|
77
|
+
rl.on('line', (line) => {
|
|
78
|
+
const [cmd, ...args] = line.trim().split(/\s+/);
|
|
79
|
+
|
|
80
|
+
if (!sessionEstablished && cmd !== 'quit') {
|
|
81
|
+
console.log('ā ļø Session not established yet');
|
|
82
|
+
rl.prompt();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
switch (cmd) {
|
|
87
|
+
case 'stay':
|
|
88
|
+
const stayPartition = parseInt(args[0] || '1');
|
|
89
|
+
const stayCode = args[1] || config.masterCode;
|
|
90
|
+
console.log(`Arming partition ${stayPartition} in STAY mode...`);
|
|
91
|
+
client.armStay(stayPartition, stayCode);
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
case 'away':
|
|
95
|
+
const awayPartition = parseInt(args[0] || '1');
|
|
96
|
+
const awayCode = args[1] || config.masterCode;
|
|
97
|
+
console.log(`Arming partition ${awayPartition} in AWAY mode...`);
|
|
98
|
+
client.armAway(awayPartition, awayCode);
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case 'disarm':
|
|
102
|
+
const disarmPartition = parseInt(args[0] || '1');
|
|
103
|
+
const disarmCode = args[1] || config.masterCode;
|
|
104
|
+
console.log(`Disarming partition ${disarmPartition}...`);
|
|
105
|
+
client.disarm(disarmPartition, disarmCode);
|
|
106
|
+
break;
|
|
107
|
+
|
|
108
|
+
case 'status':
|
|
109
|
+
const zones = client.getZones();
|
|
110
|
+
const partitions = client.getPartitions();
|
|
111
|
+
|
|
112
|
+
console.log('\n=== Current Status ===');
|
|
113
|
+
console.log('\nZones:');
|
|
114
|
+
for (const [zoneNum, zone] of Object.entries(zones)) {
|
|
115
|
+
console.log(` Zone ${zoneNum}: ${zone.open ? 'OPEN' : 'CLOSED'}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log('\nPartitions:');
|
|
119
|
+
for (const [partNum, partition] of Object.entries(partitions)) {
|
|
120
|
+
console.log(` Partition ${partNum}: ${partition.armedState || 'Unknown'}`);
|
|
121
|
+
}
|
|
122
|
+
console.log();
|
|
123
|
+
break;
|
|
124
|
+
|
|
125
|
+
case 'quit':
|
|
126
|
+
case 'exit':
|
|
127
|
+
console.log('Closing session...');
|
|
128
|
+
client.stop().then(() => process.exit(0));
|
|
129
|
+
return;
|
|
130
|
+
|
|
131
|
+
case '':
|
|
132
|
+
// Empty line, just show prompt again
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
default:
|
|
136
|
+
console.log(`Unknown command: ${cmd}`);
|
|
137
|
+
console.log('Type "stay", "away", "disarm", "status", or "quit"');
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
rl.prompt();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Start
|
|
145
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
146
|
+
console.log('ā DSC ITV2 Arm/Disarm Control Example ā');
|
|
147
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n');
|
|
148
|
+
|
|
149
|
+
client.start().catch((error) => {
|
|
150
|
+
console.error('Failed to start:', error.message);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Zone Monitoring Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows the simplest way to use the ITV2Client library
|
|
5
|
+
* to monitor zone status changes on your DSC alarm panel.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ITV2Client } from '../index.js';
|
|
9
|
+
|
|
10
|
+
// Configuration - update with your panel's credentials
|
|
11
|
+
const config = {
|
|
12
|
+
integrationId: process.env.INTEGRATION_ID || '123123123123',
|
|
13
|
+
accessCode: process.env.ACCESS_CODE || '12345678',
|
|
14
|
+
masterCode: process.env.MASTER_CODE || '5555',
|
|
15
|
+
port: parseInt(process.env.UDP_PORT || '3073'),
|
|
16
|
+
logLevel: process.env.LOG_LEVEL || 'minimal' // 'silent', 'minimal', 'verbose'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Create client
|
|
20
|
+
const client = new ITV2Client(config);
|
|
21
|
+
|
|
22
|
+
// Handle session events
|
|
23
|
+
client.on('listening', (address) => {
|
|
24
|
+
console.log(`\nš§ Listening on ${address.address}:${address.port}`);
|
|
25
|
+
console.log('ā³ Waiting for panel to connect...\n');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
client.on('session:connecting', () => {
|
|
29
|
+
console.log('š Panel connecting...');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
client.on('session:established', (keys) => {
|
|
33
|
+
console.log('ā
Session established!');
|
|
34
|
+
console.log('š Encrypted communication enabled\n');
|
|
35
|
+
console.log('š” Monitoring zone changes (open/close a door or window)...\n');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
client.on('session:closed', () => {
|
|
39
|
+
console.log('\nš Session closed');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
client.on('session:error', (error) => {
|
|
43
|
+
console.error('ā Session error:', error.message);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Handle zone events
|
|
47
|
+
client.on('zone:open', (zoneNumber) => {
|
|
48
|
+
console.log(`šŖ Zone ${zoneNumber} OPENED`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
client.on('zone:closed', (zoneNumber) => {
|
|
52
|
+
console.log(`š Zone ${zoneNumber} CLOSED`);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
client.on('zone:status', (zoneNumber, status) => {
|
|
56
|
+
// This event includes full status details
|
|
57
|
+
if (status.open) {
|
|
58
|
+
console.log(` ā¹ļø Zone ${zoneNumber} details: ${JSON.stringify(status)}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Handle errors
|
|
63
|
+
client.on('error', (error) => {
|
|
64
|
+
console.error('ā Error:', error.message);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Graceful shutdown
|
|
68
|
+
process.on('SIGINT', async () => {
|
|
69
|
+
console.log('\n\nš Shutting down gracefully...');
|
|
70
|
+
await client.stop();
|
|
71
|
+
process.exit(0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Start the client
|
|
75
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
76
|
+
console.log('ā DSC ITV2 Basic Zone Monitoring ā');
|
|
77
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n');
|
|
78
|
+
|
|
79
|
+
client.start().catch((error) => {
|
|
80
|
+
console.error('Failed to start client:', error.message);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|