dsc-itv2-client 1.0.29 → 2.0.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 CHANGED
@@ -1,21 +1,18 @@
1
1
  # DSC ITV2 Client Library
2
2
 
3
- Reverse engineered, completely unofficial node.js library for communicating with DSC alarm panels using the ITV2 protocol over TL280R communicators.
4
- Not affiliated with DSC or DSC Alarm in any way, shape or form. Use at your own risk.
3
+ Reverse engineered, completely unofficial Node.js library for communicating with DSC alarm panels (Neo series) using the ITV2 protocol over TL280/TL280E communicators. Zero external dependencies - uses only Node.js built-ins.
5
4
 
6
- ## Features
7
-
8
- **Event-Driven Architecture** - Subscribe to zone changes with EventEmitter
9
-
10
- **Full Protocol Implementation** - Complete ITV2 handshake with Type 1 and 2 encryption
11
-
12
- **Real-Time Notifications** - Automatic zone status updates from panel
5
+ Not affiliated with DSC, Johnson Controls, or Tyco in any way. Use at your own risk.
13
6
 
14
- **Partition Control** - Arm and disarm partitions
15
-
16
- **Encrypted Communication** - AES-128-ECB with dynamic key exchange
7
+ ## Features
17
8
 
18
- **Auto-Reconnect** - Graceful handling of disconnections
9
+ - **Real-Time Zone Monitoring** - Open/close, tamper, alarm, bypass events via push notifications
10
+ - **Partition Control** - Arm stay/away/night, disarm with real-time confirmation
11
+ - **Async Status Querying** - Query zone status, partition status, system capabilities on demand
12
+ - **Trouble Detail Parsing** - Human-readable trouble notifications from official SDK enums
13
+ - **Encrypted Communication** - AES-128-ECB with automatic Type 1/Type 2 key exchange
14
+ - **Event-Driven Architecture** - Subscribe to events with EventEmitter
15
+ - **Automatic Session Setup** - Capabilities query, initial status pull, heartbeat keepalive
19
16
 
20
17
  ## Quick Start
21
18
 
@@ -25,64 +22,54 @@ Not affiliated with DSC or DSC Alarm in any way, shape or form. Use at your own
25
22
  npm install dsc-itv2-client
26
23
  ```
27
24
 
28
- ### Basic Zone Monitoring
25
+ ### Basic Usage
29
26
 
30
27
  ```javascript
31
28
  import { ITV2Client } from 'dsc-itv2-client';
32
29
 
33
30
  const client = new ITV2Client({
34
- integrationId: '250228754543',
35
- accessCode: '28754543',
36
- port: 3073
31
+ integrationId: '250228754543', // Section [851][422]
32
+ accessCode: '28754543', // Section [851][423]
33
+ masterCode: '5555', // User code for arm/disarm
34
+ port: 3072, // TCP port (panel connects to us)
37
35
  });
38
36
 
39
- // Subscribe to events
40
- client.on('session:established', () => {
41
- console.log('Connected to panel!');
37
+ client.on('session:established', () => console.log('Connected!'));
38
+ client.on('zone:open', (zone) => console.log(`Zone ${zone} opened`));
39
+ client.on('zone:closed', (zone) => console.log(`Zone ${zone} closed`));
40
+ client.on('partition:arming', ({ partition, modeName }) => {
41
+ console.log(`Partition ${partition}: ${modeName}`);
42
42
  });
43
43
 
44
- client.on('zone:open', (zoneNumber) => {
45
- console.log(`Zone ${zoneNumber} opened`);
46
- });
44
+ // Status is automatically queried on connect
45
+ client.on('status:ready', async ({ zones, partition }) => {
46
+ console.log(`${zones.length} zones loaded`);
47
47
 
48
- client.on('zone:closed', (zoneNumber) => {
49
- console.log(`Zone ${zoneNumber} closed`);
48
+ // Query on demand anytime
49
+ const current = await client.queryZoneStatus();
50
+ const part = await client.queryPartitionStatus(1);
50
51
  });
51
52
 
52
- // Start listening
53
53
  await client.start();
54
54
  ```
55
55
 
56
- ### Arm/Disarm Control
56
+ ### Arm/Disarm
57
57
 
58
58
  ```javascript
59
- // Arm partition in STAY mode
60
- client.armStay(1, '5555');
61
-
62
- // Arm partition in AWAY mode
63
- client.armAway(1, '5555');
64
-
65
- // Disarm partition
66
- client.disarm(1, '5555');
59
+ client.armStay(1, '5555'); // Arm partition 1 in stay mode
60
+ client.armAway(1, '5555'); // Arm partition 1 in away mode
61
+ client.armNight(1, '5555'); // Arm partition 1 in night mode
62
+ client.disarm(1, '5555'); // Disarm partition 1
67
63
  ```
68
64
 
69
- ## Examples
70
-
71
- Run the included examples:
65
+ ### Examples
72
66
 
73
67
  ```bash
74
- # Basic zone monitoring
75
- npm run example:basic
76
-
77
- # Arm/disarm control
78
- npm run example:control
79
-
80
- # Full interactive CLI
81
- npm run example:cli
68
+ npm run example:basic # Zone monitoring
69
+ npm run example:control # Arm/disarm demo
70
+ npm run example:cli # Interactive CLI with querying
82
71
  ```
83
72
 
84
- See [src/examples/README.md](src/examples/README.md) for detailed examples and usage.
85
-
86
73
  ## API Reference
87
74
 
88
75
  ### Constructor
@@ -91,256 +78,191 @@ See [src/examples/README.md](src/examples/README.md) for detailed examples and u
91
78
  const client = new ITV2Client(options);
92
79
  ```
93
80
 
94
- **Options:**
95
- - `integrationId` (string) - 12-digit panel integration ID
96
- - `accessCode` (string) - 8-digit (Type 1) or 32-hex (Type 2) access code
97
- - `masterCode` (string, optional) - Master code for arm/disarm (default: '5555')
98
- - `port` (number, optional) - UDP port to listen on (default: 3073)
99
- - `encryptionType` (number, optional) - null=auto-detect, 1=Type 1, 2=Type 2 (default: null)
100
- - `logLevel` (string, optional) - 'silent', 'minimal', 'verbose' (default: 'minimal')
101
-
102
- #### Encryption Types
103
-
104
- **Type 1 (default, most common):**
105
- ```javascript
106
- new ITV2Client({
107
- integrationId: '250228754543',
108
- accessCode: '28754543' // 8-digit code
109
- });
110
- ```
111
-
112
- **Type 2 (for panels requiring 32-hex code):**
113
- ```javascript
114
- new ITV2Client({
115
- integrationId: '250228754543',
116
- accessCode: '25022875250228752502287525022875', // 32-hex code
117
- encryptionType: 2 // Optional: auto-detected from panel
118
- });
119
- ```
120
-
121
- #### Log Levels
122
-
123
- **'silent'** - No logging output at all
124
- **'minimal'** (default) - Key events only (session established, zone changes)
125
- **'verbose'** - Full protocol details including packet dumps and crypto operations
126
-
127
- ```javascript
128
- // Minimal logging (default)
129
- const client = new ITV2Client({
130
- integrationId: '...',
131
- accessCode: '...'
132
- });
133
-
134
- // Verbose logging for debugging
135
- const client = new ITV2Client({
136
- integrationId: '...',
137
- accessCode: '...',
138
- logLevel: 'verbose'
139
- });
140
-
141
- // Silent mode
142
- const client = new ITV2Client({
143
- integrationId: '...',
144
- accessCode: '...',
145
- logLevel: 'silent'
146
- });
147
- ```
81
+ | Option | Type | Default | Description |
82
+ |--------|------|---------|-------------|
83
+ | `integrationId` | string | required | 12-digit panel integration ID (section [851][422]) |
84
+ | `accessCode` | string | required | 8-digit code (section [851][423]) or 32-hex (section [851][700]) |
85
+ | `masterCode` | string | `'5555'` | User code for arm/disarm operations |
86
+ | `port` | number | `3072` | TCP port to listen on (panel connects to us) |
87
+ | `logLevel` | string | `'minimal'` | `'silent'`, `'minimal'`, or `'verbose'` |
88
+ | `encryptionType` | number | `null` | `null` = auto-detect, `1` = Type 1, `2` = Type 2 |
148
89
 
149
90
  ### Methods
150
91
 
151
- | Method | Description |
152
- |--------|-------------|
153
- | `start()` | Start UDP server and wait for panel connection |
154
- | `stop()` | Gracefully close session and shutdown |
155
- | `armStay(partition, code)` | Arm partition in STAY mode |
156
- | `armAway(partition, code)` | Arm partition in AWAY mode |
157
- | `disarm(partition, code)` | Disarm partition |
158
- | `getZones()` | Get current zone states |
159
- | `getPartitions()` | Get current partition states |
92
+ | Method | Returns | Description |
93
+ |--------|---------|-------------|
94
+ | `start()` | `Promise` | Start TCP server, wait for panel connection |
95
+ | `stop()` | `Promise` | Send END_SESSION, close connection |
96
+ | `armStay(partition, code)` | void | Arm partition in stay mode |
97
+ | `armAway(partition, code)` | void | Arm partition in away mode |
98
+ | `armNight(partition, code)` | void | Arm partition in night mode |
99
+ | `armNoEntryDelay(partition, code)` | void | Arm with no entry delay |
100
+ | `disarm(partition, code)` | void | Disarm partition |
101
+ | `queryCapabilities()` | `Promise<object>` | Query system capabilities (max zones, partitions) |
102
+ | `queryZoneStatus()` | `Promise<Array>` | Query all zone statuses |
103
+ | `queryPartitionStatus(n)` | `Promise<object>` | Query partition status |
104
+ | `queryTroubleStatus()` | `Promise<Array>` | Query system troubles |
105
+ | `getZones()` | `Array` | Get cached zone states |
106
+ | `getPartitions()` | `Array` | Get cached partition states |
160
107
 
161
108
  ### Events
162
109
 
163
- #### Session Events
110
+ #### Session
164
111
 
165
112
  | Event | Payload | Description |
166
113
  |-------|---------|-------------|
167
- | `listening` | `{ address, port }` | UDP server started |
114
+ | `listening` | `{ address, port }` | TCP server started |
168
115
  | `session:connecting` | - | Panel initiated connection |
169
- | `session:established` | `{ encryptionType, sendKey, recvKey }` | Handshake complete |
116
+ | `session:established` | `{ encryptionType, sendKey, recvKey }` | Encrypted session active |
117
+ | `session:ready` | - | Initial notification burst complete |
118
+ | `status:ready` | `{ zones, partition, capabilities }` | Initial status pull done |
170
119
  | `session:closed` | - | Session ended |
171
- | `session:error` | `Error` | Handshake failed |
172
120
 
173
- #### Zone Events
121
+ #### Zone
174
122
 
175
123
  | Event | Payload | Description |
176
124
  |-------|---------|-------------|
177
125
  | `zone:open` | `zoneNumber` | Zone opened |
178
126
  | `zone:closed` | `zoneNumber` | Zone closed |
179
- | `zone:status` | `zoneNumber, status` | Full zone status |
127
+ | `zone:status` | `zoneNumber, statusObject` | Full zone status update |
180
128
 
181
- **Status Object:**
129
+ Zone status object:
182
130
  ```javascript
183
- {
184
- open: boolean,
185
- tamper: boolean,
186
- fault: boolean,
187
- lowBattery: boolean,
188
- delinquency: boolean,
189
- alarm: boolean,
190
- alarmInMemory: boolean,
191
- bypassed: boolean,
192
- statusByte: number
193
- }
131
+ { open, tamper, fault, lowBattery, delinquency, alarm, alarmInMemory, bypassed, rawStatus }
194
132
  ```
195
133
 
196
- #### Partition Events
134
+ #### Partition
197
135
 
198
136
  | Event | Payload | Description |
199
137
  |-------|---------|-------------|
200
- | `partition:armed` | `partition, mode` | Partition armed |
201
- | `partition:disarmed` | `partition` | Partition disarmed |
138
+ | `partition:arming` | `{ partition, armMode, modeName, method }` | Arming state changed |
139
+ | `partition:ready` | `{ partition, isReady }` | Partition ready state |
140
+ | `partition:trouble` | `{ partition, troubleFlags }` | Partition trouble |
202
141
 
203
- #### Error Events
142
+ #### Trouble
204
143
 
205
144
  | Event | Payload | Description |
206
145
  |-------|---------|-------------|
207
- | `error` | `Error` | General error |
208
- | `command:error` | `{ code, message, rawData }` | Panel rejected command |
146
+ | `trouble:detail` | `Array<TroubleRecord>` | Detailed trouble notification |
209
147
 
210
- ## Panel Configuration
211
-
212
- To use this library, your DSC panel must be configured with the TL280R communicator module and proper integration settings.
213
-
214
- ### Required Panel Settings
215
-
216
- #### 1. Integration ID (Section [422])
217
-
218
- The 12-digit Integration ID identifies your integration to the panel. This must match the `integrationId` in your client configuration.
148
+ Trouble record:
149
+ ```javascript
150
+ { deviceType, deviceTypeName, deviceNumber, troubleType, troubleTypeName, troubleState, troubleStateName }
151
+ ```
219
152
 
220
- **Default:** `250228754543`
153
+ #### Error
221
154
 
222
- #### 2. Access Code (Section [423] for Type 1)
155
+ | Event | Payload | Description |
156
+ |-------|---------|-------------|
157
+ | `error` | `Error` | General error |
158
+ | `command:error` | `{ failedCommand, nackCode, message }` | Panel NACK response |
223
159
 
224
- An 8-digit numeric code used for encryption key derivation in Type 1 encryption.
160
+ ## Panel Configuration
225
161
 
226
- **Default:** `28754543`
162
+ ### TL280/TL280E Setup
227
163
 
228
- #### 3. Integration Access Code (Section [700] for Type 2)
164
+ Reference: [Johnson Controls TL280 Configuration Guide](https://docs.johnsoncontrols.com/dsc/api/khub/documents/TBs~T4HbUlFAb5fFkKsJGQ/content)
229
165
 
230
- A 32-digit hexadecimal code used for Type 2 encryption. Less common than Type 1.
166
+ #### 1. Enable Alternate Communicator
231
167
 
232
- **Example:** `25022875250228752502287525022875`
168
+ **Section 382** - Enable option 5 (Alternate Communicator). Use star key to toggle. Hash back once.
233
169
 
234
- #### 4. Integration Polling Port (Section [430])
170
+ **Section 300** - Receiver 1: set to Alternate Com Receiver 1. Hash back once.
235
171
 
236
- The UDP port where your server listens for panel connections.
172
+ **Section 380** - Ensure comms are enabled (should be on by default). Hash once.
237
173
 
238
- **Default:** `3073` (0x0C01)
174
+ **Section 310** - Enter a 4-digit system account code. Scroll right and enter the same matching code in the partition account code. Hash back once.
239
175
 
240
- ### TL280R Communicator Setup
176
+ #### 2. Configure Communicator (Section 851)
241
177
 
242
- 1. **Install TL280R module** in your DSC panel
243
- 2. **Configure network settings:**
244
- - Set TL280R IP address (static recommended)
245
- - Configure your server's IP address as the destination
246
- - Set integration polling port (default: 3073)
178
+ **Network Settings:**
179
+ - For static IP: enter sections 001, 002, 003, 007, and 008
180
+ - For DHCP: skip to section 005
247
181
 
248
- 3. **Configure integration settings:**
249
- - Enter Integration ID in section [422]
250
- - Enter Access Code in section [423] (Type 1) or [700] (Type 2)
251
- - Enable integration polling
182
+ **851 > 005** - Enable option 3 (option 6 should already be enabled). Hash once.
252
183
 
253
- 4. **Test connection:**
254
- - TL280R should initiate connection to your server
255
- - Panel will send OPEN_SESSION to start handshake
184
+ **851 > 010** - Enable video verification (good practice even if not using it).
256
185
 
257
- ### Finding Your Panel Configuration
186
+ **851 > 100** - Turn on option 2.
258
187
 
259
- If you don't know your Integration ID and Access Code:
188
+ **851 > 104** - Verify it reads 0BF5.
260
189
 
261
- - **Check panel programming:**
262
- - Enter installer code (*8 + installer code)
263
- - Navigate to integration settings
264
- - Section [422] = Integration ID
265
- - Section [423] = Access Code (Type 1)
266
- - Section [700] = Integration Access Code (Type 2)
190
+ #### 3. Integration Settings
267
191
 
268
- ### Network Requirements
192
+ **851 > 425** - Enable options 3 and 5.
269
193
 
270
- - **Firewall:** Allow UDP port 3073 inbound
271
- - **Network:** Panel and server must be on same network (or routable)
272
- - **Static IP recommended:** For the server running this library
273
- - **NAT:** If using NAT, configure port forwarding for UDP 3073
194
+ **851 > 426** - Turn on option 3 (required for real-time notifications).
274
195
 
275
- ### Encryption Type Detection
196
+ **851 > 428** - Enter your server IP address (the machine running this library).
276
197
 
277
- The library automatically detects whether your panel uses Type 1 or Type 2 encryption.
278
- You don't need to configure this - it's auto-detected during the handshake.
198
+ **851 > 422** - Read the 12-digit Integration ID (two groups of 6 digits, written in blocks of 3). Scroll 6 times right for the second group. This is your `integrationId`.
279
199
 
280
- ## Protocol Notes
200
+ **851 > 423** - Read the 8-digit Access Code. This is your `accessCode`.
281
201
 
282
- ### Push Notification Model
202
+ **851 > 101** - Enter a unique identifier.
283
203
 
284
- The DSC panel uses **push notifications**, not query/response:
204
+ #### 4. Reboot Communicator
285
205
 
286
- - Panel automatically pushes zone status changes (0x0210)
287
- - ✅ Real-time updates when zones open/close
288
- - ❌ Cannot query for current status on demand
289
- - ℹ️ Must wait for panel to send notifications
206
+ **851 > 999** - Enter 55 to reboot the communicator. Hash out 3 times. A trouble condition on the keypad is normal during reboot.
290
207
 
291
- ### Session Establishment
208
+ ### Network Requirements
292
209
 
293
- 1. Panel sends OPEN_SESSION (plaintext)
294
- 2. Encrypted handshake with REQUEST_ACCESS
295
- 3. Type 1 key exchange (asymmetric encryption keys)
296
- 4. All post-handshake communication uses AES-128-ECB encryption
210
+ - **TCP port 3072** must be reachable from the panel to your server
211
+ - Panel and server must be on the same network (or routable)
212
+ - Static IP recommended for the server
213
+ - The panel initiates the TCP connection to your server (outbound from panel)
297
214
 
298
- ### Tested On
215
+ ### Finding Your Credentials
299
216
 
300
- - DSC TL280R Communicator
301
- - DSC Neo Panel (firmware 2905)
302
- - Protocol version 6202
217
+ If the panel is already configured, enter installer programming (*8 + installer code) and read:
218
+ - **Section [851][422]** Integration ID (12 digits)
219
+ - **Section [851][423]** — Access Code (8 digits, Type 1)
220
+ - **Section [851][700]** — Integration Access Code (32 hex, Type 2)
303
221
 
304
222
  ## Configuration
305
223
 
306
- Use environment variables to configure:
224
+ Use environment variables:
307
225
 
308
226
  ```bash
309
227
  INTEGRATION_ID=250228754543 \
310
228
  ACCESS_CODE=28754543 \
311
229
  MASTER_CODE=5555 \
312
- UDP_PORT=3073 \
313
- npm run example:basic
314
- ```
315
-
316
- ## Development
317
-
318
- Run the full interactive CLI (includes all commands and debugging features):
319
-
320
- ```bash
230
+ PORT=3072 \
231
+ LOG_LEVEL=minimal \
321
232
  npm run example:cli
322
233
  ```
323
234
 
324
235
  ## Troubleshooting
325
236
 
326
- ### No zone events
237
+ ### Panel won't connect
327
238
 
328
- - Panel only sends notifications when zones **change state**
329
- - Open/close a door or window to trigger notifications
330
- - Ensure session is established first
239
+ - Verify server IP is set correctly in section [851][428]
240
+ - Ensure TCP port 3072 is open in firewall
241
+ - Check panel and server are on the same network
242
+ - Reboot communicator: section [851][999], enter 55
331
243
 
332
244
  ### Session won't establish
333
245
 
334
- - Verify `integrationId` and `accessCode` match panel configuration
335
- - Check panel is configured to connect to your server IP
336
- - Ensure UDP port 3073 is open in firewall
337
- - Enable `debug: true` for detailed protocol logs
246
+ - Verify `integrationId` matches section [851][422]
247
+ - Verify `accessCode` matches section [851][423]
248
+ - Enable `logLevel: 'verbose'` for full protocol details
249
+
250
+ ### Zone queries fail
251
+
252
+ - System capabilities must be queried first (automatic on connect)
253
+ - Zone count must match panel's actual zone count (automatic when using `queryZoneStatus()`)
254
+
255
+ ### Arm/disarm not working
256
+
257
+ - Verify `masterCode` is a valid user code on the panel
258
+ - Check partition number is correct (usually 1)
259
+ - Panel sends confirmation via `partition:arming` event
338
260
 
339
- ### Authentication/command errors
261
+ ## Tested On
340
262
 
341
- - Verify `masterCode` is correct
342
- - Panel may require specific access codes
343
- - Some commands may not be supported by all panel firmware versions
263
+ - DSC Neo Panel (HS2032/HS2064/HS2128)
264
+ - TL280/TL280E Communicator
265
+ - Type 1 encryption (most common)
344
266
 
345
267
  ## License
346
268
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "dsc-itv2-client",
3
3
  "author": "fajitacat",
4
- "version": "1.0.29",
5
- "description": "Reverse engineered DSC ITV2 Protocol Client Library for TL280R Communicator - Monitor and control DSC alarm panels",
4
+ "version": "2.0.0",
5
+ "description": "Reverse engineered DSC ITV2 Protocol Client Library for TL280/TL280E - Monitor and control DSC Neo alarm panels with real-time zone/partition status, arming, and trouble detail",
6
6
  "main": "src/index.js",
7
7
  "type": "module",
8
8
  "exports": {
@@ -31,7 +31,8 @@
31
31
  "itv2",
32
32
  "alarm",
33
33
  "security",
34
- "tl280r",
34
+ "tl280",
35
+ "tl280e",
35
36
  "event-emitter",
36
37
  "monitoring",
37
38
  "home-automation",