npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsc-itv2-client

v2.0.10

Published

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

Readme

DSC ITV2 Client Library

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.

Not affiliated with DSC, Johnson Controls, or Tyco in any way. Use at your own risk.

Features

  • Real-Time Zone Monitoring - Open/close, tamper, alarm, bypass events via push notifications
  • Partition Control - Arm stay/away/night, disarm with real-time confirmation
  • Async Status Querying - Query zone status, partition status, system capabilities on demand
  • Trouble Detail Parsing - Human-readable trouble notifications from official SDK enums
  • Encrypted Communication - AES-128-ECB with automatic Type 1/Type 2 key exchange
  • Event-Driven Architecture - Subscribe to events with EventEmitter
  • Automatic Session Setup - Capabilities query, initial status pull, heartbeat keepalive

Quick Start

Installation

npm install dsc-itv2-client

Basic Usage

import { ITV2Client } from 'dsc-itv2-client';

const client = new ITV2Client({
  integrationId: '250228754543',  // Section [851][422]
  accessCode: '28754543',         // Section [851][423]
  masterCode: '5555',             // User code for arm/disarm
  port: 3072,                     // TCP port (panel connects to us)
});

client.on('session:established', () => console.log('Connected!'));
client.on('zone:open', (zone) => console.log(`Zone ${zone} opened`));
client.on('zone:closed', (zone) => console.log(`Zone ${zone} closed`));
client.on('partition:arming', ({ partition, modeName }) => {
  console.log(`Partition ${partition}: ${modeName}`);
});

// Status is automatically queried on connect
client.on('status:ready', async ({ zones, partition }) => {
  console.log(`${zones.length} zones loaded`);

  // Query on demand anytime
  const current = await client.queryZoneStatus();
  const part = await client.queryPartitionStatus(1);
});

await client.start();

Arm/Disarm

client.armStay(1, '5555');   // Arm partition 1 in stay mode
client.armAway(1, '5555');   // Arm partition 1 in away mode
client.armNight(1, '5555');  // Arm partition 1 in night mode
client.disarm(1, '5555');    // Disarm partition 1

Examples

npm run example:basic      # Zone monitoring
npm run example:control    # Arm/disarm demo
npm run example:cli        # Interactive CLI with querying

API Reference

Constructor

const client = new ITV2Client(options);

| Option | Type | Default | Description | |--------|------|---------|-------------| | integrationId | string | required | 12-digit panel integration ID (section [851][422]) | | accessCode | string | required | 8-digit code (section [851][423]) or 32-hex (section [851][700]) | | masterCode | string | '5555' | User code for arm/disarm operations | | port | number | 3072 | TCP port to listen on (panel connects to us) | | logLevel | string | 'minimal' | 'silent', 'minimal', or 'verbose' | | encryptionType | number | null | null = auto-detect, 1 = Type 1, 2 = Type 2 |

Methods

| Method | Returns | Description | |--------|---------|-------------| | start() | Promise | Start TCP server, wait for panel connection | | stop() | Promise | Send END_SESSION, close connection | | armStay(partition, code) | void | Arm partition in stay mode | | armAway(partition, code) | void | Arm partition in away mode | | armNight(partition, code) | void | Arm partition in night mode | | armNoEntryDelay(partition, code) | void | Arm with no entry delay | | disarm(partition, code) | void | Disarm partition | | queryCapabilities() | Promise<object> | Query system capabilities (max zones, partitions) | | queryZoneStatus() | Promise<Array> | Query all zone statuses | | queryPartitionStatus(n) | Promise<object> | Query partition status | | queryTroubleStatus() | Promise<Array> | Query system troubles | | getZones() | Array | Get cached zone states | | getPartitions() | Array | Get cached partition states |

Events

Session

| Event | Payload | Description | |-------|---------|-------------| | listening | { address, port } | TCP server started | | session:connecting | - | Panel initiated connection | | session:established | { encryptionType, sendKey, recvKey } | Encrypted session active | | session:ready | - | Initial notification burst complete | | status:ready | { zones, partition, capabilities } | Initial status pull done | | session:closed | - | Session ended |

Zone

| Event | Payload | Description | |-------|---------|-------------| | zone:open | zoneNumber | Zone opened | | zone:closed | zoneNumber | Zone closed | | zone:status | zoneNumber, statusObject | Full zone status update |

Zone status object:

{ open, tamper, fault, lowBattery, delinquency, alarm, alarmInMemory, bypassed, rawStatus }

Partition

| Event | Payload | Description | |-------|---------|-------------| | partition:arming | { partition, armMode, modeName, method } | Arming state changed | | partition:ready | { partition, isReady } | Partition ready state | | partition:trouble | { partition, troubleFlags } | Partition trouble |

Trouble

| Event | Payload | Description | |-------|---------|-------------| | trouble:detail | Array<TroubleRecord> | Detailed trouble notification |

Trouble record:

{ deviceType, deviceTypeName, deviceNumber, troubleType, troubleTypeName, troubleState, troubleStateName }

Error

| Event | Payload | Description | |-------|---------|-------------| | error | Error | General error | | command:error | { failedCommand, nackCode, message } | Panel NACK response |

Panel Configuration

TL280/TL280E Setup

Reference: Johnson Controls TL280 Configuration Guide

1. Enable Alternate Communicator

Section 382 - Enable option 5 (Alternate Communicator). Use star key to toggle. Hash back once.

Section 300 - Receiver 1: set to Alternate Com Receiver 1. Hash back once.

Section 380 - Ensure comms are enabled (should be on by default). Hash once.

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.

2. Configure Communicator (Section 851)

Network Settings:

  • For static IP: enter sections 001, 002, 003, 007, and 008
  • For DHCP: skip to section 005

851 > 005 - Enable option 3 (option 6 should already be enabled). Hash once.

851 > 010 - Enable video verification (good practice even if not using it).

851 > 100 - Turn on option 2.

851 > 104 - Verify it reads 0BF5.

3. Integration Settings

851 > 425 - Enable options 3 and 5.

851 > 426 - Turn on option 3 (required for real-time notifications).

851 > 428 - Enter your server IP address (the machine running this library).

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.

851 > 423 - Read the 8-digit Access Code. This is your accessCode.

851 > 101 - Enter a unique identifier.

4. Reboot Communicator

851 > 999 - Enter 55 to reboot the communicator. Hash out 3 times. A trouble condition on the keypad is normal during reboot.

Network Requirements

  • TCP port 3072 must be reachable from the panel to your server
  • Panel and server must be on the same network (or routable)
  • Static IP recommended for the server
  • The panel initiates the TCP connection to your server (outbound from panel)

Finding Your Credentials

If the panel is already configured, enter installer programming (*8 + installer code) and read:

  • Section [851][422] — Integration ID (12 digits)
  • Section [851][423] — Access Code (8 digits, Type 1)
  • Section [851][700] — Integration Access Code (32 hex, Type 2)

Configuration

Use environment variables:

INTEGRATION_ID=250228754543 \
ACCESS_CODE=28754543 \
MASTER_CODE=5555 \
PORT=3072 \
LOG_LEVEL=minimal \
npm run example:cli

Troubleshooting

Panel won't connect

  • Verify server IP is set correctly in section [851][428]
  • Ensure TCP port 3072 is open in firewall
  • Check panel and server are on the same network
  • Reboot communicator: section [851][999], enter 55

Session won't establish

  • Verify integrationId matches section [851][422]
  • Verify accessCode matches section [851][423]
  • Enable logLevel: 'verbose' for full protocol details

Zone queries fail

  • System capabilities must be queried first (automatic on connect)
  • Zone count must match panel's actual zone count (automatic when using queryZoneStatus())

Arm/disarm not working

  • Verify masterCode is a valid user code on the panel
  • Check partition number is correct (usually 1)
  • Panel sends confirmation via partition:arming event

Tested On

  • DSC Neo Panel (HS2032/HS2064/HS2128)
  • TL280/TL280E Communicator
  • Type 1 encryption (most common)

License

MIT