Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New support - Bali/Zwave via Blinds.com #1

Open
hypyke opened this issue Mar 31, 2017 · 11 comments
Open

New support - Bali/Zwave via Blinds.com #1

hypyke opened this issue Mar 31, 2017 · 11 comments

Comments

@hypyke
Copy link

hypyke commented Mar 31, 2017

I have confirmed this works with the Somfy via Bali zwave shades I just purchased via blinds.com

You might want to add support as they are not currently autodetected.

zw:F type:1107 mfr:026E prod:4353 model:5A31 ver:11.02 zwv:4.33 lib:03 cc:5E,26,85,59,72,86,5A,73,25,7A,80 role:07 ff:9A00 ui:9A00

If you need more info let me know

@ericvitale
Copy link
Owner

Thanks, just updated it. I hope that works.

@nmelanson75
Copy link

I the pluggin with Somfy via Bali Zwave shades but having an issue with Homebridge. The pluggin communicates in Homebridge but does not return status instead I get the circling of death for status. If I use the build in Spring Fashions code below it works perfect but the device is detected as a light for the icon instead of a blind. Any chance any of you can help? Here is the built in one that works and returns status properly but shows as a Dimmer at the bottom and here is the live logging error I see.

cf132972-5e28-440f-a03c-7c32f5f36b0f 10:58:37 AM: info postEventToEndpoint: event successfully posted.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:58:37 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:58:37 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:58:37 AM: debug Property Change Event level: 27 (source: DEVICE)
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:37 AM: debug Sending Update to 192.168.75.79:8000
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:37 AM: debug Sending Update to 192.168.75.79:8000
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:58:37 AM: debug Parsed 'zw device: 02, command: 2603, payload: 1B 1B 00 ' to [['name':'windowShade', 'value':'partially open', 'descriptionText':Living Room Shade shade is 27% open, 'isStateChange':true, 'displayed':true, 'linkText':'Living Room Shade'], ['name':'level', 'value':27, 'unit':'%', 'displayed':false, 'isStateChange':true, 'linkText':'Living Room Shade', 'descriptionText':Living Room Shade level is 27%]]
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:37 AM: debug Sending Update to 192.168.75.79:8000
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:58:37 AM: debug Parsed 'zw device: 02, command: 8003, payload: 44 2B C7 FF FF FE B5 00 00 5B 25 00 00 41 FD 00 00 2C ED AA 1B C0 00 00 ' to ['name':'battery', 'unit':'%', 'value':68, 'isStateChange':true, 'displayed':true, 'linkText':'Living Room Shade', 'descriptionText':Living Room Shade battery is 68%]
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:30 AM: info Command Successful for Device Living Room Shade, Command setLevel
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:30 AM: info Command Request
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:58:30 AM: debug setLevel(27)
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:58:30 AM: info Command Successful for Device Living Room Shade, Command setLevel

/**

  • Copyright 2017 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: "Springs Window Fashions Shade", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.blind") {
capability "Window Shade"
capability "Battery"
capability "Refresh"
capability "Health Check"
capability "Actuator"
capability "Sensor"

    command "stop"

    capability "Switch Level"   // until we get a Window Shade Level capability

    // This device handler is specifically for SWF window coverings
    //

// fingerprint type: "0x1107", cc: "0x5E,0x26", deviceJoinName: "Window Shade"
// fingerprint type: "0x9A00", cc: "0x5E,0x26", deviceJoinName: "Window Shade"
fingerprint mfr:"026E", prod:"4353", model:"5A31", deviceJoinName: "Window Shade"
fingerprint mfr:"026E", prod:"5253", model:"5A31", deviceJoinName: "Roller Shade"
}

simulator {
    status "open":  "command: 2603, payload: FF"
    status "closed": "command: 2603, payload: 00"
    status "10%": "command: 2603, payload: 0A"
    status "66%": "command: 2603, payload: 42"
    status "99%": "command: 2603, payload: 63"
    status "battery 100%": "command: 8003, payload: 64"
    status "battery low": "command: 8003, payload: FF"

    // reply messages
    reply "2001FF,delay 1000,2602": "command: 2603, payload: 10 FF FE"
    reply "200100,delay 1000,2602": "command: 2603, payload: 60 00 FE"
    reply "200142,delay 1000,2602": "command: 2603, payload: 10 42 FE"
    reply "200163,delay 1000,2602": "command: 2603, payload: 10 63 FE"
}

tiles(scale: 2) {
    multiAttributeTile(name:"windowShade", type: "generic", width: 6, height: 4){
        tileAttribute ("device.windowShade", key: "PRIMARY_CONTROL") {
            attributeState "open", label:'${name}', action:"close", icon:"st.shades.shade-open", backgroundColor:"#79b821", nextState:"closing"
            attributeState "closed", label:'${name}', action:"open", icon:"st.shades.shade-closed", backgroundColor:"#ffffff", nextState:"opening"
            attributeState "partially open", label:'Open', action:"close", icon:"st.shades.shade-open", backgroundColor:"#79b821", nextState:"closing"
            attributeState "opening", label:'${name}', action:"stop", icon:"st.shades.shade-opening", backgroundColor:"#79b821", nextState:"partially open"
            attributeState "closing", label:'${name}', action:"stop", icon:"st.shades.shade-closing", backgroundColor:"#ffffff", nextState:"partially open"
        }
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
            attributeState "level", action:"setLevel"
        }
    }

    standardTile("home", "device.level", width: 2, height: 2, decoration: "flat") {
        state "default", label: "home", action:"presetPosition", icon:"st.Home.home2"
    }

    standardTile("refresh", "device.refresh", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh", nextState: "disabled"
        state "disabled", label:'', action:"", icon:"st.secondary.refresh"
    }

    valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
        state "battery", label:'batt.', unit:"",
                backgroundColors:[
                        [value: 0, color: "#bc2323"],
                        [value: 6, color: "#44b621"]
                ]
    }

    preferences {
        input "switchDirection", "bool", title: "Flip the orientation of the shade", defaultValue: false, required: false, displayDuringSetup: false

// input "preset", "number", title: "Default half-open position (1-100). Springs Window Fashions users should consult their manuals.", defaultValue: 50, required: false, displayDuringSetup: false
}

    main(["windowShade"])
    details(["windowShade", "home", "refresh", "battery"])

}

}

def parse(String description) {
def result = null
//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()}"
return result
}

def getCheckInterval() {
// These are battery-powered devices, and it's not very critical
// to know whether they're online or not – 12 hrs
4 * 60 * 60
}

def installed() {
sendEvent(name: "checkInterval", value: checkInterval, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
response(refresh())
}

def updated() {
if (device.latestValue("checkInterval") != checkInterval) {
sendEvent(name: "checkInterval", value: checkInterval, displayed: false)
}
def cmds = []
if (!device.latestState("battery")) {
cmds << zwave.batteryV1.batteryGet().format()
}

if (!device.getDataValue("MSR")) {
    cmds << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
}

log.debug("Updated with settings $settings")
cmds << zwave.switchMultilevelV1.switchMultilevelGet().format()
response(cmds)

}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
handleLevelReport(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
handleLevelReport(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
handleLevelReport(cmd)
}

private handleLevelReport(physicalgraph.zwave.Command cmd) {
def descriptionText = null
def shadeValue = null

def level = cmd.value as Integer
level = switchDirection ? 99-level : level
if (level >= 99) {
    level = 100
    shadeValue = "open"
} else if (level <= 0) {
    level = 0  // unlike dimmer switches, the level isn't saved when closed
    shadeValue = "closed"
} else {
    shadeValue = "partially open"
    descriptionText = "${device.displayName} shade is ${level}% open"
}
def levelEvent = createEvent(name: "level", value: level, unit: "%", displayed: false)
def stateEvent = createEvent(name: "windowShade", value: shadeValue, descriptionText: descriptionText, isStateChange: levelEvent.isStateChange)

def result = [stateEvent, levelEvent]
if (!state.lastbatt || now() - state.lastbatt > 24 * 60 * 60 * 1000) {
    log.debug "requesting battery"
    state.lastbatt = (now() - 23 * 60 * 60 * 1000) // don't queue up multiple battery reqs in a row
    result << response(["delay 15000", zwave.batteryV1.batteryGet().format()])
}
result

}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelStopLevelChange cmd) {
[ createEvent(name: "windowShade", value: "partially open", displayed: false, descriptionText: "$device.displayName shade stopped"),
response(zwave.switchMultilevelV1.switchMultilevelGet().format()) ]
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
updateDataValue("MSR", msr)
if (cmd.manufacturerName) {
updateDataValue("manufacturer", cmd.manufacturerName)
}
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF || cmd.batteryLevel == 0) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = now()
if (map.value <= 1 && device.latestValue("battery") - map.value > 20) {
// Springs shades sometimes erroneously report a low battery when rapidly actuated manually. They'll still
// refuse to actuate after one of these reports, but this will limit the bad data that gets surfaced
log.warn "Erroneous battery report dropped from ${device.latestValue("battery")} to $map.value. Not reporting"
} else {
createEvent(map)
}
}

def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
// the docs we got said that the device would send a notification report, but we've determined that
// is not true
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.debug "unhandled $cmd"
return []
}

def open() {
log.debug "open()"
def level = switchDirection ? 0 : 99
zwave.basicV1.basicSet(value: level).format()
// zwave.basicV1.basicSet(value: 0xFF).format()
}

def close() {
log.debug "close()"
def level = switchDirection ? 99 : 0
zwave.basicV1.basicSet(value: level).format()
//zwave.basicV1.basicSet(value: 0).format()
}

def setLevel(value, duration = null) {
log.debug "setLevel(${value.inspect()})"
Integer level = value as Integer
level = switchDirection ? 99-level : level
if (level < 0) level = 0
if (level > 99) level = 99
zwave.basicV1.basicSet(value: level).format()
}

def presetPosition() {
zwave.switchMultilevelV1.switchMultilevelSet(value: 0xFF).format()
}

def stop() {
log.debug "stop()"
zwave.switchMultilevelV3.switchMultilevelStopLevelChange().format()
}

def ping() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def refresh() {
log.debug "refresh()"
delayBetween([
zwave.switchMultilevelV1.switchMultilevelGet().format(),
zwave.batteryV1.batteryGet().format()
], 1500)
}

@ericvitale
Copy link
Owner

Any chance you can share the values for your blinds? You can find them in the IDE under the specific device.

Data | MSR: 026E-4353-5A31 manufacturer: null
Raw Description | zw:F type:1107 mfr:026E prod:4353 model:5A31 ver:11.00 zwv:4.33 lib:03 cc:5E,80,86,72,5A,73,85,59,20,26,25,7A role:07 ff:9A00 ui:9A00

@nmelanson75
Copy link

For sure, anything you need. I really appreciate the help.

Data | MSR: 026E-4353-5A31

Raw Description | zw:F type:1107 mfr:026E prod:4353 model:5A31 ver:11.02 zwv:4.33 lib:03 cc:5E,26,85,59,72,86,5A,73,25,7A,80 role:07 ff:9A00 ui:9A00

  • | --
    Current States | battery: 37 %level: 78 %checkInterval: 14400windowShade: partially open
    Preferences (edit) | NameTypeValueswitchDirectionboolfalse | switchDirection | bool | false

switchDirection | bool | false

@nmelanson75
Copy link

nmelanson75 commented Sep 21, 2018 via email

@ericvitale
Copy link
Owner

Can you try this branch? Do you know how to update from a branch that is not the master?

https://github.com/ericvitale/ST-Z-Wave-Shade/blob/dev-new-hardware-model-1/devicetypes/ericvitale/zwave-shade.src/zwave-shade.groovy

@nmelanson75
Copy link

I'm not a 100% do I just change it under the repository from master to something else?

Thanks again for all your help I really appreciate it.

@ericvitale
Copy link
Owner

Don't update via github integration. Just copy all the code from this page...

https://raw.githubusercontent.com/ericvitale/ST-Z-Wave-Shade/dev-new-hardware-model-1/devicetypes/ericvitale/zwave-shade.src/zwave-shade.groovy

and paste into the device handler code window of that device handler in the IDE.

@nmelanson75
Copy link

Good morning, sorry for the delay.

I am getting a error when trying to save
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script_dth_metadata_4acd8b7d_f752_4127_820d_4cf061563bea: 62: expecting '}', found ':' @ line 62, column 126.
3,0x7A,0x85,0x86," outClusters: "0x82",

Here is what I used copied from the site then to notepad++ before pasting to the IDE.

/**

  • Copyright 2016 [email protected]
  • Version 1.0.7 - Updated "on" indicator color to match ST blue (#00a0dc). 08/03/2018
  • Version 1.0.6 - Cleaned up a bit. 06/30/2017
  • Version 1.0.5 - Added auto-detect support for Somfy by Bali. 03/31/2017
  • Version 1.0.4 - Added support for the Window Shade capability. 10/15/2016
  • Version 1.0.3 - Tweaked configuration calling.
  • Version 1.0.2 - Added support for poll, fixed battery reporting bug.
  • Version 1.0.1 - Added support for battery level.
  • Version 1.0.0 - Initial Release
  • 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.
  • You can find this device handler @ https://github.com/ericvitale/ST-Z-Wave-Shade
  • You can find my other device handlers & SmartApps @ https://github.com/ericvitale
  • Credit to SmartThings for the following device handler
  • https://github.com/SmartThingsCommunity/SmartThingsPublic/blob/master/devicetypes/smartthings/zwave-dimmer-switch-generic.src/zwave-dimmer-switch-generic.groovy

*/

def dhVersion() { return "1.0.2" }

metadata {
definition (name: "Z-Wave Shade", namespace: "ericvitale", author: "[email protected]") {
capability "Switch Level"
capability "Actuator"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Battery"
capability "Configuration"
capability "Window Shade"

    command "sceneOne"
    command "sceneTwo"
    command "sceneThree"
    command "sceneFour"
    command "sceneFive"
    command "getBattery"
    command "doPoll"
    command "levelOpenClose"
    
    attribute "lastActivity", "string"
    attribute "lastConfigured", "string"
    attribute "lastPoll", "string"
    attribute "lastBattery", "string"

    fingerprint mfr: "026E", prod: "4345", model: "0038"
    fingerprint mfr: "026E", prod: "4345", model: "5A31"
    fingerprint deviceId: "0x1007", inClusters: "0x5E,0x80,0x25,0x70,0x72,0x59,0x85,0x73,0x7A,0x5A,0x86,0x20,0x26", outClusters: "0x82", deviceJoinName: "Z-Wave Shade"
    fingerprint deviceId: "0x1107", inClusters: "0x5E,0x80,0x25,0x70,0x72,0x59,0x85,0x73,0x7A,0x5A,0x86,0x20,0x26", outClusters: "0x82", deviceJoinName: "Z-Wave Shade" 
	fingerprint deviceId: "0x1107", inClusters: "0x20,0x26,0x80,0x25,0x59,0x5A,0x5E,0x70,0x72,0x73,0x7A,0x85,0x86," outClusters: "0x82", deviceJoinName: "Z-Wave Shade"
	fingerprint deviceId: "0x1107", inClusters: "0x26,0x80,0x25,0x59,0x5A,0x5E,0x72,0x73,0x7A,0x85,0x86," outClusters: "0x82", deviceJoinName: "Z-Wave Shade"
}

preferences {
    input "customLevel", "number", title: "Custom Level", required: true, defaultValue: 66, range: "0..100"
    input "logging", "enum", title: "Log Level", required: false, defaultValue: "INFO", options: ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]
}

tiles(scale: 2) {
	multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
		tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
			attributeState "on", label:'${name}', action:"switch.off", icon:"st.Home.home9", backgroundColor:"#00a0dc", nextState:"turningOff"
			attributeState "off", label:'${name}', action:"switch.on", icon:"st.Home.home9", backgroundColor:"#ffffff", nextState:"turningOn"
			attributeState "turningOn", label:'${name}', action:"switch.on", icon:"st.Home.home9", backgroundColor:"#00a0dc", nextState:"turningOff"
			attributeState "turningOff", label:'${name}', action:"switch.off", icon:"st.Home.home9", backgroundColor:"#ffffff", nextState:"turningOn"
		}
		
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
			attributeState "level", action:"switch level.setLevel"
		}
	}
	multiAttributeTile(name:"switchDetails", type: "lighting", width: 6, height: 4, canChangeIcon: true){
		tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
			attributeState "on", label:'${name}', action:"switch.off", icon:"st.Home.home9", backgroundColor:"#00a0dc", nextState:"turningOff"
			attributeState "off", label:'${name}', action:"switch.on", icon:"st.Home.home9", backgroundColor:"#ffffff", nextState:"turningOn"
			attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.Home.home9", backgroundColor:"#00a0dc", nextState:"turningOff"
			attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.Home.home9", backgroundColor:"#ffffff", nextState:"turningOn"
		}
        
        tileAttribute ("device.battery", key: "SECONDARY_CONTROL") {
			attributeState "default", label:'Battery: ${currentValue}%', action: "refresh.refresh"
		}
	}

	standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
		state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
	}
    
    valueTile("ShadeLevel", "device.level", width: 2, height: 1) {
    	state "level", label: 'Shade is ${currentValue}% up'
    }
    
    controlTile("levelSliderControl", "device.level", "slider", width: 4, height: 1) {
    	state "level", action:"switch level.setLevel"
    }
    
    standardTile("sceneOne", "device.sceneOne", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:'${currentValue}%', action:"sceneOne", icon: "st.Weather.weather14"
	}
    
    standardTile("sceneTwo", "device.sceneTwo", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:"20%", action:"sceneTwo", icon: "st.Weather.weather14"
	}
    
    standardTile("sceneThree", "device.sceneThree", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:"40%", action:"sceneThree", icon: "st.Weather.weather14"
	}
    
    standardTile("sceneFour", "device.sceneFour", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:"60%", action:"sceneFour", icon: "st.Weather.weather14"
	}
    
    standardTile("sceneFive", "device.sceneFive", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:"80%", action:"sceneFive", icon: "st.Weather.weather14"
	}

	valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "level", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
	}
    
    standardTile("doPoll", "device.doPoll", inactiveLabel: false, decoration: "flat", height: 2, width: 2) {
		state "default", label:"Do Poll", action:"doPoll", icon: "st.Weather.weather14"
	}
    
    valueTile("LastActivity", "device.lastActivity", width: 6, height: 2) {
    	state "default", label: 'Last Activity ${currentValue}'
    }
    
    valueTile("LastConfigured", "device.lastConfigured", width: 6, height: 2) {
    	state "default", label: 'Last Configured ${currentValue}'
    }
    
    valueTile("LastPoll", "device.lastPoll", width: 6, height: 2) {
    	state "default", label: 'Last Poll ${currentValue}'
    }
    
    valueTile("LastBattery", "device.lastBattery", width: 6, height: 2) {
    	state "default", label: 'Last Battery ${currentValue}'
    }

    main(["switch", "level"])
	details(["switchDetails", "ShadeLevel", "levelSliderControl", "sceneOne", "sceneTwo", "sceneThree", "sceneFour", "sceneFive", "refresh", "top", "bottom"])

}

}

def installed() {
poll()
}

def configure() {
delayBetween([
def result = zwave.wakeUpV1.wakeUpNoMoreInformation().format(),
zwave.wakeUpV1.wakeUpIntervalSet(seconds:4 * 3600, nodeid:zwaveHubNodeId).format()
])
}

def updated() {
log("${getVersionStatementString()}", "DEBUG")

sendEvent(name: "sceneOne", value: customLevel, display: false , displayed: false)
log("Custom Level Selected: ${customLevel}.", "INFO")
log("Debug Level Selected: ${logging}.", "INFO")

poll()

}

def doPoll() {
poll()
}

def poll() {
log("Polling...", "DEBUG")

updateDeviceLastPoll(new Date())

log("${getVersionStatementString()}", "DEBUG")

configCheck()

def commands = []

commands << zwave.switchMultilevelV1.switchMultilevelGet().format()
commands << zwave.batteryV1.batteryGet().format()

if (getDataValue("MSR") == null) {
	commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
}

def result = delayBetween(commands,100)

log("result = ${result}", "DEBUG")

return result

}

def refresh() {

log("Refreshing.", "DEBUG")
log("${getVersionStatementString()}", "DEBUG")
log("windowShade = ${device.currentValue('windowShade')}.", "INFO")

def commands = []
commands << zwave.switchMultilevelV1.switchMultilevelGet().format()
commands << zwave.batteryV1.batteryGet().format()
if (getDataValue("MSR") == null) {
	commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
}
def result = delayBetween(commands,100)
log("result = ${result}", "DEBUG")

return result

}

def parse(String description) {
def result = null
if (description != "updated") {
log("parse() >> zwave.parse($description)", "DEBUG")
if(description.trim().endsWith("payload: 00 00 00")) {
sendEvent(name: "level", value: 0, unit: "%")
log("Shade is down, setting level to 0%.", "DEBUG")
} else if(description.contains("command: 2603")) {
def hexVal = description.trim()[-8..-7]
def movingHex = description.trim()[-2..-1]
log("hexVal = ${hexVal}.", "DEBUG")
try {
def intVal = zigbee.convertHexToInt(hexVal)
def movingInt = zigbee.convertHexToInt(movingHex)
log("intVal = ${intVal}.", "DEBUG")

            if(movingInt == 0) {
            	log("Shade has stopped.", "INFO")
            } else if(movingInt == 254) {
            	log("Shade is moving.", "INFO")
            } else {
            	log("movingInt = ${movingInt}.", "INFO")
            }
            
            sendEvent(name: "level", value: intVal, unit: "%")
        } catch(e) {
        	log("Exception ${e}", "ERROR")
        }
    } else if(description.contains("command: 8003")) {
    	log("Battery Reported.", "DEBUG")
    }
    
	def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
}
if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) {
	result = [result, response(zwave.basicV1.basicGet())]
	log("Was hailed: requesting state update", "DEBUG")
} else {
	log("Parse returned ${result?.descriptionText}", "DEBUG")
}

return result

}

def configCheck() {
if(shouldReconfigure() == true || isConfigured() == false) {
log("Reconfiguring the device as the state value has changed.", "DEBUG")
configure()
setStateVersion(getNewStateVersion())
state.configured = true
updateDeviceLastConfigured(new Date())
} else {
log("Device already configured.", "DEBUG")
}
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
log("BatteryReport", "INFO")
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) { // Special value for low battery alert
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
// Store time of last battery update so we don't ask every wakeup, see WakeUpNotification handler
state.lastbatt = new Date().time
updateDeviceLastBattery(new Date())
createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
log("WakeUpNotification", "INFO")
updateDeviceLastActivity(new Date())
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]

    if (!state.lastbatt || (new Date().time) - state.lastbatt > 24*60*60*1000) {
            result << response(zwave.batteryV1.batteryGet())
            result << response("delay 1200")  // leave time for device to respond to batteryGet
    }
    result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
    result

}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) {
dimmerEvents(cmd)
}

private dimmerEvents(physicalgraph.zwave.Command cmd) {
def value = (cmd.value ? "on" : "off")
def result = [createEvent(name: "switch", value: value)]
if (cmd.value && cmd.value <= 100) {
result << createEvent(name: "level", value: cmd.value, unit: "%")
}
return result
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "ConfigurationReport $cmd"
def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"}
createEvent([name: "indicatorStatus", value: value])
}

def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
createEvent([name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false])
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
log.debug "manufacturerId: ${cmd.manufacturerId}"
log.debug "manufacturerName: ${cmd.manufacturerName}"
log.debug "productId: ${cmd.productId}"
log.debug "productTypeId: ${cmd.productTypeId}"
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
updateDataValue("MSR", msr)
updateDataValue("manufacturer", cmd.manufacturerName)
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
[createEvent(name:"switch", value:"on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
log("Unhandled Event ${cmd}", "DEBUG")
[:]
}

def on() {
setLevel(99)
}

def off() {
setLevel(0)
}

def setLevel(level) {
log("setLevel(${level}).", "DEBUG")

if(level >= 100) {
	level = getMaxLevel()
} else if(level < 0) {
	level = 0
}

if (level > 0 && level < 99) {
	sendEvent(name: "switch", value: "on")
    sendEvent(name: "windowShade", value: "partially open")
} else if(level == 0) {
	sendEvent(name: "switch", value: "off")
    sendEvent(name: "windowShade", value: "closed")
} else {
	sendEvent(name: "windowShade", value: "open")
}

sendEvent(name: "level", value: level, unit: "%")
delayBetween ([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)

}

def setLevel(value, duration) {
setLevel(value)
}

def open() {
setLevel(getMaxLevel())
}

def close() {
setLevel(0)
}

def presetPosition() {
setLevel(customLevel)
}

def levelOpenClose(value) {
log("levelOpenClose called with value ${value}.", "DEBUG")
if (value) {
on()
} else {
off()
}
}

/************ Begin Logging Methods *******************************************************/

def determineLogLevel(data) {
switch (data?.toUpperCase()) {
case "TRACE":
return 0
break
case "DEBUG":
return 1
break
case "INFO":
return 2
break
case "WARN":
return 3
break
case "ERROR":
return 4
break
default:
return 1
}
}

def log(data, type) {
data = "Z-Wave Shade -- v${dhVersion()} -- ${data ?: ''}"

if (determineLogLevel(type) >= determineLogLevel(settings?.logging ?: "INFO")) {
    switch (type?.toUpperCase()) {
        case "TRACE":
            log.trace "${data}"
            break
        case "DEBUG":
            log.debug "${data}"
            break
        case "INFO":
            log.info "${data}"
            break
        case "WARN":
            log.warn "${data}"
            break
        case "ERROR":
            log.error "${data}"
            break
        default:
            log.error "Z-Wave Shade -- Invalid Log Setting"
    }
}

}

/************ End Logging Methods *********************************************************/

def sceneOne() {
setLevel(customLevel)
}

def sceneTwo() {
setLevel(20)
}

def sceneThree() {
setLevel(40)
}

def sceneFour() {
setLevel(60)
}

def sceneFive() {
setLevel(80)
}

def getMaxLevel() {
return 99
}

def isConfigured() {
log("${getVersionStatementString()}", "DEBUG")
if (state.configured == null || state.configured == false) {
return false
} else {
return true
}
}

def getStateVersion() {
if(state.version != null) {
return state.version
} else {
return 0
}
}

def setStateVersion(val) {
log("Updating State Version to ${val}.", "INFO")
state.version = val
}

def getNewStateVersion() {
return 10
}

def getVersionStatementString() {
return "Current state version is ${getStateVersion()} and new state version is ${getNewStateVersion()}."
}

def shouldReconfigure() {
if(getNewStateVersion() > getStateVersion()) {
return true
} else {
return false
}
}

def getBattery() {
def commands = []
commands << zwave.batteryV1.batteryGet().format()
def result = delayBetween(commands,100)
log("result = ${result}", "DEBUG")
return result
}

def updateDeviceLastActivity(lastActivity) {
def finalString = lastActivity?.format('MM/d/yyyy hh:mm a',location.timeZone)
sendEvent(name: "lastActivity", value: finalString, display: false , displayed: false)
}

def updateDeviceLastConfigured(lastConfigured) {
def finalString = lastConfigured?.format('MM/d/yyyy hh:mm a',location.timeZone)
log("Raising lastConfigured event with ${finalString}.", "INFO")
sendEvent(name: "lastConfigured", value: finalString, display: false , displayed: false)
}

def updateDeviceLastPoll(lastPoll) {
def finalString = lastPoll?.format('MM/d/yyyy hh:mm a',location.timeZone)
sendEvent(name: "lastPoll", value: finalString, display: false , displayed: false)
}

def updateDeviceLastBattery(lastBattery) {
def finalString = lastBattery?.format('MM/d/yyyy hh:mm a',location.timeZone)
sendEvent(name: "lastBattery", value: finalString, display: false , displayed: false)
}

@nmelanson75
Copy link

I was able to fix the code above it was just a couple of spots where the , was before the " unfortunately this did not resolve the issue. Homebridge still does not pull back current status of the device and I see this error in Live Logger

cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:06 AM: info postEventToEndpoint: event successfully posted.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:06 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:06 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:06 AM: debug Property Change Event level: 99 (source: DEVICE)
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:56:06 AM: debug Sending Update to 192.168.75.79:8000
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:06 AM: info Z-Wave Shade -- v1.0.2 -- Shade has stopped.
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:06 AM: info Z-Wave Shade -- v1.0.2 -- Shade is moving.
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:06 AM: info Z-Wave Shade -- v1.0.2 -- Shade is moving.
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:05 AM: info Z-Wave Shade -- v1.0.2 -- Shade is moving.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:05 AM: info postEventToEndpoint: event successfully posted.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:05 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:05 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:56:05 AM: debug Property Change Event level: 93 (source: DEVICE)
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:56:05 AM: debug Sending Update to 192.168.75.79:8000
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:05 AM: info Z-Wave Shade -- v1.0.2 -- Shade is moving.
b8c5309d-e321-4a70-9293-6dcc223f2da8 10:56:05 AM: info Z-Wave Shade -- v1.0.2 -- Shade is moving.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:55:58 AM: info postEventToEndpoint: event successfully posted.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:55:58 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:55:58 AM: warn Device type 'blind' unknown. Mapping to 'OTHER' instead.
cf132972-5e28-440f-a03c-7c32f5f36b0f 10:55:58 AM: debug Property Change Event level: 99 (source: DEVICE)
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:55:58 AM: debug Sending Update to 192.168.75.79:8000
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:55:58 AM: debug Sending Update to 192.168.75.79:8000
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:55:58 AM: info Command Successful for Device Living Room Shade, Command setLevel
9853cfb0-6f3b-4598-bf58-3eaf5aa34657 10:55:57 AM: info Command Request
10:55:55 AM: info Waiting on events...
10:55:55 AM: info For past logs for individual things go to the My Devices section, find the device and click on the Events link on the device information page.
10:55:55 AM: info This console provides live logging of your SmartThings.
thumbnail_image-1

@nmelanson75
Copy link

Actually just reading one of your other threads below, this update works perfectly even the on and off. Only small issue is in Homebridge it shows up as a dimmer not sure if there is a easy fix I can do.

SmartThingsCommunity/SmartThingsPublic#3316

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants