Learning to Code

I'm assuming i'm not the only one trying to workout how to wright drivers or port/ fix them. So I'm hoping the community can help me and possibly others with some questions. This isn't about directly porting as that is covered in other threads, more about the crux of getting things working from scratch or for copying others.

In my case in a driver I have these lines of code under preferences:

input name: "IP1Type", type: "enum", title: "Input 1 Type",
                    options: ["Contact", "Motion"], defaultValue: "Contact", displayDuringSetup: true
	 	input name: "IP2Type", type: "enum", title: "Input 2 Type",
                    options: ["Contact", "Motion"], defaultValue: "Contact", displayDuringSetup: true

these works well and where needed i use it for stuff like this

if (IP2Type == "Contact") sendEvent(name: "contact2", value: "closed", descriptionText: "$device.displayName - IP2 was set to closed", type: "digital")
	if (IP2Type == "Motion") sendEvent(name: "contact2", value: "active", descriptionText: "$device.displayName - IP2 was set to active", type: "digital")

But i also want to define a bool in the driver for this:

if (IP1Type == "Contact" || IP2Type == "Contact") { ContactUsed = true
	if (txtEnable)	log.info "At least 1 Contact selected"
	} else { ContactUsed = false
	if (txtEnable)	log.info "Contact's not selected"	
			
		   }

	if (IP1Type == "Motion" || IP2Type == "Motion") { MotionUsed = true
	if (txtEnable)	log.info "At least 1 Motion selected"
	} else { MotionUsed = false
	if (txtEnable)	log.info "Motion not selected"	
			
		   }

I think this code works (the logs seem to say the correct thing) but how do i create the bool ContactUsed and MotionUsed?

i've tried quite a few things but nothing works currently im trying under def updated() I tried this:

input name: "ContactUsed", type: "bool"
	input name: "MotionUsed", type: "bool"

but i'm litery stabbing in the dark here :frowning:

currently i'm doing this to get over it

if (IP1Type == "Motion" || IP2Type == "Motion") childDevice.sendEvent(name: "motion", value: motionstate, descriptionText: "IP${cmd.sourceEndPoint} has become ${motionstate}", type: "physical")
if (IP1Type == "Contact" || IP2Type == "Contact") childDevice.sendEvent(name: "contact", value: currentstate, descriptionText: "IP${cmd.sourceEndPoint} has ${currentstate}ed", type: "physical")

rather than

if (MotionUsed) childDevice.sendEvent(name: "motion", value: motionstate, descriptionText: "IP${cmd.sourceEndPoint} has become ${motionstate}", type: "physical")
if (ContactUsed) childDevice.sendEvent(name: "contact", value: currentstate, descriptionText: "IP${cmd.sourceEndPoint} has ${currentstate}ed", type: "physical")

and it works, but to me the driver working out this if (IP1Type == "Contact" || IP2Type == "Contact")
20 times must be quite expensive so doing it once and sticking it in a variable is better?

2 Likes

To persist a variable, you need to use “state” to store these variables/values.

Try state.MotionUsed and state.ContactUsed as your “variables”.

is there anywhere in particular i need to add this in the driver?

Just prefix your current MotionUsed and ContactUsed variables with “state.” in every place you reference those two variables.

So I don't need to define them anywhere then. as in this is my variable A? I can just go straight ahead and do this:

if (IP1Type == "Contact" || IP2Type == "Contact") { state.ContactUsed = true
	if (txtEnable)	log.info "At least 1 Contact selected"
	} else { state.ContactUsed = false
	if (txtEnable)	log.info "Contact's not selected"	
			
		   }

	if (IP1Type == "Motion" || IP2Type == "Motion") { state.MotionUsed = true
	if (txtEnable)	log.info "At least 1 Motion selected"
	} else { state.MotionUsed = false
	if (txtEnable)	log.info "Motion not selected"	
			
		   }

then use them like this

if (state.MotionUsed) childDevice.sendEvent(name: "motion", value: motionstate, descriptionText: "IP${cmd.sourceEndPoint} has become ${motionstate}", type: "physical")
if (state.ContactUsed) childDevice.sendEvent(name: "contact", value: currentstate, descriptionText: "IP${cmd.sourceEndPoint} has ${currentstate}ed", type: "physical")

Yes, I believe that should work.

1 Like

Take a look at this documentation regarding state and atomicState. I believe atomicState May only work in Apps, not Drivers...but I could be wrong about that...:thinking:

https://docs.smartthings.com/en/latest/smartapp-developers-guide/state.html?highlight=state

2 Likes

brilliant thanks :sunglasses::+1: worked a treat!

this now appears in the driver

image

1 Like

@ogiewon is there a way to clear these variables? I have some devices that i have swapped drivers for and they seem to cling.

state.remove("version")
state.remove("Version")
state.remove("sensorTemp")

During development of a driver, I'll make typos like above, or just change my mind, and will add those lines to update(), run it, then remove the lines.

1 Like

so no blanket clean, you have to wipe each one separately. I was thinking of having a basic clean driver with a wipe in then could convert back.

you should be able to use any of the Groovy Map functions plus any of the underlying Java functions on it as state is just a Map

https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#clear--

void clear() ? how do i use is?

I'm not 100% sure, but would simply try "state.clear()" and see what happens.

Yes, that is correct: state.clear()

1 Like

So where do I sign up for the courses? :wink: This is something I would like to get into at some point. Thanks for starting this thread.

1 Like

like this?

def configure() {
	WipeState()
}

def WipeState() {
	log.warn "wiping states"
	state.clear()
}

Blanket clean is uninstall the driver (not your code but the driver using your code), then install and configure any needed options again. This will get rid of all associated variables and you can start fresh. You should do this before releasing code as well to make sure that it installs from scratch for a new user as you expect it to.

now state.clear() works, I built a little blanket clean driver :slight_smile: clears the states and any schedules. Have to start somewhere :laughing:

https://raw.githubusercontent.com/borristhecat/HUBITAT/master/Clean%20Device.groovy

4 Likes

whats the difference between

state.remove("temperature")
state.clear("temperature")