How to record and use a state?


(Jack Browne) #1

Hi Everyone,
So I’m very new to all this but I’m trying write a device handler for a Smartenit ZBLC15 (4033a) dual relay to operate motorized blinds.

The blinds have a dry contact for up and one for down that needs a momentary close. Stop is achieved by closing either of the contacts. Excuse my ignorance if I’m wrong here but I’m calling these my 3 states on the blind controller: up, down and stop.

I’ve copied and pasted a few bits together to write a device handler that will momentarily close the up or down dry contacts. My problem is that if you press up once and the blind goes all the way to the motor limit you need to press down twice to get it to go down. ie. state changes to stop on the first press and down on the second. I want to get all my blinds on scenes so this is a problem as if the blind controller is not in the stop state then a scene to put the blinds up will only change the state to stop if the last thing it did was go all the way down to the motor limit.

The only way I can think of to get around this is to record the state somehow and then return the blind controller to stop (after it has had enough time to go all the way up or down) using if and delay functions. I’ve tried a few times with no luck so I’m hoping someone here might be able to point me in the right direction. I’ve included the code for the momentary up and down that works quite well (for my first device handler at least).

metadata {
    definition (name: "Dual-Relay Controller blinds 3", namespace: "", author: "") {
        capability "Actuator"
        capability "Configuration"
        capability "Refresh"
        capability "Switch"

        command "on1"
        command "off1"
        command "on2"
        command "off2"
        command "up1"
        command "down1"

		attribute "switch1","ENUM", ["on","off"]
        attribute "switch2","ENUM", ["on","off"]


        fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
        fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006", manufacturer: "Smartenit ", model: "ZBLC15 Dual Relay ", deviceJoinName: "Blind controller "
    }

	simulator {
    }

    tiles {
        standardTile("up", "device.switch") {
        	state "default", label: "Up", action: "up1", icon:"http://cdn.device-icons.smartthings.com/thermostat/thermostat-up@2x.png"
        }
        standardTile("down", "device.switch") {
        	state "default", label: "Down", action: "down1", icon:"http://cdn.device-icons.smartthings.com/thermostat/thermostat-down@2x.png"
        }
        standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
            state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
        }
       	main (["up", "down"])
		details (["up", "down", "refresh"])
    }
}

// Parse incoming device messages to generate events
 def parse(String description) {
     log.debug "Parse description $description"
     def name = null
     def value = null

     if (description?.startsWith("catchall: 0104 0006 01")) {
         log.debug "up command received from EP 1"
         if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001000")){
         	name = "switch1"
             value = "off"}
         else if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001001")){
         	name = "switch1"
             value = "on"}                        
     }  
     else if (description?.startsWith("catchall: 0104 0006 02")) {
         log.debug "Down command received from EP 2"    
         if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001000")){
         	name = "switch2"
             value = "off"}
         else if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001001")){
         	name = "switch2"
             value = "on"}
     }

 	def result = createEvent(name: name, value: value)
     log.debug "Parse returned ${result?.descriptionText}"
     return result
 }
 
 //Commands to device 
def on1() {
	
    log.debug "Relay 1 on()"
 	sendEvent(name: "switch1", value: "on")
 	"st cmd 0x${device.deviceNetworkId} 0x01 0x0006 0x1 {}"
}
def off1(){    
    log.debug "Relay 1 off()"
 	sendEvent(name: "switch1", value: "off")
 	"st cmd 0x${device.deviceNetworkId} 0x01 0x0006 0x0 {}"
 }


 def on2() {
 	log.debug "Relay 2 on()"
 	sendEvent(name: "switch2", value: "on")
 	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x1 {}"
    }
def off2(){
    log.debug "Relay 2 off()"
 	sendEvent(name: "switch2", value: "off")
 	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x0 {}"
    }
    
def up1() {
	delayBetween([
	on2(),
	off2()
	], 10)
    }
    
def down1() {
	delayBetween([
	on1(),
	off1()
	], 10)
    }
    
def on(){
	up1()
    }
    
def off(){
	down1()
    }
	

 def poll(){
 	log.debug "Poll is calling refresh"
 	refresh()
 }

 def refresh() {
 	log.debug "sending refresh command"
     def cmd = []

     cmd << "st rattr 0x${device.deviceNetworkId} 0x01 0x0006 0x0000"	// Read on / off value at End point 0x01 
     cmd << "delay 150"

     cmd << "st rattr 0x${device.deviceNetworkId} 0x02 0x0006 0x0000"	// Read on / off value at End point 0x02 

     cmd
 }



 def configure() {
 	log.debug "Binding SEP 0x01 and 0x02 DEP 0x01 Cluster 0x0006 On / Off cluster to hub" 
     def cmd = []
     cmd << "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0006 {${device.zigbeeId}} {}"	// Bind on/off output to SmartThings hub for end point 1
     cmd << "delay 150"
     cmd << "zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0006 {${device.zigbeeId}} {}" 	// Bind on/off output to SmartThings hub for end point 2
     cmd
 }

Thanks,
Jack


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #2

I have a motorized Projection Screen (i.e., essentially a roll-up blind!) and solved this really simply…

  • Just always send two commands (i.e., To go up, always send “up,up”, down send “down,down”).

Unless the blinds controller has some undesired action with two commands in a row (such as taking that to mean stop…), then this works great – for me!


(Jack Browne) #3

Yeah unfortunately this will cycle through two states. Perfect if I was going max up and max down like your projector screen but not if I want to be able to stop the blinds anywhere or slightly adjust them. Thanks though.