GitHub Viewer
/*
DSC Keybus Interface
Functions used by the KeybusReader sketch to decode and print Keybus data, with
documentation of each message - including portions that are currently undecoded
and unknown. Contributions to improve decoding are always welcome!
https://github.com/taligentx/dscKeybusInterface
panelData[] and moduleData[] store panel and keypad/module data in an array: command [0], stop bit by itself [1],
followed by the remaining data.
panelData[] example:
Byte 0 Byte 2 Byte 3 Byte 4 Byte 5
00000101 0 10000001 00000001 10010001 11000111 [0x05] Partition 1: Ready Backlight - Partition ready | Partition 2: disabled
^Byte 1 (stop bit) ^Bit 7 ^Bit 0
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "dscKeybus.h"
/*
* printPanelMessage() checks the first byte of a message from the
* panel (panelData[0]) to process known commands.
*
* Structure decoding status refers to whether all bits of the message have
* a known purpose.
*
* Content decoding status refers to whether all values of the message are known.
*/
void dscKeybusInterface::printPanelMessage() {
// Checks for errors on panel commands with CRC data
switch (panelData[0]) {
case 0x05: // Skips panel commands without CRC data
case 0x11:
case 0x1B:
case 0x1C:
case 0x22:
case 0x28:
case 0x33:
case 0x39:
case 0x41:
case 0x4C:
case 0x57:
case 0x58:
case 0x70:
case 0x94:
case 0x9E:
case 0xD5:
case 0xE6: break; // 0xE6 is checked separately as only some of its subcommands use CRC
default: { // Checks remaining panel commands
if (!validCRC()) {
stream->print(F("[CRC Error]"));
return;
}
}
}
// Processes known panel commands from the first byte of the panel message: panelData[0]
switch (panelData[0]) {
case 0x05: printPanel_0x05(); return; // Panel status: partitions 1-4 | Structure: complete | Content: *incomplete
case 0x0A:
case 0x0F: printPanel_0x0A_0F(); return; // Panel status in alarm/programming, partitions 1-2 | Structure: complete | Content: *incomplete
case 0x11: printPanel_0x11(); return; // Module supervision query | Structure: complete | Content: complete
case 0x16: printPanel_0x16(); return; // Panel configuration | Structure: *incomplete | Content: *incomplete
case 0x1B: printPanel_0x1B(); return; // Panel status: partitions 5-8 | Structure: complete | Content: *incomplete
case 0x1C: printPanel_0x1C(); return; // Verify keypad Fire/Auxiliary/Panic | Structure: complete | Content: complete
case 0x22:
case 0x28:
case 0x33:
case 0x39: printPanel_0x22_28_33_39(); return; // Zone expanders 0-3 query | Structure: complete | Content: complete
case 0x27: printPanel_0x27(); return; // Panel status and zones 1-8 status | Structure: complete | Content: *incomplete
case 0x2D: printPanel_0x2D(); return; // Panel status and zones 9-16 status | Structure: complete | Content: *incomplete
case 0x34: printPanel_0x34(); return; // Panel status and zones 17-24 status | Structure: complete | Content: *incomplete
case 0x3E: printPanel_0x3E(); return; // Panel status and zones 25-32 status | Structure: complete | Content: *incomplete
case 0x41: printPanel_0x41(); return; // Wireless module query | Structure: complete | Content: complete
case 0x4C: printPanel_0x4C(); return; // Module tamper query | Structure: complete | Content: *incomplete
case 0x57: printPanel_0x57(); return; // Wireless key query | Structure: complete | Content: *incomplete
case 0x58: printPanel_0x58(); return; // Module status query | Structure: complete | Content: *incomplete
case 0x5D:
case 0x63: printPanel_0x5D_63(); return; // Flash panel lights: status and zones 1-32, partitions 1-2 | Structure: complete | Content: complete
case 0x64: printPanel_0x64(); return; // Beep, partition 1 | Structure: complete | Content: complete
case 0x69: printPanel_0x69(); return; // Beep, partition 2 | Structure: complete | Content: complete
case 0x6E: printPanel_0x6E(); return; // LCD keypad display | Structure: complete | Content: complete
case 0x70: printPanel_0x70(); return; // LCD keypad data query | Structure: complete | Content: complete
case 0x75: printPanel_0x75(); return; // Tone, partition 1 | Structure: complete | Content: complete
case 0x7A: printPanel_0x7A(); return; // Tone, partition 2 | Structure: complete | Content: complete
case 0x7F: printPanel_0x7F(); return; // Buzzer, partition 1 | Structure: complete | Content: complete
case 0x82: printPanel_0x82(); return; // Buzzer, partition 2 | Structure: complete | Content: complete
case 0x87: printPanel_0x87(); return; // PGM outputs | Structure: complete | Content: complete
case 0x8D: printPanel_0x8D(); return; // RF module programming - it sends data from panel to RF module after programming entry is done | Structure: *incomplete | Content: *incomplete
case 0x94: printPanel_0x94(); return; // Requesting and getting data from RF module to the panel | Structure: *incomplete | Content: *incomplete
case 0x9E: printPanel_0x9E(); return; // DLS query | Structure: complete | Content: complete
case 0xA5: printPanel_0xA5(); return; // Date, time, system status messages - partitions 1-2 | Structure: *incomplete | Content: *incomplete
case 0xAA: printPanel_0xAA(); return; // Event buffer messages | Structure: complete | Content: *incomplete
case 0xB1: printPanel_0xB1(); return; // Enabled zones 1-32 | Structure: complete | Content: complete
case 0xBB: printPanel_0xBB(); return; // Bell | Structure: *incomplete | Content: *incomplete
case 0xC3: printPanel_0xC3(); return; // Keypad and dialer status | Structure: *incomplete | Content: *incomplete
case 0xCE: printPanel_0xCE(); return; // Panel status | Structure: *incomplete | Content: *incomplete
case 0xD5: printPanel_0xD5(); return; // Keypad zone query | Structure: complete | Content: complete
case 0xE6: printPanel_0xE6(); return; // Extended status command split into multiple subcommands to handle up to 8 partitions/64 zones | Structure: *incomplete | Content: *incomplete
case 0xEB: printPanel_0xEB(); return; // Date, time, system status messages - partitions 1-8 | Structure: *incomplete | Content: *incomplete
case 0xEC: printPanel_0xEC(); return; // Event buffer messages | Structure: *incomplete | Content: *incomplete
default: {
stream->print("Unknown data");
return;
}
}
}
// Processes keypad and module notifications and responses to panel queries
void dscKeybusInterface::printModuleMessage() {
switch (moduleData[0]) {
case 0xBB: printModule_0xBB(); return; // Keypad fire alarm | Structure: complete | Content: complete
case 0xDD: printModule_0xDD(); return; // Keypad auxiliary alarm | Structure: complete | Content: complete
case 0xEE: printModule_0xEE(); return; // Keypad panic alarm | Structure: complete | Content: complete
}
stream->print(F("[Module/0x"));
if (moduleCmd < 16) stream->print("0");
stream->print(moduleCmd, HEX);
if (moduleCmd == 0xE6) {
stream->print(".");
if (moduleSubCmd < 16) stream->print("0");
stream->print(moduleSubCmd, HEX);
}
stream->print(F("] "));
// Keypad and module responses to panel queries
switch (moduleCmd) {
case 0x05:
case 0x0A:
case 0x0F:
case 0x1B:
case 0x27:
case 0x2D:
case 0x3E: printModule_Status(); return; // Module notifications sent during panel status commands | Structure: *incomplete | Content: *incomplete
case 0x11: printModule_0x11(); return; // Module supervision query response | Structure: *incomplete | Content: *incomplete
case 0x41: printModule_0x41(); return; // Wireless module query response | Structure: *incomplete | Content: *incomplete
case 0x4C: printModule_0x4C(); return; // Module tamper query response | Structure: *incomplete | Content: *incomplete
case 0x57: printModule_0x57(); return; // Wireless key query response | Structure: *incomplete | Content: *incomplete
case 0x58: printModule_0x58(); return; // Module status query response | Structure: *incomplete | Content: *incomplete
case 0x70: printModule_0x70(); return; // LCD keypad data entry | Structure: complete | Content: complete
case 0x94: printModule_0x94(); return; // Module programming response | Structure: *incomplete | Content: *incomplete
case 0xD5: printModule_0xD5(); return; // Keypad zone query response | Structure: *incomplete | Content: *incomplete
case 0x22:
case 0x28:
case 0x33:
case 0x39: printModule_Expander(); return; // Zone expanders 1-3 response
case 0xE6: {
switch (moduleSubCmd) {
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x20:
case 0x21: printModule_Status(); return; // Module notifications sent during installer programming
case 0x08:
case 0x0A:
case 0x0C:
case 0x0E: printModule_Expander(); return; // Zone expanders 4-7 response
}
}
default: stream->print("Unknown data");
}
}
/*
* Keypad status lights for panel commands: 0x05, 0x0A, 0x1B, 0x27, 0x2D, 0x34, 0x3E, 0x5D
* Structure decoding: complete
* Content decoding: complete
*
* This decodes the following byte as a status message by default.
*/
void dscKeybusInterface::printPanelLights(byte panelByte, bool printMessage) {
if (panelData[panelByte] == 0) stream->print(F("none "));
else {
if (bitRead(panelData[panelByte], 0)) stream->print(F("Ready "));
if (bitRead(panelData[panelByte], 1)) stream->print(F("Armed "));
if (bitRead(panelData[panelByte], 2)) stream->print(F("Memory "));
if (bitRead(panelData[panelByte], 3)) stream->print(F("Bypass "));
if (bitRead(panelData[panelByte], 4)) stream->print(F("Trouble "));
if (bitRead(panelData[panelByte], 5)) stream->print(F("Program "));
if (bitRead(panelData[panelByte], 6)) stream->print(F("Fire "));
if (bitRead(panelData[panelByte], 7)) stream->print(F("Backlight "));
}
if (printMessage) {
stream->print(F("- "));
printPanelMessages(panelByte + 1);
}
}
/*
* Status messages for panel commands: 0x05, 0x0A, 0x1B, 0x27, 0x2D, 0x34, 0x3E
* Structure decoding: complete
* Content decoding: *incomplete
*/
void dscKeybusInterface::printPanelMessages(byte panelByte) {
switch (panelData[panelByte]) {
case 0x01: stream->print(F("Partition ready")); break;
case 0x02: stream->print(F("Stay zones open")); break;
case 0x03: stream->print(F("Zones open")); break;
case 0x04: stream->print(F("Armed: Stay")); break;
case 0x05: stream->print(F("Armed: Away")); break;
case 0x06: stream->print(F("Armed: Stay with no entry delay")); break;
case 0x07: stream->print(F("Failed to arm")); break;
case 0x08: stream->print(F("Exit delay in progress")); break;
case 0x09: stream->print(F("Arming: No entry delay")); break;
case 0x0B: stream->print(F("Quick exit in progress")); break;
case 0x0C: stream->print(F("Entry delay in progress")); break;
case 0x0D: stream->print(F("Entry delay after alarm")); break;
case 0x0E: stream->print(F("Function not available")); break;
case 0x10: stream->print(F("Keypad lockout")); break;
case 0x11: stream->print(F("Partition in alarm")); break;
case 0x12: stream->print(F("Battery check in progress")); break;
case 0x14: stream->print(F("Auto-arm in progress")); break;
case 0x15: stream->print(F("Arming with bypassed zones")); break;
case 0x16: stream->print(F("Armed: Away with no entry delay")); break;
case 0x19: stream->print(F("Disarmed: Alarm memory")); break;
case 0x22: stream->print(F("Disarmed: Recent closing")); break;
case 0x2F: stream->print(F("Keypad LCD test")); break;
case 0x33: stream->print(F("Command output in progress")); break;
case 0x3D: stream->print(F("Disarmed: Alarm memory")); break;
case 0x3E: stream->print(F("Partition disarmed")); break;
case 0x17: // Keypad blanking with trouble light flashing
case 0x40: stream->print(F("Keypad blanking")); break;
case 0x8A: stream->print(F("Activate stay/away zones")); break;
case 0x8B: stream->print(F("Quick exit")); break;
case 0x8E: stream->print(F("Function not available")); break;
case 0x8F: stream->print(F("Invalid access code")); break;
case 0x9E: stream->print(F("Enter * function key")); break;
case 0x9F: stream->print(F("Enter access code")); break;
case 0xA0: stream->print(F("*1: Zone bypass")); break;
case 0xA1: stream->print(F("*2: Trouble")); break;
case 0xA2: stream->print(F("*3: Alarm memory")); break;
case 0xA3: stream->print(F("Door chime enabled")); break;
case 0xA4: stream->print(F("Door chime disabled")); break;
case 0xA5: stream->print(F("Enter master code")); break;
case 0xA6: stream->print(F("*5: Access codes")); break;
case 0xA7: stream->print(F("*5: Enter 4-digit code")); break;
case 0xA9: stream->print(F("*6: User functions")); break;
case 0xAA: stream->print(F("*6: Time and date")); break;
case 0xAB: stream->print(F("*6: Auto-arm time")); break;
case 0xAC: stream->print(F("*6: Auto-arm enabled")); break;
case 0xAD: stream->print(F("*6: Auto-arm disabled")); break;
case 0xAF: stream->print(F("*6: System test")); break;
case 0xB0: stream->print(F("*6: Enable DLS")); break;
case 0xB2:
case 0xB3: stream->print(F("*7: Command output")); break;
case 0xB7: stream->print(F("Enter installer code")); break;
case 0xB8: stream->print(F("Enter * function key while armed")); break;
case 0xB9: stream->print(F("*2: Zone tamper menu")); break;
case 0xBA: stream->print(F("*2: Zones with low batteries")); break;
case 0xBC: stream->print(F("*5: Enter 6-digit code")); break;
case 0xBF: stream->print(F("*6: Auto-arm select day")); break;
case 0xC6: stream->print(F("*2: Zone fault menu")); break;
//case 0xC7: stream->print(F("Partition not available")); break;
case 0xC8: stream->print(F("*2: Service required menu")); break;
case 0xCD: stream->print(F("Downloading in progress")); break;
case 0xCE: stream->print(F("Active camera monitor selection")); break;
case 0xD0: stream->print(F("*2: Keypads with low batteries")); break;
case 0xD1: stream->print(F("*2: Keyfobs with low batteries")); break;
case 0xD4: stream->print(F("*2: Zones with RF Delinquency")); break;
case 0xE4: stream->print(F("*8: Installer programming, 3 digits")); decimalInput = false; break;
case 0xE5: stream->print(F("Keypad slot assignment")); break;
case 0xE6: stream->print(F("Input: 2 digits")); break;
case 0xE7: stream->print(F("Input: 3 digits")); decimalInput = true; break;
case 0xE8: stream->print(F("Input: 4 digits")); break;
case 0xE9: stream->print(F("Input: 5 digits")); break;
case 0xEA: stream->print(F("Input HEX: 2 digits")); break;
case 0xEB: stream->print(F("Input HEX: 4 digits")); break;
case 0xEC: stream->print(F("Input HEX: 6 digits")); break;
case 0xED: stream->print(F("Input HEX: 32 digits")); break;
case 0xEE: stream->print(F("Input: 1 option per zone")); break;
case 0xEF: stream->print(F("Module supervision field")); break;
case 0xF0: stream->print(F("Function key 1")); break;
case 0xF1: stream->print(F("Function key 2")); break;
case 0xF2: stream->print(F("Function key 3")); break;
case 0xF3: stream->print(F("Function key 4")); break;
case 0xF4: stream->print(F("Function key 5")); break;
case 0xF5: stream->print(F("Wireless module placement test")); break;
case 0xF6: stream->print(F("Activate device for test")); break;
case 0xF7: stream->print(F("*8: Installer programming, 2 digits")); decimalInput = false; break;
case 0xF8: stream->print(F("Keypad programming")); break;
case 0xFA: stream->print(F("Input: 6 digits")); break;
default:
stream->print(F("Unknown data: 0x"));
if (panelData[panelByte] < 10) stream->print("0");
stream->print(panelData[panelByte], HEX);
break;
}
}
/*
* Status messages set 0x00 for panel commands: 0xA5, 0xAA, 0xCE, 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use bits 0,1 of the preceding byte to
* select from multiple sets of status messages, split into printPanelStatus0...printPanelStatus2.
*/
void dscKeybusInterface::printPanelStatus0(byte panelByte) {
bool decoded = true;
switch (panelData[panelByte]) {
/*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 10110000 11101100 01001001 11111111 11110000 [0xA5] 2018.03.29 16:59 | Partition 1 | Duress alarm
* 10100101 0 00011000 01001111 11001110 10111100 01001010 11111111 11011111 [0xA5] 2018.03.30 14:47 | Partition 1 | Disarmed after alarm in memory
* 10100101 0 00011000 01001111 11001010 01000100 01001011 11111111 01100100 [0xA5] 2018.03.30 10:17 | Partition 1 | Partition in alarm
* 10100101 0 00011000 01010000 01001001 10111000 01001100 11111111 01011001 [0xA5] 2018.04.02 09:46 | Partition 1 | Zone expander supervisory alarm
* 10100101 0 00011000 01010000 01001010 00000000 01001101 11111111 10100011 [0xA5] 2018.04.02 10:00 | Partition 1 | Zone expander supervisory restored
* 10100101 0 00011000 01001111 01110010 10011100 01001110 11111111 01100111 [0xA5] 2018.03.27 18:39 | Partition 1 | Keypad Fire alarm
* 10100101 0 00011000 01001111 01110010 10010000 01001111 11111111 01011100 [0xA5] 2018.03.27 18:36 | Partition 1 | Keypad Aux alarm
* 10100101 0 00011000 01001111 01110010 10001000 01010000 11111111 01010101 [0xA5] 2018.03.27 18:34 | Partition 1 | Keypad Panic alarm
* 10100101 0 00010110 00010111 11101101 00010000 01010000 10010001 10110000 [0xA5] 2016.05.31 13:04 | Keypad Panic alarm
* 10100101 0 00010001 01101101 01100000 00000100 01010001 11111111 11010111 [0xA5] 2011.11.11 00:01 | Partition 1 | Auxiliary input alarm
* 10100101 0 00011000 01001111 01110010 10011100 01010010 11111111 01101011 [0xA5] 2018.03.27 18:39 | Partition 1 | Keypad Fire alarm restored
* 10100101 0 00011000 01001111 01110010 10010000 01010011 11111111 01100000 [0xA5] 2018.03.27 18:36 | Partition 1 | Keypad Aux alarm restored
* 10100101 0 00011000 01001111 01110010 10001000 01010100 11111111 01011001 [0xA5] 2018.03.27 18:34 | Partition 1 | Keypad Panic alarm restored
* 10100101 0 00011000 01001111 11110110 00110100 10011000 11111111 11001101 [0xA5] 2018.03.31 22:13 | Partition 1 | Keypad lockout
* 10100101 0 00011000 01001111 11101011 10100100 10111110 11111111 01011000 [0xA5] 2018.03.31 11:41 | Partition 1 | Armed partial: Zones bypassed
* 10100101 0 00011000 01001111 11101011 00011000 10111111 11111111 11001101 [0xA5] 2018.03.31 11:06 | Partition 1 | Armed special: quick-arm/auto-arm/keyswitch/wireless key/DLS
* 10100101 0 00010001 01101101 01100000 00101000 11100101 11111111 10001111 [0xA5] 2011.11.11 00:10 | Partition 1 | Auto-arm cancelled
* 10100101 0 00011000 01001111 11110111 01000000 11100110 11111111 00101000 [0xA5] 2018.03.31 23:16 | Partition 1 | Disarmed special: keyswitch/wireless key/DLS
* 10100101 0 00011000 01001111 01101111 01011100 11100111 11111111 10111101 [0xA5] 2018.03.27 15:23 | Partition 1 | Panel battery trouble
* 10100101 0 00011000 01001111 10110011 10011000 11101000 11111111 00111110 [0xA5] 2018.03.29 19:38 | Partition 1 | Panel AC power trouble
* 10100101 0 00011000 01001111 01110100 01010000 11101001 11111111 10111000 [0xA5] 2018.03.27 20:20 | Partition 1 | Bell trouble
* 10100101 0 00011000 01001111 11000000 10001000 11101100 11111111 00111111 [0xA5] 2018.03.30 00:34 | Partition 1 | Telephone line trouble
* 10100101 0 00011000 01001111 01101111 01110000 11101111 11111111 11011001 [0xA5] 2018.03.27 15:28 | Partition 1 | Panel battery restored
* 10100101 0 00011000 01010000 00100000 01011000 11110000 11111111 01110100 [0xA5] 2018.04.01 00:22 | Partition 1 | Panel AC power restored
* 10100101 0 00011000 01001111 01110100 01011000 11110001 11111111 11001000 [0xA5] 2018.03.27 20:22 | Partition 1 | Bell restored
* 10100101 0 00011000 01001111 11000000 10001000 11110100 11111111 01000111 [0xA5] 2018.03.30 00:34 | Partition 1 | Telephone line restored
* 10100101 0 00011000 01001111 11100001 01011000 11111111 11111111 01000011 [0xA5] 2018.03.31 01:22 | Partition 1 | System test
* Byte 0 1 2 3 4 5 6 7 8
*/
// 0x09 - 0x28: Zone alarm, zones 1-32
// 0x29 - 0x48: Zone alarm restored, zones 1-32
case 0x49: stream->print(F("Duress alarm")); break;
case 0x4A: stream->print(F("Disarmed: Alarm memory")); break;
case 0x4B: stream->print(F("Recent closing alarm")); break;
case 0x4C: stream->print(F("Zone expander supervisory alarm")); break;
case 0x4D: stream->print(F("Zone expander supervisory restored")); break;
case 0x4E: stream->print(F("Keypad Fire alarm")); break;
case 0x4F: stream->print(F("Keypad Aux alarm")); break;
case 0x50: stream->print(F("Keypad Panic alarm")); break;
case 0x51: stream->print(F("PGM2 input alarm")); break;
case 0x52: stream->print(F("Keypad Fire alarm restored")); break;
case 0x53: stream->print(F("Keypad Aux alarm restored")); break;
case 0x54: stream->print(F("Keypad Panic alarm restored")); break;
case 0x55: stream->print(F("PGM2 input alarm restored")); break;
// 0x56 - 0x75: Zone tamper, zones 1-32
// 0x76 - 0x95: Zone tamper restored, zones 1-32
case 0x98: stream->print(F("Keypad lockout")); break;
// 0x99 - 0xBD: Armed: Access codes 1-34, 40-42
case 0xBE: stream->print(F("Armed: Partial")); break;
case 0xBF: stream->print(F("Armed: Special")); break;
// 0xC0 - 0xE4: Disarmed: Access codes 1-34, 40-42
case 0xE5: stream->print(F("Auto-arm cancelled")); break;
case 0xE6: stream->print(F("Disarmed: Special")); break;
case 0xE7: stream->print(F("Panel battery trouble")); break;
case 0xE8: stream->print(F("Panel AC power trouble")); break;
case 0xE9: stream->print(F("Bell trouble")); break;
case 0xEA: stream->print(F("Fire zone trouble")); break;
case 0xEB: stream->print(F("Panel aux supply trouble")); break;
case 0xEC: stream->print(F("Telephone line trouble")); break;
case 0xEF: stream->print(F("Panel battery restored")); break;
case 0xF0: stream->print(F("Panel AC power restored")); break;
case 0xF1: stream->print(F("Bell restored")); break;
case 0xF2: stream->print(F("Fire zone trouble restored")); break;
case 0xF3: stream->print(F("Panel aux supply restored")); break;
case 0xF4: stream->print(F("Telephone line restored")); break;
case 0xF7: stream->print(F("Phone 1 FTC")); break;
case 0xF8: stream->print(F("Phone 2 FTC")); break;
case 0xF9: stream->print(F("Event buffer threshold")); break; //75% full since last DLS upload
case 0xFA: stream->print(F("DLS lead-in")); break;
case 0xFB: stream->print(F("DLS lead-out")); break;
case 0xFE: stream->print(F("Periodic test transmission")); break;
case 0xFF: stream->print(F("System test")); break;
default: decoded = false;
}
if (decoded) return;
/*
* Zone alarm, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 01001001 11011000 00001001 11111111 00110101 [0xA5] 2018.03.26 09:54 | Partition 1 | Zone alarm: 1
* 10100101 0 00011000 01001111 01001010 00100000 00001110 11111111 10000011 [0xA5] 2018.03.26 10:08 | Partition 1 | Zone alarm: 6
* 10100101 0 00011000 01001111 10010100 11001000 00010000 11111111 01110111 [0xA5] 2018.03.28 20:50 | Partition 1 | Zone alarm: 8
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x09 && panelData[panelByte] print("Zone alarm: ");
printNumberOffset(panelByte, -8);
return;
}
/*
* Zone alarm restored, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 10010100 11001100 00101001 11111111 10010100 [0xA5] 2018.03.28 20:51 | Partition 1 | Zone alarm restored: 1
* 10100101 0 00011000 01001111 10010100 11010100 00101110 11111111 10100001 [0xA5] 2018.03.28 20:53 | Partition 1 | Zone alarm restored: 6
* 10100101 0 00011000 01001111 10010100 11010000 00110000 11111111 10011111 [0xA5] 2018.03.28 20:52 | Partition 1 | Zone alarm restored: 8
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x29 && panelData[panelByte] print("Zone alarm restored: ");
printNumberOffset(panelByte, -40);
return;
}
/*
* Zone tamper, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00000001 01000100 00100010 01011100 01010110 11111111 10111101 [0xA5] 2001.01.01 02:23 | Partition 1 | Zone tamper: 1
* 10100101 0 00010001 01101101 01101011 10010000 01011011 11111111 01111000 [0xA5] 2011.11.11 11:36 | Partition 1 | Zone tamper: 6
* 11101011 0 10000000 00100000 00101010 00010111 11010000 00000000 01010111 11111111 11110010 [0xEB] 2020.10.16 23:52 | Partition 8 | Zone tamper: 2
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
if (panelData[panelByte] >= 0x56 && panelData[panelByte] print("Zone tamper: ");
printNumberOffset(panelByte, -85);
return;
}
/*
* Zone tamper restored, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00000001 01000100 00100010 01011100 01110110 11111111 11011101 [0xA5] 2001.01.01 02:23 | Partition 1 | Zone tamper restored: 1
* 10100101 0 00010001 01101101 01101011 10010000 01111011 11111111 10011000 [0xA5] 2011.11.11 11:36 | Partition 1 | Zone tamper restored: 6
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x76 && panelData[panelByte] print("Zone tamper restored: ");
printNumberOffset(panelByte, -117);
return;
}
/*
* Armed by access codes 1-34, 40-42
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001101 00001000 10010000 10011001 11111111 00111010 [0xA5] 2018.03.08 08:36 | Partition 1 | Armed: User code 1
* 10100101 0 00011000 01001101 00001000 10111100 10111011 11111111 10001000 [0xA5] 2018.03.08 08:47 | Partition 1 | Armed: Master code 40
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x99 && panelData[panelByte] print(F("Armed: "));
printPanelAccessCode(dscCode);
return;
}
/*
* Disarmed by access codes 1-34, 40-42
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001101 00001000 11101100 11000000 11111111 10111101 [0xA5] 2018.03.08 08:59 | Partition 1 | Disarmed: User code 1
* 10100101 0 00011000 01001101 00001000 10110100 11100010 11111111 10100111 [0xA5] 2018.03.08 08:45 | Partition 1 | Disarmed: Master code 40
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0xC0 && panelData[panelByte] print(F("Disarmed: "));
printPanelAccessCode(dscCode);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x01 for panel commands: 0xA5, 0xAA, 0xCE, 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use bits 0,1 of the preceding byte to
* select from multiple sets of status messages, split into printPanelStatus0...printPanelStatus3.
*/
void dscKeybusInterface::printPanelStatus1(byte panelByte) {
switch (panelData[panelByte]) {
/*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 11001010 10001001 00000011 11111111 01100001 [0xA5] 2018.03.30 10:34 | Partition 1 | Cross zone alarm
* 10100101 0 00010001 01101101 01101010 00000001 00000100 11111111 10010001 [0xA5] 2011.11.11 10:00 | Partition 1 | Delinquency alarm
* 10100101 0 00010001 01101101 01100000 10101001 00100100 00000000 01010000 [0xA5] 2011.11.11 00:42 | Partition 1 | Duress code 33
* 10100101 0 00010001 01101101 01100000 10110101 00100101 00000000 01011101 [0xA5] 2011.11.11 00:45 | Partition 1 | Duress code 34
* 10100101 0 00010001 01101101 01100000 00101001 00100110 00000000 11010010 [0xA5] 2011.11.11 00:10 | Partition 1 | Master code 40
* 10100101 0 00010001 01101101 01100000 10010001 00100111 00000000 00111011 [0xA5] 2011.11.11 00:36 | Partition 1 | Supervisor code 41
* 10100101 0 00010001 01101101 01100000 10111001 00101000 00000000 01100100 [0xA5] 2011.11.11 00:46 | Partition 1 | Supervisor code 42
* 10100101 0 00011000 01001111 10100000 10011101 00101011 00000000 01110100 [0xA5] 2018.03.29 00:39 | Partition 1 | Armed: Auto-arm
* 10100101 0 00011000 01001101 00001010 00001101 10101100 00000000 11001101 [0xA5] 2018.03.08 10:03 | Partition 1 | Exit *8 programming
* 10100101 0 00011000 01001101 00001001 11100001 10101101 00000000 10100001 [0xA5] 2018.03.08 09:56 | Partition 1 | Enter *8 programming
* 10100101 0 00010001 01101101 01100010 11001101 11010000 00000000 00100010 [0xA5] 2011.11.11 02:51 | Partition 1 | Command output 4
* 10100101 0 00010110 01010110 00101011 11010001 11010010 00000000 11011111 [0xA5] 2016.05.17 11:52 | Partition 1 | Armed with no entry delay cancelled
* Byte 0 1 2 3 4 5 6 7 8
*/
case 0x03: stream->print(F("Cross zone alarm")); return;
case 0x04: stream->print(F("Delinquency alarm")); return;
case 0x05: stream->print(F("Late to close")); return;
// 0x24 - 0x28: Access codes 33-34, 40-42
case 0x29: stream->print(F("Downloading forced answer")); return;
case 0x2B: stream->print(F("Armed: Auto-arm")); return;
// 0x2C - 0x4B: Zone battery restored, zones 1-32
// 0x4C - 0x6B: Zone battery low, zones 1-32
// 0x6C - 0x8B: Zone fault restored, zones 1-32
// 0x8C - 0xAB: Zone fault, zones 1-32
case 0xAC: stream->print(F("Exit installer programming")); return;
case 0xAD: stream->print(F("Enter installer programming")); return;
case 0xAE: stream->print(F("Walk test end")); return;
case 0xAF: stream->print(F("Walk test begin")); return;
// 0xB0 - 0xCF: Zones bypassed, zones 1-32
case 0xD0: stream->print(F("Command output 4")); return;
case 0xD1: stream->print(F("Exit fault pre-alert")); return;
case 0xD2: stream->print(F("Armed: Entry delay")); return;
case 0xD3: stream->print(F("Downlook remote trigger")); return;
}
/*
* Access codes 33-34, 40-42
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01100000 10101001 00100100 00000000 01010000 [0xA5] 2011.11.11 00:42 | Partition 1 | Duress code 33
* 10100101 0 00010001 01101101 01100000 10110101 00100101 00000000 01011101 [0xA5] 2011.11.11 00:45 | Partition 1 | Duress code 34
* 10100101 0 00010001 01101101 01100000 00101001 00100110 00000000 11010010 [0xA5] 2011.11.11 00:10 | Partition 1 | Master code 40
* 10100101 0 00010001 01101101 01100000 10010001 00100111 00000000 00111011 [0xA5] 2011.11.11 00:36 | Partition 1 | Supervisor code 41
* 10100101 0 00010001 01101101 01100000 10111001 00101000 00000000 01100100 [0xA5] 2011.11.11 00:46 | Partition 1 | Supervisor code 42
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x24 && panelData[panelByte] = 0x2C && panelData[panelByte] print(F("Zone battery restored: "));
printNumberOffset(panelByte, -43);
return;
}
/*
* Zone low battery, zones 1-32
*/
if (panelData[panelByte] >= 0x4C && panelData[panelByte] print(F("Zone battery low: "));
printNumberOffset(panelByte, -75);
return;
}
/*
* Zone fault restored, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01101011 01000001 01101100 11111111 00111010 [0xA5] 2011.11.11 11:16 | Partition 1 | Zone fault restored: 1
* 10100101 0 00010001 01101101 01101011 01010101 01101101 11111111 01001111 [0xA5] 2011.11.11 11:21 | Partition 1 | Zone fault restored: 2
* 10100101 0 00010001 01101101 01101011 10000101 01101111 11111111 10000001 [0xA5] 2011.11.11 11:33 | Partition 1 | Zone fault restored: 4
* 10100101 0 00010001 01101101 01101011 10001001 01110000 11111111 10000110 [0xA5] 2011.11.11 11:34 | Partition 1 | Zone fault restored: 5
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x6C && panelData[panelByte] print(F("Zone fault restored: "));
printNumberOffset(panelByte, -107);
return;
}
/*
* Zone fault, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01101011 00111101 10001100 11111111 01010110 [0xA5] 2011.11.11 11:15 | Partition 1 | Zone fault: 1
* 10100101 0 00010001 01101101 01101011 01010101 10001101 11111111 01101111 [0xA5] 2011.11.11 11:21 | Partition 1 | Zone fault: 2
* 10100101 0 00010001 01101101 01101011 10000001 10001111 11111111 10011101 [0xA5] 2011.11.11 11:32 | Partition 1 | Zone fault: 4
* 10100101 0 00010001 01101101 01101011 10001001 10010000 11111111 10100110 [0xA5] 2011.11.11 11:34 | Partition 1 | Zone fault: 5
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0x8C && panelData[panelByte] print(F("Zone fault: "));
printNumberOffset(panelByte, -139);
return;
}
/*
* Zones bypassed, zones 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 10110001 10101001 10110001 00000000 00010111 [0xA5] 2018.03.29 17:42 | Partition 1 | Zone bypassed: 2
* 10100101 0 00011000 01001111 10110001 11000001 10110101 00000000 00110011 [0xA5] 2018.03.29 17:48 | Partition 1 | Zone bypassed: 6
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0xB0 && panelData[panelByte] print(F("Zone bypassed: "));
printNumberOffset(panelByte, -175);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x02 for panel commands: 0xAA, 0xCE, 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use bits 0,1 of the preceding byte to
* select from multiple sets of status messages, split into printPanelStatus0...printPanelStatus3.
*/
void dscKeybusInterface::printPanelStatus2(byte panelByte) {
switch (panelData[panelByte]) {
/*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 01001111 10101111 10000110 00101010 00000000 01101011 [0xA5] 2018.03.29 15:33 | Partition 1 | Quick exit
* 10100101 0 00010001 01101101 01110101 00111010 01100011 00000000 00110101 [0xA5] 2011.11.11 21:14 | Partition 1 | Keybus fault restored
* 10100101 0 00011000 01001111 11110111 01110110 01100110 00000000 11011111 [0xA5] 2018.03.31 23:29 | Partition 1 | Enter *1 zone bypass programming
* 10100101 0 00010001 01101101 01100010 11001110 01101001 00000000 10111100 [0xA5] 2011.11.11 02:51 | Partition 1 | Command output 3
* 10100101 0 00011000 01010000 01000000 00000010 10001100 00000000 11011011 [0xA5] 2018.04.02 00:00 | Partition 1 | Loss of system time
* 10100101 0 00011000 01001111 10101110 00001110 10001101 00000000 01010101 [0xA5] 2018.03.29 14:03 | Partition 1 | Power on
* 10100101 0 00011000 01010000 01000000 00000010 10001110 00000000 11011101 [0xA5] 2018.04.02 00:00 | Partition 1 | Panel factory default
* 10100101 0 00011000 01001111 11101010 10111010 10010011 00000000 01000011 [0xA5] 2018.03.31 10:46 | Partition 1 | Disarmed by keyswitch
* 10100101 0 00011000 01001111 11101010 10101110 10010110 00000000 00111010 [0xA5] 2018.03.31 10:43 | Partition 1 | Armed by keyswitch
* 10100101 0 00011000 01001111 10100000 01100010 10011000 00000000 10100110 [0xA5] 2018.03.29 00:24 | Partition 1 | Armed by quick-arm
* 10100101 0 00010001 01101101 01100000 00101110 10011001 00000000 01001010 [0xA5] 2011.11.11 00:11 | Partition 1 | Activate stay/away zones
* 10100101 0 00011000 01001111 00101101 00011010 10011010 00000000 11101101 [0xA5] 2018.03.25 13:06 | Partition 1 | Armed: stay
* 10100101 0 00011000 01001111 00101101 00010010 10011011 00000000 11100110 [0xA5] 2018.03.25 13:04 | Partition 1 | Armed: away
* 10100101 0 00011000 01001111 00101101 10011010 10011100 00000000 01101111 [0xA5] 2018.03.25 13:38 | Partition 1 | Armed with no entry delay
* 10100101 0 00011000 01001111 00101100 11011110 11000011 00000000 11011001 [0xA5] 2018.03.25 12:55 | Partition 1 | Enter *5 programming
* 10100101 0 00011000 01001111 00101110 00000010 11100110 00000000 00100010 [0xA5] 2018.03.25 14:00 | Partition 1 | Enter *6 programming
* Byte 0 1 2 3 4 5 6 7 8
*/
case 0x2A: stream->print(F("Quick exit")); return;
case 0x63: stream->print(F("Keybus fault restored")); return;
case 0x64: stream->print(F("Keybus fault")); return;
case 0x66: stream->print(F("*1: Zone bypass")); return;
// 0x67 - 0x69: *7: Command output 1-3
case 0x8C: stream->print(F("Cold start")); return;
case 0x8D: stream->print(F("Warm start")); return;
case 0x8E: stream->print(F("Panel factory default")); return;
case 0x91: stream->print(F("Swinger shutdown")); return;
case 0x93: stream->print(F("Disarmed: Keyswitch")); return;
case 0x96: stream->print(F("Armed: Keyswitch")); return;
case 0x97: stream->print(F("Armed: Keypad away")); return;
case 0x98: stream->print(F("Armed: Quick-arm")); return;
case 0x99: stream->print(F("Activate stay/away zones")); return;
case 0x9A: stream->print(F("Armed: Stay")); return;
case 0x9B: stream->print(F("Armed: Away")); return;
case 0x9C: stream->print(F("Armed: No entry delay")); return;
// 0x9E - 0xC2: *1: Access codes 1-34, 40-42
// 0xC3 - 0xC5: *5: Access codes 40-42
// 0xC6 - 0xE5: Access codes 1-34, 40-42
// 0xE6 - 0xE8: *6: Access codes 40-42
// 0xE9 - 0xF0: Keypad restored: Slots 1-8
// 0xF1 - 0xF8: Keypad trouble: Slots 1-8
// 0xF9 - 0xFE: Zone expander restored: 1-6
case 0xFF: stream->print(F("Zone expander trouble: 1")); return;
}
/*
* *7: Command output 1-3
*/
if (panelData[panelByte] >= 0x67 && panelData[panelByte] print(F("Command output: "));
printNumberOffset(panelByte, -0x66);
return;
}
/*
* *1: Access codes 1-34, 40-42
*/
if (panelData[panelByte] >= 0x9E && panelData[panelByte] print(F("*1: "));
printPanelAccessCode(dscCode);
return;
}
/*
* *5: Access codes 40-42
*/
if (panelData[panelByte] >= 0xC3 && panelData[panelByte] print(F("*5: "));
printPanelAccessCode(dscCode);
return;
}
/*
* Access codes 1-32
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01100000 00111110 11000110 00000000 10000111 [0xA5] 2011.11.11 00:15 | Partition 1 | User code 1
* 10100101 0 00010001 01101101 01100000 01111010 11100101 00000000 11100010 [0xA5] 2011.11.11 00:30 | Partition 1 | User code 32
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0xC6 && panelData[panelByte] = 0xE6 && panelData[panelByte] print(F("*6: "));
printPanelAccessCode(dscCode);
return;
}
/*
* Keypad restored: Slots 1-8
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01110100 10001110 11101001 11111111 00001101 [0xA5] 2011.11.11 20:35 | Partition 1 | Keypad restored: Slot 1
* 10100101 0 00010001 01101101 01110100 00110010 11110000 11111111 10111000 [0xA5] 2011.11.11 20:12 | Partition 1 | Keypad restored: Slot 8
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0xE9 && panelData[panelByte] print(F("Keypad restored: Slot "));
printNumberOffset(panelByte, -232);
return;
}
/*
* Keypad trouble: Slots 1-8
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00010001 01101101 01110100 10000110 11110001 11111111 00001101 [0xA5] 2011.11.11 20:33 | Partition 1 | Keypad trouble: Slot 1
* 10100101 0 00010001 01101101 01110100 00101110 11111000 11111111 10111100 [0xA5] 2011.11.11 20:11 | Partition 1 | Keypad trouble: Slot 8
* Byte 0 1 2 3 4 5 6 7 8
*/
if (panelData[panelByte] >= 0xF1 && panelData[panelByte] print(F("Keypad trouble: Slot "));
printNumberOffset(panelByte, -240);
return;
}
/*
* Zone expander restored: 1-6
*/
if (panelData[panelByte] >= 0xF9 && panelData[panelByte] print(F("Zone expander restored: "));
printNumberOffset(panelByte, -248);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x03 for panel commands: 0xAA, 0xCE, 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use bits 0,1 of the preceding byte to
* select from multiple sets of status messages, split into printPanelStatus0...printPanelStatus3.
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00100000 00101010 01100000 10111111 01000010 11111111 01001111 [0xA5] 2020.10.19 00:47 | PC/RF5132: Tamper
* 10100101 0 00100000 00101010 01100000 10111111 01000001 11111111 01001110 [0xA5] 2020.10.19 00:47 | PC/RF5132: Tamper restored
* 10100101 0 00100000 00001001 10000000 11010011 01000100 11111111 01100100 [0xA5] 2020.02.12 00:52 | PC5208: Tamper
* 10100101 0 00100000 00101010 11000000 11011111 01010001 11111111 11011110 [0xA5] 2020.10.22 00:55 | Module tamper restored: Slot 16
* 10100101 0 00100000 00101010 11000000 11011111 01010010 11111111 11011111 [0xA5] 2020.10.22 00:55 | Module tamper: Slot 16
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanelStatus3(byte panelByte) {
switch (panelData[panelByte]) {
case 0x05: stream->print(F("PC/RF5132: Supervisory restored")); return;
case 0x06: stream->print(F("PC/RF5132: Supervisory trouble")); return;
case 0x09: stream->print(F("PC5204: Supervisory restored")); return;
case 0x0A: stream->print(F("PC5204: Supervisory trouble")); return;
case 0x17: stream->print(F("Zone expander restored: 7")); return;
case 0x18: stream->print(F("Zone expander trouble: 7")); return;
// 0x25 - 0x2C: Keypad tamper restored, slots 1-8
// 0x2D - 0x34: Keypad tamper, slots 1-8
// 0x35 - 0x3A: Module tamper restored, slots 9-14
// 0x3B - 0x40: Module tamper, slots 9-14
case 0x41: stream->print(F("PC/RF5132: Tamper restored")); return;
case 0x42: stream->print(F("PC/RF5132: Tamper")); return;
case 0x43: stream->print(F("PC5208: Tamper restored")); return;
case 0x44: stream->print(F("PC5208: Tamper")); return;
case 0x45: stream->print(F("PC5204: Tamper restored")); return;
case 0x46: stream->print(F("PC5204: Tamper")); return;
case 0x51: stream->print(F("Zone expander tamper restored: 7")); return;
case 0x52: stream->print(F("Zone expander tamper: 7")); return;
case 0xB3: stream->print(F("PC5204: Battery restored")); return;
case 0xB4: stream->print(F("PC5204: Battery trouble")); return;
case 0xB5: stream->print(F("PC5204: Aux supply restored")); return;
case 0xB6: stream->print(F("PC5204: Aux supply trouble")); return;
case 0xB7: stream->print(F("PC5204: Output 1 restored")); return;
case 0xB8: stream->print(F("PC5204: Output 1 trouble")); return;
case 0xFF: stream->print(F("Extended status")); return;
}
/*
* Zone expander trouble: 2-6
*/
if (panelData[panelByte] print(F("Zone expander trouble: "));
printNumberOffset(panelByte, 2);
return;
}
/*
* Keypad tamper restored: 1-8
*/
if (panelData[panelByte] >= 0x25 && panelData[panelByte] print(F("Keypad tamper restored: "));
printNumberOffset(panelByte, -0x24);
return;
}
/*
* Keypad tamper: 1-8
*/
if (panelData[panelByte] >= 0x2D && panelData[panelByte] print(F("Keypad tamper: "));
printNumberOffset(panelByte, -0x2C);
return;
}
/*
* Zone expander tamper restored: 1-6
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00100000 00101010 11000110 00101011 00110101 11111111 00010100 [0xA5] 2020.10.22 06:10 | Zone expander tamper restored: 1
* 10100101 0 00100000 00101010 11000000 00101111 00111010 11111111 00010111 [0xA5] 2020.10.22 00:11 | Zone expander tamper restored: 6
* 11101011 0 00000000 00100000 00101010 11000110 00101000 00000011 00110101 11111111 01011010 [0xEB] 2020.10.22 06:10 | Zone expander tamper restored: 1
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
if (panelData[panelByte] >= 0x35 && panelData[panelByte] print(F("Zone expander tamper restored: "));
printNumberOffset(panelByte, -52);
return;
}
/*
* Zone expander tamper: 1-6
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00100000 00101010 11000110 00101011 00111011 11111111 00011010 [0xA5] 2020.10.22 06:10 | Zone expander tamper: 1
* 10100101 0 00100000 00101010 11000000 00101111 01000000 11111111 00011101 [0xA5] 2020.10.22 00:11 | Zone expander tamper: 6
* 11101011 0 00000000 00100000 00101010 11000110 00101000 00000011 00111011 11111111 01100000 [0xEB] 2020.10.22 06:10 | Zone expander tamper: 1
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
if (panelData[panelByte] >= 0x3B && panelData[panelByte] print(F("Zone expander tamper: "));
printNumberOffset(panelByte, -58);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x04 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*
* Command Partition YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 11101011 0 00000001 00011000 00011000 10001111 00101000 00000100 00000000 10010001 01101000 [0xEB] 2018.06.04 15:10 | Partition 1 | Zone alarm: 33
* 11101011 0 00000001 00000001 00000100 01100000 00010100 00000100 01000000 10000001 00101010 [0xEB] 2001.01.03 00:05 | Partition 1 | Zone tamper: 33
* 11101011 0 00000001 00000001 00000100 01100000 00001000 00000100 01011111 10000001 00111101 [0xEB] 2001.01.03 00:02 | Partition 1 | Zone tamper: 64
* 11101011 0 00000001 00000001 00000100 01100000 00011000 00000100 01100000 11111111 11001100 [0xEB] 2001.01.03 00:06 | Partition 1 | Zone tamper restored: 33
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanelStatus4(byte panelByte) {
switch (panelData[panelByte]) {
case 0x86: stream->print(F("Periodic test with trouble")); return;
case 0x87: stream->print(F("Exit fault")); return;
case 0x89: stream->print(F("Alarm cancelled")); return;
}
if (panelData[panelByte] print("Zone alarm: ");
printNumberOffset(panelByte, 33);
}
else if (panelData[panelByte] >= 0x20 && panelData[panelByte] print("Zone alarm restored: ");
printNumberOffset(panelByte, 1);
}
else if (panelData[panelByte] >= 0x40 && panelData[panelByte] print("Zone tamper: ");
printNumberOffset(panelByte, -31);
}
else if (panelData[panelByte] >= 0x60 && panelData[panelByte] print("Zone tamper restored: ");
printNumberOffset(panelByte, -63);
}
else stream->print("Unknown data");
}
/*
* Status messages set 0x05 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus5(byte panelByte) {
/*
* Armed by access codes 35-95
* 0x00 - 0x04: Access codes 35-39
* 0x05 - 0x39: Access codes 43-95
*/
if (panelData[panelByte] print(F("Armed: "));
printPanelAccessCode(dscCode, false);
return;
}
/*
* Disarmed by access codes 35-95
* 0x3A - 0x3E: Access codes 35-39
* 0x3F - 0x73: Access codes 43-95
*/
if (panelData[panelByte] >= 0x3A && panelData[panelByte] print(F("Disarmed: "));
printPanelAccessCode(dscCode, false);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x14 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus14(byte panelByte) {
#if !defined(__AVR__) // Excludes Arduino/AVR to conserve storage space
switch (panelData[panelByte]) {
case 0xC0: stream->print(F("TLink com fault")); return;
case 0xC2: stream->print(F("Tlink network fault")); return;
case 0xC4: stream->print(F("TLink receiver trouble")); return;
case 0xC5: stream->print(F("TLink receiver restored")); return;
}
#endif
printUnknownData();
}
/*
* Status messages set 0x16 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus16(byte panelByte) {
switch (panelData[panelByte]) {
case 0x80: stream->print(F("Trouble acknowledged")); return;
case 0x81: stream->print(F("RF delinquency trouble")); return;
case 0x82: stream->print(F("RF delinquency restore")); return;
}
printUnknownData();
}
/*
* Status messages set 0x17 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus17(byte panelByte) {
/*
* *1: Access codes 35-95
* 0x4A - 0x83: *1: Access codes 35-39, 43-95
*/
if (panelData[panelByte] >= 0x4A && panelData[panelByte] print(F("*1: "));
printPanelAccessCode(dscCode, false);
return;
}
/*
* *2: Access codes 1-95
* 0x00 - 0x24: *2: Access code 1-32, 40-42
* 0x84 - 0xBD: *2: Access codes 35-39, 43-95
*/
if (panelData[panelByte] print(F("*2: "));
printPanelAccessCode(dscCode);
return;
}
if (panelData[panelByte] >= 0x84 && panelData[panelByte] print(F("*2: "));
printPanelAccessCode(dscCode, false);
return;
}
/*
* *3: Access codes 1-95
* 0x25 - 0x49: *3: Access code 1-32, 40-42
* 0xBE - 0xF7: *3: Access codes 35-39, 43-95
*/
if (panelData[panelByte] >= 0x25 && panelData[panelByte] print(F("*3: "));
printPanelAccessCode(dscCode);
return;
}
if (panelData[panelByte] >= 0xBE && panelData[panelByte] print(F("*3: "));
printPanelAccessCode(dscCode, false);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x18 for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus18(byte panelByte) {
/*
* *7/User/Auto-arm cancel by access codes 35-95
*
* 0x00 - 0x04: *7, * Access codes 35-39
* 0x05 - 0x39: *7, * Access codes 43-95
*/
if (panelData[panelByte] = 0x3A && panelData[panelByte] print(F("*5: "));
printPanelAccessCode(dscCode, false);
return;
}
/*
* *6: Access codes 1-95
*
* 0x96 - 0xBC: *6: Access codes 1-39
* 0xBD - 0xF1: *6: Access codes 43-95
*/
if (panelData[panelByte] >= 0x96 && panelData[panelByte] print(F("*6: "));
printPanelAccessCode(dscCode, false);
return;
}
stream->print("Unknown data");
}
/*
* Status messages set 0x1B for panel commands: 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: likely incomplete - observed messages from logs have been decoded, but there are gaps in
* the numerical list of messages.
*
* These commands use 1 byte for the status message, and appear to use the preceding byte to select
* from multiple sets of status messages, split into printPanelStatus4...printPanelStatus1B.
*/
void dscKeybusInterface::printPanelStatus1B(byte panelByte) {
switch (panelData[panelByte]) {
case 0xF1: stream->print(F("System reset transmission")); return;
}
printUnknownData();
}
/*
* 0x05: Status - partitions 1-4
* Interval: constant
* CRC: no
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 1 lights, printPanelLights()
* Byte 3: Partition 1 status, printPanelMessages()
* Byte 4: Partition 2 lights
* Byte 5: Partition 2 status
*
* Later generation panels:
* Byte 6: Partition 3 lights
* Byte 7: Partition 3 status
* Byte 8: Partition 4 lights
* Byte 9: Partition 4 status
*
* Early generation panels:
* Command 1:Lights 1:Status 2:Lights 2:Status
* 00000101 0 10000001 00000001 10010001 11000111 [0x05] Partition 1: Ready Backlight - Partition ready | Partition 2: disabled
* 00000101 0 10010000 00000011 10010001 11000111 [0x05] Partition 1: Trouble Backlight - Zones open | Partition 2: disabled
* 00000101 0 10001010 00000100 10010001 11000111 [0x05] Partition 1: Armed Bypass Backlight - Armed stay | Partition 2: disabled
* 00000101 0 10000010 00000101 10010001 11000111 [0x05] Partition 1: Armed Backlight - Armed away | Partition 2: disabled
* 00000101 0 10000010 00010001 10010001 11000111 [0x05] Partition 1: Armed Backlight - Partition in alarm | Partition 2: disabled
* 00000101 0 10000001 00111110 10010001 11000111 [0x05] Partition 1: Ready Backlight - Partition disarmed | Partition 2: disabled
* Byte 0 1 2 3 4 5
*
* Later generation panels:
* Command 1:Lights 1:Status 2:Lights 2:Status 3:Lights 3:Status 4:Lights 4:Status
* 00000101 0 10000000 00000011 10000010 00000101 10000010 00000101 00000000 11000111 [0x05] Partition 1: Backlight - Zones open | Partition 2: Armed Backlight - Armed away | Partition 3: Armed Backlight - Armed away | Partition 4: disabled
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0x05() {
printPanelPartitionStatus(1, 3, 5);
if (!keybusVersion1) {
stream->print(" | ");
printPanelPartitionStatus(3, 7, 9);
}
}
/*
* 0x0A_0F: Status in programming, partitions 1-2
* Interval: constant in *8 programming
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition lights, printPanelLights()
* Byte 3: Partition status, printPanelMessages()
* Byte 4: Zone lights 1-8
* Byte 5: Zone lights 9-16
* Byte 6: Zone lights 17-24
* Byte 7: Zone lights 25-32
* Byte 8: Zone lights for *5 access codes 33,34,41,42
* Byte 9: CRC
*
* Command 1:Lights 1:Status Zones1+ Zones9+ Zones17+ Zones25+ CRC
* 00001010 0 10000010 11100100 00000000 00000000 00000000 00000000 00000000 01110000 [0x0A] Armed Backlight - *8: Main menu | Zone lights: none
* 00001010 0 10000001 11101110 01100101 00000000 00000000 00000000 00000000 11011110 [0x0A] Ready Backlight - *8: Input required: 1 option per zone | Zone lights: 1 3 6 7
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0x0A_0F() {
byte partition = 0;
switch (panelData[0]) {
case 0x0A: partition = 1; break;
case 0x0F: partition = 2; break;
}
printPanelPartitionStatus(partition, 3, 3);
printZoneLights();
bool zoneLights = printPanelZones(4, 1);
if (panelData[8] != 0 && panelData[8] != 128) {
zoneLights = true;
if (bitRead(panelData[8], 0)) printNumberSpace(33);
if (bitRead(panelData[8], 1)) printNumberSpace(34);
if (bitRead(panelData[8], 3)) printNumberSpace(41);
if (bitRead(panelData[8], 4)) printNumberSpace(42);
}
if (!zoneLights) stream->print(F("none"));
}
/*
* 0x11: Module supervision query
* Interval: 30s
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 2-6: 10101010
*
* Later generation panels:
* Bytes 7-8: 10101010
*
* Early generation panels:
* 00010001 0 10101010 10101010 10101010 10101010 10101010 [0x11] Module supervision query
* 11111111 1 00111111 11111111 11111111 11111111 11111111 [Module/0x11] Keypad slots: 1
* 11111111 1 11111111 11111100 11111111 11111111 11111111 [Module/0x11] Keypad slots: 8
* Byte 0 1 2 3 4 5 6
*
* Later generation panels:
* 00010001 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x11] Module supervision query
* 11111111 1 00111111 11111111 11111111 11001111 11111111 11111111 11111111 [Module/0x11] Keypad slots: 1 | Zone expander: 6
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanel_0x11() {
stream->print(F("Module supervision query"));
}
/*
* 0x16: Panel configuration
* Interval: 4min
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Unknown data, 00001110 observed on all tested panels
* Byte 3: Panel version
* Byte 4 bits 0,1: Zone wiring resistors configuration
* Byte 4 bit 2: Unknown data
* Byte 4 bit 3: Code length flag
* Byte 4 bit 4: *8 programming mode flag
* Byte 4 bits 5-7: Unknown data
* Byte 5: CRC
*
* Command Version CRC
* 00010110 0 00001110 00100011 11010010 00011001 [0x16] Panel version: v2.3 | Zone wiring: EOL | Code length: 4 digits | *8 programming: no
* 00010110 0 00001110 00100011 11100001 00101000 [0x16] Panel version: v2.3 | Zone wiring: NC | Code length: 4 digits | *8 programming: yes
* 00010110 0 00001110 00100011 11100110 00101101 [0x16] Panel version: v2.3 | Zone wiring: EOL | Code length: 4 digits | *8 programming: yes
* 00010110 0 00001110 00100011 11110010 00111001 [0x16] Panel version: v2.3 | Zone wiring: EOL | Code length: 4 digits | *8 programming: no
* 00010110 0 00001110 00010000 11110011 00100111 [0x16] Panel version: v1.0 | Zone wiring: DEOL | Code length: 4 digits | *8 programming: no
* 00010110 0 00001110 01000001 11110101 01011010 [0x16] Panel version: v4.1 | Zone wiring: NC | Code length: 4 digits | *8 programming: no
* 00010110 0 00001110 01000010 10110101 00011011 [0x16] Panel version: v4.2 | Zone wiring: NC | Code length: 4 digits | *8 programming: no
* 00010110 0 00001110 01000010 10110001 00010111 [0x16] Panel version: v4.2 | Zone wiring: NC | Code length: 4 digits | *8 programming: no
* Byte 0 1 2 3 4 5
*/
void dscKeybusInterface::printPanel_0x16() {
if (panelData[2] == 0x0E) {
// Panel version
stream->print(F("Panel version: v"));
stream->print(panelData[3] >> 4);
stream->print(".");
stream->print(panelData[3] & 0x0F);
// Zone wiring
stream->print(F(" | Zone wiring: "));
switch (panelData[4] & 0x03) {
case 0x01: stream->print(F("NC ")); break;
case 0x02: stream->print(F("EOL ")); break;
case 0x03: stream->print(F("DEOL ")); break;
}
// Code length
stream->print(F("| Code length: "));
if (panelData[4] & 0x08) stream->print(F("6"));
else stream->print(F("4"));
stream->print(F(" digits "));
// *8 programming mode status
stream->print(F("| *8 programming: "));
if (panelData[4] & 0x10) stream->print(F("no "));
else stream->print(F("yes "));
}
else printUnknownData();
}
/*
* 0x1B: Status - partitions 5-8
* Interval: constant
* CRC: no
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 5 lights, printPanelLights()
* Byte 3: Partition 5 status, printPanelMessages()
* Byte 4: Partition 6 lights
* Byte 5: Partition 6 status
* Byte 6: Partition 7 lights
* Byte 7: Partition 7 status
* Byte 8: Partition 8 lights
* Byte 9: Partition 8 status
*
* Command 5:Lights 5:Status 6:Lights 6:Status 7:Lights 7:Status 8:Lights 8:Status
* 00011011 0 10010001 00000001 00010000 11000111 00010000 11000111 00010000 11000111 [0x1B] Partition 5: Ready Trouble Backlight - Partition ready | Partition 6: disabled | Partition 7: disabled | Partition 8: disabled
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0x1B() {
printPanelPartitionStatus(5, 3, 9);
}
/*
* 0x1C: Verify keypad Fire/Auxiliary/Panic
* Interval: immediate after keypad button press
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* 01110111 1 11111111 11111111 11111111 11111111 [Keypad] Fire alarm
* 00011100 0 [0x1C] Verify keypad Fire/Auxiliary/Panic
* 01110111 1 [Keypad] Fire alarm
*/
void dscKeybusInterface::printPanel_0x1C() {
stream->print(F("Verify keypad Fire/Auxiliary/Panic"));
}
/*
* 0x22: Zone expander 0 (PC/RF5132) query
* Interval: after zone expander status notification
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 2-6: 11111111
*
* 11111111 1 11111111 11111111 01111111 11111111 [Module/0x05] Zone expander notification: 0
* 00100010 0 11111111 11111111 11111111 11111111 11111111 [0x22] Zone expander query: 0
* 11111111 1 01011001 01010101 01010101 01010101 10000100 [Module/0x22] Zone expander: 0 | Zones changed: 2 tamper
*
* 11111111 1 11111111 11111111 10111111 11111111 [Module/0x05] Zone expander notification: 1
* 00101000 0 11111111 11111111 11111111 11111111 11111111 [0x28] Zone expander query: 1
* 11111111 1 01010111 01010101 11111111 11111111 01101111 [Module/0x28] Zone expander: 1 | Zones changed: 9 open (D/EOL)
* Byte 0 1 2 3 4 5 6
*/
void dscKeybusInterface::printPanel_0x22_28_33_39() {
byte expander = 0;
switch (panelData[0]) {
case 0x22: expander = 0; break;
case 0x28: expander = 1; break;
case 0x33: expander = 2; break;
case 0x39: expander = 3; break;
}
stream->print(F("Zone expander query: "));
stream->print(expander);
}
/*
* 0x27: Status with zones 1-8
* Interval: 4m
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 1 lights, printPanelLights()
* Byte 3: Partition 1 status, printPanelMessages()
* Byte 4: Partition 2 lights
* Byte 5: Partition 2 status
* Byte 6: Zones 1-8
* Byte 7: CRC
*
* Command 1:Lights 1:Status 2:Lights 3:Status Zones1+ CRC
* 00100111 0 10000001 00000001 10010001 11000111 00000000 00000001 [0x27] Partition 1: Ready Backlight - Partition ready | Partition 2: disabled | Zones 1-8 open: none
* 00100111 0 10000001 00000001 10010001 11000111 00000010 00000011 [0x27] Partition 1: Ready Backlight - Partition ready | Partition 2: disabled | Zones 1-8 open: 2
* 00100111 0 10001010 00000100 10010001 11000111 00000000 00001101 [0x27] Partition 1: Armed Bypass Backlight - Armed stay | Partition 2: disabled | Zones 1-8 open: none
* 00100111 0 10001010 00000100 11111111 11111111 00000000 10110011 [0x27] Partition 1: Armed Bypass Backlight - Armed stay | Zones 1-8 open: none
* 00100111 0 10000010 00000101 10010001 11000111 00000000 00000110 [0x27] Partition 1: Armed Backlight - Armed away | Partition 2: disabled | Zones 1-8 open: none
* 00100111 0 10000010 00000101 11111111 11111111 00000000 10101100 [0x27] Partition 1: Armed Backlight - Armed away | Zones 1-8 open: none
* 00100111 0 10000010 00001100 10010001 11000111 00000001 00001110 [0x27] Partition 1: Armed Backlight - Entry delay in progress | Partition 2: disabled | Zones 1-8 open: 1
* 00100111 0 10000010 00010001 10010001 11000111 00000001 00010011 [0x27] Partition 1: Armed Backlight - Partition in alarm | Partition 2: disabled | Zones 1-8 open: 1
* 00100111 0 10000010 00001101 10010001 11000111 00000001 00001111 [0x27] Partition 1: Armed Backlight - Opening after alarm | Partition 2: disabled | Zones 1-8 open: 1
* 00100111 0 10000010 00010001 11011011 11111111 00000010 10010110 [0x27] Partition 1: Armed Backlight - Partition in alarm | Zones 1-8 open: 2
* 00100111 0 00000001 00000001 11111111 11111111 00000000 00100111 [0x27] Partition 1: Ready - Partition ready | Zones 1-8 open: none
* 00100111 0 10010001 00000001 11111111 11111111 00000000 10110111 [0x27] Partition 1: Ready Trouble Backlight - Partition ready | Zones 1-8 open: none
* 00100111 0 10010001 00000001 10100000 00000000 00000000 01011001 [0x27] Partition 1: Ready Trouble Backlight - Partition ready | Partition 2: Program Backlight - Unknown data: 0x00 | Zones 1-8 open: none
* 00100111 0 10010000 00000011 11111111 11111111 00111111 11110111 [0x27] Partition 1: Trouble Backlight - Zones open | Zones 1-8 open: 1 2 3 4 5 6
* 00100111 0 10010000 00000011 10010001 11000111 00111111 01010001 [0x27] Partition 1: Trouble Backlight - Zones open | Partition 2: disabled | Zones 1-8 open: 1 2 3 4 5 6
* 00100111 0 10000000 00000011 10000010 00000101 00011101 01001110 [0x27] Partition 1: Backlight - Zones open | Partition 2: Armed Backlight - Armed away | Zones 1-8 open: 1 3 4 5
* Byte 0 1 2 3 4 5 6 7
*/
void dscKeybusInterface::printPanel_0x27() {
printPanelPartitionStatus(1, 3, 5);
stream->print(F(" | Zones 1-8 open: "));
printPanelBitNumbers(6, 1);
}
/*
* 0x2D: Status with zones 9-16
* Interval: 4m
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 1 lights, printPanelLights()
* Byte 3: Partition 1 status, printPanelMessages()
* Byte 4: Partition 2 lights
* Byte 5: Partition 2 status
* Byte 6: Zones 9-16
* Byte 7: CRC
*
* Command 1:Lights 1:Status 2:Lights 3:Status Zones9+ CRC
* 00101101 0 10000000 00000011 10000001 11000111 00000001 11111001 [0x2D] Partition 1: Backlight - Zones open | Partition 2: disabled | Zones 9-16 open: 9
* 00101101 0 10000000 00000011 10000010 00000101 00000000 00110111 [0x2D] Partition 1: Backlight - Zones open | Partition 2: Armed Backlight - Armed away | Zones 9-16 open: none
* Byte 0 1 2 3 4 5 6 7
*/
void dscKeybusInterface::printPanel_0x2D() {
printPanelPartitionStatus(1, 3, 5);
stream->print(F(" | Zones 9-16 open: "));
printPanelBitNumbers(6, 9);
}
/*
* 0x34: Status with zones 17-24
* Interval: 4m
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 1 lights, printPanelLights()
* Byte 3: Partition 1 status, printPanelMessages()
* Byte 4: Partition 2 lights
* Byte 5: Partition 2 status
* Byte 6: Zones 17-24
* Byte 7: CRC
*/
void dscKeybusInterface::printPanel_0x34() {
printPanelPartitionStatus(1, 3, 5);
stream->print(F(" | Zones 17-24 open: "));
printPanelBitNumbers(6, 17);
}
/*
* 0x3E: Status with zones 25-32
* Interval: 4m
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2: Partition 1 lights, printPanelLights()
* Byte 3: Partition 1 status, printPanelMessages()
* Byte 4: Partition 2 lights
* Byte 5: Partition 2 status
* Byte 6: Zones 25-32
* Byte 7: CRC
*/
void dscKeybusInterface::printPanel_0x3E() {
printPanelPartitionStatus(1, 3, 5);
stream->print(F(" | Zones 25-32 open: "));
printPanelBitNumbers(6, 25);
}
/*
* 0x41: Wireless module query
* Interval: immediate on wireless module notification
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 2-10: 11111111
*
* 11111111 1 11111111 11111111 11110111 11111111 [Module/0x05] Wireless module battery notification
* 01000001 0 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [0x41] Wireless module query
* 11111111 1 11111111 11011111 11111111 11111111 11111111 11111111 11111111 11111111 11011000 [Module/0x41] Wireless module | Battery low zones: 11
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0x41() {
stream->print(F("Wireless module query"));
}
/*
* 0x4C: Module tamper query
* Interval: immediate on module tamper notification & after exiting *8 programming
* CRC: no
* Structure decoding: complete
* Content decoding: *incomplete
*
* Bytes 2-12: 10101010
*
* Later generation panels:
* Bytes 13-14: 10101010
*
* 11111111 1 11111111 11111111 11111110 11111111 [Module/0x05] Module tamper notification
* 01001100 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x4C] Module tamper query
* 11111111 1 00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 1
* Byte 0 1 2 3 4 5 6 7 8 9 10 11 12
*
* Later generation panels:
* 01001100 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x4C] Module tamper query
* 11111111 1 11111111 11111111 11111111 11110000 00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper: Slot 9
* Byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
*/
void dscKeybusInterface::printPanel_0x4C() {
stream->print(F("Module tamper query"));
}
/*
* 0x57: Wireless key query
* Interval: immediate on wireless key notification
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 2-10: 11111111
*
* 11111111 1 11111111 11111111 11111111 10111111 [Module/0x05] Wireless key notification
* 01010111 0 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [0x57] Wireless key query
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0x57() {
stream->print(F("Wireless key query"));
}
/*
* 0x58: Module status query - valid response produces 0xA5 command, byte 6 0xB1-0xC0
* Interval: immediate on module status notification and at power on after panel reset
* CRC: no
* Structure decoding: complete
* Content decoding: *incomplete
*
* Bytes 2-5: 10101010
*
* 11111111 1 11111111 11111111 11111111 11011111 [Module/0x05] Module status notification
* 01011000 0 10101010 10101010 10101010 10101010 [0x58] Module status query
* 11111111 1 11111100 11111111 11111111 11111111 [Module/0x58] PC5204: Battery restored
* Byte 0 1 2 3 4 5
*/
void dscKeybusInterface::printPanel_0x58() {
stream->print(F("Module status query"));
}
/*
* 0x5D_63: Flash panel lights: status and zones 1-32, partitions 1-2
* Interval: 30s
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Status lights
* Byte 3: Zones 1-8
* Byte 4: Zones 9-16
* Byte 5: Zones 17-24
* Byte 6: Zones 25-32
* Byte 7: CRC
*
* Command 1:Lights Zones1+ Zones9+ Zones17+ Zones25+ CRC
* 01011101 0 00000000 00000000 00000000 00000000 00000000 01011101 [0x5D] Partition 1 | Status lights flashing: none | Zones 1-32 flashing: none
* 01011101 0 00100000 00000000 00000000 00000000 00000000 01111101 [0x5D] Partition 1 | Status lights flashing: Program | Zones 1-32 flashing: none
* 01011101 0 00000000 00100000 00000000 00000000 00000000 01111101 [0x5D] Partition 1 | Status lights flashing: none | Zones 1-32 flashing: 6
* 01011101 0 00000100 00100000 00000000 00000000 00000000 10000001 [0x5D] Partition 1 | Status lights flashing: Memory | Zones 1-32 flashing: 6
* 01011101 0 00000000 00000000 00000001 00000000 00000000 01011110 [0x5D] Partition 1 | Status lights flashing: none | Zones 1-32 flashing: 9
*
* 01100011 0 00000000 00000000 00000000 00000000 00000000 01100011 [0x63] Partition 2 | Status lights flashing: none | Zones 1-32 flashing: none
* 01100011 0 00000100 10000000 00000000 00000000 00000000 11100111 [0x63] Partition 2 | Status lights flashing: Memory | Zones 1-32 flashing: 8
* Byte 0 1 2 3 4 5 6 7
*/
void dscKeybusInterface::printPanel_0x5D_63() {
byte partition = 0;
switch (panelData[0]) {
case 0x5D: partition = 1; break;
case 0x63: partition = 2; break;
}
printPartition();
printNumberSpace(partition);
printStatusLightsFlashing();
printPanelLights(2, false);
stream->print(F("| Zones 1-32 flashing: "));
printPanelZones(3, 1);
}
/*
* 0x64: Beep, partition 1
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Beeps number
* Byte 3: CRC
*
* Command Beeps CRC
* 01100100 0 00000100 01101000 [0x64] Partition 1 | Beep: 2 beeps
* 01100100 0 00000110 01101010 [0x64] Partition 1 | Beep: 3 beeps
* 01100100 0 00001000 01101100 [0x64] Partition 1 | Beep: 4 beeps
* 01100100 0 00001010 01101110 [0x64] Partition 1 | Beep: 5 beeps
* 01100100 0 00001100 01110000 [0x64] Partition 1 | Beep: 6 beeps
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x64() {
printPartition();
printNumberSpace(1);
printPanelBeeps(2);
}
/*
* 0x69: Beep, partition 2
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Beeps number
* Byte 3: CRC
*
* Command Beeps CRC
* 01101001 0 00001100 01110101 [0x69] Partition 2 | Beep: 6 beeps
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x69() {
printPartition();
printNumberSpace(2);
printPanelBeeps(2);
}
/*
* 0x6E: LCD keypad display
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2 bits 0-3: Digit 1
* Byte 2 bits 4-7: Digit 2
* Byte 3 bits 0-3: Digit 3
* Byte 3 bits 4-7: Digit 4
* Byte 4 bits 0-3: Digit 5
* Byte 4 bits 4-7: Digit 6
* Byte 5 bits 0-3: Digit 7
* Byte 5 bits 4-7: Digit 8
* Byte 6: CRC
*
* Command Digits Digits CRC
* 01101110 0 00000001 00000001 00000000 00000000 01110000 [0x6E] Access code: 010100
* 01101110 0 10101010 10101010 00000000 00000000 11000010 [0x6E] Access code: AAAA00
* Byte 0 1 2 3 4 5 6
*/
void dscKeybusInterface::printPanel_0x6E() {
stream->print(F("LCD display: "));
if (decimalInput) {
if (panelData[2] print("0");
if (panelData[2] print("0");
stream->print(panelData[2], DEC);
}
else {
for (byte panelByte = 2; panelByte print(panelData[panelByte] >> 4, HEX);
stream->print(panelData[panelByte] & 0x0F, HEX);
}
}
}
/*
* 0x70: LCD keypad data query
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2-6: 11111111
*
* Command Tone CRC
* 01110000 0 11111111 11111111 11111111 11111111 11111111 [0x70] LCD keypad data query
* Byte 0 1 2 3 4 5 6
*/
void dscKeybusInterface::printPanel_0x70() {
stream->print(F("LCD keypad data query"));
}
/*
* 0x75: Tone, partition 1
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Tone pattern
* Byte 3: CRC
*
* Command Tone CRC
* 01110101 0 10000000 11110101 [0x75] Partition 1 | Tone: constant tone
* 01110101 0 00000000 01110101 [0x75] Partition 1 | Tone: none
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x75() {
printPartition();
printNumberSpace(1);
printPanelTone(2);
}
/*
* 0x7A: Tone, partition 2
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Tone pattern
* Byte 3: CRC
*
* Command Tone CRC
* 01111010 0 00000000 01111010 [0x7A] Partition 2 | Tone: none
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x7A() {
printPartition();
printNumberSpace(2);
printPanelTone(2);
}
/*
* 0x7F: Buzzer, partition 1
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Buzzer pattern
* Byte 3: CRC
*
* Command Buzzer CRC
* 01111111 0 00000001 10000000 [0x7F] Partition 1 | Buzzer: 1s
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x7F() {
printPartition();
printNumberSpace(1);
printPanelBuzzer(2);
}
/*
* 0x82: Buzzer, partition 2
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Buzzer pattern
* Byte 3: CRC
*
* Command Buzzer CRC
* 10000010 0 00000010 10000100 [0x82] Partition 2 | Buzzer: 2s
* Byte 0 1 2 3
*/
void dscKeybusInterface::printPanel_0x82() {
printPartition();
printNumberSpace(2);
printPanelBuzzer(2);
}
/*
* 0x87: PGM outputs
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2 bit 0: PGM 3
* Byte 2 bit 1: PGM 4
* Byte 2 bit 2: PGM 5
* Byte 2 bit 3: PGM 6
* Byte 2 bit 4: PGM 7
* Byte 2 bit 5: PGM 8
* Byte 2 bit 6: PGM 9
* Byte 2 bit 7: PGM 10
* Byte 3 bit 0: PGM 1
* Byte 3 bit 1: PGM 2
* Byte 3 bit 2: Activates at midnight
* Byte 3 bit 3: Battery check when arming
* Byte 3 bit 4: PGM 11
* Byte 3 bit 5: PGM 12
* Byte 3 bit 6: PGM 13
* Byte 3 bit 7: PGM 14
* Byte 4: CRC
*
* Command PGM PGM CRC
* 10000111 0 00000000 00000000 10000111 [0x87] PGM outputs enabled: none
* 10000111 0 00000000 00000001 10001000 [0x87] PGM outputs enabled: 1
* 10000111 0 00000001 00000011 10001011 [0x87] PGM outputs enabled: 1 2 3
* 10000111 0 00010001 00000010 10011010 [0x87] PGM outputs enabled: 2 3 7
* 10000111 0 00010011 00000000 10011010 [0x87] PGM outputs enabled: 3 4 7
* 10000111 0 00010011 11110011 10001101 [0x87] PGM outputs enabled: 1 2 3 4 7 11 12 13 14
* 10000111 0 11111111 11110000 01110110 [0x87] PGM outputs enabled: 3 4 5 6 7 8 9 10 11 12 13 14
* 10000111 0 11111111 11110010 01111000 [0x87] PGM outputs enabled: 2 3 4 5 6 7 8 9 10 11 12 13 14
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0x87() {
stream->print(F("PGM outputs enabled: "));
if (panelData[2] == 0 && panelData[3] == 0) stream->print(F("none "));
else {
printPanelBitNumbers(3, 1, 0, 1, false);
printPanelBitNumbers(2, 3, 0, 7, false);
printPanelBitNumbers(3, 11, 4, 7, false);
}
if (panelData[3] & 0x04) stream->print(F("| Midnight "));
if (panelData[3] & 0x08) stream->print(F("| Battery check"));
}
/*
* 0x8D: Module programming entry, User code programming key response, codes 17-32
* Note: Wireless keys 1-16 are assigned to user codes 17-32
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Unknown
* Byte 3: Unknown
* Byte 4: Unknown
* Byte 5: Unknown
* Byte 6: Unknown
* Byte 7: Unknown
* Byte 8: Unknown
* Byte 9: CRC
*
* Command CRC
* 10001101 0 00110001 00000001 00000000 00010111 11111111 11111111 11111111 11010011 [0x8D] User code programming key response // Code 17 Key 1
* 10001101 0 00110001 00000100 00000000 00011000 11111111 11111111 11111111 11010111 [0x8D] User code programming key response // Code 18 Key 1
* 10001101 0 00110001 00000100 00000000 00010010 11111111 11111111 11111111 11010001 [0x8D] User code programming key response // Code 18 Key 2
* 10001101 0 00110001 00000101 00000000 00111000 11111111 11111111 11111111 11111000 [0x8D] User code programming key response // Code 18 Key 3
* 10001101 0 00110001 00000101 00000000 00110100 11111111 11111111 11111111 11110100 [0x8D] User code programming key response // Code 18 Key 4
* 10001101 0 00110001 00100101 00000000 00001001 11111111 11111111 11111111 11101001 [0x8D] User code programming key response // Code 29 Key 0
* 10001101 0 00110001 00100101 00000000 00000001 11111111 11111111 11111111 11100001 [0x8D] User code programming key response // Code 29 Key 1
* 10001101 0 00110001 00110000 00000000 00000000 11111111 11111111 11111111 11101011 [0x8D] User code programming key response // Message after 4th key entered
* 10001101 0 00010001 01000001 00000001 00000111 01010101 11111111 11111111 00111010 [0x8D] Wls programming key response // Before WLS zone 4 placement test
* 10001101 0 00010001 01000001 00000001 00001001 01010101 11111111 11111111 00111100 [0x8D] Wls programming key response // Before WLS zone 5 placement test
* 10001101 0 00010001 01000001 00000001 00001011 01010101 11111111 11111111 00111110 [0x8D] Wls programming key response // Before WLS zone 6 placement test
* 10001101 0 00010001 01000001 00000001 00001101 01010101 11111111 11111111 01000000 [0x8D] Wls programming key response // Before WLS zone 7 placement test
* 10001101 0 00010001 01000001 00000001 00100001 01010101 11111111 11111111 01010100 [0x8D] Wls programming key response // Before WLS zone 17 placement test
* 10001101 0 00010001 01000001 00000001 00111111 01010101 11111111 11111111 01110010 [0x8D] Wls programming key response // Before WLS zone 32 placement test
* 10001101 0 00010001 01000001 00000001 01111111 01010101 11111111 11111111 10110010 [0x8D] Wls programming key response // Before WLS zone 64 placement test
* 10001101 0 00010001 01000011 00000000 00000001 11111111 11111111 11111111 11011111 [0x8D] Wls programming key response // Location is good, same for all zones
* 10001101 0 00010001 01000001 00000001 11111111 11111111 11111111 11111111 11011100 [0x8D] Wls programming key response // Wireless zone is not-assigned
* 10001101 0 00010001 10100100 00000000 00000011 11111111 11111111 11111111 01000010 [0x8D] Wls programming key response // Enter 03 for [804][61] function 1
* 10001101 0 00010001 10100101 00000000 00000100 11111111 11111111 11111111 01000100 [0x8D] Wls programming key response // Enter 04 for [804][61] function 2
* 10001101 0 00010001 10100101 00000000 00000011 11111111 11111111 11111111 01000011 [0x8D] Wls programming key response // Enter 03 for [804][61] function 2
* 10001101 0 00010001 10101000 00000000 00000011 11111111 11111111 11111111 01000110 [0x8D] Wls programming key response // Enter 03 for [804][62] function 1
* 10001101 0 00010001 10101001 00000000 00000100 11111111 11111111 11111111 01001000 [0x8D] Wls programming key response // Enter 04 for [804][62] function 2
* 10001101 0 00010001 11000000 00000000 00000011 11111111 11111111 11111111 01011110 [0x8D] Wls programming key response // Enter 03 for [804][68] function 1
* 10001101 0 00010001 11000011 00000000 00110000 11111111 11111111 11111111 10001110 [0x8D] Wls programming key response // Enter 30 for [804][68] function 4
* 10001101 0 00010001 00111000 00000000 00010000 11111111 11111111 11111111 11100011 [0x8D] Wls programming key response // Enter 10 for [804][81] Wls supervisory window
* 10001101 0 00010001 00111000 00000000 10010110 11111111 11111111 11111111 01101001 [0x8D] Wls programming key response // Enter 96 for [804][81] Wls supervisory window
* 10001101 0 00010001 11000100 00000000 00000001 11111111 11111111 11111111 01100000 [0x8D] Wls programming key response // Enter 01 for [804][69] Keyfob 1 partition assigment
* 10001101 0 00010001 11000101 00000000 00000001 11111111 11111111 11111111 01100001 [0x8D] Wls programming key response // Enter 01 for [804][69] Keyfob 2 partition assigment
* 10001101 0 00010001 11000110 00000000 00000010 11111111 11111111 11111111 01100011 [0x8D] Wls programming key response // Enter 02 for [804][69] Keyfob 3 partition assigment
* 10001101 0 00010001 11010100 00000000 11111111 11111111 11111111 11111111 01101110 [0x8D] Wls programming key response // All 1-8 enabled in [804][82] supervision options
* 10001101 0 00010001 11010100 00000000 11110000 11111111 11111111 11111111 01011111 [0x8D] Wls programming key response // 5-8 zones enabled in [804][82] supervisiory options
* 10001101 0 00010001 11010101 00000000 00001111 11111111 11111111 11111111 01111111 [0x8D] Wls programming key response // 1-4 zones enabled in [804][83] supervisiory options
* 10001101 0 00010001 11010111 00000000 01111111 11111111 11111111 11111111 11110001 [0x8D] Wls programming key response // 1-7 zones enabled in [804][85] supervisiory options
* 10001101 0 00010001 00111010 00000000 01000000 11111111 11111111 11111111 00010101 [0x8D] Wls programming key response // Only option 7 enabled in [804][90] options
* 10001101 0 00010001 00111001 00000000 00001000 11111111 11111111 11111111 11011100 [0x8D] Wls programming key response // Set RF jamming zone 08 in [804][93] subsection
* 10001101 0 00010001 00111001 00000000 00000111 11111111 11111111 11111111 11011011 [0x8D] Wls programming key response // Set RF jamming zone 07 in [804][93] subsection
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0x8D() {
#if !defined(__AVR__)
stream->print(F("Module programming entry: "));
printModuleProgramming(panelData[2], panelData[3]);
#else
stream->print(F("Module programming entry"));
#endif
}
/*
* 0x94: Used to request programming data from modules
* Interval: immediate after entering *5 access code programming, after entering section 801-809 subsection number
* CRC: no
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Unknown
* Byte 3: Unknown
* Byte 4: Unknown
* Byte 5: Unknown
* Byte 6: Unknown
* Byte 7: Unknown
* Byte 8: Unknown
* Byte 9: Unknown
* Byte 10: CRC
*
* Command CRC
* 10010100 0 00010001 00000000 00000000 10100101 00000000 00000000 00000000 00010111 10100000 [0x94] Unknown data
* 10010100 0 00010001 00000000 00000000 10100101 00000000 00000000 00000000 01001100 11111100 [0x94] Unknown data
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0x94() {
#if !defined(__AVR__)
stream->print(F("Module programming request: "));
printModuleProgramming(panelData[2], panelData[3]);
#else
stream->print(F("Module programming request"));
#endif
}
/*
* 0x9E: DLS query
* Structure decoding: complete
* Content decoding: complete
* CRC: no
*
* Bytes 2-6: 11111111
*
* 10011110 0 11111111 11111111 11111111 11111111 11111111 [0x9E] DLS query
* Byte 0 1 2 3 4 5 6
*/
void dscKeybusInterface::printPanel_0x9E() {
stream->print(F("DLS query"));
}
/*
* 0xA5: Date, time, system status messages - partitions 1-2
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2 bit 0-3: Year digit 2
* Byte 2 bit 4-7: Year digit 1
* Byte 3 bit 0-1: Day digit part 1
* Byte 3 bit 2-5: Month
* Byte 3 bit 6-7: Partition
* Byte 4 bit 0-4: Hour
* Byte 4 bit 5-7: Day digit part 2
* Byte 5 bit 0-1: Selects set of status commands
* Byte 5 bit 2-7: Minute
* Byte 6: Status, printPanelStatus0...printPanelStatus3
* Byte 7: Unknown
* Byte 8: CRC
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 10100101 0 00011000 00001110 11101101 10000000 00000000 00000000 00111000 [0xA5] 2018.03.23 13:32 | Timestamp
* 10100101 0 00011000 01001111 11001010 01000100 01001011 11111111 01100100 [0xA5] 2018.03.30 10:17 | Partition 1 | Partition in alarm
* 10100101 0 00011000 01010000 01001001 10111000 01001100 11111111 01011001 [0xA5] 2018.04.02 09:46 | Partition 1 | Zone expander supervisory alarm
* 10100101 0 00011000 01010000 01001010 00000000 01001101 11111111 10100011 [0xA5] 2018.04.02 10:00 | Partition 1 | Zone expander supervisory restored
* 10100101 0 00011000 01001111 01110010 10011100 01001110 11111111 01100111 [0xA5] 2018.03.27 18:39 | Partition 1 | Keypad Fire alarm
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanel_0xA5() {
printPanelTime(2);
if (panelData[6] == 0 && panelData[7] == 0) {
stream->print(F(" | Timestamp"));
return;
}
stream->print(" | ");
switch (panelData[3] >> 6) {
case 0x01: printPartition(); printNumberSpace(1); stream->print("| "); break;
case 0x02: printPartition(); printNumberSpace(2); stream->print("| "); break;
}
switch (panelData[5] & 0x03) {
case 0x00: printPanelStatus0(6); return;
case 0x01: printPanelStatus1(6); return;
case 0x02: printPanelStatus2(6); return;
case 0x03: printPanelStatus3(6); return;
}
}
/*
* 0xAA: Event buffer
* CRC: yes
* Structure decoding: complete
* Content decoding: *incomplete
*
* Byte 2 bit 0-3: Year digit 2
* Byte 2 bit 4-7: Year digit 1
* Byte 3 bit 0-1: Day digit part 1
* Byte 3 bit 2-5: Month
* Byte 3 bit 6-7: Partition
* Byte 4 bit 0-4: Hour
* Byte 4 bit 5-7: Day digit part 2
* Byte 5 bit 0-1: Selects set of status commands
* Byte 5 bit 2-7: Minute
* Byte 6: Status, printPanelStatus0...printPanelStatus3
* Byte 7: Event number
* Byte 8: CRC
*
* Command YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status Event# CRC
* 10101010 0 00100001 01000110 00001000 00100100 00011100 11111111 01011000 [0xAA] Event: 255 | 2021.01.16 08:09 | Zone alarm: 20
* 10101010 0 00100000 01100110 10001101 00111000 10011001 00001000 10010110 [0xAA] Event: 008 | 2020.09.20 13:14 | Armed by user code 1
* 10101010 0 00100000 01100110 10001100 11010000 10111111 00000110 01010001 [0xAA] Event: 006 | 2020.09.20 12:52 | Armed special: quick-arm/auto-arm/keyswitch/wireless key/DLS
* 10101010 0 00100000 01100110 10001100 11010000 11100010 00000010 01110000 [0xAA] Event: 002 | 2020.09.20 12:52 | Disarmed by master code 40
* 10101010 0 00100000 01100110 10001100 11010000 00001011 00000101 10011100 [0xAA] Event: 005 | 2020.09.20 12:52 | Zone alarm: 3
* 10101010 0 00100000 01100110 10001100 11010000 01001011 00000100 11011011 [0xAA] Event: 004 | 2020.09.20 12:52 | Partition in alarm
* 10101010 0 00100000 01100110 10001100 11010110 11100110 00000000 01111000 [0xAA] Event: 000 | 2020.09.20 12:53 | Enter *6 programming
* 10101010 0 00100000 01100110 10101101 10010001 00101011 00000011 10011100 [0xAA] Event: 003 | 2020.09.21 13:36 | Armed by auto-arm
* 10101010 0 00100000 01100110 10101101 11000101 10101101 00000010 01010001 [0xAA] Event: 002 | 2020.09.21 13:49 | Enter *8 programming
* 10101010 0 00100000 01100110 10101101 11000101 10101100 00000001 01001111 [0xAA] Event: 001 | 2020.09.21 13:49 | Exit *8 programming
* 10101010 0 00010110 10011010 00000000 00110110 11000100 00000001 01010101 [0xAA] Event: 001 | 2016.06.16 00:13 | Partition 2 | Unknown data // *5 by code 41
* Byte 0 1 2 3 4 5 6 7 8
*
*/
void dscKeybusInterface::printPanel_0xAA() {
stream->print(F("Event: "));
if (panelData[7] < 10) stream->print("00");
else if (panelData[7] < 100) stream->print("0");
stream->print(panelData[7]);
stream->print(" | ");
printPanelTime(2);
stream->print(" | ");
switch (panelData[3] >> 6) {
case 0x01: printPartition(); printNumberSpace(1); stream->print("| "); break;
case 0x02: printPartition(); printNumberSpace(2); stream->print("| "); break;
}
switch (panelData[5] & 0x03) {
case 0x00: printPanelStatus0(6); return;
case 0x01: printPanelStatus1(6); return;
case 0x02: printPanelStatus2(6); return;
case 0x03: printPanelStatus3(6); return;
}
}
/*
* 0xB1: Enabled zones 1-32, partitions 1,2
* Interval: 4m
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2: Partition 1 enabled zones 1-8
* Byte 3: Partition 1 enabled zones 9-16
* Byte 4: Partition 1 enabled zones 17-24
* Byte 5: Partition 1 enabled zones 25-32
* Byte 6: Partition 2 enabled zones 1-8
* Byte 7: Partition 2 enabled zones 9-16
* Byte 8: Partition 2 enabled zones 17-24
* Byte 9: Partition 2 enabled zones 25-32
* Byte 10: CRC
*
* Command 1:Zone1+ Zones9+ Zones17+ Zones25+ 2:Zone1+ Zones9+ Zones17+ Zones25+ CRC
* 10110001 0 11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10110000 [0xB1] Enabled zones 1-32 | Partition 1: 1 2 3 4 5 6 7 8 | Partition 2: none
* 10110001 0 10010001 10001010 01000001 10100100 00000000 00000000 00000000 00000000 10110001 [0xB1] Enabled zones 1-32 | Partition 1: 1 5 8 10 12 16 17 23 27 30 32 | Partition 2: none
* 10110001 0 11111111 00000000 00000000 11111111 00000000 00000000 00000000 00000000 10101111 [0xB1] Enabled zones 1-32 | Partition 1: 1 2 3 4 5 6 7 8 25 26 27 28 29 30 31 32 | Partition 2: none
* 10110001 0 01111111 11111111 00000000 00000000 10000000 00000000 00000000 00000000 10101111 [0xB1] Enabled zones 1-32 | Partition 1: 1 2 3 4 5 6 7 9 10 11 12 13 14 15 16 | Partition 2: 8
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0xB1() {
stream->print(F("Enabled zones 1-32 | Partition 1: "));
printPanelZones(2, 1);
stream->print(F("| Partition 2: "));
printPanelZones(6, 1);
}
/*
* 0xBB: Bell
* Interval: immediate after alarm tripped except silent zones
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2 bit 0-4: Unknown
* Byte 2 bit 5: Bell status
* Byte 2 bit 6-7: Unknown
* Byte 3: Unknown
* Byte 4: CRC
*
* Command CRC
* 10111011 0 00100000 00000000 11011011 [0xBB] Bell: on
* 10111011 0 00100000 00000101 11100000 [0xBB] Bell: on // PC5015
* 10111011 0 00000000 00000000 10111011 [0xBB] Bell: off
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xBB() {
stream->print(F("Bell: "));
if (bitRead(panelData[2], 5)) stream->print(F("on"));
else stream->print(F("off"));
}
/*
* 0xC3: Keypad and dialer status
* Interval: 30s (PC1616/PC1832/PC1864)
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: bit 0-2 unknown
* Byte 2: bit 3 TLM available or communications disabled (no trouble)
* Byte 2: bit 4 TLM trouble or dialing attempt (with/without trouble)
* Byte 2: bit 5 keypad lockout active
* Byte 2: bit 6-7 unknown
* Byte 3: Unknown, always observed as 11111111
* Byte 4: CRC
*
* Command CRC
* 11000011 0 00001000 11111111 11001010 [0xC3] Unknown data
* 11000011 0 00010000 11111111 11010010 [0xC3] Unknown data
* 11000011 0 00110000 11111111 11110010 [0xC3] Keypad lockout
* 11000011 0 00000000 11111111 11000010 [0xC3] Keypad ready
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xC3() {
if (panelData[3] == 0xFF) {
stream->print(F("TLM: "));
if (panelData[2] & 0x10) stream->print(F("trouble/attempt"));
else stream->print(F("available/disabled"));
if (panelData[2] & 0x08) stream->print(F(" | Dialer call attempt"));
if (panelData[2] & 0x20) stream->print(F(" | Keypad lockout"));
}
else printUnknownData();
}
/*
* 0xCE: Panel status
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Unknown
* Byte 3 bit 0-1: Selects set of status commands
* Byte 3 bit 2-7: Unknown
* Byte 4: Status, printPanelStatus0...printPanelStatus2
* Byte 5: Unknown
* Byte 6: Unknown
* Byte 7: CRC
*
* Command Status CRC
* 11001110 0 00100000 00000000 11101001 00000000 00000000 11010111 [0xCE] Bell trouble
* 11001110 0 00100000 00011101 10001100 00000000 00000000 10010111 [0xCE] Zone fault: 1
* 11001110 0 00100000 10001100 01010000 00000000 00000000 11001010 [0xCE] Keypad Panic alarm
* Byte 0 1 2 3 4 5 6 7
*
* Command Unknown CRC
* 11001110 0 00000001 10100000 00000000 00000000 00000000 01101111 [0xCE] Unknown data [Byte 2/0x01] // Partition 1 exit delay
* 11001110 0 00000001 10110001 00000000 00000000 00000000 10000000 [0xCE] Unknown data [Byte 2/0x01] // Partition 1 armed stay
* 11001110 0 00000001 10110011 00000000 00000000 00000000 10000010 [0xCE] Unknown data [Byte 2/0x01] // Partition 1 armed away
* 11001110 0 00000001 10100100 00000000 00000000 00000000 01110011 [0xCE] Unknown data [Byte 2/0x01] // Partition 2 armed away
* 11001110 0 01000000 11111111 11111111 11111111 11111111 00001010 [0xCE] Unknown data [Byte 2/0x40] // Unknown data
* 11001110 0 01000000 11111111 11111111 11111111 11111111 00001010 [0xCE] Unknown data [Byte 2/0x40] // LCD: System is in Alarm
* Byte 0 1 2 3 4 5 6 7
*/
void dscKeybusInterface::printPanel_0xCE() {
if (panelData[2] & 0x20) {
switch (panelData[3] & 0x03) {
case 0x00: printPanelStatus0(4); return;
case 0x01: printPanelStatus1(4); return;
case 0x02: printPanelStatus2(4); return;
case 0x03: printPanelStatus3(4); return;
}
}
else {
printUnknownData();
stream->print(F(" [Byte 2/0x"));
if (panelData[2] < 16) stream->print("0");
stream->print(panelData[2], HEX);
stream->print(F("] "));
}
}
/*
* 0xD5: Keypad zone query
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 2-9: 1010101010
*
* 11111111 1 11111111 11111111 11111111 11111011 [Module/0x05] Keypad zone status notification
* 11010101 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0xD5] Keypad zone query
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 [Module/0xD5] [Keypad] Slot 8 zone open
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0xD5() {
stream->print(F("Keypad zone query"));
}
/*
* 0xE6: Extended status, partitions 1-8
* Panels: PC5020, PC1616, PC1832, PC1864
*
* 0xE6 commands are split into multiple subcommands to handle up to 8 partitions/64 zones.
*
* Byte 2: Subcommand
*/
void dscKeybusInterface::printPanel_0xE6() {
switch (panelData[2]) {
case 0x08:
case 0x0A:
case 0x0C:
case 0x0E: break; // Skips panel commands without CRC data
default: { // Checks remaining panel commands
if (!validCRC()) {
stream->print(F("[CRC Error]"));
return;
}
}
}
switch (panelData[2]) {
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x20:
case 0x21: printPanel_0xE6_0x01_06_20_21(); break; // Partitions 1-8 status in programming | Structure: *incomplete | Content: *incomplete
case 0x08:
case 0x0A:
case 0x0C:
case 0x0E: printPanel_0xE6_0x08_0A_0C_0E(); break; // Zone expander 4-7 query | Structure: complete | Content: complete
case 0x09: printPanel_0xE6_0x09(); break; // Zones 33-40 status | Structure: complete | Content: complete
case 0x0B: printPanel_0xE6_0x0B(); break; // Zones 41-48 status | Structure: complete | Content: complete
case 0x0D: printPanel_0xE6_0x0D(); break; // Zones 49-56 status | Structure: complete | Content: complete
case 0x0F: printPanel_0xE6_0x0F(); break; // Zones 57-64 status | Structure: complete | Content: complete
case 0x17: printPanel_0xE6_0x17(); break; // Flash panel lights: status and zones 1-32, partitions 1-8 | Structure: complete | Content: complete
case 0x18: printPanel_0xE6_0x18(); break; // Flash panel lights: status and zones 33-64, partitions 1-8 | Structure: complete | Content: complete
case 0x19: printPanel_0xE6_0x19(); break; // Beep, partitions 3-8 | Structure: complete | Content: complete
case 0x1A: printPanel_0xE6_0x1A(); break; // Panel status | Structure: *incomplete | Content: *incomplete
case 0x1D: printPanel_0xE6_0x1D(); break; // Tone, partitions 3-8 | Structure: complete | Content: complete
case 0x1F: printPanel_0xE6_0x1F(); break; // Buzzer, partitions 3-8 | Structure: complete | Content: complete
case 0x2B: printPanel_0xE6_0x2B(); break; // Enabled zones 1-32, partitions 1-8 | Structure: complete | Content: complete
case 0x2C: printPanel_0xE6_0x2C(); break; // Enabled zones 33-64, partitions 1-8 | Structure: complete | Content: complete
case 0x41: printPanel_0xE6_0x41(); break; // Status in access code programming, zone lights 65-95| Structure: *incomplete | Content: *incomplete
default: stream->print("Unknown data");
}
}
/*
* 0xE6.01 - 0xE6.06: Status in alarm/programming, partitions 1-8
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Command Subcommand Lights Status Zones33+ Zones41+ Zones49+ Zones57+ CRC
* 11100110 0 00000001 10000010 11100100 00000000 00000000 00000000 00000000 00000000 01001101 [0xE6.01] Partition 3: Armed Backlight - *8: Installer programming
* 11100110 0 00000010 10000010 11100100 00000000 00000000 00000000 00000000 00000000 01001110 [0xE6.02] Partition 4: Armed Backlight - *8: Installer programming
* 11100110 0 00000011 10000001 11111000 00000000 00000000 00000000 00000000 00000000 01100010 [0xE6.03] Partition 5: Ready Backlight - Keypad programming
* 11100110 0 00000100 10000010 11100100 00000000 00000000 00000000 00000000 00000000 01010000 [0xE6.04] Partition 6: Armed Backlight - *8: Installer programming
* 11100110 0 00000101 10000010 11100100 00000000 00000000 00000000 00000000 00000000 01010001 [0xE6.05] Partition 7: Armed Backlight - *8: Installer programming
* 11100110 0 00000110 10000010 11100100 00000000 00000000 00000000 00000000 10000000 11010010 [0xE6.06] Partition 8: Armed Backlight - *8: Installer programming
* 11100110 0 00100000 10000000 10011110 00000000 00000000 00000000 00000000 10000000 10100100 [0xE6.20] Partition 1: Backlight - Enter * function code | Zone lights: none
* 11100110 0 00100000 10000000 10011111 00000000 00000000 00000000 00000000 10000000 10100101 [0xE6.20] Partition 1: Backlight - Enter access code | Zone lights: none
* 11100110 0 00100000 10000001 11111000 00000000 00000000 00000000 00000000 10000000 11111111 [0xE6.20] Partition 1: Ready Backlight - Keypad programming | Zone lights: none
* 11100110 0 00100000 10000010 10100110 10000000 00000001 00000000 00000000 10000000 00101111 [0xE6.20] Partition 1: Armed Backlight - *5: Access codes | Zones 33-64 lights: 40 41
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0xE6_0x01_06_20_21() {
byte partition = 0;
switch(panelData[2]) {
case 0x01: partition = 3; break;
case 0x02: partition = 4; break;
case 0x03: partition = 5; break;
case 0x04: partition = 6; break;
case 0x05: partition = 7; break;
case 0x06: partition = 8; break;
case 0x20: partition = 1; break;
case 0x21: partition = 2; break;
}
printPanelPartitionStatus(partition, 4, 4);
if (panelData[9] & 0x80) {
printZoneLights(false);
printPanelZones(5, 33);
}
else {
printZoneLights();
printPanelZones(5,1);
}
}
/*
* 0xE6.08,0A,0C,0E: Zone expander 4-7 query
* Interval: immediate after zone expander status notification
* CRC: no
* Structure decoding: complete
* Content decoding: complete
*
* Bytes 3-8: 11111111
*
* 11111111 1 11111111 11111111 11111111 11111111 11111111 01111111 11111111 11111111 [Module/0x05] Zone expander notification: 4
* 11100110 0 00001000 11111111 11111111 11111111 11111111 11111111 11111111 [0xE6.08] Zone expander query: 4
* 11111111 1 11111111 11000011 11001111 11111111 11111111 10101111 11111111 [Module/0xE6] Zone expander: 4 | Zones changed: 34 open
*
* 11111111 1 11111111 11111111 11111111 11111111 11111111 10111111 11111111 11111111 [Module/0x05] Zone expander notification: 5
* 11100110 0 00001010 11111111 11111111 11111111 11111111 11111111 11111111 [0xE6.0A] Zone expander query: 5
* 11111111 1 11111111 11000011 11001111 11111111 11111111 10101111 11111111 [Module/0xE6] Zone expander: 5 | Zones changed: 42 open
*
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11011111 11111111 11111111 [Module/0x05] Zone expander notification: 6
* 11100110 0 00001100 11111111 11111111 11111111 11111111 11111111 11111111 [0xE6.0C] Zone expander query: 6
* 11111111 1 11111111 11000011 11001111 11111111 11111111 10101111 11111111 [Module/0xE6] Zone expander: 6 | Zones changed: 50 open
*
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11101111 11111111 11111111 [Module/0x05] Zone expander notification: 7
* 11100110 0 00001110 11111111 11111111 11111111 11111111 11111111 11111111 [0xE6.0E] Zone expander query: 7
* 11111111 1 11111111 11000011 11001111 11111111 11111111 10101111 11111111 [Module/0xE6] Zone expander: 7 | Zones changed: 58 open
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanel_0xE6_0x08_0A_0C_0E() {
byte expander = 0;
switch (panelData[2]) {
case 0x08: expander = 4; break;
case 0x0A: expander = 5; break;
case 0x0C: expander = 6; break;
case 0x0E: expander = 7; break;
}
stream->print(F("Zone expander query: "));
stream->print(expander);
}
/*
* 0xE6.09: Zones 33-40 status
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3 bit 0-7: Zone 33-40
* Byte 4: CRC
*
* Command Subcommand Zones33+ CRC
* 11100110 0 00001001 00000000 11101111 [0xE6.09] Zones 33-40 open: none
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xE6_0x09() {
stream->print(F("Zones 33-40 open: "));
printPanelBitNumbers(3, 33);
}
/*
* 0xE6.0B: Zones 41-48 status
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3 bit 0-7: Zone 41-48
* Byte 4: CRC
*
* Command Subcommand Zones41+ CRC
* 11100110 0 00001011 00000000 11110001 [0xE6.0B] Zones 41-48 open: none
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xE6_0x0B() {
stream->print(F("Zones 41-48 open: "));
printPanelBitNumbers(3, 41);
}
/*
* 0xE6.0D: Zones 49-56 status
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3 bit 0-7: Zone 49-56
* Byte 4: CRC
*
* Command Subcommand Zones49+ CRC
* 11100110 0 00001101 00000000 11110011 [0xE6.0D] Zones 49-56 open: none
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xE6_0x0D() {
stream->print(F("Zones 49-56 open: "));
printPanelBitNumbers(3, 49);
}
/*
* 0xE6.0F: Zones 57-64 status
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3 bit 0-7: Zone 57-64
* Byte 4: CRC
*
* Command Subcommand Zones57+ CRC
* 11100110 0 00001111 00000000 11110101 [0xE6.0F] Zones 57-64 open: none
* Byte 0 1 2 3 4
*/
void dscKeybusInterface::printPanel_0xE6_0x0F() {
stream->print(F("Zones 57-64 open: "));
printPanelBitNumbers(3, 57);
}
/*
* 0xE6.17: Flash panel lights: status and zones 1-32, partitions 1-8
* Interval: intermittent
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition
* Byte 4: Status lights flashing
* Byte 5: Zones 1-8
* Byte 6: Zones 9-16
* Byte 7: Zones 17-24
* Byte 8: Zones 25-32
* Byte 9: CRC
*
* Command Subcmd Partition Lights Zones1+ Zones9+ Zones17+ Zones25+ CRC
* 11100110 0 00010111 00000100 00000000 00000100 00000000 00000000 00000000 00000101 [0xE6.17] Partition 3 | Status lights flashing: none | Zones 1-32 flashing: 3
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0xE6_0x17() {
printPartition();
printPanelBitNumbers(3, 1);
printStatusLightsFlashing();
printPanelLights(4, false);
stream->print(F("| Zones 1-32 flashing: "));
printPanelZones(5, 1);
}
/*
* 0xE6.18: Flash panel lights: status and zones 33-64, partitions 1-8
* Interval: intermittent
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition
* Byte 4: Status lights flashing
* Byte 5: Zones 33-40
* Byte 6: Zones 41-48
* Byte 7: Zones 49-56
* Byte 8: Zones 57-64
* Byte 9: CRC
*
* Command Subcmd Partition Lights Zones33+ Zones41+ Zones49+ Zones57+ CRC
* 11100110 0 00011000 00000001 00000000 00000000 00000000 00000000 00000000 11111111 [0xE6.18] Partition 1 | Status lights flashing: none | Zones 33-64 flashing: none
* 11100110 0 00011000 00000001 00000000 00000001 00000000 00000000 00000000 00000000 [0xE6.18] Partition 1 | Status lights flashing: none | Zones 33-64 flashing: 33
* 11100110 0 00011000 00000001 00000100 00000000 00000000 00000000 10000000 10000011 [0xE6.18] Partition 1 | Status lights flashing: Memory | Zones 33-64 flashing: 64
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printPanel_0xE6_0x18() {
printPartition();
printPanelBitNumbers(3, 1);
printStatusLightsFlashing();
printPanelLights(4, false);
stream->print(F("| Zones 33-64 flashing: "));
printPanelZones(5, 33);
}
/*
* 0xE6.19: Beep, partitions 3-8
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition number
* Byte 4: Beeps number
* Byte 5: CRC
*
* Command Subcmd Partition Beeps CRC
* 11100110 0 00011001 00000100 00000110 00001001 [0xE6.19] Partition 3 | Beep: 3 beeps
* 11100110 0 00011001 00001000 00001100 00010011 [0xE6.19] Partition 4 | Beep: 6 beeps
* Byte 0 1 2 3 4 5
*/
void dscKeybusInterface::printPanel_0xE6_0x19() {
printPartition();
printPanelBitNumbers(3, 1);
printPanelBeeps(4);
}
/*
* 0xE6.1A: Panel status
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 3: Unknown
* Byte 4: Partitions in alarm
* Byte 5: Unknown
* Byte 6 bit 0-2: Unknown
* Byte 6 bit 3: Loss of system time status
* Byte 6 bit 4: AC power trouble status
* Byte 6 bit 5: Unknown
* Byte 6 bit 6: Fail to communicate status
* Byte 6 bit 7: Fire alarm
* Byte 7: Unknown
* Byte 8: Unknown
* Byte 9: Unknown
* Byte 10: CRC
*
* Command Subcmd Alarm CRC
* 11100110 0 00011010 01000000 00000001 00000000 00010001 00000000 00000000 00000000 01010010 [0xE6.1A] Partitions in alarm: 1 | AC power trouble
* 11100110 0 00011010 01000000 00000000 00000000 00011001 00000000 00000000 00000000 01011001 [0xE6.1A] Partitions in alarm: none | Loss of system time | AC power trouble
* 11100110 0 00011010 01000000 00000000 00000000 00001001 00000000 00000000 00000000 01001001 [0xE6.1A] Partitions in alarm: none | Loss of system time // All partitions exit delay in progress, disarmed
* 11100110 0 00011010 01000000 00010001 00000000 00001001 00000000 00000000 00000000 01011010 [0xE6.1A] Partitions in alarm: 1 5 | Loss of system time // Keypad panic alarm
* 11100110 0 00011010 01000000 00000010 00000000 00001001 00000000 00000000 00000000 01001011 [0xE6.1A] Partitions in alarm: 2 | Loss of system time
* 11100110 0 00011010 01000000 00000001 00000000 00001001 00000000 00000000 00000000 01001010 [0xE6.1A] Partitions in alarm: 1 | Loss of system time
* 11100110 0 00011010 01000000 10000000 00000000 00001001 00000000 00000000 00000000 11001001 [0xE6.1A] Partitions in alarm: 8 | Loss of system time
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0xE6_0x1A() {
stream->print(F("Partitions in alarm: "));
printPanelBitNumbers(4, 1);
if (panelData[6] & 0x08) stream->print(F("| Loss of system time "));
if (panelData[6] & 0x10) stream->print(F("| AC power trouble "));
if (panelData[6] & 0x40) stream->print(F("| Fail to communicate "));
if (panelData[6] & 0x80) stream->print(F("| Fire alarm "));
}
/*
* 0xE6.1D: Tone, partitions 3-8
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition number
* Byte 4: Tone
* Byte 5: CRC
*
* Command Subcmd Partition Tone CRC
* 11100110 0 00011101 00000100 00000000 00000111 [0xE6.1D] Partition 3 | Tone: off
* 11100110 0 00011101 00001000 10000000 10001011 [0xE6.1D] Partition 4 | Tone: constant tone
* Byte 0 1 2 3 4 5
*/
void dscKeybusInterface::printPanel_0xE6_0x1D() {
printPartition();
printPanelBitNumbers(3, 1);
printPanelTone(4);
}
/*
* 0xE6.1F: Buzzer, partitions 3-8
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition number
* Byte 4: Buzzer pattern
* Byte 5: CRC
*
* Command Subcmd Partition Buzzer CRC
* 11100110 0 00011111 00001000 00000001 00001110 [0xE6.1F] Partition 4 | Buzzer: 1s
* Byte 0 1 2 3 4 5
*/
void dscKeybusInterface::printPanel_0xE6_0x1F() {
printPartition();
printPanelBitNumbers(3, 1);
printPanelBuzzer(4);
}
/*
* 0xE6.2B: Enabled zones 1-32, partitions 3-8
* Interval: 60s
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition number
* Byte 4: Zones enabled 1-8
* Byte 5: Zones enabled 9-16
* Byte 6: Zones enabled 17-24
* Byte 7: Zones enabled 25-32
* Byte 8: CRC
*
* Command Subcmd Partition Zones1+ Zones9+ Zones17+ Zones25+ CRC
* 11100110 0 00101011 00000100 00000100 00000000 00000000 00000000 00011001 [0xE6.2B] Partition 3 | Enabled zones 1-32: 3
* 11100110 0 00101011 00001000 00001000 00000000 00000000 00000000 00100001 [0xE6.2B] Partition 4 | Enabled zones 1-32: 4
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanel_0xE6_0x2B() {
printPartition();
printPanelBitNumbers(3, 1);
stream->print(F("| Enabled zones 1-32: "));
printPanelZones(4, 1);
}
/*
* 0xE6.2C: Enabled zones 33-64, partitions 1-8
* Interval: 60s
* CRC: yes
* Structure decoding: complete
* Content decoding: complete
*
* Byte 3: Partition number
* Byte 4: Zones enabled 33-40
* Byte 5: Zones enabled 41-48
* Byte 6: Zones enabled 49-56
* Byte 7: Zones enabled 57-64
* Byte 8: CRC
*
* Command Subcmd Partition Zones33+ Zones41+ Zones49+ Zones57+ CRC
* 11100110 0 00101100 00000001 00000000 00000000 00000000 00000000 00010011 [0xE6.2C] Partition 1 | Enabled zones 33-64: none
* 11100110 0 00101100 00000010 00000000 00000000 00000000 00000000 00010100 [0xE6.2C] Partition 2 | Enabled zones 33-64: none
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printPanel_0xE6_0x2C() {
printPartition();
printPanelBitNumbers(3, 1);
stream->print(F("| Enabled zones 33-64: "));
printPanelZones(4, 33);
}
/*
* 0xE6.41: Status in programming, zone lights 65-95
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* (log data samples needed)
*/
void dscKeybusInterface::printPanel_0xE6_0x41() {
printStatusLights();
printPanelLights(3);
printZoneLights();
printPanelZones(5, 65);
}
/*
* 0xEB: Date, time, system status messages - partitions 1-8
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Partition
* Byte 3 bit 0-3: Year digit 2
* Byte 3 bit 4-7: Year digit 1
* Byte 4 bit 0-1: Day digit part 1
* Byte 4 bit 2-5: Month
* Byte 4 bit 6-7: Unknown
* Byte 5 bit 0-4: Hour
* Byte 5 bit 5-7: Day digit part 2
* Byte 6 bit 0-1: Unknown
* Byte 6 bit 2-7: Minute
* Byte 7: Selects set of status commands
* Byte 8: Status, printPanelStatus0...printPanelStatus1X
* Byte 9: Unknown
* Byte 10: CRC
*
* Partition YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status CRC
* 11101011 0 00000001 00011000 00011000 10001010 00101100 00000000 10111011 00000000 10001101 [0xEB] 2018.06.04 10:11 | Partition 1 | Armed by master code 40
* 11101011 0 00000001 00011000 00011000 10001010 00111000 00000000 10111011 00000000 10011001 [0xEB] 2018.06.04 10:14 | Partition 1 | Armed by master code 40
* 11101011 0 00000001 00011000 00011000 10001010 00111000 00000010 10011011 00000000 01111011 [0xEB] 2018.06.04 10:14 | Partition 1 | Armed: away
* 11101011 0 00000001 00011000 00011000 10001010 00110100 00000000 11100010 00000000 10111100 [0xEB] 2018.06.04 10:13 | Partition 1 | Disarmed by master code 40
* 11101011 0 00000001 00011000 00011000 10001111 00101000 00000100 00000000 10010001 01101000 [0xEB] 2018.06.04 15:10 | Partition 1 | Zone alarm: 33
* 11101011 0 00000001 00000001 00000100 01100000 00010100 00000100 01000000 10000001 00101010 [0xEB] 2001.01.03 00:05 | Partition 1 | Zone tamper: 33
* 11101011 0 00000001 00000001 00000100 01100000 00001000 00000100 01011111 10000001 00111101 [0xEB] 2001.01.03 00:02 | Partition 1 | Zone tamper: 64
* 11101011 0 00000001 00000001 00000100 01100000 00011000 00000100 01100000 11111111 11001100 [0xEB] 2001.01.03 00:06 | Partition 1 | Zone tamper restored: 33
* 11101011 0 00000000 00000001 00000100 01100000 01001000 00010100 01100000 10000001 10001101 [0xEB] 2001.01.03 00:18 | Zone fault: 33
* 11101011 0 00000000 00000001 00000100 01100000 01001100 00010100 01000000 11111111 11101111 [0xEB] 2001.01.03 00:19 | Zone fault restored: 33
* 11101011 0 00000000 00000001 00000100 01100000 00001100 00010100 01011111 11111111 11001110 [0xEB] 2001.01.03 00:03 | Zone fault restored: 64
* 11101011 0 00000001 00011000 00011000 00100000 01101100 00010111 00100010 00000000 11100001 [0xEB] 2018.06.01 00:27 | Partition 1 | // Unknown data, immediate after entering *2 menu
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printPanel_0xEB() {
printPanelTime(3);
if (panelData[2] == 0) stream->print(" | ");
else {
stream->print(F(" | Partition "));
printPanelBitNumbers(2, 1);
stream->print("| ");
}
switch (panelData[7]) {
case 0x00: printPanelStatus0(8); return;
case 0x01: printPanelStatus1(8); return;
case 0x02: printPanelStatus2(8); return;
case 0x03: printPanelStatus3(8); return;
case 0x04: printPanelStatus4(8); return;
case 0x05: printPanelStatus5(8); return;
case 0x14: printPanelStatus14(8); return;
case 0x16: printPanelStatus16(8); return;
case 0x17: printPanelStatus17(8); return;
case 0x18: printPanelStatus18(8); return;
case 0x1B: printPanelStatus1B(8); return;
}
printUnknownData();
}
/*
* 0xEC: Event buffer - partitions 1-8
* CRC: yes
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Partition
* Byte 3 bit 0-3: Year digit 2
* Byte 3 bit 4-7: Year digit 1
* Byte 4 bit 0-1: Day digit part 1
* Byte 4 bit 2-5: Month
* Byte 4 bit 6-7: Event number multiplier (* 256)
* Byte 5 bit 0-4: Hour
* Byte 5 bit 5-7: Day digit part 2
* Byte 6 bit 0-1: Unknown
* Byte 6 bit 2-7: Minute
* Byte 7: Selects set of status commands
* Byte 8: Status, printPanelStatus0...printPanelStatus1X
* Byte 9: Event number
* Byte 10: CRC
*
* Partition YYY1YYY2 MMMMDD DDDHHHHH MMMMMM Status Event# CRC
* 11101100 0 00000000 00100000 00101101 01100011 10111100 00000001 10101100 00001011 00010000 [0xEC] Event: 011 | 2020.11.11 03:47 | Exit *8 programming
* 11101100 0 00000000 00100000 00110000 00100000 00000000 00000011 00001010 00001001 01110010 [0xEC] Event: 009 | 2020.12.01 00:00 | PC5204: Supervisory trouble
* 11101100 0 00000000 00010110 00011000 10100001 01000000 00000010 10010001 11111100 10001010 [0xEC] Event: 252 | 2016.06.05 01:16 | Swinger shutdown
* 11101100 0 00000000 00010110 01011000 10100001 00101000 00000010 10010001 00000100 10111010 [0xEC] Event: 260 | 2016.06.05 01:10 | Swinger shutdown
* 11101100 0 00000000 00001011 01000100 00100000 00000000 11111111 11111111 01110100 11001101 [0xEC] Event: 372 | 200B.01.01 00:00 | No entry
* Byte 0 1 2 3 4 5 6 7 8 9 10
*
*/
void dscKeybusInterface::printPanel_0xEC() {
int eventNumber = panelData[9] + ((panelData[4] >> 6) * 256);
stream->print(F("Event: "));
if (eventNumber < 10) stream->print("00");
else if (eventNumber < 100) stream->print("0");
stream->print(eventNumber);
stream->print(" | ");
printPanelTime(3);
stream->print(" | ");
if (panelData[2] != 0) {
printPartition();
printPanelBitNumbers(2, 1);
stream->print("| ");
}
switch (panelData[7]) {
case 0x00: printPanelStatus0(8); return;
case 0x01: printPanelStatus1(8); return;
case 0x02: printPanelStatus2(8); return;
case 0x03: printPanelStatus3(8); return;
case 0x04: printPanelStatus4(8); return;
case 0x05: printPanelStatus5(8); return;
case 0x14: printPanelStatus14(8); return;
case 0x16: printPanelStatus16(8); return;
case 0x17: printPanelStatus17(8); return;
case 0x18: printPanelStatus18(8); return;
case 0x1B: printPanelStatus1B(8); return;
case 0xFF: stream->print(F("No entry")); return;
}
printUnknownData();
}
/*
* Keypad: Fire alarm
* Structure decoding: complete
* Content decoding: complete
*
* Byte 0: 10111011
*
* 10111011 1 11111111 11111111 11111111 11111111 11111111 11111111 [Keypad] Fire alarm
*/
void dscKeybusInterface::printModule_0xBB() {
stream->print(F("[Keypad] Fire alarm"));
}
/*
* Keypad: Auxiliary alarm
* Structure decoding: complete
* Content decoding: complete
*
* Byte 0: 11011101
*
* 11011101 1 11111111 11111111 11111111 11111111 11111111 11111111 [Keypad] Aux alarm
*/
void dscKeybusInterface::printModule_0xDD() {
stream->print(F("[Keypad] Auxiliary alarm"));
}
/*
* Keypad: Panic alarm
* Structure decoding: complete
* Content decoding: complete
*
* Byte 0: 11101110
*
* 11101110 1 11111111 11111111 11111111 11111111 11111111 11111111 [Keypad] Panic alarm
*/
void dscKeybusInterface::printModule_0xEE() {
stream->print(F("[Keypad] Panic alarm"));
}
/*
* Module data during panel commands 0x05, 0x0A, 0x1B: Panel status
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Keypad keys: 0x05/0x0A Partition 1, 0x1B Partition 5
* Byte 3: Keypad keys: 0x05/0x0A Partition 2, 0x1B Partition 6
* Byte 4 bit 0: Module tamper notification, panel response: 0x4C Module tamper query
* Byte 4 bit 1-2: Unknown
* Byte 4 bit 3: Wireless module battery notification, panel response: 0x41 Wireless module query
* Byte 4 bit 4: Zone expander 3 notification, panel response: 0x39 Zone expander 3 query
* Byte 4 bit 5: Zone expander 2 notification, panel response: 0x33 Zone expander 2 query
* Byte 4 bit 6: Zone expander 1 notification, panel response: 0x28 Zone expander 1 query
* Byte 4 bit 7: Zone expander 0 notification, panel response: 0x22 Zone expander 0 query
* Byte 5 bit 0: Unknown
* Byte 5 bit 1: Wireless module unknown notification, panel response: 0xE6.25 then Module0xE6
* Byte 5 bit 2: Keypad zone status notification, panel response: 0xD5 Keypad zone query
* Byte 5 bit 3-4: Unknown
* Byte 5 bit 5: Module status notification, panel response: 0x58 Module status query
* Byte 5 bit 6-7: Unknown
*
* Later generation panels:
* Byte 6: Unknown
* Byte 7 bit 0-2: Unknown
* Byte 7 bit 3: Keypad idle notification, panel response: 0x1B, keypad responds on byte 4 with its partition number
* Byte 7 bit 4: Zone expander 7 notification, panel response: 0xE6.0E Zone expander 7 query
* Byte 7 bit 5: Zone expander 6 notification, panel response: 0xE6.0C Zone expander 6 query
* Byte 7 bit 6: Zone expander 5 notification, panel response: 0xE6.0A Zone expander 5 query
* Byte 7 bit 7: Zone expander 4 notification, panel response: 0xE6.08 Zone expander 4 query
* Byte 8: Keypad keys: 0x05/0x0A Partition 3, 0x1B Partition 7
* Byte 9: Keypad keys: 0x05/0x0A Partition 4, 0x1B Partition 8
*
* 00000101 0 10000001 00000001 10010001 11000111 [0x05] Partition 1: Ready Backlight - Partition ready | Partition 2: disabled
*
* Module 1:Keys 2:Keys
* 11111111 1 00000101 11111111 11111111 11111111 [Module/0x05] Partition 1 Key: 1
* 11111111 1 11111111 00010001 11111111 11111111 [Module/0x05] Partition 2 Key: 4
* 11111111 1 11111111 11111111 01111111 11111111 [Module/0x05] Zone expander notification: 0
* 11111111 1 11111111 11111111 10111111 11111111 [Module/0x05] Zone expander notification: 1
* 11111111 1 11111111 11111111 11011111 11111111 [Module/0x05] Zone expander notification: 2
* 11111111 1 11111111 11111111 11101111 11111111 [Module/0x05] Zone expander notification: 3
* 11111111 1 11111111 11111111 11110111 11111111 [Module/0x05] Wireless module battery notification
* 11111111 1 11111111 11111111 11111110 11111111 [Module/0x05] Module tamper notification
* 11111111 1 11111111 11111111 11111111 11011111 [Module/0x05] Module status notification
* 11111111 1 11111111 11111111 11111111 11111011 [Module/0x05] Keypad zone notification
* Byte 0 1 2 3 4 5
*
* Later generation panels:
*
* Module 1:Keys 2:Keys 3:Keys 4:Keys
* 11111111 1 11111111 11111111 11111111 11111111 11111111 01111111 11111111 11111111 [Module/0x05] Zone expander notification: 4
* 11111111 1 11111111 11111111 11111111 11111111 11111111 10111111 11111111 11111111 [Module/0x05] Zone expander notification: 5
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11011111 11111111 11111111 [Module/0x05] Zone expander notification: 6
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11101111 11111111 11111111 [Module/0x05] Zone expander notification: 7
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11110111 11111111 11111111 [Module/0x05] // Unknown notification, observed on PC1832
* Byte 0 1 2 3 4 5 6 7 8 9
*
* Module 5:Keys 6:Keys 7:Keys 8:Keys
* 11111111 1 00000101 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x1B] Partition 5 Key: 1
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printModule_Status() {
bool printedMessage = false;
// Keypad keys
if (printModule_Keys()) printedMessage = true;
// Keypad partition
if (moduleCmd == 0x1B && moduleData[4] != 0xFF) {
if (printedMessage) stream->print("| ");
stream->print(F("Keypad on partition: "));
printModuleSlots(1, 4, 4, 0x80, 0, 1, 0, true);
stream->print(F("going idle"));
printedMessage = true;
}
else {
// Zone expander notification
if ((moduleData[4] & 0xF0) != 0xF0 || (moduleByteCount > 6 && (moduleData[7] & 0xF0) != 0xF0)) {
if (printedMessage) stream->print("| ");
stream->print(F("Zone expander notification: "));
printedMessage = true;
printModuleSlots(0, 4, 4, 0x80, 0x10, 1, 0);
if (moduleByteCount > 6) {
printModuleSlots(4, 7, 7, 0x80, 0x20, 1, 0);
if ((moduleData[7] & 0x10) == 0) printNumberSpace(7);
}
}
// Module tamper notification, panel responds with 0x4C query
if ((moduleData[4] & 0x01) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Module tamper notification "));
printedMessage = true;
}
// Wireless module battery notification
if ((moduleData[4] & 0x08) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Wireless module battery notification "));
printedMessage = true;
}
}
// Unknown wireless notification, panel responds with 0xE6.25 then Module0xE6
if ((moduleData[5] & 0x02) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Wireless notification "));
printedMessage = true;
}
//Keypad zone notification, panel responds with 0xD5 query
if ((moduleData[5] & 0x04) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Keypad zone notification "));
printedMessage = true;
}
// Module status notification, panel responds with 0xD5 query
if ((moduleData[5] & 0x20) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Module status notification "));
printedMessage = true;
}
// Module status notification, panel responds with 0xD5 query
if ((moduleData[5] & 0x40) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Wireless key notification "));
printedMessage = true;
}
//Unknown keypad notification
if (moduleByteCount > 6 && (moduleData[7] & 0x08) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Keypad notification "));
printedMessage = true;
}
if (moduleByteCount > 6 && (moduleData[6] & 0x80) == 0 && (moduleData[6] & 0x60) != 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Door chime broadcast "));
printedMessage = true;
}
if (moduleByteCount > 6 && (moduleData[6] & 0x60) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("Zone label broadcast "));
printedMessage = true;
}
if (!printedMessage) printUnknownData();
}
/*
* Module data during panel command 0x11: Module supervision query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2 bit 0-1: Keypad slot 4
* Byte 2 bit 2-3: Keypad slot 3
* Byte 2 bit 4-5: Keypad slot 2
* Byte 2 bit 6-7: Keypad slot 1
* Byte 3 bit 0-1: Keypad slot 8
* Byte 3 bit 2-3: Keypad slot 7
* Byte 3 bit 4-5: Keypad slot 6
* Byte 3 bit 6-7: Keypad slot 5
*
* Early generation panels:
* Byte 4 bit 0-3: Zone expander 2
* Byte 4 bit 4-7: Zone expander 1
* Byte 5 bit 0-1: PC5208 PGM module (?)
* Byte 5 bit 2-3: PC/RF5132
* Byte 5 bit 4-7: Zone expander 3
* Byte 6 bit 0-5: Unknown
* Byte 6 bit 6-7: PC5204
*
* 00010001 0 10101010 10101010 10101010 10101010 10101010 [0x11] Module supervision query
*
* Slots
* Module 1 2 3 4 5 6 7 8 9 10 11
* 11111111 1 00111111 11111111 11111111 11111111 11111111 [Module/0x11] Keypad slots: 1
* 11111111 1 11111111 11111100 00001111 11111111 11111111 [Module/0x11] Keypad slots: 8 | Zone expander: 1
* Byte 0 1 2 3 4 5 6
*
* Later generation panels:
* Byte 4 bit 0-1: Zone expander 4
* Byte 4 bit 2-3: Zone expander 3
* Byte 4 bit 4-5: Zone expander 2
* Byte 4 bit 6-7: Zone expander 1
* Byte 5 bit 0-1: PC5208 PGM module
* Byte 5 bit 2-3: PC/RF5132
* Byte 5 bit 4-5: Zone expander 6
* Byte 5 bit 6-7: Zone expander 5
* Byte 6 bit 0-5: Unknown
* Byte 6 bit 6-7: PC5204
* Byte 7 bit 0-1: Zone expander 7
* Byte 7 bit 2-7: Unknown
* Byte 8: Unknown
*
* 00010001 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x11] Module supervision query
*
* Slots
* Module 1 2 3 4 5 6 7 8 9 12 14 16
* 11111111 1 00111111 11111111 00001111 11110011 11111111 11111111 11111111 [Module/0x11] Keypad slots: 1 | Zone expander: 1 2 | PC/RF5132
* 11111111 1 00111111 11111111 11001111 11111111 11111111 11111100 11111111 [Module/0x11] Keypad slots: 1 | Zone expander: 2 7
* 11111111 1 11111111 11111100 00111111 11111111 00111111 11111111 11111111 [Module/0x11] Keypad slots: 8 | Zone expander: 1 | PC5204
* Byte 0 1 2 3 4 5 6 7 8
*/
void dscKeybusInterface::printModule_0x11() {
if (moduleData[2] != 0xFF || moduleData[3] != 0xFF) {
stream->print(F("Keypad slots: "));
printModuleSlots(1, 2, 3, 0xC0, 0, 2, 0);
}
if (moduleData[4] != 0xFF || (moduleData[5] & 0xF0) != 0xF0 || ((moduleByteCount > 7) && (moduleData[7] != 0xFF))) {
stream->print(F("| Zone expander: "));
// Later generation panel slots
if (moduleByteCount > 7) {
printModuleSlots(1, 4, 5, 0xC0, 0x30, 2, 0);
if ((moduleData[7] & 0x03) == 0) printNumberSpace(7);
}
// Early generation panel slots
else {
printModuleSlots(1, 4, 5, 0xF0, 0xF0, 4, 0);
}
}
if ((moduleData[5] & 0x0C) == 0) stream->print(F("| PC/RF5132 "));
if ((moduleData[5] & 0x03) == 0) stream->print(F("| PC5208 "));
if ((moduleData[6] & 0xC0) == 0) stream->print(F("| PC5204 "));
}
/*
* Module data during panel command 0x41: Wireless module query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2: Wireless battery low zones 1-8
* Byte 3: Wireless battery low zones 9-16
* Byte 4: Wireless battery low zones 17-24
* Byte 5: Wireless battery low zones 25-32
* Byte 6: Wireless battery restored zones 1-8
* Byte 7: Wireless battery restored zones 9-16
* Byte 8: Wireless battery restored zones 17-24
* Byte 9: Wireless battery restored zones 25-32
* Byte 10: Unknown
*
* 11111111 1 11111111 11111111 11110111 11111111 [Module/0x05] Wireless module battery notification
* 01000001 0 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [0x41] Wireless module query
*
* Module Zones1+ Zones9+ Zones17+ Zones25+ Zones1+ Zones9+ Zones17+ Zones25+
* 11111111 1 11111111 11011111 11111111 11111111 11111111 11111111 11111111 11111111 11011000 [Module/0x41] Wireless module | Battery low zones: 11
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11011111 11111111 11111111 11011000 [Module/0x41] Wireless module | Battery restored zones: 11
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printModule_0x41() {
stream->print(F("Wireless module "));
if (printModuleSlots(255, 2, 5, 0x80, 0, 1, 0)) {
stream->print(F("| Battery low zones: "));
printModuleSlots(1, 2, 5, 0x80, 0, 1, 0);
}
if (printModuleSlots(255, 6, 9, 0x80, 0, 1, 0)) {
stream->print(F("| Battery restored zones: "));
printModuleSlots(1, 6, 9, 0x80, 0, 1, 0);
}
}
/*
* Module data during panel command 0x4C: Module tamper query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Bits 0-3 or 4-7 "0000" indicates a module is still tampered since a previous notification
*
* Byte 2-5 bit 0-1: Keypad slot 2,4,6,8 tamper restore
* Byte 2-5 bit 2-3: Keypad slot 2,4,6,8 tamper
* Byte 2-5 bit 4-5: Keypad slot 1,3,5,7 tamper restore
* Byte 2-5 bit 6-7: Keypad slot 1,3,5,7 tamper
* Byte 6-8 bit 0-1: Module slot 10,12,14 tamper restore
* Byte 6-8 bit 2-3: Module slot 10,12,14 tamper
* Byte 6-8 bit 4-5: Module slot 9,11,13 tamper restore
* Byte 6-8 bit 6-7: Module slot 9,11,13 tamper
* Byte 9 bit 0-1: PC5208 tamper restore
* Byte 9 bit 2-3: PC5208 tamper
* Byte 9 bit 4-5: RF5132 tamper restore
* Byte 9 bit 6-7: RF5132 tamper
* Byte 10 bit 0-3: Unknown
* Byte 10 bit 4-5: PC5204 tamper restore
* Byte 10 bit 6-7: PC5204 tamper
* Byte 11: Unknown
* Byte 12: Unknown
*
* Later generation panels:
* Byte 13 bit 0-3: Unknown
* Byte 13 bit 4-5: Module slot 16 tamper restore
* Byte 13 bit 6-7: Module slot 16 tamper
* Byte 14: Unknown
*
* 11111111 1 11111111 11111111 11111110 11111111 [Module/0x05] Module tamper notification
* 01001100 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x4C] Module tamper query
*
* Module Slots:1 2 3 4 5 6 7 8 9 10 11 12 13 14
* 11111111 1 00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 1
* 11111111 1 11001111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper restored: Slot 1
* 11111111 1 11110011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 2
* 11111111 1 11111100 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper restored: Slot 2
* 11111111 1 11111111 11001111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper restored: Slot 3
* 11111111 1 11111111 11111111 11110011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 6
* 11111111 1 11111111 11111111 11111111 11110011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 8
* 11111111 1 11111111 11111111 11111111 11111100 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper restored: Slot 8
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00111111 11111111 11111111 11111111 [Module/0x4C] RF5132: Tamper
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11001111 11111111 11111111 11111111 [Module/0x4C] RF5132: Tamper restored
* Byte 0 1 2 3 4 5 6 7 8 9 10 11 12
*
* Later generation panels:
* 11111111 1 11111111 11111111 11111110 11111111 11111111 11111111 11111111 11111111 [Module/0x05] Module tamper notification
* 01001100 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x4C] Module tamper query
*
* Module Slots:1 2 3 4 5 6 7 8 9 10 11 12 13 14 16
* 11111111 1 11111111 11111111 11111111 11111111 00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper: Slot 9
* 11111111 1 11111111 11111111 11111111 11111111 11001111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper restored: Slot 9
* 11111111 1 11111111 11111111 11111111 11111111 11110011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper: Slot 10
* 11111111 1 11111111 11111111 11111111 11111111 11111100 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper restored: Slot 10
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11110011 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper: Slot 14
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111100 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper restored: Slot 14
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00111111 11111111 [Module/0x4C] Module tamper: Slot 16
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11001111 11111111 [Module/0x4C] Module tamper restored: Slot 16
* 11111111 1 11111111 11111111 11111111 11111111 11111111 00001111 11111111 00111111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Module tamper: Slot 11 | RF5132: Tamper
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11001111 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] RF5132: Tamper restored
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11110011 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] PC5208: Tamper
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111100 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] PC5208: Tamper restored
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00111111 11111111 11111111 11111111 11111111 [Module/0x4C] PC5204: Tamper
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11001111 11111111 11111111 11111111 11111111 [Module/0x4C] PC5204: Tamper restored
* 11111111 1 00001111 11111111 11111111 11111111 11111111 00001111 11111111 00110000 11111111 11111111 11111111 11111111 11111111 [Module/0x4C] Keypad tamper: Slot 1 | Module tamper: Slot 11 | RF5132: Tamper | PC5208: Tamper
* Byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
*/
void dscKeybusInterface::printModule_0x4C() {
bool printedMessage = false;
if (printModuleSlots(255, 2, 5, 0xC0, 0, 4, 0)) {
stream->print(F("Keypad tamper: Slot "));
printModuleSlots(1, 2, 5, 0xC0, 0, 4, 0);
printedMessage = true;
}
if (printModuleSlots(255, 2, 5, 0xF0, 0, 4, 0x0C)) {
if (printedMessage) stream->print("| ");
stream->print(F("Keypad tamper restored: Slot "));
printModuleSlots(1, 2, 5, 0xF0, 0, 4, 0x0C);
printedMessage = true;
}
if (printModuleSlots(255, 6, 8, 0xC0, 0, 4, 0) || (moduleByteCount > 13 && (moduleData[13] & 0xC0) == 0)) {
if (printedMessage) stream->print("| ");
stream->print(F("Module tamper: Slot "));
printModuleSlots(9, 6, 8, 0xC0, 0, 4, 0);
if (moduleByteCount > 13 && (moduleData[13] & 0xC0) == 0) printNumberSpace(16);
printedMessage = true;
}
if (printModuleSlots(255, 6, 8, 0xF0, 0, 4, 0x0C) || (moduleByteCount > 13 && (moduleData[13] & 0xF0) == 0xC0)) {
if (printedMessage) stream->print("| ");
stream->print(F("Module tamper restored: Slot "));
printModuleSlots(9, 6, 8, 0xF0, 0, 4, 0x0C);
if (moduleByteCount > 13 && (moduleData[13] & 0xF0) == 0xC0) printNumberSpace(16);
printedMessage = true;
}
if ((moduleData[9] & 0xC0) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("RF5132: Tamper "));
printedMessage = true;
}
if ((moduleData[9] & 0xF0) == 0xC0) {
if (printedMessage) stream->print("| ");
stream->print(F("RF5132: Tamper restored "));
printedMessage = true;
}
if ((moduleData[9] & 0x0C) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5208: Tamper "));
printedMessage = true;
}
if ((moduleData[9] & 0x0F) == 0x0C) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5208: Tamper restored "));
printedMessage = true;
}
if ((moduleData[10] & 0xC0) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: Tamper "));
printedMessage = true;
}
if ((moduleData[10] & 0xF0) == 0xC0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: Tamper restored "));
printedMessage = true;
}
}
/*
* Module data during panel command 0x57: Wireless key query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2 bit 0-1: Wireless key 1 battery
* Byte 2 bit 2-3: Wireless key 2 battery
* Byte 2 bit 4-5: Wireless key 3 battery
* Byte 2 bit 6-7: Wireless key 4 battery
* Byte 3: Wireless keys 5-8 battery
* Byte 4: Wireless keys 9-12 battery
* Byte 5: Wireless keys 13-16 battery
* Byte 6: Unknown
* Byte 7: Unknown
* Byte 8: Unknown
* Byte 9: Unknown
* Byte 10: Unknown
*
* 11111111 1 11111111 11111111 11111111 10111111 [Module/0x05] Wireless key notification
* 01010111 0 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [0x57] Wireless key query
*
* Module Keys1+ Keys5+ Keys9+ Keys13+
* 11111111 1 11111101 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11110110 [Module/0x57] Wireless key low battery: 1
* 11111111 1 11111110 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11110111 [Module/0x57] Wireless key battery restored: 1
* 11111111 1 11111111 11111111 01111111 11111111 11111111 11111111 11111111 11111111 01111000 [Module/0x57] Wireless key low battery: 12
* 11111111 1 11111111 11111111 11111111 10111111 11111111 11111111 11111111 11111111 10111000 [Module/0x57] Wireless key battery restored: 16
* 11111111 1 11111011 11111111 01111111 11111111 11111111 11111111 11111111 11111111 01111000 [Module/0x57] Wireless key low battery: 12 | Wireless key battery restored: 2
* Byte 0 1 2 3 4 5 6 7 8 9 10
*/
void dscKeybusInterface::printModule_0x57() {
bool printedMessage = false;
if (printModuleSlots(255, 2, 5, 0xC0, 0, 2, 0x02, true)) {
stream->print(F("Wireless key low battery: "));
printModuleSlots(1, 2, 5, 0xC0, 0, 2, 0x02, true);
printedMessage = true;
}
if (printModuleSlots(255, 2, 5, 0xC0, 0, 2, 0x01, true)) {
if (printedMessage) stream->print(F("| "));
stream->print(F("Wireless key battery restored: "));
printModuleSlots(1, 2, 5, 0xC0, 0, 2, 0x01, true);
}
}
/*
* Module data during panel command 0x58: Module status query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Byte 2 bit 0-1: PC5204 battery restored
* Byte 2 bit 2-3: PC5204 battery trouble
* Byte 2 bit 4-5: PC5204 AC power restored
* Byte 2 bit 6-7: PC5204 AC power trouble
* Byte 3 bit 0-1: PC5204 output 1 restored
* Byte 3 bit 2-3: PC5204 output 1 trouble
* Byte 3 bit 4-7: Unknown
* Byte 4: Unknown
* Byte 5: Unknown
*
* Later generation panels:
* Byte 6: Unknown
* Byte 7: Unknown
* Byte 8: Unknown
* Byte 9: Unknown
* Byte 10: Unknown
* Byte 11: Unknown
* Byte 12: Unknown
* Byte 13: Unknown
*
* 11111111 1 11111111 11111111 11111111 11011111 [Module/0x05] Module status notification
* 01011000 0 10101010 10101010 10101010 10101010 [0x58] Module status query
*
* Module PC5204
* 11111111 1 11111100 11111111 11111111 11111111 [Module/0x58] PC5204: Battery restored
* Byte 0 1 2 3 4 5
*
* Later generation panels:
* 11111111 1 11111111 11111111 11111111 11011111 11111111 11111111 11111111 11111111 [Module/0x05] Module status notification
* 01011000 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0x58] Module status query
*
* Module PC5204
* 11111111 1 00111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x58] PC5204: AC power trouble
* Byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13
*/
void dscKeybusInterface::printModule_0x58() {
bool printedMessage = false;
if ((moduleData[2] & 0x03) == 0) {
stream->print(F("PC5204: Battery restored "));
printedMessage = true;
}
if ((moduleData[2] & 0x0C) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: Battery trouble "));
printedMessage = true;
}
if ((moduleData[2] & 0x30) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: AC power restored "));
printedMessage = true;
}
if ((moduleData[2] & 0xC0) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: AC power trouble "));
printedMessage = true;
}
if ((moduleData[3] & 0x03) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: Output 1 restored "));
printedMessage = true;
}
if ((moduleData[3] & 0x0C) == 0) {
if (printedMessage) stream->print("| ");
stream->print(F("PC5204: Output 1 trouble "));
printedMessage = true;
}
if (!printedMessage) printUnknownData();
}
/*
* Module data during panel command 0x70: LCD keypad data query
* Structure decoding: complete
* Content decoding: complete
*
* Byte 2 bits 0-3: Digit 1
* Byte 2 bits 4-7: Digit 2
* Byte 3 bits 0-3: Digit 3
* Byte 3 bits 4-7: Digit 4
* Byte 4 bits 0-3: Digit 5
* Byte 4 bits 4-7: Digit 6
* Byte 5 bits 0-3: Digit 7
* Byte 5 bits 4-7: Digit 8
* Byte 6: Unknown
*
* 11111111 1 11111111 10101010 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x05] Partition 2 Key: Submit data
* 01110000 0 11111111 11111111 11111111 11111111 11111111 [0x70] LCD keypad data query
*
* Module Digit Digit Digit Digit
* 11111111 1 00010101 00010101 00000000 00000000 00101010 [Module/0x70]
* Byte 0 1 2 3 4 5 6
*/
void dscKeybusInterface::printModule_0x70() {
stream->print(F("LCD keypad data entry: "));
if (decimalInput) {
if (moduleData[2] print("0");
if (moduleData[2] print("0");
stream->print(moduleData[2], DEC);
}
else {
for (byte moduleByte = 2; moduleByte print(moduleData[moduleByte] >> 4, HEX);
stream->print(moduleData[moduleByte] & 0x0F, HEX);
}
}
}
/*
* Module data during panel command 0x94: Requesting module programming data
* Structure decoding: *incomplete
* Content decoding: *incomplete
*/
void dscKeybusInterface::printModule_0x94() {
stream->print(F("Module programming response"));
}
/*
* Module data during panel command: 0xD5 Keypad zone query
* Structure decoding: *incomplete
* Content decoding: *incomplete
*
* Bytes 2-9: Keypad slots 1-8
* Bit 0-1: Keypad zone closed
* Bit 2-3: Unknown
* Bit 4-5: Keypad zone open
* Bit 6-7: Unknown
*
* 11111111 1 11111111 11111111 11111111 11111011 [Module/0x05] Keypad zone status notification
* 11010101 0 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 [0xD5] Keypad zone query
*
* Module Slot 1 Slot 2 Slot 3 Slot 4 Slot 5 Slot 6 Slot 7 Slot 8
* 11111111 1 00000011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1: Zone open
* 11111111 1 00001111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1: Zone open // Exit *8 programming
* 11111111 1 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 [Module/0xD5] Keypad slot 8: Zone open // Exit *8 programming
* 11111111 1 11110000 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1: Zone closed // Zone closed while unconfigured
* 11111111 1 11110011 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1 // Zone closed while unconfigured after opened once
* 11111111 1 00110000 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1: Zone closed // NC
* 11111111 1 00111100 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xD5] Keypad slot 1: Zone closed // After exiting *8 programming after NC
* Byte 0 1 2 3 4 5 6 7 8 9
*/
void dscKeybusInterface::printModule_0xD5() {
stream->print(F("Keypad "));
bool firstData = true;
for (byte moduleByte = 2; moduleByte print(F("Slot "));
firstData = false;
}
else stream->print(F(" | Slot "));
stream->print(moduleByte - 1);
if ((slotData & 0x03) == 0x03 && (slotData & 0x30) == 0) stream->print(F(": Zone open"));
if ((slotData & 0x03) == 0 && (slotData & 0x30) == 0x30) stream->print(F(": Zone closed"));
}
}
}
/*
* Keypad keys
*
* All panels, command 0x05:
* Byte 2: Partition 1 keys
* Byte 3: Partition 2 keys
*
* Later generation panels, command 0x05:
* Byte 2: Partition 1 keys
* Byte 3: Partition 2 keys
* Byte 8: Partition 3 keys
* Byte 9: Partition 4 keys
*
* Later generation panels, command 0x1B:
* Byte 2: Partition 5 keys
* Byte 3: Partition 6 keys
* Byte 8: Partition 7 keys
* Byte 9: Partition 8 keys
*
* Early generation panels:
*
* Module 1:Keys 2:Keys
* 11111111 1 00000101 11111111 11111111 11111111 [Module/0x05] Partition 1 Key: 1
* 11111111 1 00101101 11111111 11111111 11111111 [Module/0x05] Partition 1 Key: #
* 11111111 1 11111111 00010001 11111111 11111111 [Module/0x05] Partition 2 Key: 4
* Byte 0 1 2 3 4 5
*
* Later generation panels:
*
* Module 1:Keys 2:Keys 3:Keys 4:Keys
* 11111111 1 00101000 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x05] Partition 1 Key: *
* 11111111 1 11111111 00010001 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x05] Partition 2 Key: 4
* Byte 0 1 2 3 4 5 6 7 8 9
*
* Module 5:Keys 6:Keys 7:Keys 8:Keys
* 11111111 1 00000101 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0x1B] Partition 5 Key: 1
* Byte 0 1 2 3 4 5 6 7 8 9
*
* Module 1:Keys 2:Keys 3:Keys 4:Keys
* 11111111 1 11111111 11110111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 [Module/0xE6.20] Partition 1 Key: Menu navigation
* Byte 0 1 2 3 4 5 6 7 8 9 10
*
*/
bool dscKeybusInterface::printModule_Keys() {
bool printedMessage = false;
byte partitionNumber = 1;
byte startByte = 2;
byte endByte = 9;
switch (moduleCmd) {
case 0x1B: partitionNumber = 5; break;
case 0x27:
case 0x2D:
case 0x3E: endByte = 3; break;
case 0xE6: {
startByte = 3;
endByte = 3;
switch (moduleSubCmd) {
case 0x01: partitionNumber = 3; break;
case 0x02: partitionNumber = 4; break;
case 0x03: partitionNumber = 5; break;
case 0x04: partitionNumber = 6; break;
case 0x05: partitionNumber = 7; break;
case 0x06: partitionNumber = 8; break;
case 0x20: partitionNumber = 1; break;
case 0x21: partitionNumber = 2; break;
}
break;
}
}
for (byte testByte = startByte; testByte print(F("Key: "));
printModule_KeyCodes(testByte);
}
printedMessage = true;
}
partitionNumber++;
}
return printedMessage;
}
// Keypad key values
void dscKeybusInterface::printModule_KeyCodes(byte keyByte) {
switch (moduleData[keyByte]) {
case 0x00: printNumberSpace(0); break;
case 0x05: printNumberSpace(1); break;
case 0x0A: printNumberSpace(2); break;
case 0x0F: printNumberSpace(3); break;
case 0x11: printNumberSpace(4); break;
case 0x16: printNumberSpace(5); break;
case 0x1B: printNumberSpace(6); break;
case 0x1C: printNumberSpace(7); break;
case 0x22: printNumberSpace(8); break;
case 0x27: printNumberSpace(9); break;
case 0x28: stream->print(F("* ")); break;
case 0x2D: stream->print(F("# ")); break;
case 0x46: stream->print(F("Wireless key disarm ")); break; //isn't send if wls keys uses access codes 17-32 is enabled
case 0x52: stream->print(F("Identified voice prompt help ")); break;
case 0x6E: stream->print(F("Global away arm ")); break;
case 0x70: stream->print(F("Command output 3 ")); break;
case 0x7A: stream->print(F("Time and date programming ")); break;
case 0x75: stream->print(F("Entered *1/*2/*3 ? ")); break;
case 0x82: stream->print(F("Enter ")); break;
case 0x87: stream->print(F("Right arrow ")); break;
case 0x88: stream->print(F("Left arrow ")); break;
case 0x8D: stream->print(F("Bypass recall ")); break;
case 0x93: stream->print(F("Recall bypass group ")); break;
case 0x94: stream->print(F("Global label broadcast ")); break;
case 0x99: stream->print(F("Function key [25] Future Use ")); break;
case 0xA5: stream->print(F("Receive data ")); break;
case 0xAA: stream->print(F("Submit data ")); break;
case 0xAF: stream->print(F("Arm: Stay ")); break;
case 0xB1: stream->print(F("Arm: Away ")); break;
case 0xB6: stream->print(F("Arm: No entry delay ")); break;
case 0xBB: stream->print(F("Door chime configuration ")); break;
case 0xBC: stream->print(F("*6 System test ")); break;
case 0xC3: stream->print(F("*1 Zone bypass programming ")); break;
case 0xC4: stream->print(F("*2 Trouble menu ")); break;
case 0xC9: stream->print(F("*3 Alarm memory display ")); break;
case 0xCE: stream->print(F("*5 Programming ")); break;
case 0xD0: stream->print(F("*6 Programming ")); break;
case 0xD5: stream->print(F("Command output 1 ")); break;
case 0xDA: stream->print(F("Reset / Command output 2 ")); break;
case 0xDF: stream->print(F("Global stay arm ")); break;
case 0xE1: stream->print(F("Quick exit ")); break;
case 0xE6: stream->print(F("Activate stay/away zones ")); break;
case 0xEB: stream->print(F("LCD pixel test ")); break;
case 0xEC: stream->print(F("Command output 4 ")); break;
case 0xF2: stream->print(F("Global disarm ")); break; // Possible overlap with "General voice prompt help"
case 0xF7: stream->print(F("Menu navigation ")); break;
}
}
/*
* Zone expander zone status module response for panel commands: 0x22, 0x28, 0x33, 0x39, 0xE6.8, 0xE6.A, 0xE6.C, 0xE6.E
*/
void dscKeybusInterface::printModule_Expander() {
byte startByte = 2;
byte startZone = 1;
stream->print(F("Zone expander: "));
switch (moduleCmd) {
case 0x22: printNumberSpace(0); startZone = 1; break;
case 0x28: printNumberSpace(1); startZone = 9; break;
case 0x33: printNumberSpace(2); startZone = 17; break;
case 0x39: printNumberSpace(3); startZone = 25; break;
case 0xE6: {
startByte = 3;
switch (moduleSubCmd) {
case 0x08: printNumberSpace(4); startZone = 33; break;
case 0x0A: printNumberSpace(5); startZone = 41; break;
case 0x0C: printNumberSpace(6); startZone = 49; break;
case 0x0E: printNumberSpace(7); startZone = 57; break;
}
break;
}
}
if (moduleData[startByte] != moduleData[startByte + 1] || moduleData[startByte + 2] != moduleData[startByte + 3]) {
stream->print(F("| Zones changed: "));
byte zoneNumber = startZone;
for (byte zoneByte = startByte; zoneByte print(F("open ")); break;
case 1: stream->print(F("closed ")); break;
case 2: stream->print(F("tamper ")); break;
case 3: stream->print(F("open (D/EOL) ")); break;
}
}
zoneNumber++;
zoneMaskShift += 2;
}
}
}
}
/*
* Prints slots and zones for module responses to panel commands: 0x11, 0x41, 0x4C, 0x57
*
* If outputNumber is set to 0, printModuleSlots() will return 'true' if any of the specified
* bytes contains data - this is used to selectively print a label only if data is present.
*/
bool dscKeybusInterface::printModuleSlots(byte outputNumber, byte startByte, byte endByte, byte startMask, byte endMask, byte bitShift, byte matchValue, bool reverse) {
for (byte testByte = startByte; testByte >= bitShift) {
if (testByte == endByte && testMask < endMask) return false;
byte testData = moduleData[testByte];
// Reverses the bit order
if (reverse) {
testData = 0;
for (byte i = 0; i < 8; i++) testData |= ((moduleData[testByte] >> i) & 1) > matchShift == matchValue) {
if (outputNumber == 255) return true;
else printNumberSpace(outputNumber);
}
if (outputNumber != 255) outputNumber++;
matchShift -= bitShift;
}
}
return false;
}
// Print 0x8D and 0x94 section and command subsection data used for programming modules
void dscKeybusInterface::printModuleProgramming(byte panelByte2, byte panelByte3) {
switch (panelByte2) {
case 0x11: stream->print(F("RF5132")); break; //section 804 verified on pc1832 and pc5020
case 0x14: stream->print(F("RF5400")); break; //section 801 not verified
case 0x15: stream->print(F("RF5936")); break; //section 802 not verified
case 0x16: stream->print(F("LINKS2X50")); break; //section 803 not verified
case 0x17: stream->print(F("PC5108L")); break; //section 806 not verified
case 0x19: stream->print(F("RF5100")); break; //section 805 not verified
case 0x31: stream->print(F("*5 user")); break; //*5 access codes verified on pc1832 and pc5020
default: stream->print("Unknown data");
}
stream->print(" | ");
if (panelByte3 < 16) stream->print("0");
stream->print(panelByte3, HEX);
}
/*
* Panel lights and status message for commands: 0x05, 0x1B, 0x27, 0x2D, 0x34, 0x3E
*/
void dscKeybusInterface::printPanelPartitionStatus(byte startPartition, byte startByte, byte endByte) {
byte partitionCount = startPartition;
for (byte statusByte = startByte; statusByte startPartition) stream->print(" | ");
printPartition();
stream->print(partitionCount);
stream->print(": ");
if (panelData[statusByte] == 0 || panelData[statusByte] == 0xC7 || panelData[statusByte] == 0xFF) stream->print(F("disabled"));
else printPanelLights(statusByte - 1);
partitionCount++;
}
}
/*
* Date and time for panel commands: 0xA5, 0xAA, 0xEB, 0xEC
* Structure decoding: complete
* Content decoding: complete
*/
void dscKeybusInterface::printPanelTime(byte panelByte) {
byte dscYear3 = panelData[panelByte] >> 4;
byte dscYear4 = panelData[panelByte] & 0x0F;
byte dscMonth = panelData[panelByte + 1] >= 4;
byte dscDay1 = panelData[panelByte + 1] >= 3;
byte dscDay2 = panelData[panelByte + 2] >> 5;
byte dscDay = dscDay1 | dscDay2;
byte dscHour = panelData[panelByte + 2] & 0x1F;
byte dscMinute = panelData[panelByte + 3] >> 2;
if (dscYear3 >= 7) stream->print(F("19"));
else stream->print(F("20"));
stream->print(dscYear3);
stream->print(dscYear4, HEX);
stream->print(".");
if (dscMonth < 10) stream->print("0");
stream->print(dscMonth);
stream->print(".");
if (dscDay < 10) stream->print("0");
stream->print(dscDay);
stream->print(" ");
if (dscHour < 10) stream->print("0");
stream->print(dscHour);
stream->print(F(":"));
if (dscMinute < 10) stream->print("0");
stream->print(dscMinute);
}
/*
* Prints access codes for printPanelStatus0()...printPanelStatus1B() status messages
* Structure decoding: complete
* Content decoding: complete
*/
void dscKeybusInterface::printPanelAccessCode(byte dscCode, bool accessCodeIncrease) {
if (accessCodeIncrease) {
if (dscCode >= 35) dscCode += 5;
}
else {
if (dscCode >= 40) dscCode += 3;
}
switch (dscCode) {
case 40: stream->print(F("Master ")); break;
default: stream->print(F("Access ")); break;
}
stream->print(F("code "));
stream->print(dscCode);
}
/*
* Beeps number for panel commands: 0x64, 0x69, 0xE6_0x19
* Structure decoding: complete
* Content decoding: complete
*/
void dscKeybusInterface::printPanelBeeps(byte panelByte) {
stream->print(F("| Beep: "));
stream->print(panelData[panelByte] / 2);
stream->print(F(" beeps"));
}
/*
* Tone pattern for panel commands: 0x75, 0x7A, 0xE6_0x20
* Structure decoding: complete
* Content decoding: complete
*/
void dscKeybusInterface::printPanelTone(byte panelByte) {
stream->print(F("| Tone: "));
bool printedMessage = false;
if (panelData[panelByte] == 0) {
stream->print(F("none"));
return;
}
if ((panelData[panelByte] & 0x80) == 0x80) {
stream->print(F("constant tone "));
printedMessage = true;
}
if ((panelData[panelByte] & 0x70) != 0) {
if (printedMessage) stream->print("| ");
stream->print((panelData[panelByte] & 0x70) >> 4);
stream->print(F(" beep "));
}
if ((panelData[panelByte] & 0x0F) != 0) {
stream->print("| ");
stream->print(panelData[panelByte] & 0x0F);
stream->print(F("s interval"));
}
}
/*
* Buzzer pattern for panel commands: 0x7F, 0x82
* Structure decoding: complete
* Content decoding: complete
*/
void dscKeybusInterface::printPanelBuzzer(byte panelByte) {
stream->print(F("| Buzzer: "));
stream->print(panelData[panelByte]);
stream->print("s");
}
/*
* Zones for panel commands: 0x0A, 0x5D, 0x63, 0xB1, 0xE6.17, 0xE6.18, 0xE6.20, 0xE6.2B, 0xE6.2C, 0xE6.41
* Structure decoding: complete
* Content decoding: complete
*/
bool dscKeybusInterface::printPanelZones(byte inputByte, byte startZone) {
bool zonesEnabled = false;
for (byte panelByte = inputByte; panelByte print((zoneBit + startZone) + ((panelByte - inputByte) * 8));
stream->print(" ");
}
}
}
}
if (!zonesEnabled && panelData[0] != 0x0A && panelData[0] != 0x0F) stream->print(F("none"));
return zonesEnabled;
}
void dscKeybusInterface::printPartition() {
stream->print(F("Partition "));
}
void dscKeybusInterface::printUnknownData() {
stream->print("Unknown data");
}
void dscKeybusInterface::printStatusLights() {
stream->print(F("Status lights: "));
}
void dscKeybusInterface::printZoneLights(bool lowerRange) {
if (lowerRange) stream->print(F(" | Zones 1-32 lights: "));
else stream->print(F(" | Zones 33-64 lights: "));
}
void dscKeybusInterface::printStatusLightsFlashing() {
stream->print(F("| Status lights flashing: "));
}
void dscKeybusInterface::printNumberSpace(byte number) {
stream->print(number);
stream->print(" ");
}
void dscKeybusInterface::printNumberOffset(byte panelByte, int numberOffset) {
stream->print(panelData[panelByte] + numberOffset);
}
// Prints individual bits as a number for partitions and zones
void dscKeybusInterface::printPanelBitNumbers(byte panelByte, byte startNumber, byte startBit, byte stopBit, bool printNone) {
if (printNone && panelData[panelByte] == 0) stream->print(F("none "));
else {
byte bitCount = 0;
for (byte bit = startBit; bit print(startNumber + bitCount);
stream->print(" ");
}
bitCount++;
}
}
}
// Prints the panel message as binary with an optional parameter to print spaces between bytes
void dscKeybusInterface::printPanelBinary(bool printSpaces) {
for (byte panelByte = 0; panelByte < panelByteCount; panelByte++) {
if (panelByte == 1) stream->print(panelData[panelByte]); // Prints the stop bit
else {
for (byte mask = 0x80; mask; mask >>= 1) {
if (mask & panelData[panelByte]) stream->print("1");
else stream->print("0");
}
}
if (printSpaces && (panelByte != panelByteCount - 1 || displayTrailingBits)) stream->print(" ");
}
if (displayTrailingBits) {
byte trailingBits = (panelBitCount - 1) % 8;
if (trailingBits > 0) {
for (int i = trailingBits - 1; i >= 0; i--) {
stream->print(bitRead(panelData[panelByteCount], i));
}
}
}
}
// Prints the module message as binary with an optional parameter to print spaces between bytes
void dscKeybusInterface::printModuleBinary(bool printSpaces) {
for (byte moduleByte = 0; moduleByte < moduleByteCount; moduleByte++) {
if (moduleByte == 1) stream->print(moduleData[moduleByte]); // Prints the stop bit
else if (hideKeypadDigits
&& (moduleByte == 2 || moduleByte == 3 || moduleByte == 8 || moduleByte == 9)
&& (moduleData[2] print("1");
else stream->print("0");
}
}
if (printSpaces && (moduleByte != moduleByteCount - 1 || displayTrailingBits)) stream->print(" ");
}
if (displayTrailingBits) {
byte trailingBits = (moduleBitCount - 1) % 8;
if (trailingBits > 0) {
for (int i = trailingBits - 1; i >= 0; i--) {
stream->print(bitRead(moduleData[moduleByteCount], i));
}
}
}
}
// Prints the panel command as hex
void dscKeybusInterface::printPanelCommand() {
stream->print(F("0x"));
if (panelData[0] < 16) stream->print("0");
stream->print(panelData[0], HEX);
if (panelData[0] == 0xE6) {
stream->print(".");
if (panelData[2] < 16) stream->print("0");
stream->print(panelData[2], HEX);
}
}