Skip to content

Commit

Permalink
Merge pull request SmartThingsCommunity#47254 from SmartThingsCommuni…
Browse files Browse the repository at this point in the history
…ty/acceptance

Rolling up acceptance to production for deploy
  • Loading branch information
greens authored Oct 13, 2020
2 parents 95c3507 + 21c8078 commit 34115e1
Show file tree
Hide file tree
Showing 14 changed files with 1,988 additions and 452 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

148 changes: 132 additions & 16 deletions devicetypes/iblinds/iblinds-zwave.src/iblinds-zwave.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ import groovy.json.JsonOutput

metadata {
definition (name: "iblinds Z-Wave", namespace: "iblinds", author: "HABHomeIntel", ocfDeviceType: "oic.d.blind", mnmn: "SmartThings", vid: "generic-shade-3") {
capability "Window Shade"
capability "Window Shade Preset"
capability "Switch Level"
capability "Switch"
capability "Battery"
capability "Refresh"
capability "Actuator"
capability "Health Check"
capability "Window Shade"
capability "Window Shade Preset"

command "stop"

Expand Down Expand Up @@ -75,8 +74,20 @@ metadata {
}

preferences {
// V3 configuration
input title: "V3 iBlinds Device Config", description: "Configuration options for newer V3 iBlinds devices", type: "paragraph", element: "paragraph", displayDuringSetup: false
input name: "NVM_TightLevel", type: "number", title: "Close Interval", defaultValue: 22, description: "Used for Large and Heavy blinds to set the close interval. A smaller value will make the blinds close tighter", required: true, displayDuringSetup: true
input name: "NVM_Direction", type: "bool", title: "Reverse", description: "Reverse Blind Direction", defaultValue: false
input name: "NVM_Target_Value", type: "number", title: "Default ON Value", defaultValue: 50, range: "1..100", description: "Used to set the default ON level when manual push button is pushed", required: true, displayDuringSetup:false
input name: "NVM_Device_Reset_Support", type: "bool", title: "Disable Reset Button", description: "Used for situations where the top motor buttons are being pushed accidentally via a tight installation space, etc.", defaultValue: false
input name: "Speed_Parameter", type: "number", title: "Open/Close Speed (seconds)", defaultValue: 0, range:"0..100", description: "To slow down the blinds, increase the value", required: true, displayDuringSetup: false

input title: "", description: "", type: "paragraph", element: "paragraph", displayDuringSetup: false

// V2 configuration
input title: "V2 iBlinds Device Config", description: "Configuration options for older V2 iBlinds devices", type: "paragraph", element: "paragraph", displayDuringSetup: false
input "preset", "number", title: "Preset position", description: "Set the window shade preset position", defaultValue: 50, range: "1..99", required: false, displayDuringSetup: false
input "reverse", "bool", title: "Reverse", description: "Reverse Blind Direction",defaultValue: false, required: false , displayDuringSetup: false
input "reverse", "bool", title: "Reverse", description: "Reverse Blind Direction", defaultValue: false, required: false , displayDuringSetup: false
}

main(["windowShade"])
Expand All @@ -89,10 +100,12 @@ def parse(String description) {
//if (description =~ /command: 2603, payload: ([0-9A-Fa-f]{6})/)
// TODO: Workaround manual parsing of v4 multilevel report
def cmd = zwave.parse(description, [0x20: 1, 0x26: 3]) // TODO: switch to SwitchMultilevel v4 and use target value

if (cmd) {
result = zwaveEvent(cmd)
}
log.debug "Parsed '$description' to ${result.inspect()}"
log.debug "Parsed '$description' to ${result?.inspect()}"

return result
}

Expand All @@ -105,16 +118,40 @@ def getCheckInterval() {
def installed() {
sendEvent(name: "checkInterval", value: checkInterval, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
sendEvent(name: "supportedWindowShadeCommands", value: JsonOutput.toJson(["open", "close"]), displayed: false)
response(refresh())

storeParamState()

response(initialize() + refresh())
}

def updated() {
def cmds = []

if (device.latestValue("checkInterval") != checkInterval) {
sendEvent(name: "checkInterval", value: checkInterval, displayed: false)
}
if (!device.latestState("battery")) {
response(zwave.batteryV1.batteryGet())

cmds += configureParams()
storeParamState()
cmds += initialize()

response(cmds)
}

def initialize() {
def cmds = []

if (isV3Device()) {
// Set up lifeline association
cmds << zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId).format()
}

// Schedule daily battery check
unschedule()
runIn(15, getBattery)
schedule("2020-01-01T12:01:00.000-0600", getBattery)

cmds
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
Expand All @@ -131,6 +168,7 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelR

private handleLevelReport(physicalgraph.zwave.Command cmd) {
def level = cmd.value as Integer
def result = []

log.debug "handleLevelReport($level)"

Expand Down Expand Up @@ -166,19 +204,22 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
}

def open() {
Integer level = isV3Device() ? (NVM_Target_Value ?: 50) : 50 // Blinds fully open at 50%, NVM_Target_Value can't be 0%
log.debug "open()"
// Blinds fully open at 50%

sendEvent(name: "windowShade", value: "open")
sendEvent(name: "level", value: 50, unit: "%", displayed: true)
zwave.switchMultilevelV3.switchMultilevelSet(value: 50).format()
sendEvent(name: "level", value: level, unit: "%", displayed: true)

zwave.switchMultilevelV3.switchMultilevelSet(value: level).format()
}

def close() {
log.debug "close()"
Integer level = reverse ? 99 : 0
Integer level = isV3Device() ? 0 : (reverse ? 99 : 0)

sendEvent(name: "windowShade", value: "closed")
sendEvent(name: "level", value: 0, unit: "%", displayed: true)

zwave.switchMultilevelV3.switchMultilevelSet(value: level).format()
}

Expand All @@ -192,8 +233,8 @@ def setLevel(value, duration = null) {
if (level > 99) level = 99
Integer tiltLevel = level as Integer // we will use this value to decide what level is sent to device (reverse or not reversed)

// Check to see if user wants blinds to operate in reverse direction
if (reverse) {
// For older devices, check to see if user wants blinds to operate in reverse direction
if (!isV3Device() && reverse) {
tiltLevel = 99 - level
}

Expand All @@ -211,11 +252,10 @@ def setLevel(value, duration = null) {
//log.debug "Level - ${level}% & Tilt Level - ${tiltLevel}%"
sendEvent(name: "level", value: level, descriptionText: descriptionText)
zwave.switchMultilevelV3.switchMultilevelSet(value: tiltLevel).format()

}

def presetPosition() {
setLevel(preset ?: state.preset ?: 50)
isV3Device() ? open() : setLevel(preset ?: 50)
}

def pause() {
Expand All @@ -239,3 +279,79 @@ def refresh() {
zwave.batteryV1.batteryGet().format()
], 1500)
}

def configureParams() {
def cmds = []

if (isV3Device()) {
/*
Parameter No. Size Parameter Name Desc.
1 1 NVM_TightLevel Auto Calibration tightness
2 1 NVM_Direction Reverse the direction of iblinds
3 1 NVM_Target_Report Not used ****
4 1 NVM_Target_Value Default on position
5 1 NVM_Device_Reset_Support Turns off the reset button
6 1 Speed_Parameter Speed
*/

log.debug "Configuration Started"

// If paramater value has changed then add zwave configration command to cmds

if (NVM_TightLevel != null && state.param1 != NVM_TightLevel) {
cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, configurationValue: [NVM_TightLevel.toInteger()]).format()
}
if (NVM_Direction != null && state.param2 != NVM_Direction) {
def NVM_Direction_Val = boolToInteger(NVM_Direction)

cmds << zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, configurationValue: [NVM_Direction_Val.toInteger()]).format()
}
if (state.param3 != 0) {
cmds << zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, configurationValue: [0]).format()
}
if (NVM_Target_Value != null && state.param4 != NVM_Target_Value) {
cmds << zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, configurationValue: [NVM_Target_Value.toInteger()]).format()
}
if (NVM_Device_Reset_Support != null && state.param5 != NVM_Device_Reset_Support) {
def NVM_Device_Reset_Val = boolToInteger(NVM_Device_Reset_Support)

cmds << zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, configurationValue: [NVM_Device_Reset_Val.toInteger()]).format()
}
if (Speed_Parameter != null && state.param6 != Speed_Parameter) {
cmds << zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, configurationValue: [Speed_Parameter.toInteger()]).format()
}

log.debug "Configuration Complete"
}

delayBetween(cmds, 500)
}

private storeParamState() {
if (isV3Device()) {
log.debug "Storing Paramater Values"

state.param1 = NVM_TightLevel
state.param2 = NVM_Direction
state.param3 = 0 // Not used at the moment
state.param4 = NVM_Target_Value
state.param5 = NVM_Device_Reset_Support
state.param6 = Speed_Parameter
}
}

def boolToInteger(boolValue) {
boolValue ? 1 : 0
}

def getBattery() {
log.debug "get battery level"
// Use sendHubCommand to get battery level
def cmd = []
cmd << new physicalgraph.device.HubAction(zwave.batteryV1.batteryGet().format())
sendHubCommand(cmd)
}

def isV3Device() {
zwaveInfo.mfr == "0287" && zwaveInfo.prod == "0004" && zwaveInfo.model == "0071"
}
Loading

0 comments on commit 34115e1

Please sign in to comment.