MIMOlite as a Burg Alarm Control and Monitor with Fire, Burg, Armed, and Disarmed capability

/**

  • MIMOlite as a Burg Alarm Control and Monitor with Fire, Burg, Armed, and Disarmed capability.
  •     ***USE AT YOUR OWN RISK***
    
  • Copyright 2016 mignlou
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.
  • Based on code from MIMOlite Garage Door Sensor with Position Indicator by Skyjunky
  • [OBSOLETE] MIMOlite Garage Door Sensor with Position Indicator
  • Inspired by a similar handler written by Profile - johnconstantelo - SmartThings Community
    */
    // Added Preferences
    preferences {
    input name: “disarmedValue”, type: “number”, title: “Disarmed Value”, description: “Value When Disarmed”,defaultValue: “200”, range: “1…500”, displayDuringSetup: false
    input name: “armedValue”, type: “number”, title: “Armed Value”, description: “Value When Armed”,defaultValue: “150”, range: “1…500”, displayDuringSetup: false
    input name: “sirenValue”, type: “number”, title: “Siren Value”, description: “Value When Siren is Active”,defaultValue: “100”, range: “1…500”, displayDuringSetup: false
    input name: “smokeValue”, type: “number”, title: “Smoke Value”, description: “Value When Smoke in Alarm”,defaultValue: “50”, range: “1…500”, displayDuringSetup: false
    input name: “marginValue”, type: “number”, title: “Margin of Error”, description: “+/- Margin 0f Error”, defaultValue: “5”, range: “1…50”, displayDuringSetup: false
  }

metadata {
definition (name: “MIMOlite Alarm Control and Monitor”, namespace: “mignlou”, author: “mignlou”) {
capability “Polling”
capability “Refresh”
capability “Momentary”
capability “Configuration”
capability “Contact Sensor”
capability “Smoke Detector”
capability “Motion Sensor”
attribute “powerSupply”, “string”
attribute “inputValue”, “number”
attribute “armedValue”, “number”
attribute “sirenValue”, “number”
attribute “disarmedValue”, “number”
attribute “sensorValue”, “number”
command “setPosition”

    fingerprint deviceId:"0x1000", inClusters:"0x72, 0x86, 0x71, 0x30, 0x31, 0x35, 0x70, 0x85, 0x25"
}
// UI tile definitions
tiles(scale:2) {
    multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
        tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
            attributeState "open", label: "Disarmed", action: "push", icon: "st.Home.home2", backgroundColor: "#ffa81e", nextState:"closing"
            attributeState "opening", label: "Disarming", action: "push", icon: "st.Home.home3", backgroundColor: "#ffffff", nextState:"closing"
            attributeState "closed", label: "Armed", action: "push", icon: "st.Home.home3", backgroundColor: "#79b821", nextState:"opening"
            attributeState "closing", label: "Arming", action: "push", icon: "st.Home.home2", backgroundColor: "#ffffff", nextState:"opening"
            attributeState "Alarm", label: "ALARM", action: "push", icon: "st.alarm.alarm.alarm", backgroundColor: "#bc2323", nextState:"opening"
            attributeState "Smoke", label: "SMOKE", action: "push", icon: "st.alarm.smoke.smoke", backgroundColor: "#bc2323", nextState:"opening"
            attributeState "unknown", label: "Unknown", action: "push", icon: "st.alarm.alarm.alarm", backgroundColor: "#ffffff", nextState:"opening"
        }
        tileAttribute ("powerSupply", key: "SECONDARY_CONTROL") {
            attributeState "good", label: "Power Good"
            attributeState "powerOutOpen", label: "Power Out - Disarmed"
            attributeState "powerOutClosed", label: "Power Out - Armed"
        }
    }
  standardTile ("refresh", "refresh", decoration: "flat", width: 2, height: 2) {
        state "refresh", label: '', action: 'refresh', icon: "st.secondary.refresh"
    }
    
    valueTile ("inputValue", "device.inputValue", width: 4, height: 2) {
        state "inputValue", label: 'Current Input Value of MIMOlite  (${currentValue})'
    }
    main ("contact")
    details("contact", "refresh", "inputValue")
}

}

def parse(String description) {
def result = null
// supported classes
// 0x20 - BasicSet used to report when the sensor trigger level changes
// 0x25 - switch binary V1
// 0x30 - sensor binary V1
// 0x31 - sensor multilevel V1
// 0x35 - meter pulse (not tested)
// 0x70 - configuration V1
// 0x71 - alarm V1 (for supply voltage monitor, does not seem to respond to AlarmGet)
// 0x72 - manufacturer specific V1
// 0x85 - association V1
// 0x86 - version V1

def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x86: 1, 0x30: 1, 0x31: 1, 0x72: 1, 0x71: 1])
if (cmd) {
    result = createEvent(zwaveEvent(cmd))
    if (result) {
        log.debug "Parsed command: ${result?.descriptionText} raw: ${description}"
    } else {
     //MC   log.debug "Unhandled command: ${description}"
    }
} else {
    log.debug "Unparsed command: ${description}"
}
return result

}

def getSensitivity() {
return 0x1
}

def getPotOpen() {
def rc = device.currentValue(“doorPositionOpen”)
if (rc == null) {
sendEvent(name: “doorPositionOpen”, value: 168)
return 168
}
return rc

}

def getPotClosed() {// def rc = device.currentValue(“doorPositionClosed”)
def rc = device.currentValue (“doorPositionClosed”)
if (rc == null) {
sendEvent(name: “doorPositionClosed”, value: 0)
return 0
}
return rc

}

def getSiren() {// def rc = device.currentValue(“sirenPositionAlarm”)
def rc = device.currentValue (“sirenPositionAlarm”)
if (rc == null) {
sendEvent(name: “sirenPositionAlarm”, value: 200)
return 200
}
return rc

}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
// trigger fires, request the door position so we can see what state it is in
poll().collect { sendHubCommand(new physicalgraph.device.HubAction(it)) }
return null
}

def zwaveEvent(physicalgraph.zwave.commands.alarmv1.AlarmReport cmd) {
if (cmd.alarmLevel) {
if (device.currentValue(“contact”) == “closed”) {
sendEvent(name: “powerSupply”, value: “powerOutClosed”)
} else {
sendEvent(name: “powerSupply”, value: “powerOutOpen”)
}
return [name: “contact”, value: “unknown”]
}
return null
}

def convertSensorValueToDoorState( BigDecimal sensorValue ) {

  sendEvent (name: "smoke", value: "clear")
  sendEvent (name: "motion", value: "inactive")
  if (sensorValue <= smokeValue + marginValue && sensorValue >= smokeValue - marginValue){
  	sendEvent (name: "contact", value: "Smoke")
  	sendEvent (name: "smoke", value: "detected")
        log.debug "SMOKE DETECTED!"
  }
  else if (sensorValue <= sirenValue + marginValue && sensorValue >= sirenValue - marginValue){
  	sendEvent (name: "contact", value: "Alarm")
  	sendEvent (name: "motion", value: "active")
        log.debug "ALARM IS ACTIVE!"
  } 
  else if (sensorValue <= armedValue + marginValue && sensorValue >= armedValue - marginValue){
  	sendEvent (name: "contact", value: "closed")
        log.debug "System Armed"
  } 
    else if (sensorValue <= disarmedValue + marginValue && sensorValue >= disarmedValue - marginValue){
  	sendEvent (name: "contact", value: "open")
        log.debug "System Disarmed"
  } 
  else {
  	sendEvent (name: "contact", value: "unknown")
  }
  
  log.debug "MIMO Input Value ${sensorValue}"
  
return device.currentValue('contact')

}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd) {
// if we are in a power fail state this is the first message we’ll get after the power comes back
// so update the powerState
if (device.currentValue(‘powerSupply’) != “good”) {
sendEvent(name: “powerSupply”, value: “good”)
}

def adjustedValue = cmd.scaledSensorValue.intValue() >> 4
if (adjustedValue != device.currentValue('inputValue')) {
    def doorState = convertSensorValueToDoorState( adjustedValue )
    sendEvent(name: "inputValue", value: adjustedValue)
    if (device.currentValue('contact') != doorState) {     
        return [name: "contact", value: doorState]
    }
}
return null

}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren’t interested in
return null
}

def setPosition() {
sendEvent(name: “doorPositionOpen”, value: settings.disarmedValue)
sendEvent(name: “doorPositionClosed”, value: settings.armedValue)
sendEvent(name: “sirenPositionAlarm”, value: settings.sirenValue)
setTriggerLevels().collect { sendHubCommand(new physicalgraph.device.HubAction(it)) }
}

def open() {
if (device.currentValue(“contact”) == “closed”) {
push()
}
}

def close() {
if (device.currentValue(“contact”) == “open”) {
push()
}
}

def push() {
def cmds = delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xff).format(),
],500)
return cmds
}

def poll() {
delayBetween([
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
],500)
}

def refresh() {
delayBetween([
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
],500)
}

def updated() {
// called when the device is updated
configure()
}

def installed() {
// called when the device is installed
configure()
}

def setTriggerLevels() {
def openVal = getPotOpen()
def closedVal = getPotClosed()
def sirenVal = getSiren()
def slop = getSensitivity()

// if the potentiometer is installed backwards reverse the parameters

//if (openVal < closedVal) {
// def temp = closedVal
// closedVal = openVal
// openVal = temp
//}

def lowerValHigh = closedVal + (2 * slop)
def lowerValLow = closedVal + slop
def upperValHigh = openVal - slop
def upperValLow = openVal - (2 * slop)
  //Added sireValHigh and Low

// def sirenValHigh = openVal - slop
// def sirenValLow = openVal - (2 * slop)

delayBetween([
    // Lower Threshold, High (Default=0xBB)
    zwave.configurationV1.configurationSet(scaledConfigurationValue: lowerValHigh, parameterNumber: 4, size: 2).format(), 
    // Lower Threshold, Low (Default=0xAB)
    zwave.configurationV1.configurationSet(scaledConfigurationValue: lowerValLow, parameterNumber: 5, size: 2).format(), 
    // Upper Threshold, High (Default=0xFF)
    zwave.configurationV1.configurationSet(scaledConfigurationValue: upperValHigh, parameterNumber: 6, size: 2).format(),
    // Upper Threshold, Low (Default = 0xFE)
    zwave.configurationV1.configurationSet(scaledConfigurationValue: upperValLow, parameterNumber: 7, size: 2).format(), 
],500)

}

def configure() {
log.debug “configure”
def cmds = delayBetween([
// enable analog alert thresholds
zwave.configurationV1.configurationSet(scaledConfigurationValue: 0, parameterNumber: 8, size: 2).format(),
// turn on momentary button press, this presses it for 1 second
zwave.configurationV1.configurationSet(scaledConfigurationValue: 10, parameterNumber: 11, size: 2).format(),
// tell device to send multivalue sensor updates every 10 seconds
zwave.configurationV1.configurationSet(scaledConfigurationValue: 1, parameterNumber: 9, size: 2).format(),
// enable alarms to be sent to smartthings hub
zwave.associationV1.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format(),
// enable multivalue sensor updates to be sent to smartthings hub
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format(),
],500)
cmds += setTriggerLevels()
return cmds
}

1 Like