Ademco Vista-128BPT
I just got an Ademco (Honeywell) Vista-128BPT (Turbo Series) for testing and tweaking the UI module before deploying it to the field and I noticed some flaws on the AMX documented feedback. Under the SECSTATUS-<status> there are 4 documented status:
ARMED
ARMED HOME
DISARMED
ALARM
The first 3 status work, but the ALARM one, which is extremely important doesn't. I armed the system to AWAY mode or fully armed and when I breach a zone, the alarm goes off but the AMX Comm module never sends out the ALARM or ALARMED status out. I've tried many times breaching different zones and still the same issue. Therefore, the feedback on touch panels never gets to show ALARM or ALARMED, it still has the ARM AWAY button lit, even though the alarm is going off.
Another issue is that I noticed is that the Zone Status is not reported correctly in the module when the system is armed to either AWAY or HOME. It does report correctly when the system is disarmed. Again, when the system is armed and a zone is breached, the alarm goes off, but the AMX module is not sending/processing the ALARM status, neither it is reporting which zone was breached. The way it is now, the module is not reliable. It basically provides arming and disarming, but the ALARM feedback and zone Status feedback is not reliable, especially when the system is alarming, when it should matter the most. The physical alarm keypad reports the breaches correctly.
Is there anything am missing here? The system is communicating correctly, but I am having these feedback issues. Have any of you noticed this limitation?
Thanks,
Ricardo
* Note: For those that want some type of individual zone feedback other than the simple text box, here is a function I edited from another alarm module to process it:
ARMED
ARMED HOME
DISARMED
ALARM
The first 3 status work, but the ALARM one, which is extremely important doesn't. I armed the system to AWAY mode or fully armed and when I breach a zone, the alarm goes off but the AMX Comm module never sends out the ALARM or ALARMED status out. I've tried many times breaching different zones and still the same issue. Therefore, the feedback on touch panels never gets to show ALARM or ALARMED, it still has the ARM AWAY button lit, even though the alarm is going off.
Another issue is that I noticed is that the Zone Status is not reported correctly in the module when the system is armed to either AWAY or HOME. It does report correctly when the system is disarmed. Again, when the system is armed and a zone is breached, the alarm goes off, but the AMX module is not sending/processing the ALARM status, neither it is reporting which zone was breached. The way it is now, the module is not reliable. It basically provides arming and disarming, but the ALARM feedback and zone Status feedback is not reliable, especially when the system is alarming, when it should matter the most. The physical alarm keypad reports the breaches correctly.
Is there anything am missing here? The system is communicating correctly, but I am having these feedback issues. Have any of you noticed this limitation?
Thanks,
Ricardo
* Note: For those that want some type of individual zone feedback other than the simple text box, here is a function I edited from another alarm module to process it:
DEFINE_FUNCTION ProcessZones(CHAR sZnStr[])
{
//SECPOINTSTATUS-90,ACTIVE
//SECPOINTSTATUS-25,BYPASSED
//SECPOINTSTATUS-15,FAULT
//SECPOINTSTATUS-250,INVALID
nConcZone = ATOI(REMOVE_STRING(sZnStr, ',', 1))
SELECT
{
// Send Fault bitmap
ACTIVE(FIND_STRING(sZnStr , 'FAULT', 1) ||
//FIND_STRING(sZnStr , 'INVALID', 1) ||
FIND_STRING(sZnStr , 'BYPASSED', 1)):
{
ON[dvTP, dcZONE_ARRAY[nConcZone]]
dcZONE_STATUS[nConcZone] = 1
}
// Send Secure bitmap
ACTIVE(FIND_STRING(sZnStr , 'ACTIVE', 1)):
{
OFF[dvTP, dcZONE_ARRAY[nConcZone]]
dcZONE_STATUS[nConcZone] = 0
}
}
}
0
Comments
That's disappointing. I have a job in a couple weeks using that module so I can let you know what I find out. Security commands documents tend to be difficult or impossible to get, so this is not good to hear. Can you use the PASSBACK command to listen for the alarm command?
Paul
ericmedley,
Is it possible for you to upload the old non-duet module for us. It is not available from AMX anymore. Maybe it works better... as most non-duet modules do.
Thanks,
Ricardo
But, at any rate, here it is folks.
I wonder if you could just slam the rs232 port with baud 9600 commands. hmmmm... if it wasn't an alarm system it might be worth trying.
They also will NOT divulge the protocols. When we dug in hard, they admitted they were different and only disclosed to trusted corporate partners. AMX is forbidden to give out the protocol to dealers, only to provide the "black box" module. Which is woefully inadequate and faulty.
They explain that this is to protect Honeywell from Chinese knock-off boards using a public protocol.
So unless you backward engineer it like the Chinese are doing anyway*, you aren't going to get the BPT to be satisfying.
(* - as we did... but can't share or we'll be sued)
Did you call TS? If you complain they might pass it to the Duet group and someone might fix it.
Paul
I haven't done a virtual keypad in years. Does anybody have a code sample for this? I basically need numbers 1 to 9 and the OK button to process it. In addition, a text box to append the digits entered, so the end user can see what he is typing. The idea is that after typing the password and pressing OK or Done, the string gets sent to the UI module out of PORT 7.
Thanks,
Ricardo
http://houselogix.com/products/hsim-security-adapter.asp
Kevin D.
DEFINE_MODULE 'Ademco_Vista_Comm_dr1_0_0' DuetCode(vdvPRTN1, dvDevice) DEFINE_MODULE 'Ademco_Vista_UI' TP1(vdvPRTNS, dvTP_Alarm1, nCHAN_BTNS, dcZONE_ARRAY, dviPad_Family) // dvTP_Alarm1 = 10007 & dviPad_Family = 10001 MODULE_NAME='Ademco_Vista_UI' (DEV vdvPRTNS[], DEV dvTP, INTEGER nCHAN_BTN[], INTEGER dcZONE_ARRAY[], DEV dvTPText) (*{{PS_SOURCE_INFO(PROGRAM STATS) *) (***********************************************************) (* FILE CREATED ON: 03/10/2005 AT: 13:15:35 *) (***********************************************************) (* FILE_LAST_MODIFIED_ON: 05/26/2005 AT: 12:54:04 *) (***********************************************************) (* ORPHAN_FILE_PLATFORM: 1 *) (***********************************************************) (*!!FILE REVISION: Rev 0 *) (* REVISION DATE: 04/27/2005 *) (* *) (* COMMENTS: *) (* *) (***********************************************************) (*}}PS_SOURCE_INFO *) (***********************************************************) (***********************************************************) (***********************************************************) (* REV HISTORY: *) (***********************************************************) (* The Ademco BP and FBP systems use different mother boards and have different firmware. The BP systems use a simple protocol, while the FBP may be programmed to use the extended or simple protocols. See Main.axs notes for more information. The 128/250BP systems use a Simple protocol; the 128/250FBP systems can use a SImple or Extended protocol set. Use the FBP 1*78 and 1*79 program steps to turn on Extended protocol and select Extended event messages. Use the PROPERTY command to tell the Comm module whether or not to use the Extended protocol set (See the Main.axs ONLINE event) This sample UI code is written to request and send the 4-digit password for the FBP systems, and the 2-digit user id followed by the 4-digit password, for the BP systems. This is because the NetLinx programmer will not know the user id number if new passwords are addded after install. The first user id is 2, and the default password is 1234. After this, user id 3, 4, etc. may be programmed for other passwords. The partition(s) controlled by any given password are determined by Vista system programming. *) (***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE (***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_CONSTANT //Added by Ricardo 4/23/2014 INTEGER nMAX_Zones = 75 // Define the Max number of zones used here #INCLUDE 'SNAPI.AXI' (***********************************************************) (* DATA TYPE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_TYPE (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE VOLATILE CHAR sVERSION[5] = '' // STORES NETLINX COMM MODULE VERSION NUMBER VOLATILE INTEGER nDEBUG = 0 // TRACKS THE ON/OFF STATE OF DEBUG MSGS SENT TO THE TELNET SESSION VOLATILE CHAR cARMTYPE[20] VOLATILE CHAR USER_NUMBER[] = '00' //DEFAULT USER NUMBER VOLATILE INTEGER nCURRENT_PRTN = 1 // Selected partition VOLATILE CHAR cPARTITION_STATUS[9][20] // Status of all partitions - #9 (ALL) updated by fnDO_FEEDBACK VOLATILE CHAR cPOINT_STATUS[128] // 128 or 250 zones supported VOLATILE CHAR cUSER_CODE[] = '1234' // password to use for zone bypass (see function ToggleBypass) //Added by Ricardo 4/23/2014 VOLATILE INTEGER nConcZone = 0 // Zone selection VOLATILE INTEGER dcZONE_STATUS[nMAX_Zones] // 128 or 250 zones supported (***********************************************************) (* LATCHING DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_LATCHING (***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_FUNCTION fnDO_FEEDBACK() { STACK_VAR INTEGER nINDEX // Highlight current partition, and check to see if all partitions same status cPARTITION_STATUS[9] = cPARTITION_STATUS[1] // load with first status FOR (nINDEX = 1; nINDEX <= 9; nINDEX++) { [dvTP, nCHAN_BTN[nINDEX + 15]] = (nCURRENT_PRTN == nINDEX) IF(cPARTITION_STATUS[9] <> cPARTITION_STATUS[nINDEX]) cPARTITION_STATUS[9] = '' // Clear #9 if no match } [dvTP, nCHAN_BTN[1]] = (cPARTITION_STATUS[nCURRENT_PRTN] == 'ARMED HOME' || cPARTITION_STATUS[nCURRENT_PRTN] == 'ARMED_HOME') //[dvTP, nCHAN_BTN[2]] = (cPARTITION_STATUS[nCURRENT_PRTN] == 'ARM HOME NOW' || // cPARTITION_STATUS[nCURRENT_PRTN] == 'ARM_HOME_NOW') [dvTP, nCHAN_BTN[3]] = (cPARTITION_STATUS[nCURRENT_PRTN] == 'ARMED') [dvTP, nCHAN_BTN[4]] = (cPARTITION_STATUS[nCURRENT_PRTN] == 'DISARMED') [dvTP, nCHAN_BTN[25]] = (cPARTITION_STATUS[nCURRENT_PRTN] == 'ALARM') SWITCH(cPARTITION_STATUS[nCURRENT_PRTN]) { CASE 'ARMED_HOME': CASE 'ARMED HOME': { SEND_COMMAND dvTP,"'^TXT-1',',0,','ARMED TO HOME'" } CASE 'ARMED': { SEND_COMMAND dvTP,"'^TXT-1',',0,','ARMED TO AWAY'" } CASE 'DISARMED': { SEND_COMMAND dvTP,"'^TXT-1',',0,','DISARMED'" } CASE 'ALARM': { SEND_COMMAND dvTP,"'^TXT-1',',0,','ALARMED'" } } } DEFINE_FUNCTION ToggleBypass(INTEGER nZoneNumber) { STACK_VAR CHAR cString[6] cString = cUSER_CODE WHILE(LENGTH_STRING(cString)) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN],"'KEYPAD-',GET_BUFFER_CHAR(cString)" } SEND_COMMAND vdvPRTNS[nCURRENT_PRTN],"'KEYPAD-6'" cString = RIGHT_STRING("'00',ITOA(nZoneNumber)",3) WHILE(LENGTH_STRING(cString)) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN],"'KEYPAD-',GET_BUFFER_CHAR(cString)" } } //Added by Ricardo 4/23/2014///////////////////////////////////////////////// DEFINE_FUNCTION ProcessZones(CHAR sZnStr[]) { //SECPOINTSTATUS-90,ACTIVE //SECPOINTSTATUS-25,BYPASSED //SECPOINTSTATUS-15,FAULT //SECPOINTSTATUS-250,INVALID nConcZone = ATOI(REMOVE_STRING(sZnStr, ',', 1)) SELECT { // Send Fault bitmap ACTIVE(FIND_STRING(sZnStr , 'FAULT', 1) || //FIND_STRING(sZnStr , 'INVALID', 1) || FIND_STRING(sZnStr , 'BYPASSED', 1)): { ON[dvTP, dcZONE_ARRAY[nConcZone]] dcZONE_STATUS[nConcZone] = 1 } // Send Secure bitmap ACTIVE(FIND_STRING(sZnStr , 'ACTIVE', 1)): { OFF[dvTP, dcZONE_ARRAY[nConcZone]] dcZONE_STATUS[nConcZone] = 0 } } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START fnDO_FEEDBACK() // UPDATE PANEL AT START (***********************************************************) (* THE EVENTS GOES BELOW *) (***********************************************************) DEFINE_EVENT DATA_EVENT[vdvPRTNS] { COMMAND: { STACK_VAR CHAR DATUM[30] IF(nDEBUG >= 3) { send_string 0, "'UI received from Comm: ',data.text" } DATUM = remove_string(data.text, '-', 1) SWITCH(DATUM) { // FIND MATCHING STRING AND PARSE REST OF MESSAGE. PROVIDE FEEDBACK TO THE // TOUCH PANEL. CASE 'DEBUG-': { nDEBUG = ATOI(DATA.TEXT) IF (nDebug >= 3) SEND_STRING 0, "'Debug messages are now on.'" ELSE IF(nDEBUG < 3) SEND_STRING 0, "'Debug messages are now off.'" } CASE 'SECSTATUS-': { STACK_VAR INTEGER nPRTN nPRTN = DATA.DEVICE.PORT // Which partition? cPARTITION_STATUS[nPRTN] = DATA.TEXT // Save status fnDO_FEEDBACK() // Update panel buttons } CASE 'SECPOINTSTATUS-': { SEND_COMMAND dvTP,"'^TXT-',ITOA(nCHAN_BTN[28]),',0,',DATA.TEXT" ProcessZones(DATA.TEXT) //Added by Ricardo 4/23/2014 } CASE 'VERSION-': { sVERSION = DATA.TEXT } }// END SWITCH(datum) }// END COMMAND }// END DATA_EVENT[vdvPRTNS] DATA_EVENT[dvTPText] { ONLINE: { } STRING: { STACK_VAR INTEGER nINDEX IF (nDEBUG) SEND_STRING 0, "'FROM THE KEYPAD: ',DATA.TEXT" IF(FIND_STRING(DATA.TEXT, 'KEYP-', 1) == 1) { REMOVE_STRING(DATA.TEXT, 'KEYP-', 1) IF(DATA.TEXT == 'ABORT') { // DO NOTHING... } ELSE IF(LENGTH_STRING(DATA.TEXT) >= 0 && LENGTH_STRING(DATA.TEXT) <= 6) { STACK_VAR CHAR PASS_WORD[6] // PASSWORD MUST HAVE 4 DIGITS FOR EXTENDED PROTOCOL, // 6 DIGITS (USER + PW) FOR SIMPLE PROTOCOL // SO, ZERO FILL TO SIX DIGITS IF (nCURRENT_PRTN <= 8) SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'SECSTATE-',cARMTYPE,',',RIGHT_STRING("'00',DATA.TEXT",6)" ELSE // FOR PARTITION 9, DO ALL 8 { FOR (nINDEX = 1; nINDEX <= 8; nINDEX++) { SEND_COMMAND vdvPRTNS[nINDEX], "'SECSTATE-',cARMTYPE,',',RIGHT_STRING("'00',DATA.TEXT",6)" } } } // ELSE PROMPT FOR PROPER PASSWORD FORMAT HERE... } } }// END DATA_EVENT[dvTP] BUTTON_EVENT[dvTP, nCHAN_BTN] { PUSH: { STACK_VAR INTEGER nBTN nBTN = GET_LAST(nCHAN_BTN) SWITCH(nBTN) { CASE 1: //ARM TO HOME { cARMTYPE = 'ARM_HOME' //SEND_COMMAND dvTP, "'@PKP-;ENTER PASS TO ARM TO HOME'" //SEND_COMMAND dvTP, "'@PPN-Alarm Keypad'" SEND_COMMAND dvTP,"'^TXT-2',',0,','ARM TO HOME'" } CASE 2: //ARM TO HOME NOW { cARMTYPE = 'ARM_HOME_NOW' //SEND_COMMAND dvTP, "'@PKP-;ENTER PASS TO ARM TO HOME NOW'" //SEND_COMMAND dvTP, "'@PPN-Alarm Keypad'" SEND_COMMAND dvTP,"'^TXT-2',',0,','ARM TO HOME NOW'" } CASE 3: //ARM TO AWAY { cARMTYPE = 'ARM' //SEND_COMMAND dvTP, "'@PKP-;ENTER PASS TO ARM TO AWAY'" //SEND_COMMAND dvTP, "'@PPN-Alarm Keypad'" SEND_COMMAND dvTP,"'^TXT-2',',0,','ARM TO AWAY'" } CASE 4: //DISARM { cARMTYPE = 'DISARM' //SEND_COMMAND dvTP, "'@PKP-;ENTER PASS TO DISARM'" //SEND_COMMAND dvTP, "'@PPN-Alarm Keypad'" SEND_COMMAND dvTP,"'^TXT-2',',0,','DISARM'" } CASE 10: //KEY PAD 0 CASE 11: //KEY PAD 1 CASE 12: //KEY PAD 2 CASE 13: //KEY PAD 3 CASE 14: //KEY PAD 4 CASE 15: //KEY PAD 5 CASE 16: //KEY PAD 6 CASE 17: //KEY PAD 7 CASE 18: //KEY PAD 8 CASE 19: //KEY PAD 9 { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-',ITOA(nBTN - 10)" } } CASE 20: //KEY PAD * { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-A'" } } CASE 21: //KEY PAD # { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-B'" } } CASE 22: //MACRO C: Fire { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-C'" } } CASE 23: //MACRO D: Silent { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-D'" } } CASE 24: //MACRO E: Medical { IF (nCURRENT_PRTN <= 8) { SEND_COMMAND vdvPRTNS[nCURRENT_PRTN], "'KEYPAD-E'" } } CASE 31: // ACTIVE PARTITION SELECT CASE 32: CASE 33: CASE 34: CASE 35: CASE 36: CASE 37: CASE 38: CASE 39: { nCURRENT_PRTN = nBTN - 30 // REMEMBER PARTITION } }// END SWITCH(nBTN) fnDO_FEEDBACK() // UPDATE PANEL }// END PUSH }// END BUTTON_EVENT[dvTP, nCHAN_BTN] (***********************************************************) (* THE ACTUAL PROGRAM GOES BELOW *) (***********************************************************) DEFINE_PROGRAM [dvTP, nCHAN_BTN[26]] = [vdvPRTNS[1],251] // ONLINE [dvTP, nCHAN_BTN[27]] = [vdvPRTNS[1],252] // DATA INITIALIZED //Zone feedback WAIT 1 { [dvTP, 101] = (dcZONE_STATUS[1] == 1) [dvTP, 102] = (dcZONE_STATUS[2] == 1) [dvTP, 103] = (dcZONE_STATUS[3] == 1) [dvTP, 104] = (dcZONE_STATUS[4] == 1) [dvTP, 105] = (dcZONE_STATUS[5] == 1) [dvTP, 106] = (dcZONE_STATUS[6] == 1) [dvTP, 107] = (dcZONE_STATUS[7] == 1) [dvTP, 108] = (dcZONE_STATUS[8] == 1) [dvTP, 110] = (dcZONE_STATUS[10] == 1) [dvTP, 112] = (dcZONE_STATUS[12] == 1) [dvTP, 113] = (dcZONE_STATUS[13] == 1) [dvTP, 114] = (dcZONE_STATUS[14] == 1) [dvTP, 118] = (dcZONE_STATUS[18] == 1) [dvTP, 119] = (dcZONE_STATUS[19] == 1) [dvTP, 120] = (dcZONE_STATUS[20] == 1) [dvTP, 121] = (dcZONE_STATUS[21] == 1) [dvTP, 122] = (dcZONE_STATUS[22] == 1) [dvTP, 123] = (dcZONE_STATUS[23] == 1) [dvTP, 124] = (dcZONE_STATUS[24] == 1) [dvTP, 125] = (dcZONE_STATUS[25] == 1) [dvTP, 126] = (dcZONE_STATUS[26] == 1) [dvTP, 127] = (dcZONE_STATUS[27] == 1) [dvTP, 128] = (dcZONE_STATUS[28] == 1) [dvTP, 129] = (dcZONE_STATUS[29] == 1) [dvTP, 130] = (dcZONE_STATUS[30] == 1) [dvTP, 131] = (dcZONE_STATUS[31] == 1) [dvTP, 132] = (dcZONE_STATUS[32] == 1) [dvTP, 134] = (dcZONE_STATUS[34] == 1) [dvTP, 135] = (dcZONE_STATUS[35] == 1) [dvTP, 136] = (dcZONE_STATUS[36] == 1) [dvTP, 137] = (dcZONE_STATUS[37] == 1) [dvTP, 138] = (dcZONE_STATUS[38] == 1) [dvTP, 139] = (dcZONE_STATUS[39] == 1) [dvTP, 140] = (dcZONE_STATUS[40] == 1) [dvTP, 141] = (dcZONE_STATUS[41] == 1) [dvTP, 158] = (dcZONE_STATUS[58] == 1) [dvTP, 159] = (dcZONE_STATUS[59] == 1) [dvTP, 160] = (dcZONE_STATUS[60] == 1) [dvTP, 161] = (dcZONE_STATUS[61] == 1) [dvTP, 162] = (dcZONE_STATUS[62] == 1) [dvTP, 163] = (dcZONE_STATUS[63] == 1) [dvTP, 165] = (dcZONE_STATUS[65] == 1) [dvTP, 166] = (dcZONE_STATUS[66] == 1) [dvTP, 167] = (dcZONE_STATUS[67] == 1) [dvTP, 168] = (dcZONE_STATUS[68] == 1) [dvTP, 169] = (dcZONE_STATUS[69] == 1) [dvTP, 170] = (dcZONE_STATUS[70] == 1) [dvTP, 171] = (dcZONE_STATUS[71] == 1) [dvTP, 172] = (dcZONE_STATUS[72] == 1) [dvTP, 173] = (dcZONE_STATUS[73] == 1) [dvTP, 174] = (dcZONE_STATUS[74] == 1) [dvTP, 175] = (dcZONE_STATUS[75] == 1) } (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************)To enter Programming: Installer Code + 8 + 0 + 0 + 0
Program *05: Enter 1 to view all zone faults/restores, enter 0 to view only events enabled in 1*79
Program *14: Enter 1 to set RS232 input at TB4 (Built-in Serial Port)
Program *79: Zone types restore reports for types 1-8 set to 1
Program *80: Zone types restore reports for types 9,10,16 and 14 set to 1
SETTINGS these last 3 made the difference
Program 1*78: Enter 1 for Extended Protocol Event reports, enter 0 for Simple
Program 1*79: To enable Event Log Types, enter 1 for each entry, 0 = disable
Program 1*80: When enabled automatically transfers zone fault/restore data of the RS232 output (TB4)
To program a field like 1*78 you need to enter the ALT PROGRAMMING by using #94 while in regular programming mode, then just enter *78 as regular programming. This was what hold me up until talking to an alarm expert.
Cheers!
Paul