Changes in / [20:30]


Ignore:
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • /I_ElkAlarmPanel1.lua

    r20 r30  
    22 
    33-- Flags 
    4 local DEBUG_MODE = true 
    5 local UPDATE_AT_STARTUP = true 
     4local DEBUG_MODE = false 
    65 
    76-- Constants 
    87local VERSION = "1.0 alpha" 
    98 
    10 local PANEL_SID = "urn:micasaverde-com:serviceId:ElkAlarmPanel1" 
    11 local PARTITION_SID = "urn:micasaverde-com:serviceId:AlarmPartition2" 
    12 local SECURITY_SID = "urn:micasaverde-com:serviceId:SecuritySensor1" 
    13  
    14 local TASK_ERROR = 2 
    15 local TASK_ERROR_PERM = -2 
    16 local TASK_SUCCESS = 4 
    17 local TASK_BUSY = 1 
    18  
    19 local MAX_RETRIES = 3 
     9local SID = { 
     10    PANEL = "urn:micasaverde-com:serviceId:ElkAlarmPanel1", 
     11    PARTITION = "urn:micasaverde-com:serviceId:AlarmPartition2", 
     12    SECURITY = "urn:micasaverde-com:serviceId:SecuritySensor1" 
     13} 
     14 
     15local TASK = { 
     16    ERROR = 2, 
     17    ERROR_PERM = -2, 
     18    SUCCESS = 4, 
     19    BUSY = 1 
     20} 
     21 
     22local MAX_RETRIES = 2 
     23local MAX_READS = 3 
    2024 
    2125-- Globals 
    22 local g_remoteArmEnabled = false 
    23 local g_remoteDisarmEnabled = false 
    24 local g_remotePanicEnabled = false 
    25  
    2626local lug_device = nil 
    27 local g_errorMessage = nil 
    28 local g_pinCode = nil 
     27local g_pinCodes = {} 
    2928local g_taskHandle = -1 
    3029 
    3130local g_childDevices = { 
    32     partitions = {}, 
    33     zones = {}, 
    34 } 
    35  
    36 local log = luup.log 
     31    partitions = { 
     32        -- Members: 
     33        -- * device 
     34        -- * label 
     35        -- * zones 
     36        -- * armingStatus 
     37        -- * armUpState 
     38        -- * alarmState 
     39    }, 
     40    zones = { 
     41        -- Members: 
     42        -- * device 
     43        -- * label 
     44        -- * partition 
     45        -- * armed 
     46        -- * tripped 
     47    }, 
     48} 
     49 
     50local g_status = { 
     51    errorMessage = nil, 
     52    startup = false 
     53} 
     54 
     55local g_remote = { 
     56    armEnabled = false, 
     57    disarmEnabled = false, 
     58    panicEnabled = false 
     59} 
    3760 
    3861 
     
    4669    ['2'] = "Voice only", 
    4770    ['3'] = "Chime and voice" 
    48 }]] 
    49  
    50 local EVENTS = { 
    51     FIRE_ALARM = 1001, 
    52     FIRE_SUPERVISORY_ALARM = 1002, 
    53     BURGLAR_ALARM = 1003, 
    54     MEDICAL_ALARM = 1004, 
    55     POLICE_ALARM = 1005, 
    56     AUX1_ALARM = 1006, 
    57     AUX2_ALARM = 1007, 
    58     CARBON_MONOXIDE_ALARM = 1008, 
    59     EMERGENCY_ALARM = 1009, 
    60     FREEZE_ALARM = 1010, 
    61     GAS_ALARM = 1011, 
    62     HEAT_ALARM = 1012, 
    63     WATER_ALARM = 1013, 
    64     ANY_ALARM = 1014, 
    65     BURGLAR = 1015, 
    66     MEDICAL = 1023, 
    67     POLICE = 1031, 
    68     AUX1 = 1039, 
    69     AUX2 = 1047, 
    70     CO = 1055, 
    71     EMERGENCY = 1063, 
    72     FREEZE = 1071, 
    73     GAS = 1079, 
    74     HEAT = 1087, 
    75     WATER = 1095, 
    76     ANY = 1103 
    77 } 
    78  
    79 local TROUBLES = { 
    80     "AC Fail Trouble", 
    81     "Box Tamper Trouble", 
    82     "Fail To Communicate Trouble", 
    83     "EProm Memory Error Trouble", 
    84     "Low Battery Control Trouble", 
    85     "Transmitter Low Battery Trouble", 
    86     "Over Current Trouble", 
    87     "Telephone Fault Trouble", 
    88     "N/A", 
    89     "Output 2 Trouble", 
    90     "Missing Keypad Trouble", 
    91     "Zone Expander Trouble", 
    92     "Output Expander Trouble", 
    93     "N/A", 
    94     "ELKRP Remote Access Trouble", 
    95     "N/A", 
    96     "Common Area Not Armed Trouble", 
    97     "Flash Memory Error Trouble", 
    98     "Security Alert Trouble", 
    99     "Serial Port Expander Trouble", 
    100     "Lost Transmitter Trouble", 
    101     "GE Smoke CleanMe Trouble", 
    102     "Ethernet Trouble", 
    103     "N/A", 
    104     "N/A", 
    105     "N/A", 
    106     "N/A", 
    107     "N/A", 
    108     "N/A", 
    109     "N/A", 
    110     "N/A", 
    111     "Display Message In Keypad Line 1 Trouble", 
    112     "Display Message In Keypad Line 2 Trouble", 
    113     "Fire Trouble" 
    114 } 
    115  
    116 local ARMING_STATUSES = { 
    117     ['0'] = "Disarmed", 
    118     ['1'] = "Armed", 
    119     ['2'] = "Stay", 
    120     ['3'] = "StayInstant", 
    121     ['4'] = "Night", 
    122     ['5'] = "NightInstant", 
    123     ['6'] = "Vacation" 
    12471} 
    12572 
     
    13279    ['5'] = "ForceArmed", 
    13380    ['6'] = "ArmedWithBypass" 
    134 } 
    135  
    136 local ALARM_STATES = { 
    137     ['0'] = "None", 
    138     ['1'] = "EntranceDelay", 
    139     ['2'] = "AlarmAbortDelay", 
    140     ['3'] = "FireAlarm", 
    141     ['4'] = "MedicalAlarm", 
    142     ['5'] = "PoliceAlarm", 
    143     ['6'] = "BurglarAlarm", 
    144     ['7'] = "Aux1Alarm", 
    145     ['8'] = "Aux2Alarm", 
    146     ['9'] = "Aux3Alarm", -- not used 
    147     [':'] = "Aux4Alarm", -- not used 
    148     [';'] = "CarbonMonoxideAlarm", 
    149     ['<'] = "EmergencyAlarm", 
    150     ['='] = "FreezeAlarm", 
    151     ['>'] = "GasAlarm", 
    152     ['?'] = "HeatAlarm", 
    153     ['@'] = "WaterAlarm", 
    154     ['A'] = "FireSupervisory", 
    155     ['B'] = "VerifyFire" 
    156 } 
    157  
    158 local ZONE_STATUSES = { 
    159     ['0'] = {"Normal", "Unconfigured"}, 
    160     ['1'] = {"Normal", "Open"}, 
    161     ['2'] = {"Normal", "EOL"}, 
    162     ['3'] = {"Normal", "Short"}, 
    163     ['4'] = nil, 
    164     ['5'] = {"Trouble", "Open"}, 
    165     ['6'] = {"Trouble", "EOL"}, 
    166     ['7'] = {"Trouble", "Short"}, 
    167     ['8'] = nil, 
    168     ['9'] = {"Violated", "Open"}, 
    169     ['A'] = {"Violated", "EOL"}, 
    170     ['B'] = {"Violated", "Short"}, 
    171     ['C'] = {"Bypassed", nil}, 
    172     ['D'] = {"Bypassed", "Open"}, 
    173     ['E'] = {"Bypassed", "EOL"}, 
    174     ['F'] = {"Bypassed", "Short"} 
    175 } 
    176  
    177 local LABEL_TYPES = { 
    178     ["00"] = "Zone Name", 
    179     ["01"] = "Area Name", 
    180     ["02"] = "User Name", 
    181     ["03"] = "Keypad Name", 
    182     ["04"] = "Output Name", 
    183     ["05"] = "Task Name", 
    184     ["06"] = "Telephone Name", 
    185     ["07"] = "Light Name", 
    186     ["08"] = "Alarm Duration Name", 
    187     ["09"] = "Custom Settings", 
    188     ["10"] = "Counters Names", 
    189     ["11"] = "Thermostat Names", 
    190     ["12"] = "Function Key 1 Name", 
    191     ["13"] = "Function Key 2 Name", 
    192     ["14"] = "Function Key 3 Name", 
    193     ["15"] = "Function Key 4 Name", 
    194     ["16"] = "Function Key 5 Name", 
    195     ["17"] = "Function Key 6 Name", 
    196     ["18"] = "Audio Zone Name", 
    197     ["19"] = "Audio Source Name" 
    19881} 
    19982 
     
    237120    ['T'] = "Intercom Key" 
    238121} 
     122]] 
     123 
     124local EVENTS = { 
     125    FIRE_ALARM = 1001, 
     126    FIRE_SUPERVISORY_ALARM = 1002, 
     127    BURGLAR_ALARM = 1003, 
     128    MEDICAL_ALARM = 1004, 
     129    POLICE_ALARM = 1005, 
     130    AUX1_ALARM = 1006, 
     131    AUX2_ALARM = 1007, 
     132    CARBON_MONOXIDE_ALARM = 1008, 
     133    EMERGENCY_ALARM = 1009, 
     134    FREEZE_ALARM = 1010, 
     135    GAS_ALARM = 1011, 
     136    HEAT_ALARM = 1012, 
     137    WATER_ALARM = 1013, 
     138    ANY_ALARM = 1014, 
     139    BURGLAR = 1015, 
     140    MEDICAL = 1023, 
     141    POLICE = 1031, 
     142    AUX1 = 1039, 
     143    AUX2 = 1047, 
     144    CO = 1055, 
     145    EMERGENCY = 1063, 
     146    FREEZE = 1071, 
     147    GAS = 1079, 
     148    HEAT = 1087, 
     149    WATER = 1095, 
     150    ANY = 1103 
     151} 
     152 
     153local TROUBLES = { 
     154    "AC Fail Trouble", 
     155    "Box Tamper Trouble", 
     156    "Fail To Communicate Trouble", 
     157    "EProm Memory Error Trouble", 
     158    "Low Battery Control Trouble", 
     159    "Transmitter Low Battery Trouble", 
     160    "Over Current Trouble", 
     161    "Telephone Fault Trouble", 
     162    "N/A", 
     163    "Output 2 Trouble", 
     164    "Missing Keypad Trouble", 
     165    "Zone Expander Trouble", 
     166    "Output Expander Trouble", 
     167    "N/A", 
     168    "ELKRP Remote Access Trouble", 
     169    "N/A", 
     170    "Common Area Not Armed Trouble", 
     171    "Flash Memory Error Trouble", 
     172    "Security Alert Trouble", 
     173    "Serial Port Expander Trouble", 
     174    "Lost Transmitter Trouble", 
     175    "GE Smoke CleanMe Trouble", 
     176    "Ethernet Trouble", 
     177    "N/A", 
     178    "N/A", 
     179    "N/A", 
     180    "N/A", 
     181    "N/A", 
     182    "N/A", 
     183    "N/A", 
     184    "N/A", 
     185    "Display Message In Keypad Line 1 Trouble", 
     186    "Display Message In Keypad Line 2 Trouble", 
     187    "Fire Trouble" 
     188} 
     189 
     190local ARMING_STATUSES = { 
     191    ['0'] = "Disarmed", 
     192    ['1'] = "Armed", 
     193    ['2'] = "Stay", 
     194    ['3'] = "StayInstant", 
     195    ['4'] = "Night", 
     196    ['5'] = "NightInstant", 
     197    ['6'] = "Vacation" 
     198} 
     199 
     200local ALARM_STATES = { 
     201    ['0'] = "None", 
     202    ['1'] = "Entrance Delay", 
     203    ['2'] = "Alarm Abort Delay", 
     204    ['3'] = "Fire Alarm", 
     205    ['4'] = "Medical Alarm", 
     206    ['5'] = "Police Alarm", 
     207    ['6'] = "Burglar Alarm", 
     208    ['7'] = "Aux1 Alarm", 
     209    ['8'] = "Aux2 Alarm", 
     210    -- ['9'] = "Aux3 Alarm", -- not used 
     211    -- [':'] = "Aux4 Alarm", -- not used 
     212    [';'] = "Carbon Monoxide Alarm", 
     213    ['<'] = "Emergency Alarm", 
     214    ['='] = "Freeze Alarm", 
     215    ['>'] = "Gas Alarm", 
     216    ['?'] = "Heat Alarm", 
     217    ['@'] = "Water Alarm", 
     218    ['A'] = "Fire Supervisory", 
     219    ['B'] = "Verify Fire" 
     220} 
     221 
     222local ZONE_STATUSES = { 
     223    ['0'] = "Normal", -- "Unconfigured" 
     224    ['1'] = "Normal", -- "Open" 
     225    ['2'] = "Normal", -- "EOL" 
     226    ['3'] = "Normal", -- "Short" 
     227    ['4'] = "N/A", 
     228    ['5'] = "Trouble", -- "Open" 
     229    ['6'] = "Trouble", -- "EOL" 
     230    ['7'] = "Trouble", -- "Short" 
     231    ['8'] = "N/A", 
     232    ['9'] = "Violated", -- "Open" 
     233    ['A'] = "Violated", -- "EOL" 
     234    ['B'] = "Violated", -- "Short" 
     235    ['C'] = "Bypassed", 
     236    ['D'] = "Bypassed", -- "Open" 
     237    ['E'] = "Bypassed", -- "EOL" 
     238    ['F'] = "Bypassed"  -- "Short" 
     239} 
     240 
     241local LABEL_TYPES = { 
     242    ["00"] = "Zone Name", 
     243    ["01"] = "Area Name", 
     244    ["02"] = "User Name", 
     245    ["03"] = "Keypad Name", 
     246    ["04"] = "Output Name", 
     247    ["05"] = "Task Name", 
     248    ["06"] = "Telephone Name", 
     249    ["07"] = "Light Name", 
     250    ["08"] = "Alarm Duration Name", 
     251    ["09"] = "Custom Settings", 
     252    ["10"] = "Counters Names", 
     253    ["11"] = "Thermostat Names", 
     254    ["12"] = "Function Key 1 Name", 
     255    ["13"] = "Function Key 2 Name", 
     256    ["14"] = "Function Key 3 Name", 
     257    ["15"] = "Function Key 4 Name", 
     258    ["16"] = "Function Key 5 Name", 
     259    ["17"] = "Function Key 6 Name", 
     260    ["18"] = "Audio Zone Name", 
     261    ["19"] = "Audio Source Name" 
     262} 
    239263 
    240264local COMMAND_DESCRIPTIONS = { 
     265    ["a0"] = "Disarm", 
     266    ["a1"] = "Arm Away", 
     267    ["a2"] = "Arm Stay", 
     268    ["a3"] = "Arm Stay Instant", 
     269    ["a4"] = "Arm Night", 
     270    ["a5"] = "Arm Night Instant", 
     271    ["a6"] = "Arm Vacation", 
    241272    ["as"] = "Request arming status", 
    242273    ["kf"] = "Request chime modes", 
     
    253284 
    254285 
     286local log = luup.log 
     287 
    255288local function debug (text) 
    256289    if (DEBUG_MODE == true) then 
     
    262295local function task (text, mode) 
    263296    debug (string.format ("(task) %s", text)) 
    264     if (mode == TASK_ERROR_PERM) then 
    265         g_taskHandle = luup.task (text, TASK_ERROR, "ElkAlarmPanel", g_taskHandle) 
     297    if (mode == TASK.ERROR_PERM) then 
     298        g_taskHandle = luup.task (text, TASK.ERROR, "ElkAlarmPanel", g_taskHandle) 
    266299    else 
    267300        g_taskHandle = luup.task (text, mode, "ElkAlarmPanel", g_taskHandle) 
    268301 
    269302        -- Clear the previous error, since they're all transient 
    270         if (mode ~= TASK_SUCCESS) then 
     303        if (mode ~= TASK.SUCCESS) then 
    271304            luup.call_delay ("clearTask", 30, "", false) 
    272305        end 
     
    276309 
    277310function clearTask() 
    278     task ("Clearing...", TASK_SUCCESS) 
     311    task ("Clearing...", TASK.SUCCESS) 
     312    return true 
    279313end 
    280314 
     
    323357 
    324358 
     359local function setZoneState (zoneNo, variable, value) 
     360    local device = g_childDevices.zones[zoneNo].device 
     361    if (device) then 
     362        debug (string.format ("(setZoneState) zone %d (device %d), set %s='%s'", zoneNo, device, variable, tostring (value))) 
     363        luup.variable_set (SID.SECURITY, variable, value, device) 
     364    else 
     365        log (string.format ("(setZoneState) ERROR: No device for zone %d (variable=%s, value='%s').", zoneNo, variable, tostring (value))) 
     366    end 
     367end 
     368 
     369 
     370local function getPartitionState (partNo, variable) 
     371    local device = g_childDevices.partitions[partNo].device 
     372    if (device) then 
     373        local v = luup.variable_get (SID.PARTITION, variable, device) 
     374        debug (string.format ("(getPartitionState) partition %d (device %d), got '%s'", partNo, device, tostring (v))) 
     375    else 
     376        log (string.format ("(getPartitionState) ERROR: No device for partition %d (variable=%s).", partNo, variable)) 
     377        return nil 
     378    end 
     379end 
     380 
     381 
    325382local function setPartitionState (partNo, variable, value) 
    326     if (g_childDevices.partitions[partNo].device ~= nil) then 
    327         luup.variable_set (PARTITION_SID, variable, value, g_childDevices.partitions[partNo].device) 
     383    local device = g_childDevices.partitions[partNo].device 
     384    if (device) then 
     385        debug (string.format ("(setPartitionState) partition %d (device %d), set %s='%s'", partNo, device, variable, tostring (value))) 
     386        luup.variable_set (SID.PARTITION, variable, value, device) 
    328387    else 
    329         log (string.format ("(setPartitionState) ERROR: Non-existent partition #%d (variable = %s, value = %s).", partNo, variable, tostring (value))) 
     388        log (string.format ("(setPartitionState) ERROR: No device for partition %d (variable=%s, value='%s').", partNo, variable, tostring (value))) 
    330389    end 
    331390end 
     
    339398    end 
    340399 
    341     local length, msgType, data, checksum = msg:match ("^(%x%x)(%a%w)(.*)00(%x%x)$") 
     400    local length, msgType, data, misc, checksum = msg:match ("^(%x%x)(%a%w)(.*)(%x%x)(%x%x)$") 
    342401    if ((length == nil) or (msgType == nil) or (checksum == nil)) then 
     402        debug ("(checkMessage) Received message: " .. msg) 
    343403        log ("(checkMessage) ERROR: The received message has invalid format.") 
    344         debug ("(checkMessage) Received message: " .. msg) 
    345         task ("ERROR: The received message has invalid format.", TASK_ERROR) 
    346404        return nil 
    347405    end 
    348     debug (string.format ("(checkMessage) length=%d(0x%s), message type=%s, data='%s', checksum=%s", tonumber (length, 16) or 0, length, msgType, tostring (data), checksum)) 
     406 
     407    debug (string.format ("(checkMessage) length=%d(0x%s), message type=%s, data='%s', misc=%s, checksum=%s", tonumber (length, 16) or 0, length, msgType, tostring (data), misc, checksum)) 
     408 
     409    -- There is a bug in the version 5.1.20: the reported length for EE, which is 0F is incorrect. 
     410    -- The correct length is 0E. This affects the checksum, so we bypass this message. 
     411    if (msgType == "EE") then 
     412        return "EE" 
     413    end 
    349414 
    350415    data = data or "" 
    351416 
    352     local calculatedLength = #msgType + #data + 2 + #checksum 
     417    local calculatedLength = #msgType + #data + #misc + #checksum 
    353418    if (calculatedLength ~= tonumber (length, 16)) then 
    354419        log ("(checkMessage) ERROR: The received message length is incorrect.") 
    355         task ("ERROR: The received message length is incorrect.", TASK_ERROR) 
    356420        return nil 
    357421    end 
    358422 
    359     local calculatedChecksum = calculateChecksum (length .. msgType .. data .. "00") 
     423    local calculatedChecksum = calculateChecksum (length .. msgType .. data .. misc) 
    360424    if (calculatedChecksum ~= tonumber (checksum, 16)) then 
    361425        log ("(checkMessage) ERROR: The calculated checksum is incorrect.") 
    362         task ("ERROR: The calculated checksum is incorrect.", TASK_ERROR) 
    363426        return nil 
    364427    end 
     
    429492 
    430493local function processArmingStatusReport (data) 
    431     S = {} 
    432     U = {} 
    433     A = {} 
     494    S = {} -- Arming statuses 
     495    U = {} -- Arm up states 
     496    A = {} -- Alarm states 
    434497 
    435498    for i = 1, 8 do 
     
    443506    end 
    444507 
    445     for i in ipairs (g_childDevices.partitions) do 
     508    for i in pairs (g_childDevices.partitions) do 
    446509        g_childDevices.partitions[i].armingStatus = ARMING_STATUSES[S[i]] 
    447         g_childDevices.partitions[i].armUpState = ARM_UP_STATES[U[i]] 
     510        g_childDevices.partitions[i].armUpState = U[i] 
    448511        g_childDevices.partitions[i].alarmState = A[i] 
    449         if (A[i] and A[i] >= '3') then 
    450             -- We have an alarm. 
    451             local message = string.format ("ALARM: %s, partition #%d", ALARM_STATES[A[i]], i) 
     512 
     513        if (A[i] >= '3') then -- We have an alarm. 
     514            local message = string.format ("ALARM: %s, %s", ALARM_STATES[A[i]], g_childDevices.partitions[i].label) 
    452515            log (message) 
    453             task (message, TASK_ERROR_PERM) 
     516            task (message, TASK.ERROR_PERM) 
     517             
     518            setPartitionState (i, "Alarm", "Active") 
     519            setPartitionState (i, "AlarmMemory", "1") 
     520            setPartitionState (i, "LastAlarmActive", os.date()) 
     521        else 
     522            if (getPartitionState (i, "AlarmMemory") == "1") then -- There was an alarm, but it has been deactivated. 
     523                setPartitionState (i, "Alarm", "None") 
     524                setPartitionState (i, "AlarmMemory", "0") 
     525                clearTask() 
     526            end 
     527        end 
     528    end 
     529 
     530    for k, v in pairs (g_childDevices.partitions) do 
     531        local message = string.format ("armingStatus=%s, armUpState=%s, alarmState=%s", v.armingStatus, v.armUpState, v.alarmState) 
     532        debug ("(processArmingStatusReport) partition " .. tostring (k) .. ", " .. message) 
     533        if (not v.armingStatus) then 
     534            -- We don't have this partition's status. Consider it Disarmed and NotReady just to be safe. 
     535            setPartitionState (k, "ArmMode", "Disarmed") 
     536            setPartitionState (k, "DetailedArmMode", "NotReady") 
     537        elseif (v.armingStatus ~= "Disarmed") then 
     538            -- The partition is in one of the armed states. 
     539            setPartitionState (k, "ArmMode", "Armed") 
     540            setPartitionState (k, "DetailedArmMode", v.armingStatus) 
     541        else 
     542            -- The partition is disarmed. 
     543            setPartitionState (k, "ArmMode", "Disarmed") 
     544            if (v.armUpState == '0') then 
     545                setPartitionState (k, "DetailedArmMode", "NotReady") 
     546            elseif (v.armUpState <= '2') then 
     547                setPartitionState (k, "DetailedArmMode", "Ready") 
     548            else 
     549                log ("(processArmingStatusReport) Impossible combination of 'armingStatus' and 'armUpState'.") 
     550            end 
    454551        end 
    455552    end 
     
    464561        local alarmZone = (tonumber (eventData) <= 208) and eventData or "N/A" 
    465562        log (string.format ("ALARM: Alarm type = %s, area = %s, zone = %s", alarmType, tostring (alarmArea or "N/A"), alarmZone)) 
    466         setPartitionState (area, "Alarm", "Active") 
    467         setPartitionState (area, "AlarmMemory", "1") 
    468         setPartitionState (area, "LastAlarmActive", os.date()) 
    469         task (string.format ("ALARM: Alarm type = %s, area = %s, zone = %s", alarmType, tostring (alarmArea or "N/A"), alarmZone), TASK_ERROR_PERM) 
     563         
     564        task (string.format ("ALARM: Alarm type = %s, area = %s, zone = %s", alarmType, tostring (alarmArea or "N/A"), alarmZone), TASK.ERROR_PERM) 
    470565    else 
    471566        debug ("Unhandled event") 
     
    497592            end 
    498593            log (message) 
    499             task (message, TASK_ERROR_PERM) 
     594            task (message, TASK.ERROR_PERM) 
     595        end 
     596    end 
     597end 
     598 
     599 
     600local function processZoneChangeUpdate (data) 
     601    local zoneNo, status = data:match ("^(%d%d%d)(%x)$") 
     602    zoneNo = tonumber (zoneNo, 10) 
     603    debug (string.format ("(processZoneChangeUpdate) zone=%d, status=%s", zoneNo, ZONE_STATUSES[status])) 
     604    if (ZONE_STATUSES[status] == "Normal") then 
     605        luup.variable_set (SID.SECURITY, "Armed", "1", g_childDevices.zones[zoneNo].device) 
     606        luup.variable_set (SID.SECURITY, "Tripped", "0", g_childDevices.zones[zoneNo].device) 
     607    elseif (ZONE_STATUSES[status] == "Violated") then 
     608        luup.variable_set (SID.SECURITY, "Tripped", "1", g_childDevices.zones[zoneNo].device) 
     609    elseif (ZONE_STATUSES[status] == "Bypassed") then 
     610        luup.variable_set (SID.SECURITY, "Armed", "0", g_childDevices.zones[zoneNo].device) 
     611    else -- It's either in Trouble or in an invalid state. 
     612        luup.variable_set (SID.SECURITY, "Armed", "0", g_childDevices.zones[zoneNo].device) 
     613        luup.variable_set (SID.SECURITY, "Tripped", "0", g_childDevices.zones[zoneNo].device) 
     614    end 
     615end 
     616 
     617 
     618local function processZonePartitionReport (data) 
     619    for i in pairs (g_childDevices.zones) do 
     620        local c = data:sub (i, i) 
     621        if (c ~= '0') then 
     622            p = tonumber (c) 
     623            g_childDevices.zones[i].partition = p; 
     624            if (not g_childDevices.partitions[p]) then 
     625                g_childDevices.partitions[p] = {zones = {i}} 
     626            else 
     627                table.insert (g_childDevices.partitions[p].zones, i) 
     628            end 
     629        else 
     630            g_childDevices.zones[i].partition = 1; 
    500631        end 
    501632    end 
     
    504635 
    505636local function processZoneStatusReport (data) 
    506     for i = 1, #data do 
    507         c = data:sub (i, i) 
    508         if (g_childDevices.zones[i]) then 
    509             if (ZONE_STATUSES[c][1] == "Trouble" or ZONE_STATUSES[c][1] == "Violated") then 
    510                 luup.variable_set (SECURITY_SID, "Armed", "1", g_childDevices.zones[i].device) 
    511                 luup.variable_set (SECURITY_SID, "Tripped", "1", g_childDevices.zones[i].device) 
    512             elseif (ZONE_STATUSES[c][1] == "Bypassed") then 
    513                 luup.variable_set (SECURITY_SID, "Armed", "0", g_childDevices.zones[i].device) 
    514                 luup.variable_set (SECURITY_SID, "Tripped", "0", g_childDevices.zones[i].device) 
    515             else -- By default, the sensors will be armed and untripped. 
    516                 luup.variable_set (SECURITY_SID, "Armed", "1", g_childDevices.zones[i].device) 
    517                 luup.variable_set (SECURITY_SID, "Tripped", "0", g_childDevices.zones[i].device) 
    518             end 
    519         end 
    520     end 
    521 end 
    522  
    523  
    524 local function processZonePartitionReport (data) 
    525     for i = 1, #data do 
    526         c = data:sub (i, i) 
    527         if (g_childDevices.zones[i]) then 
    528             if (c ~= '0') then 
    529                 p = tonumber (c) 
    530                 g_childDevices.zones[i].partition = p; 
    531                 if (not g_childDevices.partitions[p]) then 
    532                     g_childDevices.partitions[p] = {zones = {i}} 
    533                 else 
    534                     table.insert (g_childDevices.partitions[p].zones, i) 
    535                 end 
    536             else 
    537                 g_childDevices.zones[i].partition = "no partition"; 
    538             end 
    539         end 
    540     end 
    541     table.sort (g_childDevices.partitions) 
     637    for i in pairs (g_childDevices.zones) do 
     638        local c = data:sub (i, i) 
     639        debug (string.format ("(processZoneStatusReport) zone %d, status=%s", i, ZONE_STATUSES[c])) 
     640        if (ZONE_STATUSES[c] == "Normal") then 
     641            g_childDevices.zones[i].armed = "1" 
     642            g_childDevices.zones[i].tripped = "0" 
     643        elseif (ZONE_STATUSES[c] == "Violated") then 
     644            g_childDevices.zones[i].armed = "1" 
     645            g_childDevices.zones[i].tripped = "1" 
     646        elseif (ZONE_STATUSES[c] == "Bypassed") then 
     647            g_childDevices.zones[i].armed = "0" 
     648            g_childDevices.zones[i].tripped = "0" 
     649        else -- It's either in Trouble or in an invalid state. 
     650            g_childDevices.zones[i].armed = "0" 
     651            g_childDevices.zones[i].tripped = "0" 
     652        end 
     653    end 
    542654end 
    543655 
     
    571683                          debug ("(handlerFunc) Message type description: " .. self.description) 
    572684                          data = data:sub(4) -- We're interested only in the Chime information. 
    573                           for i in ipairs (g_childDevices.partitions) do 
    574                               g_childDevices.partitions[i].chimeMode = data[i] 
     685                          for i in pairs (g_childDevices.partitions) do 
     686                              local chimeEnabled = (data[i] == '0') and "0" or "1" 
     687                              setPartitionState (i, "ChimeEnabled", chimeEnabled) 
    575688                          end 
    576689                          return true 
     
    615728                          local zone, status = data:match ("^(%d%d%d)(%d)$") 
    616729                          if (status == "1") then 
    617                               return "bypassed", zone 
     730                              return "bypassed" 
    618731                          end 
    619                           return "unbypassed", zone 
     732                          return "unbypassed" 
    620733                      end 
    621734    }, 
     
    624737        handlerFunc = function (self, data) 
    625738                          debug ("(handlerFunc) Message type description: " .. self.description) 
    626                           processZoneStatusReport (data) 
     739                          processZoneChangeUpdate (data) 
    627740                          return true 
    628741                      end 
     
    635748                              c = data:sub (i, i) 
    636749                              if (c ~= '0') then 
    637                                   g_childDevices.zones[i] = {definition = ZONE_DEFINITIONS[c]} 
     750                                  g_childDevices.zones[i] = {} -- Create zone. 
    638751                              end 
    639752                          end 
     
    663776    if (not msgType) then 
    664777        msgType, data = checkMessage (data) 
     778        if (not msgType or tostring (msgType) == "") then 
     779            return false 
     780        end 
    665781    end 
    666782 
     
    685801    if (not msgType) then 
    686802        log (string.format ("(%s) ERROR: %s", functionName, errorMsg)) 
    687         g_errorMessage = errorMsg 
    688         return false 
    689     end 
    690  
    691     local status = processMessage (data, msgType) 
    692      
     803        g_status.errorMessage = errorMsg 
     804        return false 
     805    end 
     806 
     807    local status, data = processMessage (data, msgType) 
     808 
    693809    if (msgType == expectedMsgType) then -- We received the expected message. 
     810        debug ("(readResponse) Got expected message.") 
    694811        if (not status) then 
    695812            log (string.format ("(%s) ERROR: %s", functionName, errorMsg)) 
    696             g_errorMessage = errorMsg 
    697         end 
    698         return status 
     813            g_status.errorMessage = errorMsg 
     814        end 
     815        return status, data 
    699816    end 
    700817 
    701818    -- We received other message. Process it and read the next message. 
    702819    local retryCount = 0 
    703     while (retryCount < MAX_RETRIES) do 
     820    while (retryCount <= MAX_RETRIES) do 
     821        luup.io.intercept() 
    704822        debug ("(readResponse) Unexpected response type. Intercept next message.") 
    705823        retryCount = retryCount + 1 
     
    708826        if (not msgType) then 
    709827            log (string.format ("(%s) ERROR: %s", functionName, errorMsg)) 
    710             g_errorMessage = errorMsg 
     828            g_status.errorMessage = errorMsg 
    711829            return false 
    712830        end 
    713831 
    714         status = processMessage (data, msgType) 
    715          
     832        status, data = processMessage (data, msgType) 
     833 
    716834        if (msgType == expectedMsgType) then -- We received the expected message. 
     835            debug ("(readResponse) Got expected message.") 
    717836            if (not status) then 
    718837                log (string.format ("(%s) ERROR: %s", functionName, errorMsg)) 
    719                 g_errorMessage = errorMsg 
     838                g_status.errorMessage = errorMsg 
    720839            end 
    721             return status 
     840            return status, data 
    722841        end 
    723842    end 
     
    725844    -- Shouldn't get here. 
    726845    return nil 
     846end 
     847 
     848 
     849local function readArmRequestResponse() 
     850 
     851    local readCnt = 0 
     852 
     853    while (readCnt <= MAX_READS) do 
     854        local msgType, data = checkMessage (luup.io.read()) 
     855        if (not msgType) then 
     856            return false 
     857        end 
     858 
     859        if (msgType == "AS") then 
     860            debug ("(readArmRequestResponse) Got expected message.") 
     861            return true 
     862        elseif (msgType == "IC") then -- Invalid PIN code. 
     863            debug ("(readArmRequestResponse) Got expected message.") 
     864            return "IC" 
     865        else 
     866            debug ("(readArmRequestResponse) Got unexpected message. Ignore it.") 
     867            readCnt = readCnt + 1 
     868            if (readCnt < MAX_READS) then 
     869                luup.io.intercept() 
     870            end 
     871        end 
     872    end 
     873 
     874    return false 
     875end 
     876 
     877 
     878local function readBypassRequestResponse() 
     879 
     880    local readCnt = 0 
     881 
     882    while (readCnt <= MAX_READS) do 
     883        local msgType, data = checkMessage (luup.io.read()) 
     884        if (not msgType) then 
     885            return false 
     886        end 
     887 
     888        if (msgType == "ZB") then 
     889            debug ("(readBypassRequestResponse) Got expected message.") 
     890            return processMessage (data, msgType) 
     891        elseif (msgType == "IC") then -- Invalid PIN code. 
     892            debug ("(readBypassRequestResponse) Got expected message.") 
     893            return "IC" 
     894        else 
     895            debug ("(readBypassRequestResponse) Got unexpected message. Process it and intercept the next one.") 
     896            readCnt = readCnt + 1 
     897            if (readCnt < MAX_READS) then 
     898                luup.io.intercept() 
     899            end 
     900            processMessage (data, msgType) 
     901        end 
     902    end 
     903 
     904    return false 
    727905end 
    728906 
     
    748926    if (not sendCommand (msgType, data)) then 
    749927        log (string.format ("(%s) ERROR: %s", functionName, errorMsg)) 
    750         g_errorMessage = errorMsg 
     928        g_status.errorMessage = errorMsg 
    751929        return false 
    752930    end 
     
    759937 
    760938 
    761 function storePinCode (pinCode) 
    762     debug ("(storePinCode) pinCode=" .. tostring (pinCode)) 
     939function storePinCode (device, pinCode) 
     940 
     941    local partitionNo = extractPartition (luup.devices[device].id) 
     942    if (not partitionNo) then 
     943        log ("(storePinCode) ERROR: Found unexpected child.") 
     944        task ("Found unexpected child.", TASK.ERROR) 
     945        return false 
     946    end 
    763947 
    764948    if (not pinCode or pinCode == "") then 
    765949        log ("(storePinCode) ERROR: Invalid PIN code.") 
    766         task ("ERROR: Invalid PIN code.", TASK_ERROR) 
     950        task ("Invalid PIN code.", TASK.ERROR) 
    767951        return false 
    768952    end 
     
    771955    if (not pinCode:match ("^%d%d%d%d%d%d$")) then 
    772956        log ("(storePinCode) ERROR: Invalid PIN code.") 
    773         task ("ERROR: Invalid PIN code.", TASK_ERROR) 
    774         return false 
    775     end 
    776  
    777     g_pinCode = pinCode 
     957        task ("Invalid PIN code.", TASK.ERROR) 
     958        return false 
     959    end 
     960 
     961    g_pinCodes[tonumber (partitionNo)] = pinCode 
     962    debug ("(storePinCode) PIN code stored for partition " .. partitionNo .. ".") 
     963    return true 
     964end 
     965 
     966 
     967function clearPinCode (device) 
     968    local partitionNo = extractPartition (luup.devices[device].id) 
     969    if (not partitionNo) then 
     970        log ("(clearPinCode) ERROR: Found unexpected child.") 
     971        task ("Found unexpected child.", TASK.ERROR) 
     972        return false 
     973    end 
     974 
     975    g_pinCodes[tonumber (partitionNo)] = nil 
     976    debug ("(clearPinCode) PIN code cleared for partition " .. partitionNo .. ".") 
     977    return true 
    778978end 
    779979 
    780980 
    781981function requestArmMode (device, state, pinCode) 
    782     debug (string.format ("(requestArmMode) device=%d, state=%s, pinCode=%s", device, state, tostring (pinCode))) 
    783  
    784     if ((not pinCode or pinCode == "") and (not g_pinCode)) then 
     982    local functionName = "requestArmMode" 
     983    local errorMessage = "Failed to go into the requested arm mode." 
     984 
     985    debug (string.format ("(requestArmMode) device=%d, state=%s", device, state)) 
     986 
     987    local partitionNo = extractPartition (luup.devices[device].id) 
     988    if (not partitionNo) then 
     989        log ("(requestArmMode) ERROR: Found unexpected child.") 
     990        task ("Found unexpected child.", TASK.ERROR) 
     991        return false 
     992    end 
     993 
     994    partitionNo = tonumber (partitionNo) 
     995 
     996    pinCode = tonumber (pinCode) or g_pinCodes[partitionNo] 
     997    if (not pinCode) then 
    785998        log ("(requestArmMode) ERROR: PIN code required.") 
    786         task ("ERROR: PIN code required.", TASK_ERROR) 
    787         return false 
    788     end 
    789  
    790     local partition = extractPartition (luup.devices[device].id) 
    791     if (not partition) then 
    792         log ("(requestArmMode) ERROR: Found unexpected child.") 
    793         task ("ERROR: Unknown error encountered.", TASK_ERROR) 
     999        task ("PIN code required.", TASK.ERROR) 
    7941000        return false 
    7951001    end 
     
    7971003    -- All the arming commands are implicitly 'forced', 
    7981004    -- so for the 'Force' request use 'Away' instead. 
     1005    state = (state == "Force") and "Armed" or state 
     1006 
    7991007    local command 
    8001008    if (state == "Disarmed") then 
    801         command = "a0" 
     1009        command = "a0" -- Disarm 
    8021010    elseif ((state == "Armed") or (state == "Force")) then 
    803         command = "a1" 
     1011        command = "a1" -- Arm Away 
    8041012    elseif (state == "Stay") then 
    805         command = "a2" 
     1013        command = "a2" -- Arm Stay 
    8061014    elseif (state == "StayInstant") then 
    807         command = "a3" 
     1015        command = "a3" -- Arm Stay Instant 
    8081016    elseif (state == "Night") then 
    809         command = "a4" 
     1017        command = "a4" -- Arm Night 
    8101018    elseif (state == "NightInstant") then 
    811         command = "a5" 
     1019        command = "a5" -- Arm Night Instant 
    8121020    elseif (state == "Vacation") then 
    813         command = "a6" 
     1021        command = "a6" -- Arm Vacation 
    8141022    else 
    8151023        log ("(requestArmMode) ERROR: Invalid state requested.") 
    816         task ("Invalid state requested.", TASK_ERROR) 
     1024        task ("Invalid state requested.", TASK.ERROR) 
    8171025        return false 
    8181026    end 
     
    8201028    local data 
    8211029    if (pinCode and pinCode ~= "") then 
    822         data = partition .. padLeft (pinCode, 6, '0') 
     1030        data = partitionNo .. padLeft (pinCode, 6, '0') 
    8231031    else 
    824         data = partition .. g_pinCode 
    825     end 
    826  
    827     local status = sendCommand (command, data) 
     1032        data = partitionNo .. g_pinCodes 
     1033    end 
     1034 
     1035    local status = sendIntercepted (command, functionName, errorMessage, data) 
    8281036    if (not status) then 
    829         log ("(requestArmMode) ERROR: Failed to send command.") 
    830         task ("Failed to send command.", TASK_ERROR) 
    831         return false 
    832     end 
    833  
    834     g_pinCode = pinCode 
     1037        task ("Failed to send command.", TASK.ERROR) 
     1038        return false 
     1039    end 
     1040 
     1041    local status = readArmRequestResponse() 
     1042    if (not status) then 
     1043        log ("(requestArmMode) ERROR: " .. errorMessage) 
     1044        task (errorMessage, TASK.ERROR) 
     1045        return false 
     1046    elseif (status == "IC") then 
     1047        log ("(requestArmMode) ERROR: Invalid PIN code.") 
     1048        task ("Invalid PIN code.", TASK.ERROR) 
     1049        return false 
     1050    end 
     1051 
     1052    g_pinCodes[partitionNo] = pinCode 
     1053    debug ("(requestArmMode) SUCCESS: Succesfully changed to the requested arm mode.") 
     1054    task ("SUCCESS: Arm mode succesfully changed.") 
    8351055    return true 
    8361056end 
     
    8391059function requestQuickArmMode (device, state) 
    8401060    log ("(requestQuickArmMode) Quick Arm not supported.") 
    841     task ("One Touch Arm/Disarm not supported.", TASK_ERROR) 
     1061    task ("One Touch Arm/Disarm not supported.", TASK.ERROR) 
    8421062    return false 
    8431063end 
     
    8461066function requestPanicMode (device, state) 
    8471067    log ("(requestPanicMode) Panic Modes not supported.") 
    848     task ("Panic Modes not supported.", TASK_ERROR) 
     1068    task ("Panic Modes not supported.", TASK.ERROR) 
    8491069    return false 
    8501070end 
    8511071 
    8521072 
    853 local function unbypassZone (zoneNo, tryCount) 
    854     local functionName = "unbypassZone" 
     1073local function unbypassZone (zoneNo, pinCode, tryCount) 
    8551074    local errorMessage = string.format ("Failed to unbypass zone %d.", zoneNo) 
    8561075 
    857     local status = sendIntercepted ("zb", functionName, errorMessage, string.format ("%s1%s", padLeft (zoneNo, 3, '0'), padLeft (g_pinCode, 6, '0'))) 
     1076    debug ("(unbypassZone) tryCount=" .. tostring (tryCount)) 
     1077 
     1078    local data = string.format ("%s%d%s", padLeft (zoneNo, 3, '0'), g_childDevices.zones[zoneNo].partition, padLeft (pinCode, 6, '0')) 
     1079    local status = sendIntercepted ("zb", "unbypassZone", errorMessage, data) 
    8581080    if (not status) then 
    859         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    860         return false 
    861     end 
    862  
    863     local status, zone = readResponse ({"ZB", "IC"}, functionName, errorMessage) 
    864     if (not status or zone ~= zoneNo) then 
    865         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    866         return false 
    867     end 
    868  
    869     if (status == "unbypassed") then 
    870         debug (string.format ("(%s) SUCCESS: Unbypass successful.", functionName)) 
     1081        task (errorMessage, TASK.ERROR) 
     1082        return false 
     1083    end 
     1084 
     1085    local status = readBypassRequestResponse() 
     1086    debug ("(unbypassZone) status=" .. tostring (status)) 
     1087    if (not status) then 
     1088        log ("(unbypassZone) ERROR: " .. errorMessage) 
     1089        task (errorMessage, TASK.ERROR) 
     1090        return false 
     1091    elseif (status == "IC") then 
     1092        log ("(unbypassZone) ERROR: Invalid PIN code.") 
     1093        task ("Invalid PIN code.", TASK.ERROR) 
     1094        return false 
     1095    elseif (status == "unbypassed") then 
     1096        debug ("(unbypassZone) SUCCESS: Unbypass successful.") 
    8711097        return true 
    8721098    end 
     
    8741100    tryCount = (tryCount or 0) + 1 
    8751101    if (tryCount >= MAX_RETRIES) then 
    876         log (string.format ("(%s) ERROR: %s", functionName, errorMessage)) 
    877         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    878         return false 
    879     end 
    880  
    881     return unbypassZone (zoneNo, tryCount) 
    882 end 
    883  
    884  
    885 local function bypassZone (zoneNo, tryCount) 
    886     local functionName = "bypassZone" 
     1102        log ("(unbypassZone) ERROR: " .. errorMessage) 
     1103        task (errorMessage, TASK.ERROR) 
     1104        return false 
     1105    end 
     1106 
     1107    debug ("(unbypassZone) Unbypass failed, trying again...") 
     1108    return unbypassZone (zoneNo, pinCode, tryCount) 
     1109end 
     1110 
     1111 
     1112local function bypassZone (zoneNo, pinCode, tryCount) 
    8871113    local errorMessage = string.format ("Failed to bypass zone %d.", zoneNo) 
    8881114 
    889     local status = sendIntercepted ("zb", functionName, errorMessage, string.format ("%s1%s", padLeft (zoneNo, 3, '0'), padLeft (g_pinCode, 6, '0'))) 
     1115    debug ("(bypassZone) tryCount=" .. tostring (tryCount)) 
     1116 
     1117    local data = string.format ("%s%d%s", padLeft (zoneNo, 3, '0'), g_childDevices.zones[zoneNo].partition, padLeft (pinCode, 6, '0')) 
     1118    local status = sendIntercepted ("zb", "bypassZone", errorMessage, data) 
    8901119    if (not status) then 
    891         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    892         return false 
    893     end 
    894  
    895     local status, zone = readResponse ({"ZB", "IC"}, functionName, errorMessage) 
    896     if (not status or zone ~= zoneNo) then 
    897         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    898         return false 
    899     end 
    900  
    901     if (status == "bypassed") then 
    902         debug (string.format ("(%s) SUCCESS: Bypass successful.", functionName)) 
     1120        task (errorMessage, TASK.ERROR) 
     1121        return false 
     1122    end 
     1123 
     1124    local status = readBypassRequestResponse() 
     1125    debug ("(bypassZone) status=" .. tostring (status)) 
     1126    if (not status) then 
     1127        log ("(bypassZone) ERROR: " .. errorMessage) 
     1128        task (errorMessage, TASK.ERROR) 
     1129        return false 
     1130    elseif (status == "IC") then 
     1131        log ("(bypassZone) ERROR: Invalid PIN code.") 
     1132        task ("Invalid PIN code.", TASK.ERROR) 
     1133        return false 
     1134    elseif (status == "bypassed") then 
     1135        debug ("(bypassZone) SUCCESS: Bypass successful.") 
    9031136        return true 
    9041137    end 
     
    9061139    tryCount = (tryCount or 0) + 1 
    9071140    if (tryCount >= MAX_RETRIES) then 
    908         log (string.format ("(%s) ERROR: %s", functionName, errorMessage)) 
    909         task ("ERROR: " .. errorMessage, TASK_ERROR) 
    910         return false 
    911     end 
    912  
    913     return bypassZone (zoneNo, tryCount) 
     1141        log ("(bypassZone) ERROR: " .. errorMessage) 
     1142        task (errorMessage, TASK.ERROR) 
     1143        return false 
     1144    end 
     1145 
     1146    debug ("(bypassZone) Bypass failed, trying again...") 
     1147    return bypassZone (zoneNo, pinCode, tryCount) 
    9141148end 
    9151149 
    9161150 
    9171151function setArmed (device, newArmedValue) 
    918     debug (string.format ("(setArmed) device=%d, newArmedValue=%s, g_pinCode=%s", device, newArmedValue, tostring (g_pinCode))) 
    919  
    920     if (not g_pinCode) then 
     1152    debug (string.format ("(setArmed) device=%d, newArmedValue=%s", device, newArmedValue)) 
     1153 
     1154    local zoneNo = extractZone (luup.devices[device].id) 
     1155    if (not zoneNo) then 
     1156        log ("(setArmed) ERROR: Found unexpected child.") 
     1157        task ("Found unexpected child.", TASK.ERROR) 
     1158        return false 
     1159    end 
     1160 
     1161    zoneNo = tonumber (zoneNo) 
     1162 
     1163    local pinCode = g_pinCodes[g_childDevices.zones[zoneNo].partition] 
     1164    if (not pinCode) then 
    9211165        log ("(setArmed) ERROR: Pin code required.") 
    922         task ("ERROR: Pin code required.", TASK_ERROR) 
    923         return false 
    924     end 
    925  
    926     local zone = extractZone (luup.devices[device].id) 
    927     if (not zone) then 
    928         log ("(setArmed) ERROR: Found unexpected child.") 
    929         task ("Unknown error encountered.", TASK_ERROR) 
    930         return false 
    931     end 
    932  
    933     local status; 
     1166        task ("Pin code required.", TASK.ERROR) 
     1167        return false 
     1168    end 
     1169 
    9341170    if (newArmedValue == "0") then 
    935         status = bypassZone (zone) 
     1171        return bypassZone (zoneNo, pinCode) 
    9361172    else 
    937         status = unbypassZone (zone) 
    938     end 
    939  
    940     if (status) then 
    941         luup.variable_set (SECURITY_SID, "Armed", newArmedValue, device) 
     1173        return unbypassZone (zoneNo, pinCode) 
    9421174    end 
    9431175end 
     
    9471179 
    9481180 
     1181local function updateZoneStates (zoneNo) 
     1182    for k, v in pairs (g_childDevices.zones) do 
     1183        setZoneState (k, "Armed", v.armed) 
     1184        setZoneState (k, "Tripped", v.tripped) 
     1185    end 
     1186end 
     1187 
     1188 
     1189local function updatePartitionStates() 
     1190    for k, v in pairs (g_childDevices.partitions) do 
     1191        local armMode = (v.armingStatus == "Disarmed") and "Disarmed" or "Armed" 
     1192 
     1193        local detailedArmMode 
     1194        if (armMode == "Disarmed") then 
     1195            local boolExpr = (v.armUpState == '1') or (v.armUpState == '2') 
     1196            detailedArmMode = boolExpr and "Ready" or "NotReady" 
     1197        else 
     1198            detailedArmMode = v.armingStatus 
     1199        end 
     1200 
     1201        local alarm 
     1202        if (v.alarmState >= '0' and v.alarmState <= '2') then 
     1203            alarm = "None" 
     1204        elseif (v.alarmState >= '3') then 
     1205            alarm = "Active" 
     1206        end 
     1207 
     1208        local chimeEnabled = (v.chimeMode == '0') and "0" or "1" 
     1209         
     1210        setPartitionState (k, "ArmMode", armMode) 
     1211        setPartitionState (k, "DetailedArmMode", detailedArmMode) 
     1212        setPartitionState (k, "Alarm", alarm) 
     1213        setPartitionState (k, "ChimeEnabled", chimeEnabled) 
     1214    end 
     1215end 
     1216 
     1217 
    9491218local function getChildDevices() 
    950     g_childDevices.partitions = {} 
    951  
    952     for k, v in ipairs (luup.devices) do 
     1219    for k, v in pairs (luup.devices) do 
    9531220        if (v.device_num_parent == lug_device) then 
    954             debug (string.format ("(getChildDevices) Parsing luup.devices[%d]", k)) 
    9551221            local zone = extractZone (v.id) 
    9561222            if (zone ~= nil) then 
     1223                debug (string.format ("(getChildDevices) zone %s device=%d", zone, k)) 
    9571224                g_childDevices.zones[tonumber (zone)].device = k 
    9581225            else 
    9591226                local partition = extractPartition (v.id) 
    9601227                if (partition ~= nil) then 
     1228                    debug (string.format ("(getChildDevices) partition %s device=%d", partition, k)) 
    9611229                    g_childDevices.partitions[tonumber (partition)].device = k 
    9621230                else 
     
    9711239local function presetParameters (t) 
    9721240    local params = {} 
    973     for _, param in ipairs (t) do 
     1241    for _, param in pairs (t) do 
     1242        debug (string.format ("(presetParameters) %s = %s", tostring (param[2]), tostring (param[3]))) 
    9741243        table.insert (params, string.format ("%s,%s=%s", unpack (param))) 
    9751244    end 
    9761245 
    9771246    return table.concat (params, "\n") 
    978 end 
    979  
    980  
    981 local function getZoneParams (zoneNo) 
    982     local armed 
    983     if ((not g_childDevices.zones[zoneNo].status) or (g_childDevices.zones[zoneNo].status == "Bypassed")) then 
    984         armed = "0" 
    985     else 
    986         armed = "1" 
    987     end 
    988  
    989     return presetParameters ({{SECURITY_SID, "Armed", armed}}) 
    9901247end 
    9911248 
     
    9971254 
    9981255    -- Door Sensors 
    999     doorSensors = luup.variable_get (PANEL_SID, "DoorSensors", lug_device) or "" 
    1000     for zn in doorSensors:gmatch ("%d+") do 
    1001         if (tonumber (zn, 10) == zoneNo) then 
    1002             return {type = "urn:schemas-micasaverde-com:device:DoorSensor:1", file = "D_DoorSensor1.xml"} 
     1256    local doorSensors = luup.variable_get (SID.PANEL, "DoorSensors", lug_device) or "" 
     1257    if (doorSensors == "") then 
     1258        luup.variable_set (SID.PANEL, "DoorSensors", doorSensors, lug_device) 
     1259    else 
     1260        for zn in doorSensors:gmatch ("%d+") do 
     1261            if (tonumber (zn, 10) == zoneNo) then 
     1262                return {type = "urn:schemas-micasaverde-com:device:DoorSensor:1", file = "D_DoorSensor1.xml"} 
     1263            end 
    10031264        end 
    10041265    end 
    10051266 
    10061267    -- Smoke Sensors 
    1007     smokeSensors = luup.variable_get (PANEL_SID, "SmokeSensors", lug_device) or "" 
    1008     for zn in smokeSensors:gmatch ("%d+") do 
    1009         if (tonumber (zn, 10) == zoneNo) then 
    1010             return {type = "urn:schemas-micasaverde-com:device:SmokeSensor:1", file = "D_SmokeSensor1.xml"} 
    1011         end 
    1012     end 
    1013  
    1014     -- Humidity Sensors 
    1015     humiditySensors = luup.variable_get (PANEL_SID, "HumiditySensors", lug_device) or "" 
    1016     for zn in humiditySensors:gmatch ("%d+") do 
    1017         if (tonumber (zn, 10) == zoneNo) then 
    1018             return {type = "urn:schemas-micasaverde-com:device:HumiditySensor:1", file = "D_HumiditySensor1.xml"} 
     1268    local smokeSensors = luup.variable_get (SID.PANEL, "SmokeSensors", lug_device) or "" 
     1269    if (smokeSensors == "") then 
     1270        luup.variable_set (SID.PANEL, "SmokeSensors", smokeSensors, lug_device) 
     1271    else 
     1272        for zn in smokeSensors:gmatch ("%d+") do 
     1273            if (tonumber (zn, 10) == zoneNo) then 
     1274                return {type = "urn:schemas-micasaverde-com:device:SmokeSensor:1", file = "D_SmokeSensor1.xml"} 
     1275            end 
    10191276        end 
    10201277    end 
     
    10251282 
    10261283local function appendZones (rootPtr) 
    1027     for k, v in ipairs (g_childDevices.zones) do 
     1284    for k, v in pairs (g_childDevices.zones) do 
    10281285        debug (string.format ("(appendZones) Appending zone %d", k)) 
    10291286        local device = getDeviceType (k) 
    1030         luup.chdev.append (lug_device, rootPtr, string.format ("elk_zone_%d", k), string.format ("Zone %d: %s", k, v.label), device.type, device.file, nil, getZoneParams (k), false) 
     1287        luup.chdev.append (lug_device, rootPtr, string.format ("elk_zone_%d", k), string.format ("Zone %d: %s", k, v.label), device.type, device.file, nil, nil, false) 
    10311288    end 
    10321289end 
     
    10501307    local errorMessage = "Failed to get zone names." 
    10511308 
    1052     for i in ipairs (g_childDevices.zones) do 
     1309    for i in pairs (g_childDevices.zones) do 
    10531310        local status = sendIntercepted ("sd", functionName, errorMessage, string.format ("00%03d", i)) 
    10541311        if (status) then 
     
    10641321 
    10651322 
    1066 local function getPartitionParams (partNo) 
    1067     local armMode = (g_childDevices.partitions[partNo].armingStatus == "Disarmed") and "Disarmed" or "Armed" 
    1068  
    1069     local detailedArmMode 
    1070     if (armMode == "Disarmed") then 
    1071         detailedArmMode = (g_childDevices.partitions[partNo].armUpState == "Ready") and "Ready" or "NotReady" 
    1072     end 
    1073  
    1074     local alarm 
    1075     if (g_childDevices.partitions[partNo].alarmState == '0') then 
    1076         alarm = "None" 
    1077     elseif (g_childDevices.partitions[partNo].alarmState >= '3') then 
    1078         alarm = "Active" 
    1079     end 
    1080  
    1081     local chimeEnabled = (g_childDevices.partitions[partNo].chimeMode == '0') and "0" or "1" 
    1082  
    1083     return presetParameters ({{PARTITION_SID, "ArmMode", armMode}, {PARTITION_SID, "DetailedArmMode", detailedArmMode}, {PARTITION_SID, "Alarm", alarm}, {PARTITION_SID, "ChimeEnabled", chimeEnabled}}) 
    1084 end 
    1085  
    1086  
    10871323local function appendPartitions (rootPtr) 
    1088     for k, v in ipairs (g_childDevices.partitions) do 
     1324    for k, v in pairs (g_childDevices.partitions) do 
    10891325        debug (string.format ("(appendPartitions) Appending partition %d", k)) 
    1090         luup.chdev.append (lug_device, rootPtr, string.format ("elk_partition_%d", k), string.format ("Partition %d: %s", k, v.label), "urn:schemas-micasaverde-com:device:ElkAlarmPartition:1", "D_ElkAlarmPartition1.xml", nil, getPartitionParams (k), false) 
     1326        luup.chdev.append (lug_device, rootPtr, string.format ("elk_partition_%d", k), string.format ("Partition %d: %s", k, v.label), "urn:schemas-micasaverde-com:device:ElkAlarmPartition:1", "D_ElkAlarmPartition1.xml", nil, nil, false) 
    10911327    end 
    10921328end 
     
    11231359    local errorMessage = "Failed to get partition names." 
    11241360 
    1125     for i in ipairs (g_childDevices.partitions) do 
     1361    for i in pairs (g_childDevices.partitions) do 
    11261362        local status = sendIntercepted ("sd", functionName, errorMessage, string.format ("01%03d", i)) 
    11271363        if (status) then 
     
    11801416 
    11811417function start (lul_device) 
    1182     log ("Elk M1 Alarm Panel Plugin version " .. VERSION) 
     1418    log ("Elk M1 Panel Plugin version " .. VERSION .. " starting up...") 
     1419 
     1420    -- Mark the beginning of the startup process. 
     1421    g_status.startup = true 
     1422 
     1423    do 
     1424        local debugMode = luup.variable_get (SID.PANEL, "DebugMode", lul_device) 
     1425        if (debugMode == nil) then 
     1426            luup.variable_set (SID.PANEL, "DebugMode", "0", lul_device) 
     1427            debugMode = false 
     1428        end 
     1429        DEBUG_MODE = (debugMode == "1") and true or false 
     1430    end 
     1431 
     1432    lug_device = lul_device 
    11831433 
    11841434    local version = getVersion() or "N/A" 
    11851435    log ("M1 version " .. version) 
    1186     luup.variable_set (PANEL_SID, "FirmwareVersion", version, lul_device) 
    1187  
    1188     lug_device = lul_device 
     1436    luup.variable_set (SID.PANEL, "FirmwareVersion", version, lul_device) 
    11891437 
    11901438    local rootPtr = luup.chdev.start (lul_device) 
     
    11931441    local status = getZonesAndPartitions() 
    11941442    if (not status) then 
    1195         return false, g_errorMessage, "Elk Alarm Panel" 
     1443        return false, g_status.errorMessage, "Elk Alarm Panel" 
    11961444    end 
    11971445 
    11981446    getPartitionNames() 
     1447     
     1448    -- Create a device for each active partition. 
     1449    appendPartitions (rootPtr) 
     1450     
     1451    getZoneNames() 
     1452     
     1453    -- Create a device for each zone. 
     1454    appendZones (rootPtr) 
     1455 
     1456    luup.chdev.sync (lul_device, rootPtr) 
     1457     
     1458    -- Get a list with the created child devices. 
     1459    getChildDevices() 
    11991460 
    12001461    -- Get each Partition's status. 
    12011462    status = getPartitionStatuses() 
    12021463    if (not status) then 
    1203         return false, g_errorMessage, "Elk Alarm Panel" 
     1464        return false, g_status.errorMessage, "Elk Alarm Panel" 
    12041465    end 
    12051466 
    12061467    -- Get the Chime Mode for each partition. 
    12071468    getChimeModes() 
    1208  
    1209     -- Create a device for each active partition. 
    1210     appendPartitions (rootPtr) 
    1211  
    1212     getZoneNames() 
    1213  
    1214     -- Create a device for each zone. 
    1215     appendZones (rootPtr) 
    1216  
    1217     luup.chdev.sync (lul_device, rootPtr) 
    1218  
    1219     -- Get a list with the created child devices. 
    1220     getChildDevices() 
    12211469 
    12221470    -- Get each Zone's status. 
    12231471    status = getZoneStatuses() 
    12241472    if (not status) then 
    1225         return false, g_errorMessage, "Elk Alarm Panel" 
    1226     end 
    1227  
    1228     debug ("Elk Alarm Panel: Startup successful.") 
     1473        return false, g_status.errorMessage, "Elk Alarm Panel" 
     1474    end 
     1475     
     1476    -- Update the state variables for all partitions and zones. 
     1477    updatePartitionStates() 
     1478    updateZoneStates() 
     1479 
     1480    -- Mark the end of the startup process. 
     1481    g_status.startup = false 
     1482 
     1483    debug ("(Elk M1 Panel Plugin) SUCCESS: Startup successful.") 
    12291484    return true, "Startup successful.", "Elk Alarm Panel" 
    12301485end 
  • /S_ElkAlarmPanel1.xml

    r20 r30  
    77    <serviceStateTable> 
    88        <stateVariable> 
    9             <name>MotionSensors</name> 
     9            <name>DebugMode</name> 
     10            <datatype>boolean</datatype> 
     11            <setDefaultValue>1</setDefaultValue> 
     12            <defaultValue>0</defaultValue> 
     13        </stateVariable> 
     14        <stateVariable> 
     15            <name>FirmwareVersion</name> 
    1016            <datatype>string</datatype> 
    1117        </stateVariable> 
     
    2228            <datatype>string</datatype> 
    2329        </stateVariable> 
    24         <stateVariable> 
    25             <name>FirmwareVersion</name> 
    26             <datatype>string</datatype> 
    27         </stateVariable> 
    2830    </serviceStateTable> 
    2931    <actionList> 
     
    3335                <argument> 
    3436                    <name>PinCode</name> 
    35                     <direction>in</direction> 
    36                     <relatedStateVariable>ui4</relatedStateVariable> 
     37                    <direction>in</direction> 
     38                    <relatedStateVariable>ui4</relatedStateVariable> 
    3739                </argument> 
    3840            </argumentList> 
    3941        </action> 
     42        <action> 
     43            <name>ClearPinCode</name> 
     44            <argumentList></argumentList> 
     45        </action> 
     46        <action> 
     47            <name>ClearTask</name> 
     48            <argumentList></argumentList> 
     49        </action> 
    4050    </actionList> 
    4151</scpd> 
  • /D_ElkAlarmPartition1.xml

    r20 r30  
    1515                <SCPDURL>S_AlarmPartition2.xml</SCPDURL> 
    1616            </service> 
     17            <service> 
     18                <serviceType>urn:schemas-micasaverde-com:service:ElkAlarmPanel:1</serviceType> 
     19                <serviceId>urn:micasaverde-com:serviceId:ElkAlarmPanel1</serviceId> 
     20                <SCPDURL>S_ElkAlarmPanel1.xml</SCPDURL> 
     21            </service> 
    1722        </serviceList> 
    1823    </device> 
  • /D_ElkAlarmPartition1.json

    r20 r30  
    11{ 
    2     "flashicon": "icons\/Door_Lock.swf", 
    3     "imgIconBody": "", 
    4     "imgIconDimmable": "", 
    5     "imgIconTurnable": "", 
    6     "imgIconMin": "pics\/devices\/Door_UNLOCKED.png", 
    7     "imgIconMax": "pics\/devices\/Door_LOCKED.png", 
    8     "halloIconsDir": "pics\/hallo", 
    9     "DisplayStatus": { 
    10         "Style": "label", 
    11         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    12         "Variable": "ArmMode", 
    13         "MinValue": "Disarmed", 
    14         "MaxValue": "Armed" 
    15     }, 
    16     "doc_url": { 
    17         "doc_language": 1, 
    18         "doc_manual": 1, 
    19         "doc_version": 1, 
    20         "doc_platform": 0, 
    21         "doc_page": "devices" 
    22     }, 
    23     "ToggleButton": 1, 
    24     "Tabs": [ 
    25         { 
    26             "Label": { 
    27                 "lang_tag": "tabname_control", 
    28                 "text": "Alarm Partition" 
    29             }, 
    30             "Position": "0", 
    31             "TabType": "flash", 
    32             "ControlGroup": [ 
    33                 { 
    34                     "id": "1" 
    35                 }, 
    36                 { 
    37                     "id": "2" 
    38                 } 
    39             ], 
    40             "Control": [ 
    41                 { 
    42                     "ControlGroup": "1", 
    43                     "ControlHeader": "1", 
    44                     "ControlType": "label", 
    45                     "Label": { 
    46                         "lang_tag": "device_settings_page", 
    47                         "text": "Status" 
    48                     }, 
    49                     "Display": { 
    50                         "Top": 0, 
    51                         "Left": 50, 
    52                         "Width": 200, 
    53                         "Height": 20 
    54                     } 
    55                 }, 
    56                 { 
    57                     "ControlGroup": "1", 
    58                     "ControlHeader": "1", 
    59                     "ControlType": "variable", 
    60                     "Display": { 
    61                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    62                         "Variable": "DetailedArmMode", 
    63                         "Top": 20, 
    64                         "Left": 50, 
    65                         "Width": 200, 
    66                         "Height": 20 
    67                     } 
    68                 }, 
    69                 { 
    70                     "ControlType": "label", 
    71                     "Label": { 
    72                         "lang_tag": "device_settings_page", 
    73                         "text": "One Touch Options" 
    74                     }, 
    75                     "Display": { 
    76                         "Top": 60, 
    77                         "Left": 50, 
    78                         "Width": 200, 
    79                         "Height": 20 
    80                     } 
    81                 }, 
    82                 { 
    83                     "ControlGroup": "1", 
    84                     "ControlType": "button", 
    85                     "Label": { 
    86                         "lang_tag": "cmd_lock", 
    87                         "text": "Arm" 
    88                     }, 
    89                     "Display": { 
    90                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    91                         "Variable": "ArmMode", 
    92                         "Value": "Armed", 
    93                         "Top": 80, 
    94                         "Left": 50, 
    95                         "Width": 75, 
    96                         "Height": 20 
    97                     }, 
    98                     "Command": { 
    99                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    100                         "Action": "RequestQuickArmMode", 
    101                         "Parameters": [ 
    102                             { 
    103                                 "Name": "State", 
    104                                 "Value": "Armed" 
    105                             } 
    106                         ] 
    107                     } 
    108                 }, 
    109                 { 
    110                     "ControlGroup": "1", 
    111                     "ControlType": "button", 
    112                     "Label": { 
    113                         "lang_tag": "cmd_lock", 
    114                         "text": "Force" 
    115                     }, 
    116                     "Display": { 
    117                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    118                         "Variable": "DetailedArmMode", 
    119                         "Value": "Force", 
    120                         "Top": 100, 
    121                         "Left": 50, 
    122                         "Width": 75, 
    123                         "Height": 20 
    124                     }, 
    125                     "Command": { 
    126                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    127                         "Action": "RequestQuickArmMode", 
    128                         "Parameters": [ 
    129                             { 
    130                                 "Name": "State", 
    131                                 "Value": "ArmedInstant" 
    132                             } 
    133                         ] 
    134                     } 
    135                 }, 
    136                 { 
    137                     "ControlGroup": "1", 
    138                     "ControlType": "button", 
    139                     "Label": { 
    140                         "lang_tag": "cmd_lock", 
    141                         "text": "Stay" 
    142                     }, 
    143                     "Display": { 
    144                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    145                         "Variable": "DetailedArmMode", 
    146                         "Value": "Stay", 
    147                         "Top": 80, 
    148                         "Left": 135, 
    149                         "Width": 75, 
    150                         "Height": 20 
    151                     }, 
    152                     "Command": { 
    153                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    154                         "Action": "RequestQuickArmMode", 
    155                         "Parameters": [ 
    156                             { 
    157                                 "Name": "State", 
    158                                 "Value": "Stay" 
    159                             } 
    160                         ] 
    161                     } 
    162                 }, 
    163                 { 
    164                     "ControlGroup": "1", 
    165                     "ControlType": "button", 
    166                     "Label": { 
    167                         "lang_tag": "cmd_lock", 
    168                         "text": "iStay" 
    169                     }, 
    170                     "Display": { 
    171                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    172                         "Variable": "DetailedArmMode", 
    173                         "Value": "StayInstant", 
    174                         "Top": 100, 
    175                         "Left": 135, 
    176                         "Width": 75, 
    177                         "Height": 20 
    178                     }, 
    179                     "Command": { 
    180                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    181                         "Action": "RequestQuickArmMode", 
    182                         "Parameters": [ 
    183                             { 
    184                                 "Name": "State", 
    185                                 "Value": "StayInstant" 
    186                             } 
    187                         ] 
    188                     } 
    189                 }, 
    190                 { 
    191                     "ControlGroup": "1", 
    192                     "ControlType": "button", 
    193                     "Label": { 
    194                         "lang_tag": "cmd_lock", 
    195                         "text": "Night" 
    196                     }, 
    197                     "Display": { 
    198                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    199                         "Variable": "DetailedArmMode", 
    200                         "Value": "Night", 
    201                         "Top": 80, 
    202                         "Left": 220, 
    203                         "Width": 75, 
    204                         "Height": 20 
    205                     }, 
    206                     "Command": { 
    207                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    208                         "Action": "RequestQuickArmMode", 
    209                         "Parameters": [ 
    210                             { 
    211                                 "Name": "State", 
    212                                 "Value": "Night" 
    213                             } 
    214                         ] 
    215                     } 
    216                 }, 
    217                 { 
    218                     "ControlGroup": "1", 
    219                     "ControlType": "button", 
    220                     "Label": { 
    221                         "lang_tag": "cmd_lock", 
    222                         "text": "iNight" 
    223                     }, 
    224                     "Display": { 
    225                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    226                         "Variable": "DetailedArmMode", 
    227                         "Value": "NightInstant", 
    228                         "Top": 100, 
    229                         "Left": 220, 
    230                         "Width": 75, 
    231                         "Height": 20 
    232                     }, 
    233                     "Command": { 
    234                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    235                         "Action": "RequestQuickArmMode", 
    236                         "Parameters": [ 
    237                             { 
    238                                 "Name": "State", 
    239                                 "Value": "NightInstant" 
    240                             } 
    241                         ] 
    242                     } 
    243                 }, 
    244                 { 
    245                     "ControlGroup": "2", 
    246                     "ControlHeader": "1", 
    247                     "ControlType": "label", 
    248                     "Label": { 
    249                         "lang_tag": "device_settings_page", 
    250                         "text": "PIN Options" 
    251                     }, 
    252                     "Display": { 
    253                         "Top": 140, 
    254                         "Left": 50, 
    255                         "Width": 200, 
    256                         "Height": 20 
    257                     } 
    258                 }, 
    259                 { 
    260                     "ControlGroup": "2", 
    261                     "ControlPair": "1", 
    262                     "ControlType": "input", 
    263                     "ID": "PINCode", 
    264                     "Display": { 
    265                         "Top": 160, 
    266                         "Left": 50, 
    267                         "Width": 100, 
    268                         "Height": 20 
    269                     } 
    270                 }, 
    271                 { 
    272                     "ControlGroup": "2", 
    273                     "ControlPair": "1", 
    274                     "ControlType": "button", 
    275                     "Label": { 
    276                         "lang_tag": "cmd_set", 
    277                         "text": "Arm" 
    278                     }, 
    279                     "Display": { 
    280                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    281                         "Variable": "ArmMode", 
    282                         "Value": "Armed", 
    283                         "Top": 160, 
    284                         "Left": 160, 
    285                         "Width": 50, 
    286                         "Height": 20 
    287                     }, 
    288                     "Command": { 
    289                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    290                         "Action": "RequestArmMode", 
    291                         "Parameters": [ 
    292                             { 
    293                                 "Name": "State", 
    294                                 "Value": "Armed" 
    295                             }, 
    296                             { 
    297                                 "Name": "PINCode", 
    298                                 "ID": "PINCode" 
    299                             } 
    300                         ] 
    301                     } 
    302                 }, 
    303                 { 
    304                     "ControlGroup": "2", 
    305                     "ControlPair": "1", 
    306                     "ControlType": "button", 
    307                     "Label": { 
    308                         "lang_tag": "cmd_set", 
    309                         "text": "Stay" 
    310                     }, 
    311                     "Display": { 
    312                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    313                         "Variable": "DetailedArmMode", 
    314                         "Value": "Stay", 
    315                         "Top": 180, 
    316                         "Left": 160, 
    317                         "Width": 50, 
    318                         "Height": 20 
    319                     }, 
    320                     "Command": { 
    321                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    322                         "Action": "RequestArmMode", 
    323                         "Parameters": [ 
    324                             { 
    325                                 "Name": "State", 
    326                                 "Value": "Stay" 
    327                             }, 
    328                             { 
    329                                 "Name": "PINCode", 
    330                                 "ID": "PINCode" 
    331                             } 
    332                         ] 
    333                     } 
    334                 }, 
    335                 { 
    336                     "ControlGroup": "2", 
    337                     "ControlPair": "1", 
    338                     "ControlType": "button", 
    339                     "Label": { 
    340                         "lang_tag": "cmd_set", 
    341                         "text": "Disarm" 
    342                     }, 
    343                     "Display": { 
    344                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    345                         "Variable": "ArmMode", 
    346                         "Value": "Disarmed", 
    347                         "Top": 200, 
    348                         "Left": 160, 
    349                         "Width": 50, 
    350                         "Height": 20 
    351                     }, 
    352                     "Command": { 
    353                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    354                         "Action": "RequestArmMode", 
    355                         "Parameters": [ 
    356                             { 
    357                                 "Name": "State", 
    358                                 "Value": "Disarmed" 
    359                             }, 
    360                             { 
    361                                 "Name": "PINCode", 
    362                                 "ID": "PINCode" 
    363                             } 
    364                         ] 
    365                     } 
    366                 }, 
    367                 { 
    368                     "ControlType": "label", 
    369                     "Label": { 
    370                         "lang_tag": "device_settings_page", 
    371                         "text": "Panic Alarm Options" 
    372                     }, 
    373                     "Display": { 
    374                         "Top": 240, 
    375                         "Left": 50, 
    376                         "Width": 200, 
    377                         "Height": 20 
    378                     } 
    379                 }, 
    380                 { 
    381                     "ControlType": "button", 
    382                     "Label": { 
    383                         "lang_tag": "cmd_set", 
    384                         "text": "Police" 
    385                     }, 
    386                     "Display": { 
    387                         "Top": 260, 
    388                         "Left": 50, 
    389                         "Width": 75, 
    390                         "Height": 20 
    391                     }, 
    392                     "Command": { 
    393                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    394                         "Action": "RequestPanicMode", 
    395                         "Parameters": [ 
    396                             { 
    397                                 "Name": "State", 
    398                                 "Value": "Police" 
    399                             } 
    400                         ] 
    401                     } 
    402                 }, 
    403                 { 
    404                     "ControlType": "button", 
    405                     "Label": { 
    406                         "lang_tag": "cmd_set", 
    407                         "text": "Medical" 
    408                     }, 
    409                     "Display": { 
    410                         "Top": 260, 
    411                         "Left": 135, 
    412                         "Width": 75, 
    413                         "Height": 20 
    414                     }, 
    415                     "Command": { 
    416                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    417                         "Action": "RequestPanicMode", 
    418                         "Parameters": [ 
    419                             { 
    420                                 "Name": "State", 
    421                                 "Value": "Medical" 
    422                             } 
    423                         ] 
    424                     } 
    425                 }, 
    426                 { 
    427                     "ControlType": "button", 
    428                     "Label": { 
    429                         "lang_tag": "cmd_set", 
    430                         "text": "Fire" 
    431                     }, 
    432                     "Display": { 
    433                         "Top": 260, 
    434                         "Left": 220, 
    435                         "Width": 75, 
    436                         "Height": 20 
    437                     }, 
    438                     "Command": { 
    439                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    440                         "Action": "RequestPanicMode", 
    441                         "Parameters": [ 
    442                             { 
    443                                 "Name": "State", 
    444                                 "Value": "Fire" 
    445                             } 
    446                         ] 
    447                     } 
    448                 }, 
    449                 { 
    450                     "ControlType": "label", 
    451                     "Label": { 
    452                         "lang_tag": "device_settings_page", 
    453                         "text": "Vendor Options" 
    454                     }, 
    455                     "Display": { 
    456                         "Top": 300, 
    457                         "Left": 50, 
    458                         "Width": 200, 
    459                         "Height": 20 
    460                     } 
    461                 }, 
    462                 { 
    463                     "ControlType": "variable", 
    464                     "Display": { 
    465                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    466                         "Variable": "VendorStatus", 
    467                         "Top": 320, 
    468                         "Left": 50, 
    469                         "Width": 200, 
    470                         "Height": 20 
    471                     } 
    472                 }, 
    473                 { 
    474                     "ControlType": "variable", 
    475                     "Display": { 
    476                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    477                         "Variable": "VendorStatusCode", 
    478                         "Top": 340, 
    479                         "Left": 50, 
    480                         "Width": 200, 
    481                         "Height": 20 
    482                     } 
    483                 }, 
    484                 { 
    485                     "ControlType": "variable", 
    486                     "Display": { 
    487                         "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    488                         "Variable": "VendorStatusData", 
    489                         "Top": 360, 
    490                         "Left": 50, 
    491                         "Width": 200, 
    492                         "Height": 20 
    493                     } 
    494                 } 
    495             ] 
    496         }, 
    497         { 
    498             "Label": { 
    499                 "lang_tag": "notifications", 
    500                 "text": "Notifications" 
    501             }, 
    502             "Position": "2", 
    503             "TabType": "javascript", 
    504             "ScriptName": "shared.js", 
    505             "Function": "device_notifications" 
    506         }, 
    507         { 
    508             "Label": { 
    509                 "lang_tag": "logs", 
    510                 "text": "Logs" 
    511             }, 
    512             "Position": "3", 
    513             "TabType": "javascript", 
    514             "ScriptName": "shared.js", 
    515             "Function": "device_logs" 
    516         }, 
    517         { 
    518             "Label": { 
    519                 "lang_tag": "advanced", 
    520                 "text": "Advanced" 
    521             }, 
    522             "Position": "4", 
    523             "TabType": "javascript", 
    524             "ScriptName": "shared.js", 
    525             "Function": "advanced_device" 
    526         } 
    527     ], 
    528     "DeviceType": "urn:schemas-micasaverde-com:device:ElkAlarmPartition:1", 
    529     "eventList": { 
    530         "event_1": { 
    531             "label": "Armed state", 
    532             "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    533             "argumentList" : { 
    534                 "argument_1" : { 
    535                     "dataType": "string", 
    536                     "defaultValue": "Armed", 
    537                     "allowedValueList" : { 
    538                         "Yes" : "Armed", 
    539                         "No" : "Disarmed" 
    540                     }, 
    541                     "name": "ArmMode", 
    542                     "comparisson": "=", 
    543                     "prefix": "Is Armed?", 
    544                     "suffix": "" 
    545                 } 
    546             } 
    547         }, 
    548         "event_2": { 
    549             "label": "Armed detailed state", 
    550             "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    551             "argumentList" : { 
    552                 "argument_1" : { 
    553                     "dataType": "string", 
    554                     "defaultValue": "Armed", 
    555                     "allowedValueList" : { 
    556                         "Disarmed" : "Disarmed", 
    557                         "Armed" : "Armed", 
    558                         "Stay" : "Stay", 
    559                         "StayInstant" : "StayInstant", 
    560                         "Night" : "Night", 
    561                         "NightInstant" : "NightInstant", 
    562                         "Force" : "Force", 
    563                         "Ready" : "Ready", 
    564                         "Vacation" : "Vacation", 
    565                         "NotReady" : "NotReady", 
    566                         "FailedToArm" : "FailedToArm", 
    567                         "EntryDelay" : "EntryDelay", 
    568                         "ExitDelay" : "ExitDelay" 
    569                     }, 
    570                     "name": "DetailedArmMode", 
    571                     "comparisson": "=", 
    572                     "prefix": "Armed state", 
    573                     "suffix": "" 
    574                 } 
    575             } 
    576         }, 
    577         "event_3": { 
    578             "label": "Alarm Active", 
    579             "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    580             "argumentList" : { 
    581                 "argument_1" : { 
    582                     "dataType": "boolean", 
    583                     "defaultValue": "Active", 
    584                     "allowedValueList" : { 
    585                         "Active" : "Active", 
    586                         "NotActive" : "None" 
    587                     }, 
    588                     "name": "Alarm", 
    589                     "comparisson": "=", 
    590                     "prefix": "Is Active?", 
    591                     "suffix": "" 
    592                 } 
    593             } 
    594         }, 
    595         "event_4": { 
    596             "label": "A PIN Code is entered", 
    597             "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    598             "argumentList" : { 
    599                 "argument_1" : { 
    600                     "dataType": "string", 
    601                     "defaultValue": "", 
    602                     "name": "LastUser", 
    603                     "comparisson": "=", 
    604                     "prefix": "User", 
    605                     "suffix": "" 
    606                 } 
    607             } 
    608         }, 
    609         "event_5": { 
    610             "label": "Vendor Status Code", 
    611             "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    612             "argumentList" : { 
    613                 "argument_1" : { 
    614                     "dataType": "string", 
    615                     "defaultValue": "", 
    616                     "name": "VendorStatusCode", 
    617                     "comparisson": "=", 
    618                     "prefix": "Code", 
    619                     "suffix": "" 
    620                 } 
    621             } 
    622         } 
    623     }, 
    624     "sceneList": { 
    625         "group_1": { 
    626             "cmd_1": { 
    627                 "label": "Set Partition ... (PIN)", 
    628                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    629                 "action": "RequestArmMode", 
    630                 "argumentList": { 
    631                     "argument_1": { 
    632                         "dataType": "string", 
    633                         "defaultValue": "Disarmed", 
    634                         "allowedValueList": { 
    635                             "Disarmed" : "Disarmed", 
    636                             "Armed" : "Armed", 
    637                             "Stay" : "Stay", 
    638                             "StayInstant" : "StayInstant", 
    639                             "Night" : "Night", 
    640                             "NightInstant" : "NightInstant", 
    641                             "Force" : "Force", 
    642                             "Vacation" : "Vacation" 
    643                         }, 
    644                         "name": "State", 
    645                         "prefix": "State", 
    646                         "suffix": ""  
    647                     }, 
    648                     "argument_2": { 
    649                         "dataType": "ui4", 
    650                         "defaultValue": "1234", 
    651                         "allowedValueRange": { 
    652                             "minimum": "0", 
    653                             "maximum": "999999999999" 
    654                         }, 
    655                         "prefix" : "PIN", 
    656                         "suffix" : "0-99999999, (insecure)", 
    657                         "name": "PINCode" 
    658                     } 
    659                 } 
    660             } 
    661         }, 
    662         "group_2": { 
    663             "cmd_1": { 
    664                 "label": "Set Partition Disarmed (No PIN)", 
    665                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    666                 "action": "RequestQuickArmMode", 
    667                 "arguments": { 
    668                     "State": "Disarmed" 
    669                 } 
    670             }, 
    671             "cmd_2": { 
    672                 "label": "Set Partition Armed (No PIN)", 
    673                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    674                 "action": "RequestQuickArmMode", 
    675                 "arguments": { 
    676                     "State": "Armed" 
    677                 } 
    678             }, 
    679             "cmd_3": { 
    680                 "label": "Set Partition Stay (No PIN)", 
    681                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    682                 "action": "RequestQuickArmMode", 
    683                 "arguments": { 
    684                     "State": "Stay" 
    685                 } 
    686             }, 
    687             "cmd_4": { 
    688                 "label": "Set Partition StayInstant (No PIN)", 
    689                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    690                 "action": "RequestQuickArmMode", 
    691                 "arguments": { 
    692                     "State": "StayInstant" 
    693                 } 
    694             }, 
    695             "cmd_5": { 
    696                 "label": "Set Partition Night (No PIN)", 
    697                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    698                 "action": "RequestQuickArmMode", 
    699                 "arguments": { 
    700                     "State": "Night" 
    701                 } 
    702             }, 
    703             "cmd_6": { 
    704                 "label": "Set Partition NightInstant (No PIN)", 
    705                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    706                 "action": "RequestQuickArmMode", 
    707                 "arguments": { 
    708                     "State": "NightInstant" 
    709                 } 
    710             }, 
    711             "cmd_7": { 
    712                 "label": "Set Partition Force (No PIN)", 
    713                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    714                 "action": "RequestQuickArmMode", 
    715                 "arguments": { 
    716                     "State": "Force" 
    717                 } 
    718             }, 
    719             "cmd_8": { 
    720                 "label": "Set Partition Vacation (No PIN)", 
    721                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    722                 "action": "RequestQuickArmMode", 
    723                 "arguments": { 
    724                     "State": "Vacation" 
    725                 } 
    726             } 
    727         }, 
    728         "group_3": { 
    729             "cmd_1": { 
    730                 "label": "Request Medical Panic", 
    731                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    732                 "action": "RequestPanicMode", 
    733                 "arguments": { 
    734                     "State": "Medical" 
    735                 } 
    736             }, 
    737             "cmd_2": { 
    738                 "label": "Request Police Panic", 
    739                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    740                 "action": "RequestPanicMode", 
    741                 "arguments": { 
    742                     "State": "Police" 
    743                 } 
    744             }, 
    745             "cmd_3": { 
    746                 "label": "Request Fire Panic", 
    747                 "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
    748                 "action": "RequestPanicMode", 
    749                 "arguments": { 
    750                     "State": "Fire" 
    751                 } 
    752             } 
    753         } 
    754     } 
     2    "flashicon": "icons\/Door_Lock.swf", 
     3    "imgIconBody": "", 
     4    "imgIconDimmable": "", 
     5    "imgIconTurnable": "", 
     6    "imgIconMin": "pics\/devices\/Door_UNLOCKED.png", 
     7    "imgIconMax": "pics\/devices\/Door_LOCKED.png", 
     8    "halloIconsDir": "pics\/hallo", 
     9    "DisplayStatus": { 
     10        "Style": "label", 
     11        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     12        "Variable": "ArmMode", 
     13        "MinValue": "Disarmed", 
     14        "MaxValue": "Armed" 
     15    }, 
     16    "doc_url": { 
     17        "doc_language": 1, 
     18        "doc_manual": 1, 
     19        "doc_version": 1, 
     20        "doc_platform": 0, 
     21        "doc_page": "devices" 
     22    }, 
     23    "ToggleButton": 1, 
     24    "Tabs": [ 
     25        { 
     26            "Label": { 
     27                "lang_tag": "tab_alarm_partition", 
     28                "text": "Alarm Partition" 
     29            }, 
     30            "Position": "0", 
     31            "TabType": "flash", 
     32            "ControlGroup": [ 
     33                { 
     34                    "id": "1", 
     35                    "type": "info" 
     36                } 
     37            ], 
     38            "Control": [ 
     39                { 
     40                    "ControlGroup": "1", 
     41                    "ControlHeader": "1", 
     42                    "ControlType": "label", 
     43                    "Label": { 
     44                        "lang_tag": "label_status", 
     45                        "text": "Status:" 
     46                    }, 
     47                    "Display": { 
     48                        "Top": 20, 
     49                        "Left": 285, 
     50                        "Width": 75, 
     51                        "Height": 20 
     52                    } 
     53                }, 
     54                { 
     55                    "ControlGroup": "1", 
     56                    "ControlHeader": "1", 
     57                    "ControlType": "variable", 
     58                    "Display": { 
     59                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     60                        "Variable": "DetailedArmMode", 
     61                        "Top": 40, 
     62                        "Left": 285, 
     63                        "Width": 75, 
     64                        "Height": 20 
     65                    } 
     66                }, 
     67                { 
     68                    "ControlType": "label", 
     69                    "Label": { 
     70                        "lang_tag": "device_settings_page", 
     71                        "text": "PIN Code:" 
     72                    }, 
     73                    "Display": { 
     74                        "Top": 80, 
     75                        "Left": 70, 
     76                        "Width": 75, 
     77                        "Height": 20 
     78                    } 
     79                }, 
     80                { 
     81                    "ControlType": "input", 
     82                    "ID": "PINCode", 
     83                    "Display": { 
     84                        "Top": 105, 
     85                        "Left": 70, 
     86                        "Width": 75, 
     87                        "Height": 20 
     88                    } 
     89                }, 
     90                { 
     91                    "ControlType": "button", 
     92                    "Label": { 
     93                        "lang_tag": "button_store", 
     94                        "text": "Store" 
     95                    }, 
     96                    "Display": { 
     97                        "Top": 130, 
     98                        "Left": 70, 
     99                        "Width": 75, 
     100                        "Height": 20 
     101                    }, 
     102                    "Command": { 
     103                        "Service": "urn:micasaverde-com:serviceId:ElkAlarmPanel1", 
     104                        "Action": "StorePinCode", 
     105                        "Parameters": [ 
     106                            { 
     107                                "Name": "PinCode", 
     108                                "ID": "PINCode" 
     109                            } 
     110                        ] 
     111                    } 
     112                }, 
     113                { 
     114                    "ControlType": "button", 
     115                    "Label": { 
     116                        "lang_tag": "button_clear", 
     117                        "text": "Clear" 
     118                    }, 
     119                    "Display": { 
     120                        "Top": 150, 
     121                        "Left": 70, 
     122                        "Width": 75, 
     123                        "Height": 20 
     124                    }, 
     125                    "Command": { 
     126                        "Service": "urn:micasaverde-com:serviceId:ElkAlarmPanel1", 
     127                        "Action": "ClearPinCode", 
     128                        "Parameters": [] 
     129                    } 
     130                }, 
     131                { 
     132                    "ControlType": "label", 
     133                    "Label": { 
     134                        "lang_tag": "label_arm_mode", 
     135                        "text": "Arm Mode:" 
     136                    }, 
     137                    "Display": { 
     138                        "Top": 80, 
     139                        "Left": 285, 
     140                        "Width": 75, 
     141                        "Height": 20 
     142                    } 
     143                }, 
     144                { 
     145                    "ControlType": "button", 
     146                    "Label": { 
     147                        "lang_tag": "button_away", 
     148                        "text": "Away" 
     149                    }, 
     150                    "Display": { 
     151                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     152                        "Variable": "DetailedArmMode", 
     153                        "Value": "Armed", 
     154                        "Top": 100, 
     155                        "Left": 200, 
     156                        "Width": 75, 
     157                        "Height": 20 
     158                    }, 
     159                    "Command": { 
     160                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     161                        "Action": "RequestArmMode", 
     162                        "Parameters": [ 
     163                            { 
     164                                "Name": "State", 
     165                                "Value": "Armed" 
     166                            }, 
     167                            { 
     168                                "Name": "PINCode", 
     169                                "ID": "PINCode" 
     170                            } 
     171                        ] 
     172                    } 
     173                }, 
     174                { 
     175                    "ControlType": "button", 
     176                    "Label": { 
     177                        "lang_tag": "button_vacation", 
     178                        "text": "Vacation" 
     179                    }, 
     180                    "Display": { 
     181                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     182                        "Variable": "DetailedArmMode", 
     183                        "Value": "Vacation", 
     184                        "Top": 120, 
     185                        "Left": 200, 
     186                        "Width": 75, 
     187                        "Height": 20 
     188                    }, 
     189                    "Command": { 
     190                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     191                        "Action": "RequestArmMode", 
     192                        "Parameters": [ 
     193                            { 
     194                                "Name": "State", 
     195                                "Value": "Vacation" 
     196                            }, 
     197                            { 
     198                                "Name": "PINCode", 
     199                                "ID": "PINCode" 
     200                            } 
     201                        ] 
     202                    } 
     203                }, 
     204                { 
     205                    "ControlType": "button", 
     206                    "Label": { 
     207                        "lang_tag": "button_stay", 
     208                        "text": "Stay" 
     209                    }, 
     210                    "Display": { 
     211                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     212                        "Variable": "DetailedArmMode", 
     213                        "Value": "Stay", 
     214                        "Top": 100, 
     215                        "Left": 285, 
     216                        "Width": 75, 
     217                        "Height": 20 
     218                    }, 
     219                    "Command": { 
     220                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     221                        "Action": "RequestArmMode", 
     222                        "Parameters": [ 
     223                            { 
     224                                "Name": "State", 
     225                                "Value": "Stay" 
     226                            }, 
     227                            { 
     228                                "Name": "PINCode", 
     229                                "ID": "PINCode" 
     230                            } 
     231                        ] 
     232                    } 
     233                }, 
     234                { 
     235                    "ControlType": "button", 
     236                    "Label": { 
     237                        "lang_tag": "button_istay", 
     238                        "text": "iStay" 
     239                    }, 
     240                    "Display": { 
     241                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     242                        "Variable": "DetailedArmMode", 
     243                        "Value": "StayInstant", 
     244                        "Top": 120, 
     245                        "Left": 285, 
     246                        "Width": 75, 
     247                        "Height": 20 
     248                    }, 
     249                    "Command": { 
     250                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     251                        "Action": "RequestArmMode", 
     252                        "Parameters": [ 
     253                            { 
     254                                "Name": "State", 
     255                                "Value": "StayInstant" 
     256                            }, 
     257                            { 
     258                                "Name": "PINCode", 
     259                                "ID": "PINCode" 
     260                            } 
     261                        ] 
     262                    } 
     263                }, 
     264                { 
     265                    "ControlType": "button", 
     266                    "Label": { 
     267                        "lang_tag": "button_night", 
     268                        "text": "Night" 
     269                    }, 
     270                    "Display": { 
     271                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     272                        "Variable": "DetailedArmMode", 
     273                        "Value": "Night", 
     274                        "Top": 100, 
     275                        "Left": 370, 
     276                        "Width": 75, 
     277                        "Height": 20 
     278                    }, 
     279                    "Command": { 
     280                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     281                        "Action": "RequestArmMode", 
     282                        "Parameters": [ 
     283                            { 
     284                                "Name": "State", 
     285                                "Value": "Night" 
     286                            }, 
     287                            { 
     288                                "Name": "PINCode", 
     289                                "ID": "PINCode" 
     290                            } 
     291                        ] 
     292                    } 
     293                }, 
     294                { 
     295                    "ControlType": "button", 
     296                    "Label": { 
     297                        "lang_tag": "button_inight", 
     298                        "text": "iNight" 
     299                    }, 
     300                    "Display": { 
     301                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     302                        "Variable": "DetailedArmMode", 
     303                        "Value": "NightInstant", 
     304                        "Top": 120, 
     305                        "Left": 370, 
     306                        "Width": 75, 
     307                        "Height": 20 
     308                    }, 
     309                    "Command": { 
     310                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     311                        "Action": "RequestArmMode", 
     312                        "Parameters": [ 
     313                            { 
     314                                "Name": "State", 
     315                                "Value": "NightInstant" 
     316                            }, 
     317                            { 
     318                                "Name": "PINCode", 
     319                                "ID": "PINCode" 
     320                            } 
     321                        ] 
     322                    } 
     323                }, 
     324                { 
     325                    "ControlType": "button", 
     326                    "Label": { 
     327                        "lang_tag": "button_disarm", 
     328                        "text": "Disarm" 
     329                    }, 
     330                    "Display": { 
     331                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     332                        "Variable": "ArmMode", 
     333                        "Value": "Disarmed", 
     334                        "Top": 140, 
     335                        "Left": 285, 
     336                        "Width": 75, 
     337                        "Height": 20 
     338                    }, 
     339                    "Command": { 
     340                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     341                        "Action": "RequestArmMode", 
     342                        "Parameters": [ 
     343                            { 
     344                                "Name": "State", 
     345                                "Value": "Disarmed" 
     346                            }, 
     347                            { 
     348                                "Name": "PINCode", 
     349                                "ID": "PINCode" 
     350                            } 
     351                        ] 
     352                    } 
     353                } 
     354            ] 
     355        }, 
     356        { 
     357            "Label": { 
     358                "lang_tag": "notifications", 
     359                "text": "Notifications" 
     360            }, 
     361            "Position": "2", 
     362            "TabType": "javascript", 
     363            "ScriptName": "shared.js", 
     364            "Function": "device_notifications" 
     365        }, 
     366        { 
     367            "Label": { 
     368                "lang_tag": "logs", 
     369                "text": "Logs" 
     370            }, 
     371            "Position": "3", 
     372            "TabType": "javascript", 
     373            "ScriptName": "shared.js", 
     374            "Function": "device_logs" 
     375        }, 
     376        { 
     377            "Label": { 
     378                "lang_tag": "advanced", 
     379                "text": "Advanced" 
     380            }, 
     381            "Position": "4", 
     382            "TabType": "javascript", 
     383            "ScriptName": "shared.js", 
     384            "Function": "advanced_device" 
     385        } 
     386    ], 
     387    "DeviceType": "urn:schemas-micasaverde-com:device:ElkAlarmPartition:1", 
     388    "eventList": { 
     389        "event_1": { 
     390            "label": "Armed state", 
     391            "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     392            "argumentList" : { 
     393                "argument_1" : { 
     394                    "dataType": "string", 
     395                    "defaultValue": "Armed", 
     396                    "allowedValueList" : { 
     397                        "Yes" : "Armed", 
     398                        "No" : "Disarmed" 
     399                    }, 
     400                    "name": "ArmMode", 
     401                    "comparisson": "=", 
     402                    "prefix": "Is Armed?", 
     403                    "suffix": "" 
     404                } 
     405            } 
     406        }, 
     407        "event_2": { 
     408            "label": "Armed detailed state", 
     409            "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     410            "argumentList" : { 
     411                "argument_1" : { 
     412                    "dataType": "string", 
     413                    "defaultValue": "Armed", 
     414                    "allowedValueList" : { 
     415                        "Disarmed" : "Disarmed", 
     416                        "Armed" : "Armed", 
     417                        "Stay" : "Stay", 
     418                        "StayInstant" : "StayInstant", 
     419                        "Night" : "Night", 
     420                        "NightInstant" : "NightInstant", 
     421                        "Force" : "Force", 
     422                        "Ready" : "Ready", 
     423                        "Vacation" : "Vacation", 
     424                        "NotReady" : "NotReady", 
     425                        "FailedToArm" : "FailedToArm", 
     426                        "EntryDelay" : "EntryDelay", 
     427                        "ExitDelay" : "ExitDelay" 
     428                    }, 
     429                    "name": "DetailedArmMode", 
     430                    "comparisson": "=", 
     431                    "prefix": "Armed state", 
     432                    "suffix": "" 
     433                } 
     434            } 
     435        }, 
     436        "event_3": { 
     437            "label": "Alarm Active", 
     438            "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     439            "argumentList" : { 
     440                "argument_1" : { 
     441                    "dataType": "boolean", 
     442                    "defaultValue": "Active", 
     443                    "allowedValueList" : { 
     444                        "Active" : "Active", 
     445                        "NotActive" : "None" 
     446                    }, 
     447                    "name": "Alarm", 
     448                    "comparisson": "=", 
     449                    "prefix": "Is Active?", 
     450                    "suffix": "" 
     451                } 
     452            } 
     453        }, 
     454        "event_4": { 
     455            "label": "A PIN Code is entered", 
     456            "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     457            "argumentList" : { 
     458                "argument_1" : { 
     459                    "dataType": "string", 
     460                    "defaultValue": "", 
     461                    "name": "LastUser", 
     462                    "comparisson": "=", 
     463                    "prefix": "User", 
     464                    "suffix": "" 
     465                } 
     466            } 
     467        }, 
     468        "event_5": { 
     469            "label": "Vendor Status Code", 
     470            "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     471            "argumentList" : { 
     472                "argument_1" : { 
     473                    "dataType": "string", 
     474                    "defaultValue": "", 
     475                    "name": "VendorStatusCode", 
     476                    "comparisson": "=", 
     477                    "prefix": "Code", 
     478                    "suffix": "" 
     479                } 
     480            } 
     481        } 
     482    }, 
     483    "sceneList": { 
     484        "group_1": { 
     485            "cmd_1": { 
     486                "label": "Set Partition ... (PIN)", 
     487                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     488                "action": "RequestArmMode", 
     489                "argumentList": { 
     490                    "argument_1": { 
     491                        "dataType": "string", 
     492                        "defaultValue": "Disarmed", 
     493                        "allowedValueList": { 
     494                            "Disarmed" : "Disarmed", 
     495                            "Armed" : "Armed", 
     496                            "Stay" : "Stay", 
     497                            "StayInstant" : "StayInstant", 
     498                            "Night" : "Night", 
     499                            "NightInstant" : "NightInstant", 
     500                            "Force" : "Force", 
     501                            "Vacation" : "Vacation" 
     502                        }, 
     503                        "name": "State", 
     504                        "prefix": "State", 
     505                        "suffix": "" 
     506                    }, 
     507                    "argument_2": { 
     508                        "dataType": "ui4", 
     509                        "defaultValue": "1234", 
     510                        "allowedValueRange": { 
     511                            "minimum": "0", 
     512                            "maximum": "999999999999" 
     513                        }, 
     514                        "prefix" : "PIN", 
     515                        "suffix" : "0-99999999, (insecure)", 
     516                        "name": "PINCode" 
     517                    } 
     518                } 
     519            } 
     520        }, 
     521        "group_2": { 
     522            "cmd_1": { 
     523                "label": "Set Partition Disarmed (No PIN)", 
     524                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     525                "action": "RequestArmMode", 
     526                "arguments": { 
     527                    "State": "Disarmed" 
     528                } 
     529            }, 
     530            "cmd_2": { 
     531                "label": "Set Partition Armed (No PIN)", 
     532                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     533                "action": "RequestArmMode", 
     534                "arguments": { 
     535                    "State": "Armed" 
     536                } 
     537            }, 
     538            "cmd_3": { 
     539                "label": "Set Partition Stay (No PIN)", 
     540                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     541                "action": "RequestArmMode", 
     542                "arguments": { 
     543                    "State": "Stay" 
     544                } 
     545            }, 
     546            "cmd_4": { 
     547                "label": "Set Partition StayInstant (No PIN)", 
     548                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     549                "action": "RequestArmMode", 
     550                "arguments": { 
     551                    "State": "StayInstant" 
     552                } 
     553            }, 
     554            "cmd_5": { 
     555                "label": "Set Partition Night (No PIN)", 
     556                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     557                "action": "RequestArmMode", 
     558                "arguments": { 
     559                    "State": "Night" 
     560                } 
     561            }, 
     562            "cmd_6": { 
     563                "label": "Set Partition NightInstant (No PIN)", 
     564                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     565                "action": "RequestArmMode", 
     566                "arguments": { 
     567                    "State": "NightInstant" 
     568                } 
     569            }, 
     570            "cmd_7": { 
     571                "label": "Set Partition Force (No PIN)", 
     572                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     573                "action": "RequestArmMode", 
     574                "arguments": { 
     575                    "State": "Force" 
     576                } 
     577            }, 
     578            "cmd_8": { 
     579                "label": "Set Partition Vacation (No PIN)", 
     580                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     581                "action": "RequestArmMode", 
     582                "arguments": { 
     583                    "State": "Vacation" 
     584                } 
     585            } 
     586        }, 
     587        "group_3": { 
     588            "cmd_1": { 
     589                "label": "Request Medical Panic", 
     590                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     591                "action": "RequestPanicMode", 
     592                "arguments": { 
     593                    "State": "Medical" 
     594                } 
     595            }, 
     596            "cmd_2": { 
     597                "label": "Request Police Panic", 
     598                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     599                "action": "RequestPanicMode", 
     600                "arguments": { 
     601                    "State": "Police" 
     602                } 
     603            }, 
     604            "cmd_3": { 
     605                "label": "Request Fire Panic", 
     606                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition2", 
     607                "action": "RequestPanicMode", 
     608                "arguments": { 
     609                    "State": "Fire" 
     610                } 
     611            } 
     612        } 
     613    } 
    755614} 
  • /I_ElkAlarmPanel1.xml

    r20 r30  
    5656            <name>StorePinCode</name> 
    5757            <run> 
    58                 elkPlugin.storePinCode (lul_settings.PinCode) 
     58                elkPlugin.storePinCode (lul_device, lul_settings.PinCode) 
     59            </run> 
     60        </action> 
     61        <action> 
     62            <serviceId>urn:micasaverde-com:serviceId:ElkAlarmPanel1</serviceId> 
     63            <name>ClearPinCode</name> 
     64            <run> 
     65                elkPlugin.clearPinCode (lul_device) 
     66            </run> 
     67        </action> 
     68        <action> 
     69            <serviceId>urn:micasaverde-com:serviceId:ElkAlarmPanel1</serviceId> 
     70            <name>ClearTask</name> 
     71            <run> 
     72                elkPlugin.clearTask() 
    5973            </run> 
    6074        </action> 
Note: See TracChangeset for help on using the changeset viewer.