dsc-itv2-client 1.0.22 → 1.0.23
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/package.json +1 -1
- package/src/ITV2Client.js +93 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsc-itv2-client",
|
|
3
3
|
"author": "fajitacat",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.23",
|
|
5
5
|
"description": "Reverse engineered DSC ITV2 Protocol Client Library for TL280R Communicator - Monitor and control DSC alarm panels",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"type": "module",
|
package/src/ITV2Client.js
CHANGED
|
@@ -379,9 +379,23 @@ export class ITV2Client extends EventEmitter {
|
|
|
379
379
|
case CMD.TIME_DATE_BROADCAST:
|
|
380
380
|
this._handleTimeDateBroadcast(parsed);
|
|
381
381
|
break;
|
|
382
|
+
case CMD.ZONE_STATUS:
|
|
383
|
+
this._handleZoneStatusResponse(parsed);
|
|
384
|
+
break;
|
|
385
|
+
case CMD.PARTITION_STATUS:
|
|
386
|
+
this._handlePartitionStatusResponse(parsed);
|
|
387
|
+
break;
|
|
388
|
+
case CMD.GLOBAL_STATUS:
|
|
389
|
+
this._handleGlobalStatusResponse(parsed);
|
|
390
|
+
break;
|
|
382
391
|
default:
|
|
383
392
|
if (this.handshakeState === 'ESTABLISHED') {
|
|
384
|
-
|
|
393
|
+
const cmdHex = cmd ? '0x' + cmd.toString(16).padStart(4, '0') : 'null';
|
|
394
|
+
const cmdName = CMD_NAMES[cmd] || 'UNKNOWN';
|
|
395
|
+
this._logMinimal(`[Session] Received command ${cmdName} (${cmdHex})`);
|
|
396
|
+
if (parsed.commandData && parsed.commandData.length > 0) {
|
|
397
|
+
this._logMinimal(`[Session] Data (${parsed.commandData.length} bytes): ${parsed.commandData.toString('hex')}`);
|
|
398
|
+
}
|
|
385
399
|
this._sendPacket(this.session.buildSimpleAck());
|
|
386
400
|
}
|
|
387
401
|
break;
|
|
@@ -569,10 +583,17 @@ export class ITV2Client extends EventEmitter {
|
|
|
569
583
|
}
|
|
570
584
|
|
|
571
585
|
_handleCommandResponse(parsed) {
|
|
572
|
-
const
|
|
586
|
+
const data = parsed.commandData;
|
|
587
|
+
const responseCode = data?.[0] || 0;
|
|
573
588
|
const appSeqAsEcho = parsed.appSequence;
|
|
574
589
|
|
|
575
|
-
this._log(`[
|
|
590
|
+
this._log(`[Session] Got COMMAND_RESPONSE (app_seq: ${appSeqAsEcho}, response_code: ${responseCode})`);
|
|
591
|
+
|
|
592
|
+
// Log full data in established state for debugging query responses
|
|
593
|
+
if (this.handshakeState === 'ESTABLISHED' && data && data.length > 1) {
|
|
594
|
+
this._logMinimal(`[Command Response] Response code: ${responseCode}, data (${data.length} bytes): ${data.toString('hex')}`);
|
|
595
|
+
this.emit('command:response', { responseCode, appSequence: appSeqAsEcho, data });
|
|
596
|
+
}
|
|
576
597
|
|
|
577
598
|
const ack = this.session.buildSimpleAck();
|
|
578
599
|
this._sendPacket(ack);
|
|
@@ -655,6 +676,75 @@ export class ITV2Client extends EventEmitter {
|
|
|
655
676
|
this._sendPacket(this.session.buildSimpleAck());
|
|
656
677
|
}
|
|
657
678
|
|
|
679
|
+
// ==================== Status Query Response Handlers ====================
|
|
680
|
+
|
|
681
|
+
_handleZoneStatusResponse(parsed) {
|
|
682
|
+
const data = parsed.commandData;
|
|
683
|
+
this._logMinimal(`[Zone Status] Received zone status response`);
|
|
684
|
+
this._log(`[Zone Status] Raw data (${data?.length || 0} bytes): ${data?.toString('hex') || 'none'}`);
|
|
685
|
+
|
|
686
|
+
if (data && data.length >= 3) {
|
|
687
|
+
// Response format: [ZoneNumber 2B BE][StatusByte 1B][...more zones...]
|
|
688
|
+
const zoneNum = data.readUInt16BE(0);
|
|
689
|
+
const statusByte = data[2];
|
|
690
|
+
|
|
691
|
+
// Update internal state
|
|
692
|
+
const fullStatus = this.eventHandler.handleZoneStatus(zoneNum, statusByte);
|
|
693
|
+
|
|
694
|
+
this._logMinimal(`[Zone Status] Zone ${zoneNum}: ${fullStatus.open ? 'OPEN' : 'CLOSED'} (0x${statusByte.toString(16)})`);
|
|
695
|
+
|
|
696
|
+
// Emit event with full status
|
|
697
|
+
this.emit('zone:statusResponse', zoneNum, fullStatus);
|
|
698
|
+
this.emit('zone:status', zoneNum, fullStatus);
|
|
699
|
+
} else {
|
|
700
|
+
this._log(`[Zone Status] Empty or invalid response`);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
this._sendPacket(this.session.buildSimpleAck());
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
_handlePartitionStatusResponse(parsed) {
|
|
707
|
+
const data = parsed.commandData;
|
|
708
|
+
this._logMinimal(`[Partition Status] Received partition status response`);
|
|
709
|
+
this._log(`[Partition Status] Raw data (${data?.length || 0} bytes): ${data?.toString('hex') || 'none'}`);
|
|
710
|
+
|
|
711
|
+
if (data && data.length >= 3) {
|
|
712
|
+
// Response format: [PartitionNumber 2B BE][StatusBytes...]
|
|
713
|
+
const partitionNum = data.readUInt16BE(0);
|
|
714
|
+
const statusBytes = data.slice(2);
|
|
715
|
+
|
|
716
|
+
this._logMinimal(`[Partition Status] Partition ${partitionNum}: status bytes ${statusBytes.toString('hex')}`);
|
|
717
|
+
|
|
718
|
+
// Emit raw event - let consumers parse the detailed status
|
|
719
|
+
this.emit('partition:statusResponse', partitionNum, statusBytes);
|
|
720
|
+
} else {
|
|
721
|
+
this._log(`[Partition Status] Empty or invalid response`);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
this._sendPacket(this.session.buildSimpleAck());
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
_handleGlobalStatusResponse(parsed) {
|
|
728
|
+
const data = parsed.commandData;
|
|
729
|
+
this._logMinimal(`[Global Status] Received global status response`);
|
|
730
|
+
this._log(`[Global Status] Raw data (${data?.length || 0} bytes): ${data?.toString('hex') || 'none'}`);
|
|
731
|
+
|
|
732
|
+
if (data && data.length > 0) {
|
|
733
|
+
// Emit raw event with full data
|
|
734
|
+
this.emit('global:statusResponse', data);
|
|
735
|
+
|
|
736
|
+
// Log byte breakdown for debugging
|
|
737
|
+
this._log(`[Global Status] Byte breakdown:`);
|
|
738
|
+
for (let i = 0; i < data.length && i < 32; i++) {
|
|
739
|
+
this._log(` Byte ${i}: 0x${data[i].toString(16).padStart(2, '0')} (${data[i]})`);
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
this._log(`[Global Status] Empty response`);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
this._sendPacket(this.session.buildSimpleAck());
|
|
746
|
+
}
|
|
747
|
+
|
|
658
748
|
// ==================== Utility Methods ====================
|
|
659
749
|
|
|
660
750
|
_handleError(error) {
|