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


#1

I’ve created a device handler for the MIMOlite to control my home alarm system and monitor Smoke, Alarm, Armed and Disarmed states. I have no experience coding but have managed to copy, paste, and manipulate the code to make it work for me. Most of the code is from Skyjunky MIMOlite Garage Door Sensor with Position Indicator. It works great with Smart Home monitor. If you decide to use the device handler, you do so at your own risk. Looking forward to seeing the code being improved and getting feedback. Good Luck!


#2

/**

  • 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
  • MIMOlite Garage Door Sensor with Position Indicator
  • Inspired by a similar handler written by https://community.smartthings.com/users/johnconstantelo
    */
    // 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
}


(Simon) #3

i like the way you used the resistors to create different voltage inputs.
What make of alarm panel is this?


#4

I’m using a Napco Gemini Alarm panel. Eventually I’d like to have full alarm integration to use all my existing zones. For right now this works great! Thanks for sharing your DTH!


(Cobra01car) #5

bigmig78, I have had my alarm panel connected this way for awhile. I just set up your device handler and I have a question… First off your device handler is awesome. Secondly, how do you have smart home monitor set up? It looks to me like under security its only looking at open or closed state? How do you setup the input values?


#6

Thanks for your positive feedback! The device handler is broken up into 3 parts

1 - Arm / Disarm State (open / close)
2 - Alarm Sounding siren ( motion )
3 - Fire alarm sounding ( smoke detector)

I have it added to SHM security as a motion sensor. I do get false alarms at times but haven’t figured out what is causing the values to change. Might be from my alarm panel. Hope that helps.


(Cobra01car) #7

Thanks for the reply. To correct the “values changing” issue I used 3 relays between the alarm panel and the mimolite. I still use the resistors to give the three values needed, but only use ground outputs from the panel to close the appropriate relay. The relays then close the sensor input terminals +/- so the values are always constant.

I used a four relay module form amazon. Around $9


(Disforw) #8

This project is extremely similar to what I did with my Honeywell Vista panel and a MIMOlite!
I love what you did with the resisters though