- Files:
-
- 3 added
- 3 deleted
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
/trunk
-
/trunk/I_CaddxNX584Security.xml
r20 r30 7 7 -- 8 8 -- 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 9 13 -- 10 14 -- Version 0.1 2010-08-07 by Deborah Pickett … … 155 159 end 156 160 157 -- To do:Start enumerating child devices.161 -- Start enumerating child devices. 158 162 local childDevices = luup.chdev.start(deviceId) 159 163 … … 429 433 -- The plugin would like to know the name of a given zone 430 434 -- (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.432 435 function getZoneName(deviceId, z) 433 436 if (LOG_DEBUG) then luup.log("Sending message and waiting for response: 0x23 Zone Name Request") end … … 492 495 deviceId, childDevices, 493 496 "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", 495 498 "", "", true 496 499 ) … … 588 591 PARTITION_STATUS[partition]["isArmed"] = bitMask(string.byte(string.sub(message,2)), 64) 589 592 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) 591 595 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) 592 600 PARTITION_STATUS[partition]["lastUser"] = string.byte(string.sub(message,6)) 593 601 return partition … … 602 610 PARTITION_STATUS[partition]["isPartial"] = bitMask(string.byte(string.sub(message,partition+1)), 8) 603 611 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) 604 616 end 605 617 end … … 649 661 if (partitionDevice == nil) then return end 650 662 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) 674 693 675 694 -- Create a variable on the alarm interface matching the user who 676 695 -- 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) 679 700 end 680 701 -- 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) 682 703 end 683 704 end … … 694 715 local tripped = ZONE_STATUS[zone]["isFaulted"] and "1" or "0" 695 716 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) 699 718 700 719 -- Invert logic because alarm panel speaks of "is bypassed". 701 720 local armed = ZONE_STATUS[zone]["isBypassed"] and "0" or "1" 702 721 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) 706 723 end 707 724 end … … 1198 1215 <action> 1199 1216 <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 1200 <name>RequestQuickArm </name>1217 <name>RequestQuickArmMode</name> 1201 1218 <job> 1202 if (LOG_DEBUG) then luup.log("Job: Partition: RequestQuickArm " .. lul_device .. " job " .. getJobId(lul_job)) end1219 if (LOG_DEBUG) then luup.log("Job: Partition: RequestQuickArmMode to " .. lul_settings.State .. " " .. lul_device .. " job " .. getJobId(lul_job)) end 1203 1220 1204 1221 if (not CAPABILITY_SECONDARY_KEYPAD) then … … 1208 1225 local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 1209 1226 1210 if (LOG_DEBUG) then luup.log("Job: Adding job") end1211 1227 -- Protocol doc says that command (second byte) for "Exit" mode should be message 2, 1212 1228 -- but on my system it seems that message 0 does the job. Hmm. Hope it isn't 1213 1229 -- 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 1214 1240 addPendingJob(getJobId(lul_job), 1215 "\062 \000".. string.char(2 ^ (partition-1)),1241 "\062" .. commandByte .. string.char(2 ^ (partition-1)), 1216 1242 { 1217 1243 [29] = function(deviceId, message) … … 1243 1269 <action> 1244 1270 <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 1245 <name>RequestArm </name>1271 <name>RequestArmMode</name> 1246 1272 <job> 1247 if (LOG_DEBUG) then luup.log("Job: Partition: RequestArm ".. lul_device .. " job " .. getJobId(lul_job)) end1273 if (LOG_DEBUG) then luup.log("Job: Partition: RequestArmMode to " .. lul_settings.State .. " ".. lul_device .. " job " .. getJobId(lul_job)) end 1248 1274 1249 1275 if (not CAPABILITY_PRIMARY_KEYPAD_WITH_PIN) then … … 1255 1281 if (pinCode == nil) then return 2, nil end 1256 1282 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 1257 1293 if (LOG_DEBUG) then luup.log("Job: Adding job") end 1258 1294 addPendingJob(getJobId(lul_job), 1259 "\060" .. pinCode .. "\002".. string.char(2 ^ (partition-1)),1295 "\060" .. pinCode .. commandByte .. string.char(2 ^ (partition-1)), 1260 1296 { 1261 1297 [29] = function(deviceId, message) … … 1287 1323 <action> 1288 1324 <serviceId>urn:micasaverde-com:serviceId:AlarmPartition1</serviceId> 1289 <name>Request QuickStay</name>1325 <name>RequestPanicMode</name> 1290 1326 <job> 1291 if (LOG_DEBUG) then luup.log("Job: Partition: Request QuickStay" .. lul_device .. " job " .. getJobId(lul_job)) end1327 if (LOG_DEBUG) then luup.log("Job: Partition: RequestMedicalPanic to " .. lul_settings.State .. " " .. lul_device .. " job " .. getJobId(lul_job)) end 1292 1328 1329 if (luup.variable_get(ALARM_SERVICEID, "EnablePanic", lul_device) ~= "1") then 1330 -- Panic disabled; return error. 1331 return 2, nil 1332 end 1293 1333 if (not CAPABILITY_SECONDARY_KEYPAD) then 1294 -- Cannot quick stay; return error.1334 -- Cannot send panic; return error. 1295 1335 return 2, nil 1296 1336 end 1297 1337 local partition = tonumber(string.match(luup.devices[lul_device].id, "%d+")) 1298 1338 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. 1341 1347 return 2, nil 1342 1348 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 end1346 1347 1349 if (LOG_DEBUG) then luup.log("Job: Adding job") end 1348 1350 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)), 1394 1352 { 1395 1353 [29] = function(deviceId, message) -
/vendor/D_AlarmPartition1.json
r20 r30 37 37 "id": "2", 38 38 "isSingle": "1" 39 } 39 }, 40 { 41 "id": "3" 42 }, 40 43 ], 41 44 "Control": [ … … 161 164 "Command": { 162 165 "Service": "urn:micasaverde-com:serviceId:AlarmPartition1", 163 "Action": "RequestStay Arm",166 "Action": "RequestStay", 164 167 "Parameters": [ 165 168 { … … 171 174 }, 172 175 { 176 "ControlGroup": "3", 173 177 "ControlType": "button", 174 178 "Label": { … … 207 211 "ScriptName": "shared.js", 208 212 "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" 209 233 } 210 234 ], … … 339 363 } 340 364 } 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 } 341 443 } 342 444 }
Note: See TracChangeset
for help on using the changeset viewer.