Compare commits

...

10 Commits

Author SHA1 Message Date
Fortrezz
40e26d1f36 MSA-2096: For use with sump pump z-wave module. Allows battery backup sump pump systems made by Glentronics, inc to send alert notifications through Z-wave to the SmartThings user. 2017-07-14 11:43:38 -07:00
Vinay Rao
5beae1d9fc Merge pull request #2150 from SmartThingsCommunity/staging
Rolling down staging to master
2017-07-07 16:06:50 -07:00
Jack Chi
07064eb8cc Merge pull request #2148 from natec007/MSA-2084-5
MSA-2084: Spruce Sensor DTH new model and health check
2017-07-07 12:14:09 -07:00
natec007
f519a2d828 Update spruce-sensor.groovy
Removed checkInterval attribute
sendEvent(name: "checkInterval" already in updated and installed
2017-07-06 14:27:33 -07:00
Nathan Cauffman
4da49283bf MSA-2084: Updated with new model number and health check 2017-07-06 13:22:12 -07:00
Bob Florian
7389edf795 Merge pull request #2140 from juano2310/lifx_not_null
ICP-507 - Replace location count null with 0
2017-07-06 08:29:58 -07:00
Brian Steere
23154372d2 Merge pull request #2141 from SmartThingsCommunity/every-element-update
Update Every Element with more accurate enum settings
2017-07-06 09:02:42 -05:00
juano2310
1b0437c633 ICP-507 - Replace location count null with 0
Updated with def count = options.size().toString()
2017-07-06 09:43:47 -04:00
Vinay Rao
f647be3a62 Merge pull request #2144 from SmartThingsCommunity/staging
Rolling down staging to master
2017-07-05 14:22:13 -07:00
Brian Steere
2536c69083 Update Every Element with more accurate enum settings
Added a couple of extra enum inputs to demonstrate additional states
2017-07-05 16:01:16 -05:00
4 changed files with 195 additions and 10 deletions

View File

@@ -0,0 +1,167 @@
/**
* Copyright 2015 SmartThings
*
* 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.
*
*/
metadata {
definition (name: "Sump Pump Controller", namespace: "fortrezz", author: "FortrezZ, LLC") {
capability "Sensor"
attribute "alarmState", "string"
attribute "powerAlert", "number"
attribute "sumpAlert", "number"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x5A,0x85,0x59,0x73,0x20,0x7A,0x71"
}
simulator {
status "replace battery now": "command: 7105, payload: 00 00 00 FF 08 0B 00 00"
status "battery fully charged": "command: 7105, payload: 00 00 00 FF 08 0D 00 00"
status "AC mains disconnected": "command: 7105, payload: 00 00 00 FF 08 02 00 00"
status "AC mains reconnected": "command: 7105, payload: 00 00 00 FF 08 03 00 00"
status "Excess Pumping": "command: 7105, payload: 00 00 00 FF 09 03 01 01 00"
status "Float Error": "command: 7105, payload: 00 00 00 FF 09 03 01 02 00"
status "General Error": "command: 7105, payload: 00 00 00 FF 09 01 00 00"
}
tiles (scale: 2){
multiAttributeTile(name:"alert", type: "lighting", width: 6, height: 4){
tileAttribute ("device.alarm", key: "PRIMARY_CONTROL") {
attributeState("clear", label:"clear", icon:"http://swiftlet.technology/wp-content/uploads/2016/04/Ok-96.png", backgroundColor:"#ffffff")
attributeState("alert", label:"Alert!", icon:"http://swiftlet.technology/wp-content/uploads/2016/04/Error-96.png", backgroundColor:"#ff5b5b")
}
}
main "alert"
details(["alert"])
}
}
def parse(String description) {
def results = []
if (description.startsWith("Err")) {
results << createEvent(descriptionText:description, displayed:true)
} else {
def cmd = zwave.parse(description, [ 0x80: 1, 0x84: 1, 0x71: 2, 0x72: 1 ])
if (cmd) {
zwaveEvent(cmd, results)
}
}
log.debug "\"$description\" parsed to ${results.inspect()}"
return results
}
// Notification Report from SPM
def zwaveEvent(physicalgraph.zwave.commands.alarmv2.AlarmReport cmd, results) {
def powerAlert = device.currentValue("powerAlert")
if (powerAlert == null)
{
powerAlert = 0
}
def sumpAlert = device.currentValue("sumpAlert")
if (sumpAlert == null)
{
sumpAlert = 0
}
if (cmd.zwaveAlarmType == 8) {
if (cmd.zwaveAlarmEvent == 2) {
results << createEvent(name: "alarmState", value: "acMainsDisconnected", descriptionText: "AC Mains Disconnected")
powerAlert = powerAlert + 1
} else if (cmd.zwaveAlarmEvent == 3) {
results << createEvent(name: "alarmState", value: "acMainsReconnected", descriptionText: "AC Mains Reconnected")
powerAlert = powerAlert - 1
} else if (cmd.zwaveAlarmEvent == 11) {
results << createEvent(name: "alarmState", value: "replaceBatteryNow", descriptionText: "Replace AA batteries in Z-wave module")
powerAlert = powerAlert + 1
} else if (cmd.zwaveAlarmEvent == 13) {
results << createEvent(name: "alarmState", value: "batteryFullyCharged", descriptionText: "AA Batteries Replaced")
powerAlert = powerAlert - 1
}
if (powerAlert < 0)
{
powerAlert = 0
}
} else if (cmd.zwaveAlarmType == 9) {
if (cmd.zwaveAlarmEvent == 1) {
results << createEvent(name: "alarmState", value: "systemHardwareFailure", descriptionText: "Sump Pump Error, refer to Sump Pump Controller Unit")
sumpAlert = sumpAlert + 1
} else if (cmd.zwaveAlarmEvent == 3) {
if (cmd.eventParameter[0] == 0) {
results << createEvent(name: "alarmState", value: "alarmClear", descriptionText: "Alarm has been cleared")
sumpAlert = 0
} else if (cmd.eventParameter[0] == 1) {
results << createEvent(name: "alarmState", value: "floatError", descriptionText: "Pump or float problem")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 2) {
results << createEvent(name: "alarmState", value: "backupPumpActivated", descriptionText: "Backup pump was activated")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 3) {
results << createEvent(name: "alarmState", value: "highWater", descriptionText: "High water alarm")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 4) {
results << createEvent(name: "alarmState", value: "addWater", descriptionText: "Add distilled water to the battery")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 5) {
results << createEvent(name: "alarmState", value: "backupPumpError", descriptionText: "Backup pump is defective or not connected")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 6) {
results << createEvent(name: "alarmState", value: "9VBatteryLow", descriptionText: "9 volt battery is low or slide switch is OFF")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 7) {
results << createEvent(name: "alarmState", value: "12VBatteryError", descriptionText: "Problem with backup sump pump battery")
sumpAlert = sumpAlert + 1
} else if (cmd.eventParameter[0] == 8) {
results << createEvent(name: "alarmState", value: "checkCable", descriptionText: "Check your cable connection (to Z-wave module)")
sumpAlert = sumpAlert + 1
}
}
if (sumpAlert < 0)
{
sumpAlert = 0
}
}
if ((sumpAlert > 0) || (powerAlert > 0))
{
sendEvent(name: "alarm", value: "alert", displayed: false)
}
else
{
sendEvent(name: "alarm", value: "clear", displayed: false)
}
results
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd, results) {
results << new physicalgraph.device.HubAction(zwave.wakeUpV1.wakeUpNoMoreInformation().format())
results << createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd, results) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "$device.displayName battery is low!"
} else {
map.value = cmd.batteryLevel
}
results << createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.Command cmd, results) {
def event = [ displayed: false ]
event.linkText = device.label ?: device.name
event.descriptionText = "$event.linkText: $cmd"
results << createEvent(event)
}

View File

@@ -1,5 +1,5 @@
/**
* Spruce Sensor -Pre-release V2 10/8/2015
* Spruce Sensor -updated with SLP model number 5/2017
*
* Copyright 2014 Plaid Systems
*
@@ -14,25 +14,33 @@
*
-------10/20/2015 Updates--------
-Fix/add battery reporting interval to update
-remove polling and/or refresh(?)
-remove polling and/or refresh
-------5/2017 Updates--------
-Add fingerprints for SLP
-add device health, check every 60mins + 2mins
*/
metadata {
definition (name: "Spruce Sensor", namespace: "plaidsystems", author: "NCauffman") {
definition (name: "Spruce Sensor", namespace: "plaidsystems", author: "Plaid Systems") {
capability "Configuration"
capability "Battery"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"
capability "Sensor"
capability "Health Check"
//capability "Polling"
attribute "maxHum", "string"
attribute "minHum", "string"
command "resetHumidity"
command "refresh"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0402,0405", outClusters: "0003, 0019", manufacturer: "PLAID SYSTEMS", model: "PS-SPRZMS-01"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0402,0405", outClusters: "0003, 0019", manufacturer: "PLAID SYSTEMS", model: "PS-SPRZMS-01", deviceJoinName: "Spruce Sensor"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0402,0405", outClusters: "0003, 0019", manufacturer: "PLAID SYSTEMS", model: "PS-SPRZMS-SLP1", deviceJoinName: "Spruce Sensor"
}
preferences {
@@ -293,6 +301,11 @@ def setConfig(){
sendEvent(name: 'configuration',value: configInterval, descriptionText: "Configuration initialized")
}
def installed(){
//check every 1 hour + 2mins
sendEvent(name: "checkInterval", value: 1 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
//when device preferences are changed
def updated(){
log.debug "device updated"
@@ -303,6 +316,8 @@ def updated(){
sendEvent(name: 'configuration',value: 0, descriptionText: "Settings changed and will update at next report. Measure interval set to ${interval} mins")
}
}
//check every 1 hour + 2mins
sendEvent(name: "checkInterval", value: 1 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
//poll
@@ -395,4 +410,4 @@ private byte[] reverseArray(byte[] array) {
i++;
}
return array
}
}

View File

@@ -202,7 +202,8 @@ def inputSelectionPage() {
section("options variations") {
paragraph "tap these elements and look at the differences when selecting an option"
input(type: "enum", name: "selectionSimple", title: "Simple options", description: "no separators in the selectable options", groupedOptions: addGroup(englishOptions + spanishOptions))
input(type: "enum", name: "selectionSimple", title: "Simple options", description: "no separators in the selectable options", options: ["Thing 1", "Thing 2", "(Complicated) Thing 3"])
input(type: "enum", name: "selectionSimpleGrouped", title: "Simple (Grouped) options", description: "no separators in the selectable options", groupedOptions: addGroup(englishOptions + spanishOptions))
input(type: "enum", name: "selectionGrouped", title: "Grouped options", description: "separate groups of options with headers", groupedOptions: groupedOptions)
}
@@ -214,15 +215,15 @@ def inputSelectionPage() {
section("segmented") {
paragraph "segmented should only work if there are either 2 or 3 options to choose from"
input(type: "enum", name: "selectionSegmented1", style: "segmented", title: "1 option", groupedOptions: addGroup(["One"]))
input(type: "enum", name: "selectionSegmented4", style: "segmented", title: "4 options", groupedOptions: addGroup(["One", "Two", "Three", "Four"]))
input(type: "enum", name: "selectionSegmented1", style: "segmented", title: "1 option", options: ["One"])
input(type: "enum", name: "selectionSegmented4", style: "segmented", title: "4 options", options: ["One", "Two", "Three", "Four"])
paragraph "multiple and required will have no effect on segmented selection elements. There will always be exactly 1 option selected"
input(type: "enum", name: "selectionSegmented2", style: "segmented", title: "2 options", options: ["One", "Two"])
input(type: "enum", name: "selectionSegmented3", style: "segmented", title: "3 options", options: ["One", "Two", "Three"])
paragraph "specifying defaultValue still works with segmented selection elements"
input(type: "enum", name: "selectionSegmentedWithDefault", title: "defaulted to 'two'", groupedOptions: addGroup(["One", "Two", "Three"]), defaultValue: "Two")
input(type: "enum", name: "selectionSegmentedWithDefault", style: "segmented", title: "defaulted to 'two'", options: ["One", "Two", "Three"], defaultValue: "Two")
}
section("required: true") {
@@ -231,6 +232,8 @@ def inputSelectionPage() {
section("multiple: true") {
input(type: "enum", name: "selectionMultiple", title: "This allows multiple selections", description: "It should look different when nothing is selected", groupedOptions: addGroup(["an option", "another option", "no way, one more?"]), multiple: true)
input(type: "enum", name: "selectionMultipleDefault1", title: "This allows multiple selections with a single default", description: "It should look different when nothing is selected", groupedOptions: addGroup(["an option", "another option", "no way, one more?"]), multiple: true, defaultValue: "an option")
input(type: "enum", name: "selectionMultipleDefault2", title: "This allows multiple selections with multiple defaults", description: "It should look different when nothing is selected", groupedOptions: addGroup(["an option", "another option", "no way, one more?"]), multiple: true, defaultValue: ["an option", "another option"])
}
section("with image") {

View File

@@ -72,7 +72,7 @@ def authPage() {
log.debug "have LIFX access token"
def options = locationOptions() ?: []
def count = options.size()
def count = options.size().toString()
return dynamicPage(name:"Credentials", title:"", nextPage:"", install:true, uninstall: true) {
section("Select your location") {