Changes in / [20:30]


Ignore:
Files:
3 added
3 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • /trunk

  • /trunk/I_CaddxNX584Security.xml

    r20 r30  
    77-- 
    88-- Luup plugin for GE/Networx/Caddx NX-584/NX-8E security system interface. 
     9-- 
     10-- Version 0.2 2011-04-27 by Deborah Pickett 
     11-- * Panic modes (medical, fire, police) 
     12-- * Uses Partition API 2 
    913-- 
    1014-- Version 0.1 2010-08-07 by Deborah Pickett 
     
    155159    end 
    156160 
    157     -- To do: Start enumerating child devices. 
     161    -- Start enumerating child devices. 
    158162    local childDevices = luup.chdev.start(deviceId) 
    159163 
     
    429433-- The plugin would like to know the name of a given zone 
    430434-- (z, integer) in a Zone Name message (0x03). 
    431 -- This isn't implemented on the NX-4 so I haven't been able to test it. 
    432435function getZoneName(deviceId, z) 
    433436    if (LOG_DEBUG) then luup.log("Sending message and waiting for response: 0x23 Zone Name Request") end 
     
    492495                        deviceId, childDevices, 
    493496                        "Partition-" .. p, PARTITION_STATUS[p]["name"], 
    494                         "urn:schemas-micasaverde-com:device:AlarmPartition:1", "D_AlarmPartition1.xml", 
     497                        "urn:schemas-futzle-com:device:CaddxNX584Partition:2", "D_CaddxNX584Partition2.xml", 
    495498                        "", "", true 
    496499                    ) 
     
    588591    PARTITION_STATUS[partition]["isArmed"] = bitMask(string.byte(string.sub(message,2)), 64) 
    589592    PARTITION_STATUS[partition]["isPartial"] = bitMask(string.byte(string.sub(message,4)), 4) 
    590     PARTITION_STATUS[partition]["isSiren"] = bitMask(string.byte(string.sub(message,3)), 4) 
     593    PARTITION_STATUS[partition]["isSiren"] = bitMask(string.byte(string.sub(message,3)), 2) 
     594    PARTITION_STATUS[partition]["wasSiren"] = bitMask(string.byte(string.sub(message,3)), 1) 
    591595    PARTITION_STATUS[partition]["isReady"] = bitMask(string.byte(string.sub(message,7)), 4) 
     596    PARTITION_STATUS[partition]["isChime"] = bitMask(string.byte(string.sub(message,4)), 8) 
     597    PARTITION_STATUS[partition]["isExitDelay"] = bitMask(string.byte(string.sub(message,4)), 192) 
     598    PARTITION_STATUS[partition]["isEntryDelay"] = bitMask(string.byte(string.sub(message,4)), 16) or 
     599        bitMask(string.byte(string.sub(message,8)), 1) 
    592600    PARTITION_STATUS[partition]["lastUser"] = string.byte(string.sub(message,6)) 
    593601    return partition 
     
    602610            PARTITION_STATUS[partition]["isPartial"] = bitMask(string.byte(string.sub(message,partition+1)), 8) 
    603611            PARTITION_STATUS[partition]["isReady"] = bitMask(string.byte(string.sub(message,partition+1)), 2) 
     612            PARTITION_STATUS[partition]["isChime"] = bitMask(string.byte(string.sub(message,partition+1)), 16) 
     613            PARTITION_STATUS[partition]["isExitDelay"] = bitMask(string.byte(string.sub(message,partition+1)), 64) 
     614            PARTITION_STATUS[partition]["isEntryDelay"] = bitMask(string.byte(string.sub(message,partition+1)), 32) 
     615            PARTITION_STATUS[partition]["wasSiren"] = bitMask(string.byte(string.sub(message,partition+1)), 128) 
    604616        end 
    605617    end 
     
    649661        if (partitionDevice == nil) then return end 
    650662 
    651         local armed = PARTITION_STATUS[partition]["isArmed"] and not PARTITION_STATUS[partition]["isPartial"] and "1" or "0" 
    652         if (LOG_DEBUG) then luup.log("Armed: " .. armed) end 
    653         if (luup.variable_get(ALARM_PARTITION_SERVICEID, "Armed", partitionDevice) ~= armed) then 
    654             luup.variable_set(ALARM_PARTITION_SERVICEID, "Armed", armed, partitionDevice) 
    655         end 
    656  
    657         local stay = PARTITION_STATUS[partition]["isPartial"] and PARTITION_STATUS[partition]["isArmed"] and "1" or "0" 
    658         if (LOG_DEBUG) then luup.log("StayArmed: " .. stay) end 
    659         if (luup.variable_get(ALARM_PARTITION_SERVICEID, "StayArmed", partitionDevice) ~= stay) then 
    660             luup.variable_set(ALARM_PARTITION_SERVICEID, "StayArmed", stay, partitionDevice) 
    661         end 
    662  
    663         local disarmed = not PARTITION_STATUS[partition]["isArmed"] and not PARTITION_STATUS[partition]["isPartial"] and "1" or "0" 
    664         if (LOG_DEBUG) then luup.log("Disarmed: " .. disarmed) end 
    665         if (luup.variable_get(ALARM_PARTITION_SERVICEID, "Disarmed", partitionDevice) ~= disarmed) then 
    666             luup.variable_set(ALARM_PARTITION_SERVICEID, "Disarmed", disarmed, partitionDevice) 
    667         end 
    668  
    669         local breached = PARTITION_STATUS[partition]["isSiren"] and "1" or "0" 
    670         if (LOG_DEBUG) then luup.log("Breached: " .. breached) end 
    671         if (luup.variable_get(ALARM_PARTITION_SERVICEID, "Breached", partitionDevice) ~= breached) then 
    672             luup.variable_set(ALARM_PARTITION_SERVICEID, "Breached", breached, partitionDevice) 
    673         end 
     663        -- Simple armed state (armed or not). 
     664        local armed = PARTITION_STATUS[partition]["isArmed"] and "Armed" or "Disarmed" 
     665        if (LOG_DEBUG) then luup.log("ArMode: " .. armed) end 
     666        luup.variable_set(ALARM_PARTITION_SERVICEID, "ArmMode", armed, partitionDevice) 
     667 
     668        -- Detailed armed state. 
     669        -- Listed in increasing order of importance. 
     670        local detailArmed = "Disarmed" 
     671        detailArmed = PARTITION_STATUS[partition]["isReady"] and "Ready" or detailArmed 
     672        detailArmed = PARTITION_STATUS[partition]["isArmed"] and "Armed" or detailArmed 
     673        detailArmed = PARTITION_STATUS[partition]["isPartial"] and "Stay" or detailArmed 
     674        detailArmed = PARTITION_STATUS[partition]["isExitDelay"] and "ExitDelay" or detailArmed 
     675        detailArmed = PARTITION_STATUS[partition]["isEntryDelay"] and "EntryDelay" or detailArmed 
     676        if (LOG_DEBUG) then luup.log("DetailedArmMode: " .. detailArmed) end 
     677        luup.variable_set(ALARM_PARTITION_SERVICEID, "DetailedArmMode", detailArmed, partitionDevice) 
     678 
     679        -- Current alarm. 
     680        local breached = PARTITION_STATUS[partition]["isSiren"] and "Active" or "None" 
     681        if (LOG_DEBUG) then luup.log("Alarm: " .. breached) end 
     682        luup.variable_set(ALARM_PARTITION_SERVICEID, "Alarm", breached, partitionDevice) 
     683 
     684        -- Past alarm (which has since cleared). 
     685        local pastAlarm = PARTITION_STATUS[partition]["wasSiren"] and "1" or "0" 
     686        if (LOG_DEBUG) then luup.log("AlarmMemory: " .. pastAlarm) end 
     687        luup.variable_set(ALARM_PARTITION_SERVICEID, "AlarmMemory", pastAlarm, partitionDevice) 
     688 
     689        -- Chime mode. 
     690        local chime = PARTITION_STATUS[partition]["isChime"] and "1" or "0" 
     691        if (LOG_DEBUG) then luup.log("ChimeEnabled: " .. chime) end 
     692        luup.variable_set(ALARM_PARTITION_SERVICEID, "ChimeEnabled", chime, partitionDevice) 
    674693 
    675694        -- Create a variable on the alarm interface matching the user who 
    676695        -- last changed the partition, if there isn't already. 
    677         if (luup.variable_get(ALARM_SERVICEID, "User" .. PARTITION_STATUS[partition]["lastUser"], deviceId) == nil) then 
    678             luup.variable_set(ALARM_SERVICEID, "User" .. PARTITION_STATUS[partition]["lastUser"], "User " .. PARTITION_STATUS[partition]["lastUser"], deviceId) 
     696        local lastUser = luup.variable_get(ALARM_SERVICEID, "User" .. PARTITION_STATUS[partition]["lastUser"], deviceId) 
     697        if (lastUser == nil) then 
     698            lastUser = "User " .. PARTITION_STATUS[partition]["lastUser"]; 
     699            luup.variable_set(ALARM_SERVICEID, "User" .. PARTITION_STATUS[partition]["lastUser"], lastUser, deviceId) 
    679700        end 
    680701        -- This is the user who last modified the partition. 
    681         luup.variable_set(ALARM_PARTITION_SERVICEID, "LastUser", (PARTITION_STATUS[partition]["lastUser"]), partitionDevice) 
     702        luup.variable_set(ALARM_PARTITION_SERVICEID, "LastUser", lastUser, partitionDevice) 
    682703    end 
    683704end 
     
    694715        local tripped = ZONE_STATUS[zone]["isFaulted"] and "1" or "0" 
    695716        if (LOG_DEBUG) then luup.log("Tripped: " .. tripped) end 
    696         if (luup.variable_get(ALARM_ZONE_SERVICEID, "Tripped", zoneDevice) ~= tripped) then 
    697             luup.variable_set(ALARM_ZONE_SERVICEID, "Tripped", tripped, zoneDevice) 
    698         end 
     717        luup.variable_set(ALARM_ZONE_SERVICEID, "Tripped", tripped, zoneDevice) 
    699718 
    700719        -- Invert logic because alarm panel speaks of "is bypassed". 
    701720        local armed = ZONE_STATUS[zone]["isBypassed"] and "0" or "1" 
    702721        if (LOG_DEBUG) then luup.log("Armed: " .. armed) end 
    703         if (luup.variable_get(ALARM_ZONE_SERVICEID, "Armed", zoneDevice) ~= armed) then 
    704             luup.variable_set(ALARM_ZONE_SERVICEID, "Armed", armed, zoneDevice) 
    705         end 
     722        luup.variable_set(ALARM_ZONE_SERVICEID, "Armed", armed, zoneDevice) 
    706723    end 
    707724end 
     
    11981215        <action> 
    11991216            <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 
    1200             <name>RequestQuickArm</name> 
     1217            <name>RequestQuickArmMode</name> 
    12011218            <job> 
    1202                 if (LOG_DEBUG) then luup.log("Job: Partition: RequestQuickArm " .. lul_device .. " job " .. getJobId(lul_job)) end 
     1219                if (LOG_DEBUG) then luup.log("Job: Partition: RequestQuickArmMode to " .. lul_settings.State .. " " .. lul_device .. " job " .. getJobId(lul_job)) end 
    12031220                 
    12041221                if (not CAPABILITY_SECONDARY_KEYPAD) then 
     
    12081225                local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 
    12091226 
    1210                 if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    12111227                -- Protocol doc says that command (second byte) for "Exit" mode should be message 2, 
    12121228                -- but on my system it seems that message 0 does the job.  Hmm.  Hope it isn't 
    12131229                -- different depending on what panel you've got.  That'd be crazy. 
     1230                local command = { 
     1231                    Armed = "\002", 
     1232                    Stay = "\000" 
     1233                } 
     1234                local commandByte = command[lul_settings.State] 
     1235                if (commandByte == nil) then 
     1236                    -- Command not supported. 
     1237                    return 2, nil 
     1238                end 
     1239                if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    12141240                addPendingJob(getJobId(lul_job), 
    1215                     "\062\000" .. string.char(2 ^ (partition-1)), 
     1241                    "\062" .. commandByte .. string.char(2 ^ (partition-1)), 
    12161242                    { 
    12171243                        [29] = function(deviceId, message) 
     
    12431269        <action> 
    12441270            <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 
    1245             <name>RequestArm</name> 
     1271            <name>RequestArmMode</name> 
    12461272            <job> 
    1247                 if (LOG_DEBUG) then luup.log("Job: Partition: RequestArm " .. lul_device .. " job " .. getJobId(lul_job)) end 
     1273                if (LOG_DEBUG) then luup.log("Job: Partition: RequestArmMode to " .. lul_settings.State .. " ".. lul_device .. " job " .. getJobId(lul_job)) end 
    12481274                 
    12491275                if (not CAPABILITY_PRIMARY_KEYPAD_WITH_PIN) then 
     
    12551281                if (pinCode == nil) then return 2, nil end 
    12561282 
     1283                local command = { 
     1284                    Armed = "\002", 
     1285                    Stay = "\003", 
     1286                    Disarmed = "\001" 
     1287                } 
     1288                local commandByte = command[lul_settings.State] 
     1289                if (commandByte == nil) then 
     1290                    -- Command not supported. 
     1291                    return 2, nil 
     1292                end 
    12571293                if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    12581294                addPendingJob(getJobId(lul_job), 
    1259                     "\060" .. pinCode .. "\002" .. string.char(2 ^ (partition-1)), 
     1295                    "\060" .. pinCode .. commandByte .. string.char(2 ^ (partition-1)), 
    12601296                    { 
    12611297                        [29] = function(deviceId, message) 
     
    12871323        <action> 
    12881324            <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 
    1289             <name>RequestQuickStay</name> 
     1325            <name>RequestPanicMode</name> 
    12901326            <job> 
    1291                 if (LOG_DEBUG) then luup.log("Job: Partition: RequestQuickStay " .. lul_device .. " job " .. getJobId(lul_job)) end 
     1327                if (LOG_DEBUG) then luup.log("Job: Partition: RequestMedicalPanic to " .. lul_settings.State .. " " .. lul_device .. " job " .. getJobId(lul_job)) end 
    12921328                 
     1329                if (luup.variable_get(ALARM_SERVICEID, "EnablePanic", lul_device) ~= "1") then 
     1330                    -- Panic disabled; return error. 
     1331                    return 2, nil 
     1332                end 
    12931333                if (not CAPABILITY_SECONDARY_KEYPAD) then 
    1294                     -- Cannot quick stay; return error. 
     1334                    -- Cannot send panic; return error. 
    12951335                    return 2, nil 
    12961336                end 
    12971337                local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 
    12981338 
    1299                 if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    1300                 -- Help! The communication protocol doesn't seem to match reality on my panel. 
    1301                 -- Command (byte 2) of 0 should enter Stay mode, but it enters Armed mode. 
    1302                 -- I don't really want to try other values, because some of them are the 
    1303                 -- panic button.  Volunteers welcome! 
    1304                 addPendingJob(getJobId(lul_job), 
    1305                     "\062\000" .. string.char(2 ^ (partition-1)), 
    1306                     { 
    1307                         [29] = function(deviceId, message) 
    1308                             -- Nothing more to do.  The interface will 
    1309                             -- send a snapshot with the updated info RSN, 
    1310                             -- and we'll update the partition device then. 
    1311                             JOBS[getJobId(lul_job)]["complete"] = 4 
    1312                             return 0 
    1313                         end, 
    1314                         [31] = function(deviceId, message) 
    1315                             JOBS[getJobId(lul_job)]["complete"] = 2 
    1316                             return 0 
    1317                         end, 
    1318                     } 
    1319                 ) 
    1320                 if (LOG_DEBUG) then luup.log("Job: Processing send queue") end 
    1321                 processSendQueue() 
    1322                 if (LOG_DEBUG) then luup.log("Job: Done") end 
    1323                 -- Either the timeout or incoming task will be called next. 
    1324                 return 5, 10 
    1325             </job> 
    1326             <incoming> 
    1327                 checkJobComplete(lul_job) 
    1328             </incoming> 
    1329             <timeout> 
    1330                 checkJobComplete(lul_job) 
    1331             </timeout> 
    1332         </action> 
    1333         <action> 
    1334             <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 
    1335             <name>RequestStay</name> 
    1336             <job> 
    1337                 if (LOG_DEBUG) then luup.log("Job: Partition: RequestStay " .. lul_device .. " job " .. getJobId(lul_job)) end 
    1338                  
    1339                 if (not CAPABILITY_PRIMARY_KEYPAD_WITH_PIN) then 
    1340                     -- Cannot stay; return error. 
     1339                local command = { 
     1340                    Medical = "\005", 
     1341                    Fire = "\004", 
     1342                    Police = "\006" 
     1343                } 
     1344                local commandByte = command[lul_settings.State] 
     1345                if (commandByte == nil) then 
     1346                    -- Command not supported. 
    13411347                    return 2, nil 
    13421348                end 
    1343                 local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 
    1344                 local pinCode = validatePin(lul_settings.PINCode) 
    1345                 if (pinCode == nil) then return 2, nil end 
    1346  
    13471349                if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    13481350                addPendingJob(getJobId(lul_job), 
    1349                     "\060" .. pinCode .. "\003" .. string.char(2 ^ (partition-1)), 
    1350                     { 
    1351                         [29] = function(deviceId, message) 
    1352                             -- Nothing more to do.  The interface will 
    1353                             -- send a snapshot with the updated info RSN, 
    1354                             -- and we'll update the partition device then. 
    1355                             JOBS[getJobId(lul_job)]["complete"] = 4 
    1356                             return 0 
    1357                         end, 
    1358                         [31] = function(deviceId, message) 
    1359                             JOBS[getJobId(lul_job)]["complete"] = 2 
    1360                             return 0 
    1361                         end, 
    1362                     } 
    1363                 ) 
    1364                 if (LOG_DEBUG) then luup.log("Job: Processing send queue") end 
    1365                 processSendQueue() 
    1366                 if (LOG_DEBUG) then luup.log("Job: Done") end 
    1367                 -- Either the timeout or incoming task will be called next. 
    1368                 return 5, 10 
    1369             </job> 
    1370             <incoming> 
    1371                 checkJobComplete(lul_job) 
    1372             </incoming> 
    1373             <timeout> 
    1374                 checkJobComplete(lul_job) 
    1375             </timeout> 
    1376         </action> 
    1377         <action> 
    1378             <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 
    1379             <name>RequestDisarm</name> 
    1380             <job> 
    1381                 if (LOG_DEBUG) then luup.log("Job: Partition: RequestDisarm " .. lul_device .. " job " .. getJobId(lul_job)) end 
    1382                  
    1383                 if (not CAPABILITY_PRIMARY_KEYPAD_WITH_PIN) then 
    1384                     -- Cannot disarm; return error. 
    1385                     return 2, nil 
    1386                 end 
    1387                 local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 
    1388                 local pinCode = validatePin(lul_settings.PINCode) 
    1389                 if (pinCode == nil) then return 2, nil end 
    1390  
    1391                 if (LOG_DEBUG) then luup.log("Job: Adding job") end 
    1392                 addPendingJob(getJobId(lul_job), 
    1393                     "\060" .. pinCode .. "\001" .. string.char(2 ^ (partition-1)), 
     1351                    "\062" .. commandByte .. string.char(2 ^ (partition-1)), 
    13941352                    { 
    13951353                        [29] = function(deviceId, message) 
  • /vendor/D_AlarmPartition1.json

    r20 r30  
    3737                    "id": "2", 
    3838                    "isSingle": "1" 
    39                 } 
     39                }, 
     40                { 
     41                    "id": "3" 
     42                }, 
    4043            ], 
    4144            "Control": [ 
     
    161164                    "Command": { 
    162165                        "Service": "urn:micasaverde-com:serviceId:AlarmPartition1", 
    163                         "Action": "RequestStayArm", 
     166                        "Action": "RequestStay", 
    164167                        "Parameters": [ 
    165168                            { 
     
    171174                }, 
    172175                { 
     176                    "ControlGroup": "3", 
    173177                    "ControlType": "button", 
    174178                    "Label": { 
     
    207211            "ScriptName": "shared.js", 
    208212            "Function": "advanced_device"  
     213        }, 
     214        { 
     215            "Label": { 
     216                "lang_tag": "logs", 
     217                "text": "Logs"  
     218            }, 
     219            "Position": "3", 
     220            "TabType": "javascript", 
     221            "ScriptName": "shared.js", 
     222            "Function": "device_logs"  
     223        }, 
     224        { 
     225            "Label": { 
     226                "lang_tag": "notifications", 
     227                "text": "Notifications"  
     228            }, 
     229            "Position": "4", 
     230            "TabType": "javascript", 
     231            "ScriptName": "shared.js", 
     232            "Function": "device_notifications"  
    209233        } 
    210234    ], 
     
    339363                }  
    340364            }  
     365        }, 
     366        "group_2": { 
     367            "cmd_1": { 
     368                "label": "Arm Partition (PIN)", 
     369                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition1", 
     370                "action": "RequestArm", 
     371                "argumentList": { 
     372                    "argument_1": { 
     373                        "dataType": "ui1", 
     374                        "defaultValue": "1234", 
     375                        "allowedValueRange": { 
     376                            "minimum": "0", 
     377                            "maximum": "999999999999"  
     378                        }, 
     379                        "prefix" : "PINCode", 
     380                        "suffix" : "(0-999999999999)", 
     381                        "name": "PINCode"  
     382                    } 
     383                }  
     384            }  
     385        }, 
     386        "group_3": { 
     387            "cmd_1": { 
     388                "label": "Quick Arm Partition", 
     389                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition1", 
     390                "action": "RequestQuickArm", 
     391                "argumentList": { 
     392                }  
     393            }  
     394        }, 
     395        "group_4": { 
     396            "cmd_1": { 
     397                "label": "Stay Arm Partition (PIN)", 
     398                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition1", 
     399                "action": "RequestStay", 
     400                "argumentList": { 
     401                    "argument_1": { 
     402                        "dataType": "ui1", 
     403                        "defaultValue": "1234", 
     404                        "allowedValueRange": { 
     405                            "minimum": "0", 
     406                            "maximum": "999999999999"  
     407                        }, 
     408                        "prefix" : "PINCode", 
     409                        "suffix" : "(0-999999999999)", 
     410                        "name": "PINCode"  
     411                    } 
     412                }  
     413            }  
     414        }, 
     415        "group_5": { 
     416            "cmd_1": { 
     417                "label": "Quick Stay Arm Partition", 
     418                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition1", 
     419                "action": "RequestQuickStay", 
     420                "argumentList": { 
     421                }  
     422            }  
     423        }, 
     424        "group_6": { 
     425            "cmd_1": { 
     426                "label": "Disarm Partition (PIN)", 
     427                "serviceId": "urn:micasaverde-com:serviceId:AlarmPartition1", 
     428                "action": "RequestDisarm", 
     429                "argumentList": { 
     430                    "argument_1": { 
     431                        "dataType": "ui1", 
     432                        "defaultValue": "1234", 
     433                        "allowedValueRange": { 
     434                            "minimum": "0", 
     435                            "maximum": "999999999999"  
     436                        }, 
     437                        "prefix" : "PINCode", 
     438                        "suffix" : "(0-999999999999)", 
     439                        "name": "PINCode"  
     440                    } 
     441                }  
     442            }  
    341443        }  
    342444    }  
Note: See TracChangeset for help on using the changeset viewer.