From ad39998a05b6ca5ca990d3ba55a1abeac29f0636 Mon Sep 17 00:00:00 2001 From: Kent Holloway Date: Fri, 28 Mar 2014 21:10:17 -0500 Subject: [PATCH 1/4] First try at Smartthings integration --- alarmserver-example.cfg | 18 +- alarmserver.py | 44 ++++- dscAlarmIntegrationSmarththingsApp.groovy | 92 ++++++++++ dscPanelDeviceSmartthings.groovy | 197 ++++++++++++++++++++++ 4 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 dscAlarmIntegrationSmarththingsApp.groovy create mode 100644 dscPanelDeviceSmartthings.groovy diff --git a/alarmserver-example.cfg b/alarmserver-example.cfg index d0d5dd1..32a9f69 100644 --- a/alarmserver-example.cfg +++ b/alarmserver-example.cfg @@ -9,7 +9,6 @@ logfile= ## seconds with the web ui's. To disable all these set this to False logurlrequests=True - ## The server runs with SSL. You need a certificate and key ## server.crt and server.key are included but you should ## generate your own. @@ -34,10 +33,12 @@ httpsport=8111 eventtimeago=True ## Name of your parition(s) +## Note: For callbackURL setup only defined zones and paritions are sent callback data partition1=Home ## Zone names. Delete the zones you're not using to have them hidden. ## Add more zoneXX if you need more zones +## Note: For callbackURL setup only defined zones and paritions are sent callback data zone1=A zone2=B zone3=C @@ -60,6 +61,21 @@ user1=MyUser1 user2=MyUser2 user3=MyUser3 +## Experimental CallbackURL functionality - Mainly for Smartthings right now +## The resulting path for callbackurls looks like this +## This likely needs to be fixed to allow more flexibility for any service? +## Suggestions welcome +## ${callbackurl_base}/${callbackurl_app_id}/panel/${code}/${zoneorpartitionnumber}?access_token=${callbackurl_access_token} + +## Smartthings or generic callback URL setup +callbackurl_base=https://graph.api.smartthings.com/api/smartapps/installations +callbackurl_app_id=your_app_id_from_smartthings_or_other_oAuth_setup +callbackurl_access_token=your_resulting_acces_token_after_auth_setup +## Define the event codes you want callbacks for, the codes below +## cover zone open/close, partition ready, not ready, armed, exit delay, entry delay and in alarm status +## these should cover most use cases +callbackurl_event_codes=601,602,609,610,650,651,652,654,656,657 + [pushover] enable=False usertoken=tokengoeshere diff --git a/alarmserver.py b/alarmserver.py index 2ed02ff..bd6dbf4 100755 --- a/alarmserver.py +++ b/alarmserver.py @@ -16,6 +16,7 @@ import hashlib import time import getopt +import requests from envisalinkdefs import evl_ResponseTypes from envisalinkdefs import evl_Defaults @@ -92,6 +93,10 @@ def __init__(self, configfile): self.ALARMCODE = self.read_config_var('envisalink', 'alarmcode', 1111, 'int') self.EVENTTIMEAGO = self.read_config_var('alarmserver', 'eventtimeago', True, 'bool') self.LOGFILE = self.read_config_var('alarmserver', 'logfile', '', 'str') + self.CALLBACKURL_BASE = self.read_config_var('alarmserver', 'callbackurl_base', '', 'str') + self.CALLBACKURL_APP_ID = self.read_config_var('alarmserver', 'callbackurl_app_id', '', 'str') + self.CALLBACKURL_ACCESS_TOKEN = self.read_config_var('alarmserver', 'callbackurl_access_token', '', 'str') + self.CALLBACKURL_EVENT_CODES = self.read_config_var('alarmserver', 'callbackurl_event_codes', '', 'str') global LOGTOFILE if self.LOGFILE == '': LOGTOFILE = False @@ -337,7 +342,8 @@ def handle_event(self, code, parameters, event, message): if event['type'] in ('partition', 'zone'): if event['type'] == 'zone': if int(parameters) in self._config.ZONENAMES: - if not int(parameters) in ALARMSTATE[event['type']]: ALARMSTATE[event['type']][int(parameters)] = {'name' : self._config.ZONENAMES[int(parameters)]} + if not int(parameters) in ALARMSTATE[event['type']]: + ALARMSTATE[event['type']][int(parameters)] = {'name' : self._config.ZONENAMES[int(parameters)]} else: if not int(parameters) in ALARMSTATE[event['type']]: ALARMSTATE[event['type']][int(parameters)] = {} elif event['type'] == 'partition': @@ -365,6 +371,7 @@ def handle_event(self, code, parameters, event, message): if len(ALARMSTATE[event['type']]['lastevents']) > self._config.MAXALLEVENTS: ALARMSTATE[event['type']]['lastevents'].pop(0) ALARMSTATE[event['type']]['lastevents'].append({'datetime' : str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")), 'message' : message}) + self.callbackurl_event(code, parameters, event, message) def handle_zone(self, code, parameters, event, message): self.handle_event(code, parameters[1:], event, message) @@ -372,6 +379,37 @@ def handle_zone(self, code, parameters, event, message): def handle_partition(self, code, parameters, event, message): self.handle_event(code, parameters[0], event, message) + def callbackurl_event(self, code, parameters, event, message): + myEvents = self._config.CALLBACKURL_EVENT_CODES.split(',') + # Determin what events we are sending to smartthings then send if we match + if str(code) in myEvents: + # Now check if Zone has a custom name, if it does then send notice to Smartthings + # Check for event type + if event['type'] == 'partition': + # Is our partition setup with a custom name? + if int(parameters[0]) in self._config.PARTITIONNAMES: + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters[0])) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + else: + # We don't care about this partition + return + elif event['type'] == 'zone': + # Is our zone setup with a custom name, if so we care about it + if self._config.ZONENAMES[int(parameters)]: + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters)) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + else: + # We don't care about this zone + return + else: + # Unhandled event type.. + return + + # If we made it here we should send to Smartthings + try: + # Note: I don't currently care about the return value, fire and forget right now + requests.get(myURL) + except: + print sys.exc_info()[0] + class push_FileProducer: # a producer which reads data from a file object @@ -410,9 +448,9 @@ def handle_accept(self): alarmserver_logger('Incoming web connection from %s' % repr(addr)) try: + # HTTPChannel(self, conn, addr) HTTPChannel(self, ssl.wrap_socket(conn, server_side=True, certfile=config.CERTFILE, keyfile=config.KEYFILE, ssl_version=ssl.PROTOCOL_TLSv1), addr) except ssl.SSLError: - alarmserver_logger('Failed https connection, attempted with http') return def handle_request(self, channel, method, request, header): @@ -607,4 +645,4 @@ def main(argv): server.shutdown(socket.SHUT_RDWR) server.close() - sys.exit() \ No newline at end of file + sys.exit() diff --git a/dscAlarmIntegrationSmarththingsApp.groovy b/dscAlarmIntegrationSmarththingsApp.groovy new file mode 100644 index 0000000..4c2d4dd --- /dev/null +++ b/dscAlarmIntegrationSmarththingsApp.groovy @@ -0,0 +1,92 @@ +/** + * DSC Alarm Panel integration via REST API callbacks + * + * Author: Kent Holloway + */ + +preferences { + section("Alarm Panel") { + input "panel", "device.dSCPanel", title: "Choose Alarm Panel?", multiple: false, required: true + } +} + +mappings { + path("/panel/:code/:zoneorpart") { + action: [ + GET: "updateZoneOrPartition" + ] + } +} + +def installed() { + log.debug "Installed!" + subscribe(panel) +} + +def updated() { + log.debug "Updated!" + unsubscribe() + subscribe(panel) +} + +void updateZoneOrPartition() { + update(panel) +} + +private update(panel) { + // log.debug "update, request: params: ${params} panel: ${panel.name}" + + def zoneorpartition = params.zoneorpart + def code = params.code + if (code) + { + // log.debug "Panel: ${panel.name}" + // log.debug "Zone/Partition: ${zoneorpartition}" + // log.debug "Command: ${code}" + + // Codes come in as raw alarm codes from AlarmServer + // convert them to our device Panel commands + // OR send in a specific command which will be passed + // to the device + def newCommand = "" + switch(code) { + case "601": + newCommand = "alarm" + break + case "602": + newCommand = "closed" + break + case "609": + newCommand = "open" + break + case "610": + newCommand = "closed" + break + case "650": + newCommand = "partitionready" + break + case "651": + newCommand = "partitionnotready" + break + case "652": + newCommand = "partitionarmed" + break + case "654": + newCommand = "partitionalarm" + break + case "656": + newCommand = "partitionexitdelay" + break + case "657": + newCommand = "partitionentrydelay" + break + default: + newCommand = command + break + } + // log.debug "New Command: $newCommand" + // Send the resulting command + panel."$newCommand"(zoneorpartition) + } +} + diff --git a/dscPanelDeviceSmartthings.groovy b/dscPanelDeviceSmartthings.groovy new file mode 100644 index 0000000..ddd2a9f --- /dev/null +++ b/dscPanelDeviceSmartthings.groovy @@ -0,0 +1,197 @@ +/** + * DSC Panel + * + * Author: Kent Holloway + * Date: 2014-03-20 + */ +// for the UI +metadata { + // Automatically generated. Make future change here. + definition (name: "DSC Panel", author: "drizit@gmail.com") { + // Change or define capabilities here as needed + capability "Refresh" + capability "Switch" + capability "Contact Sensor" + capability "Indicator" + capability "Polling" + + // Add commands as needed + command "open" + command "closed" + command "alarm" + command "partitionready" + command "partitionnotready" + command "partitionarmed" + command "partitionexitdelay" + command "partitionentrydelay" + command "partitionalarm" + } + + simulator { + // Nothing here, you could put some testing stuff here if you like + } + + tiles { + // NOTE: Leave the first item "panelstatus" alone + // but edit all the remaining Tiles to match the zone numbers you care about + // You have to change both the "zone1" name and the "device.zone1" type to match your zone + // Then edit the details line further down in this section to match + // all the zone numbers you setup or the icons will be missing in your app + // You can add more rows if needed, just copy/paste the standardTile lines + // for more + + // Final note: if you add/remove/change zones you have to force quit your + // smartthings app on iOS (probably on Android also) to see the new tile layout + + // First Row + standardTile("panelstatus", "device.panelstatus", width: 2, height: 2, canChangeBackground: true, canChangeIcon: true) { + state "armed", label: 'Armed', backgroundColor: "#79b821", icon:"st.Home.home3" + state "exitdelay", label: 'Exit Delay', backgroundColor: "#ff9900", icon:"st.Home.home3" + state "entrydelay",label: 'EntryDelay', backgroundColor: "#ff9900", icon:"st.Home.home3" + state "open", label: 'Open', backgroundColor: "#ffcc00", icon:"st.Home.home2" + state "ready", label: 'Ready', backgroundColor: "#79b821", icon:"st.Home.home2" + state "alarm", label: 'Alarm', backgroundColor: "#ff0000", icon:"st.Home.home3" + } + // Top right icon + standardTile("zone1", "device.zone1", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" + } + // 2nd row far right icon + standardTile("zone2", "device.zone2", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" + } + // third row from left to right + standardTile("zone3", "device.zone3", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" + } + standardTile("zone15", "device.zone15", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000" + } + standardTile("zone16", "device.zone16", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000" + } + + // Fourth row from left to right + standardTile("zone17", "device.zone17", canChangeBackground: true, canChangeIcon: true) { + state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" + state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" + state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" + } + + // Fourth Row + standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") { + state "default", action:"polling.poll", icon:"st.secondary.refresh" + } + + // This tile will be the tile that is displayed on the Hub page. + main "panelstatus" + + // These tiles will be displayed when clicked on the device, in the order listed here. + details(["panelstatus", "zone1", "zone2", "zone3", "zone15", "zone16", "zone17", "refresh"]) + } +} + +// parse events into attributes +def parse(String description) { + // log.debug "Parsing '${description}'" + // TODO: handle 'switch' attribute + // TODO: handle 'indicatorStatus' attribute + // TODO: handle '' attribute + def myValues = description.tokenize() + // log.debug "Description: ${myValues[0]} - ${myValues[1]}" + sendEvent (name: "${myValues[0]}", value: "${myValues[1]}") +} + +// handle commands +def open(String zone) { + // log.debug "In Open function for Zone: $zone" + sendEvent (name: "${zone}", value: 'open') +} + +def closed(String zone) { + // log.debug "In Closed function for Zone: $zone" + sendEvent (name: "${zone}", value: 'closed') +} + +def alarm(String zone) { + // log.debug "Alarm for Zone: $zone" + sendEvent (name: "${zone}", value: 'alarm') +} + +def partitionready(String partition) { + // log.debug "Partition ready: $partition" + sendEvent (name: "panelstatus", value: 'ready') +} + +def partitionnotready(String partition) { + // log.debug "Partition not ready: $partition" + sendEvent (name: "panelstatus", value: 'open') +} + +def partitionarmed(String partition) { + // log.debug "Partition Armed: $partition" + sendEvent (name: "panelstatus", value: 'armed') +} + +def partitionexitdelay(String partition) { + // log.debug "Partition Exit Delay: $partition" + sendEvent (name: "panelstatus", value: 'exitdelay') +} + +def partitionentrydelay(String partition) { + // log.debug "Partition Entry Delay: $partition" + sendEvent (name: "panelstatus", value: 'entrydelay') +} + +def partitionalarm(String partition) { + // log.debug "Partition Alarm: $partition" + sendEvent (name: "panelstatus", value: 'alarm') +} + +def on() { + log.debug "Executing 'on'" + // TODO: handle 'on' command +} + +def off() { + log.debug "Executing 'off'" + // TODO: handle 'off' command +} + +def poll() { + log.debug "Executing 'poll'" + // TODO: handle 'poll' command + // On poll what should we do? nothing for now.. +} + +def indicatorWhenOn() { + log.debug "Executing 'indicatorWhenOn'" + // TODO: handle 'indicatorWhenOn' command +} + +def indicatorWhenOff() { + log.debug "Executing 'indicatorWhenOff'" + // TODO: handle 'indicatorWhenOff' command +} + +def indicatorNever() { + log.debug "Executing 'indicatorNever'" + // TODO: handle 'indicatorNever' command +} + +def refresh() { + log.debug "Executing 'refresh' which is actually poll()" + poll() + // TODO: handle 'refresh' command +} + From 4c00e18247c42a072a74f307b004e219dd05ed58 Mon Sep 17 00:00:00 2001 From: Kent Holloway Date: Sat, 29 Mar 2014 21:16:19 -0500 Subject: [PATCH 2/4] removing Smartthings specific groovy files, they are not required for the AlarmServer project at all and have been moved to a proper repo of their own. --- dscAlarmIntegrationSmarththingsApp.groovy | 92 ---------- dscPanelDeviceSmartthings.groovy | 197 ---------------------- 2 files changed, 289 deletions(-) delete mode 100644 dscAlarmIntegrationSmarththingsApp.groovy delete mode 100644 dscPanelDeviceSmartthings.groovy diff --git a/dscAlarmIntegrationSmarththingsApp.groovy b/dscAlarmIntegrationSmarththingsApp.groovy deleted file mode 100644 index 4c2d4dd..0000000 --- a/dscAlarmIntegrationSmarththingsApp.groovy +++ /dev/null @@ -1,92 +0,0 @@ -/** - * DSC Alarm Panel integration via REST API callbacks - * - * Author: Kent Holloway - */ - -preferences { - section("Alarm Panel") { - input "panel", "device.dSCPanel", title: "Choose Alarm Panel?", multiple: false, required: true - } -} - -mappings { - path("/panel/:code/:zoneorpart") { - action: [ - GET: "updateZoneOrPartition" - ] - } -} - -def installed() { - log.debug "Installed!" - subscribe(panel) -} - -def updated() { - log.debug "Updated!" - unsubscribe() - subscribe(panel) -} - -void updateZoneOrPartition() { - update(panel) -} - -private update(panel) { - // log.debug "update, request: params: ${params} panel: ${panel.name}" - - def zoneorpartition = params.zoneorpart - def code = params.code - if (code) - { - // log.debug "Panel: ${panel.name}" - // log.debug "Zone/Partition: ${zoneorpartition}" - // log.debug "Command: ${code}" - - // Codes come in as raw alarm codes from AlarmServer - // convert them to our device Panel commands - // OR send in a specific command which will be passed - // to the device - def newCommand = "" - switch(code) { - case "601": - newCommand = "alarm" - break - case "602": - newCommand = "closed" - break - case "609": - newCommand = "open" - break - case "610": - newCommand = "closed" - break - case "650": - newCommand = "partitionready" - break - case "651": - newCommand = "partitionnotready" - break - case "652": - newCommand = "partitionarmed" - break - case "654": - newCommand = "partitionalarm" - break - case "656": - newCommand = "partitionexitdelay" - break - case "657": - newCommand = "partitionentrydelay" - break - default: - newCommand = command - break - } - // log.debug "New Command: $newCommand" - // Send the resulting command - panel."$newCommand"(zoneorpartition) - } -} - diff --git a/dscPanelDeviceSmartthings.groovy b/dscPanelDeviceSmartthings.groovy deleted file mode 100644 index ddd2a9f..0000000 --- a/dscPanelDeviceSmartthings.groovy +++ /dev/null @@ -1,197 +0,0 @@ -/** - * DSC Panel - * - * Author: Kent Holloway - * Date: 2014-03-20 - */ -// for the UI -metadata { - // Automatically generated. Make future change here. - definition (name: "DSC Panel", author: "drizit@gmail.com") { - // Change or define capabilities here as needed - capability "Refresh" - capability "Switch" - capability "Contact Sensor" - capability "Indicator" - capability "Polling" - - // Add commands as needed - command "open" - command "closed" - command "alarm" - command "partitionready" - command "partitionnotready" - command "partitionarmed" - command "partitionexitdelay" - command "partitionentrydelay" - command "partitionalarm" - } - - simulator { - // Nothing here, you could put some testing stuff here if you like - } - - tiles { - // NOTE: Leave the first item "panelstatus" alone - // but edit all the remaining Tiles to match the zone numbers you care about - // You have to change both the "zone1" name and the "device.zone1" type to match your zone - // Then edit the details line further down in this section to match - // all the zone numbers you setup or the icons will be missing in your app - // You can add more rows if needed, just copy/paste the standardTile lines - // for more - - // Final note: if you add/remove/change zones you have to force quit your - // smartthings app on iOS (probably on Android also) to see the new tile layout - - // First Row - standardTile("panelstatus", "device.panelstatus", width: 2, height: 2, canChangeBackground: true, canChangeIcon: true) { - state "armed", label: 'Armed', backgroundColor: "#79b821", icon:"st.Home.home3" - state "exitdelay", label: 'Exit Delay', backgroundColor: "#ff9900", icon:"st.Home.home3" - state "entrydelay",label: 'EntryDelay', backgroundColor: "#ff9900", icon:"st.Home.home3" - state "open", label: 'Open', backgroundColor: "#ffcc00", icon:"st.Home.home2" - state "ready", label: 'Ready', backgroundColor: "#79b821", icon:"st.Home.home2" - state "alarm", label: 'Alarm', backgroundColor: "#ff0000", icon:"st.Home.home3" - } - // Top right icon - standardTile("zone1", "device.zone1", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" - } - // 2nd row far right icon - standardTile("zone2", "device.zone2", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" - } - // third row from left to right - standardTile("zone3", "device.zone3", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" - } - standardTile("zone15", "device.zone15", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000" - } - standardTile("zone16", "device.zone16", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000" - } - - // Fourth row from left to right - standardTile("zone17", "device.zone17", canChangeBackground: true, canChangeIcon: true) { - state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" - state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" - state "alarm", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ff0000" - } - - // Fourth Row - standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") { - state "default", action:"polling.poll", icon:"st.secondary.refresh" - } - - // This tile will be the tile that is displayed on the Hub page. - main "panelstatus" - - // These tiles will be displayed when clicked on the device, in the order listed here. - details(["panelstatus", "zone1", "zone2", "zone3", "zone15", "zone16", "zone17", "refresh"]) - } -} - -// parse events into attributes -def parse(String description) { - // log.debug "Parsing '${description}'" - // TODO: handle 'switch' attribute - // TODO: handle 'indicatorStatus' attribute - // TODO: handle '' attribute - def myValues = description.tokenize() - // log.debug "Description: ${myValues[0]} - ${myValues[1]}" - sendEvent (name: "${myValues[0]}", value: "${myValues[1]}") -} - -// handle commands -def open(String zone) { - // log.debug "In Open function for Zone: $zone" - sendEvent (name: "${zone}", value: 'open') -} - -def closed(String zone) { - // log.debug "In Closed function for Zone: $zone" - sendEvent (name: "${zone}", value: 'closed') -} - -def alarm(String zone) { - // log.debug "Alarm for Zone: $zone" - sendEvent (name: "${zone}", value: 'alarm') -} - -def partitionready(String partition) { - // log.debug "Partition ready: $partition" - sendEvent (name: "panelstatus", value: 'ready') -} - -def partitionnotready(String partition) { - // log.debug "Partition not ready: $partition" - sendEvent (name: "panelstatus", value: 'open') -} - -def partitionarmed(String partition) { - // log.debug "Partition Armed: $partition" - sendEvent (name: "panelstatus", value: 'armed') -} - -def partitionexitdelay(String partition) { - // log.debug "Partition Exit Delay: $partition" - sendEvent (name: "panelstatus", value: 'exitdelay') -} - -def partitionentrydelay(String partition) { - // log.debug "Partition Entry Delay: $partition" - sendEvent (name: "panelstatus", value: 'entrydelay') -} - -def partitionalarm(String partition) { - // log.debug "Partition Alarm: $partition" - sendEvent (name: "panelstatus", value: 'alarm') -} - -def on() { - log.debug "Executing 'on'" - // TODO: handle 'on' command -} - -def off() { - log.debug "Executing 'off'" - // TODO: handle 'off' command -} - -def poll() { - log.debug "Executing 'poll'" - // TODO: handle 'poll' command - // On poll what should we do? nothing for now.. -} - -def indicatorWhenOn() { - log.debug "Executing 'indicatorWhenOn'" - // TODO: handle 'indicatorWhenOn' command -} - -def indicatorWhenOff() { - log.debug "Executing 'indicatorWhenOff'" - // TODO: handle 'indicatorWhenOff' command -} - -def indicatorNever() { - log.debug "Executing 'indicatorNever'" - // TODO: handle 'indicatorNever' command -} - -def refresh() { - log.debug "Executing 'refresh' which is actually poll()" - poll() - // TODO: handle 'refresh' command -} - From 0454c96c38102b2a552f5f750bb35cc836ffa306 Mon Sep 17 00:00:00 2001 From: Kent Holloway Date: Sun, 30 Mar 2014 19:28:55 -0500 Subject: [PATCH 3/4] Bug fix for missing zone and partition keywords --- alarmserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alarmserver.py b/alarmserver.py index bd6dbf4..a0426ec 100755 --- a/alarmserver.py +++ b/alarmserver.py @@ -388,14 +388,14 @@ def callbackurl_event(self, code, parameters, event, message): if event['type'] == 'partition': # Is our partition setup with a custom name? if int(parameters[0]) in self._config.PARTITIONNAMES: - myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters[0])) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/partition" + str(int(parameters[0])) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN else: # We don't care about this partition return elif event['type'] == 'zone': # Is our zone setup with a custom name, if so we care about it if self._config.ZONENAMES[int(parameters)]: - myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters)) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/zone" + str(int(parameters)) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN else: # We don't care about this zone return From a423e918f87b7fccf728a0ef281fc31c452d437c Mon Sep 17 00:00:00 2001 From: Kent Holloway Date: Wed, 2 Jul 2014 17:54:53 -0500 Subject: [PATCH 4/4] Changing base URL to no longer include the words zone or partition --- alarmserver.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/alarmserver.py b/alarmserver.py index a0426ec..73bdca1 100755 --- a/alarmserver.py +++ b/alarmserver.py @@ -388,14 +388,14 @@ def callbackurl_event(self, code, parameters, event, message): if event['type'] == 'partition': # Is our partition setup with a custom name? if int(parameters[0]) in self._config.PARTITIONNAMES: - myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/partition" + str(int(parameters[0])) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters[0])) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN else: # We don't care about this partition return elif event['type'] == 'zone': # Is our zone setup with a custom name, if so we care about it if self._config.ZONENAMES[int(parameters)]: - myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/zone" + str(int(parameters)) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN + myURL = self._config.CALLBACKURL_BASE + "/" + self._config.CALLBACKURL_APP_ID + "/panel/" + str(code) + "/" + str(int(parameters)) + "?access_token=" + self._config.CALLBACKURL_ACCESS_TOKEN else: # We don't care about this zone return @@ -407,6 +407,10 @@ def callbackurl_event(self, code, parameters, event, message): try: # Note: I don't currently care about the return value, fire and forget right now requests.get(myURL) + #print "myURL: ", myURL + #print "Exit code: ", r.status_code + #print "Response data: ", r.text + time.sleep(0.5) except: print sys.exc_info()[0]