How to use an attribute

Hi,

got some basic code working and now want to get clever

can someone explain why this isnt working:

def GreenOn() {
if (logEnable) log.debug "GreenOn()"
eventProcess(name:"green_led", value:"on")
List cmds=[]
def currentBri = device.currentValue('ledBrightness')
def sBri = currentBri.toInteger()
def hexBri = "0x" + hubitat.helper.HexUtils.integerToHexString(sBri, 1)
if (logEnable) log.debug "ledBrightness(${hexBri}):"
//turns the green LED on
cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x50, propertyId:1, value:hexBri]]).format())
sendToDevice(cmds)
sendEvent(name:"green_led", value: "on", isStateChange:true)
}

if i use
cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x50, propertyId:1, value:0x64]]).format())

it is fine.

as you can see from the code, i take an attribute. convert it to hex. add the 0x that the code requires and put into the command.

any advice welcome

1 Like

ok some more playing.

it works with 0064.

if i use
hexBri = 0064

cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x50, propertyId:1, value:hexBri]]).format())

it works

but if i do a convert it doesnt like it.

so how do i tell it to not be a string but a 4 digit code thing

From your code, it appears that this is a String. However, it needs to be a number, specifically a Short (though Groovy is usually good at doing what you want as long as it's still a number). You can use a variable or a literal for this, and the literal can even be in decimal format, e.g., 100, even if it's more often seen in hex, e.g., 0x64 (the 0x prefix is how Groovy knows you're writing a hex literal, not decimal) -- but it can't be a string, no matter what format. You'll need to convert.

Along these lines, if your custom brightness attribute is defined as a number and not a string, this should also be easier than you're making it, since you'd get a numeric type back to start. So, you might not even need to "convert," though depending on possible values you may want to make sure it's indeed a Short.

interesting. the issue i have is the device i am sending to is very picky on what is sent.
i can send 0064 or 0x64 but not 64.

so a short would work?

also having to convert from an integer to a hex.
so the idea is that the volume can be 1 to 100 then converted to hex.

slowly learning

got round it by moving to prefences with a preset low medium high

if (ledLevel) {
switch (ledLevel.toInteger()) {
case 1:
ledLevelHex = 0001
break;
case 2:
ledLevelHex = 0032
break;
case 3:
ledLevelHex = 0064
break;
}
}

thanks

Dagaz

I think you have some confusion over how numbers can be represented in Groovy. You can use 100 or 0x64 (both as literals, not as strings) and both are equivalent. They are both 100 in decimal (the common, human-friendly base-10 number system you are undoubtedly used to).

You can try some fun tests in app or driver code to see for yourself:

// the obvious:
log.debug(100 == 100)  // will print true
// decimal vs. hexadecimal (same number):
log.debug (100 == 0x64) // will print true
// decimal vs. hexadecimal (different numbers):
log.debug (64 == 0x64) // will print false

In your example above, there is yet a third possibility, 0064. This is actually octal and would be 52 in decimal. A 0 prefix in Groovy is octal (and 0064 is equivalent to 064).

Your device shouldn't care what base (octal, decimal, hex, etc.) you use on the Hubitat/Groovy side. You can use 100 if that is easier to work with. If you type 0x64, it's literally the same. Most Z-Wave docs use hex, so it's what a lot of Z-Wave enthusiasts are used to seeing, but it's all the same in the end.

Note that, as above, your numbers here are octal: 01, 032, and 064 (or 1, 26, and 52 in decimal). These seem like odd values since you probably want 0-100 and not 0-64, but there could be oddities (perhaps working in your favor) as a result of data type conversions if these aren't really a Short. Groovy is normally smart about this but can be weird sometimes. I don't know what's going on in your case. :slight_smile:

If you want my advice for how I'd do it, I'd do something like:

Short briVal = 0x64  // or, again, 100 would be equivalent

cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x50, propertyId:1, value:briVal]]).format())

That way, you know briVal is a Short. You can retrieve the value from the device, as you are above, if you need to, and just make sure it's a Short by the time you pass it to the Z-Wave method. (You don't necessarily need to be this careful with data types as long as it's a number, but I always like to be sure...)

4 Likes

thank you. that helped hugely. odd when i started playing the commands only seemed to work with hex but now i understand the setting to int have managed to simplify.
used the enum preference with low medium and high being 1, 50 and 100
then in the routine
ledLevel = ledLevel.toInteger()
then in the command

cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0D, propertyId:1, value:ledLevel]]).format())

so all working. (ok sort of but not really, sint right setting)

could set as a button where people could choose between 1-100 but think low medium high in prefrences better.

thanks again for all the help.

see other post below.

1 Like

ok spoke too soon
it doesnt read the value right when in decimal.

will play some more but code that works is below:

def GreenOn() {
if (logEnable) log.debug "GreenOn()"
eventProcess(name:"green_led", value:"on")
List cmds=[]
if (ledLevel) {
switch (ledLevel.toInteger()) {
case 1:
ledLevelHex = 0001
break;
case 50:
ledLevelHex = 0032
break;
case 100:
ledLevelHex = 0064
break;
}
}

if (logEnable) log.debug "LedLevel(${ledLevel} ${ledLevelHex} ${briVal})"
//turns the green LED on
cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x50, propertyId:1, value:ledLevelHex]]).format())
sendToDevice(cmds)
sendEvent(name:"green_led", value: "on", isStateChange:true)

}

trying to manipulate between hex and non hex breaks it.

Interesting, but again, this is octal (and the two leading zeros could be reduced to one without any change). In base 8, base 10, and base 16, respectively 064, 52, and 0x34 are all the same, and any should work if (decimal/base 10) 52 is really what you want.

I guess I'd just make sure that whatever specs you're reading are in the same base (octal, decimal, hex, etc.) that you are expecting. For Z-Wave, this is usually hex, but it's possible whatever you're reading isn't. That could explain some of the differences. :man_shrugging:

Is all very odd

0x64 is hex for 100 decimal but sure what 0x32 came from?

0x32 in hex is 50 in decimal. (But, again, you should be able to write whatever literal format you want on Hubitat; these are numeric objects — not strings, which usually have specific requirements if you're working at that low of a level — and it should all be the same by the time it's executed...)

Am guessing is the way the device is handlijg the code it gets.

If it isn't in the form of hex it just doesn't work or it converts it from hex.

So 100 works for some commands but not all.
It is supposed to be the level of the led.

However if I use 0064 either directly in the command or as a variable set within the process being called it is fine. However if I set it under map fields as 0064 when being used hubitat is converting it to an integer which changes the way it is then handled.

If I use the hex tools it converts the decimal to a hex string but it won't read or convert it to anything that can be read.

Am at a bit of a loss.

My workaround is the case statement which works regardless but would like to fix properly.

All very odd and thank you again for the help

I'm not sure I can help more without knowing what device this is, having the documentation for how it is supposed to work, or possibly even having a real device to test with. Even then, I'm not sure. :slight_smile: Perhaps someone else may have other ideas.

However, I can tell you that as long as you're dealing with a Short or really any numeric type, there should be no difference whether you type 064 (or 0064), 52, or 0x34. This is a Groovy thing that would not be affected by your device, as long as you're dealing with the correct data type (and not, say, a string). I don't see ledLevelHex defined in your code anywhere (and, again, the fact that you might write this as a hex literal doesn't matter), but I'd write something like Short ledLevelHex = ... instead of def ledLevelHex = ... just to be sure.

went back to it and tried a variation using the decimal code and seems to be working.
thank you for the help.

full code link below:

OK, so in looking at your code, ledLevel comes from an enum input, and that value is going to be a String -- no matter what type the key of that Map may really be. That could explain some of the behavior you saw before (though it was not possible to say with only that snippet).

Other comments, should you want to consider any:

  • Your ledLevelInt should be an integer based on your code, but the type still isn't defined, and I'd recommend Short just to be extra-clear with what the Z-Wave command needs, but, as before, Groovy is usually pretty good about converting (when values are in range), so it probably still works as-is.

  • You are also logging ledLevelHex, but I don't see that defined anywhere. (No functional difference in outcome, just something you might see in your logs that is probably leftover from a previous code revision.)

  • It's also conventional for Groovy methods (and Hubitat commands, which correspond to these) to use camelCase starting with a lower-case letter rather than uppercase. Same for attributes, which you are already doing. I can't think of anywhere that this would matter for outcome, just more convention, but often nice to follow.

  • The namespace in your definition is set to "hubitat", so I assume you may have started with example code from Hubitat. It is convention to change this to a unique value for you (often your GitHub username given that this is a common code-sharing platform for Hubitat, but anything works--including this, but it could be confusing).

Otherwise, glad you were able to make something that works for you!

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.