/* * DSC Alarm Panel integration via REST API callbacks * * Author: Kent Holloway <drizit@gmail.com> * Modified by: Matt Martz <matt.martz@gmail.com> * Modified by: Jordan <jordan@xeron.cc> */ definition( name: "DSC Integration", namespace: "", author: "Jordan <jordan@xeron.cc>", description: "DSC Integration App", category: "My Apps", iconUrl: "https://dl.dropboxusercontent.com/u/2760581/dscpanel_small.png", iconX2Url: "https://dl.dropboxusercontent.com/u/2760581/dscpanel_large.png", oauth: true ) import groovy.json.JsonBuilder preferences { section("Alarm Panel:") { input "paneldevices", "capability.switch", title: "Alarm Panel (required)", multiple: true, required: false } section("Zone Devices:") { input "zonedevices", "capability.sensor", title: "DSC Zone Devices (required)", multiple: true, required: false } section("XBMC Notifications (optional):") { // TODO: put inputs here input "xbmcserver", "text", title: "XBMC IP", description: "IP Address", required: false input "xbmcport", "number", title: "XBMC Port", description: "Port", required: false } section("Notifications (optional)") { input "sendPush", "enum", title: "Push Notifiation", required: false, metadata: [ values: ["Yes","No"] ] input "phone1", "phone", title: "Phone Number", required: false } section("Notification events (optional):") { input "notifyEvents", "enum", title: "Which Events?", description: "Events to notify on", required: false, multiple: true, options: [ 'all', 'partition alarm', 'partition armed', 'partition away', 'partition disarm', 'partition entrydelay', 'partition exitdelay', 'partition forceready', 'partition instantaway', 'partition instantstay', 'partition notready', 'partition ready', 'partition restore', 'partition stay', 'partition trouble', 'ledbacklighton', 'ledbacklightoff', 'ledfireon', 'ledfireoff', 'ledprogramon', 'ledprogramoff', 'ledtroubleon', 'ledtroubleoff', 'ledbypasson', 'ledbypassoff', 'ledmemoryon', 'ledmemoryoff', 'ledarmedon', 'ledarmedoff', 'ledreadyon', 'ledreadyoff', 'zone alarm', 'zone clear', 'zone closed', 'zone fault', 'zone open', 'zone restore', 'zone smoke', 'zone tamper' ] } } mappings { path("/panel/:eventcode/:zoneorpart") { action: [ GET: "updateZoneOrPartition" ] } } def installed() { log.debug "Installed!" } def updated() { log.debug "Updated!" } void updateZoneOrPartition() { update() } private update() { def zoneorpartition = params.zoneorpart // Add more events here as needed // Each event maps to a command in your "DSC Panel" device type def eventMap = [ '510':"partition led", '511':"partition ledflash", '601':"zone alarm", '602':"zone closed", '603':"zone tamper", '604':"zone restore", '605':"zone fault", '606':"zone restore", '609':"zone open", '610':"zone closed", '631':"zone smoke", '632':"zone clear", '650':"partition ready", '651':"partition notready", '652':"partition armed", '653':"partition forceready", '654':"partition alarm", '655':"partition disarm", '656':"partition exitdelay", '657':"partition entrydelay", '663':"partition chime", '664':"partition nochime", '701':"partition armed", '702':"partition armed", '840':"partition trouble", '841':"partition restore", '6520':"partition away", '6521':"partition stay", '6522':"partition instantaway", '6523':"partition instantstay" ] // get our passed in eventcode def eventCode = params.eventcode if (eventCode) { // Lookup our eventCode in our eventMap def opts = eventMap."${eventCode}"?.tokenize() // log.debug "Options after lookup: ${opts}" // log.debug "Zone or partition: $zoneorpartition" if (opts[0]) { if (['510', '511'].contains(eventCode)) { def flash = (opts[1] == 'ledflash') ? 'flash ' : '' def ledMap = [ '0':'backlight', '1':'fire', '2':'program', '3':'trouble', '4':'bypass', '5':'memory', '6':'armed', '7':'ready' ] for (def i = 0; i < 8; i++) { def name = ledMap."${i}" def status = (zoneorpartition[i] == '1') ? 'on' : 'off' if (notifyEvents && (notifyEvents.contains('all') || notifyEvents.contains('led'+name+status))) { sendMessage("${opts[0]} 1 ${name} led in ${flash}${status} state") } } updatePartitions(paneldevices, '1',"${opts[1]}${zoneorpartition}") } else { if (notifyEvents && (notifyEvents.contains('all') || notifyEvents.contains(eventMap[eventCode]))) { sendMessage("${opts[0]} ${zoneorpartition} in ${opts[1]} state") } // We have some stuff to send to the device now // this looks something like panel.zone("open", "1") // log.debug "Test: ${opts[0]} and: ${opts[1]} for $zoneorpartition" if ("${opts[0]}" == 'zone') { //log.debug "It was a zone... ${opts[1]}" updateZoneDevices(zonedevices,"$zoneorpartition","${opts[1]}") } if ("${opts[0]}" == 'partition') { //log.debug "It was a zone... ${opts[1]}" updatePartitions(paneldevices, "$zoneorpartition","${opts[1]}") } } } } } private updateZoneDevices(zonedevices,zonenum,zonestatus) { log.debug "zonedevices: $zonedevices - ${zonenum} is ${zonestatus}" // log.debug "zonedevices.id are $zonedevices.id" // log.debug "zonedevices.displayName are $zonedevices.displayName" // log.debug "zonedevices.deviceNetworkId are $zonedevices.deviceNetworkId" def zonedevice = zonedevices.find { it.deviceNetworkId == "dsczone${zonenum}" } if (zonedevice) { log.debug "Was True... Zone Device: $zonedevice.displayName at $zonedevice.deviceNetworkId is ${zonestatus}" //Was True... Zone Device: Front Door Sensor at zone1 is closed zonedevice.zone("${zonestatus}") if ("${settings.xbmcserver}" != "") { //Note: I haven't tested this if statement, but it looks like it would work. def lanaddress = "${settings.xbmcserver}:${settings.xbmcport}" def deviceNetworkId = "1234" def json = new JsonBuilder() def messagetitle = "$zonedevice.displayName".replaceAll(' ','%20') log.debug "$messagetitle" json.call("jsonrpc":"2.0","method":"GUI.ShowNotification","params":[title: "$messagetitle",message: "${zonestatus}"],"id":1) def xbmcmessage = "/jsonrpc?request="+json.toString() def result = new physicalgraph.device.HubAction("""GET $xbmcmessage HTTP/1.1\r\nHOST: $lanaddress\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}") sendHubCommand(result) } } } private updatePartitions(paneldevices, partitionnum, partitionstatus) { log.debug "paneldevices: $paneldevices - ${partitionnum} is ${partitionstatus}" def paneldevice = paneldevices.find { it.deviceNetworkId == "dscpanel${partitionnum}" } if (paneldevice) { log.debug "Was True... Panel device: $paneldevice.displayName at $paneldevice.deviceNetworkId is ${partitionstatus}" //Was True... Zone Device: Front Door Sensor at zone1 is closed paneldevice.partition("${partitionstatus}", "${partitionnum}") } def awayswitch = paneldevices.find { it.deviceNetworkId == "dscaway${partitionnum}" } if (awayswitch) { log.debug "Was True... Away Switch device: $awayswitch.displayName at $awayswitch.deviceNetworkId is ${partitionstatus}" //Was True... Zone Device: Front Door Sensor at zone1 is closed awayswitch.partition("${partitionstatus}", "${partitionnum}") } def stayswitch = paneldevices.find { it.deviceNetworkId == "dscstay${partitionnum}" } if (stayswitch) { log.debug "Was True... Stay Switch device: $stayswitch.displayName at $stayswitch.deviceNetworkId is ${partitionstatus}" //Was True... Zone Device: Front Door Sensor at zone1 is closed stayswitch.partition("${partitionstatus}", "${partitionnum}") } } private sendMessage(msg) { def newMsg = "Alarm Notification: $msg" if (phone1) { sendSms(phone1, newMsg) } if (sendPush == "Yes") { sendPush(newMsg) } }