I'm trying to convert Zigbee data ID:29 which is a 16 bit integer.
Negative numbers do not seem to work with the nexStrinToInt function. I see the max into that function is 0x8000 and my negative data is something like 0xFCC9 which is above 0x8000 so I don't know how to convert my sensor data that in today's weather is going negative.
What am I missing?
Signed 16-bit integer int16 0x29 2 0x8000
My Logged Data:
My Code:
if (descMap.cluster == "0402"){
SHThexData = descMap.value // the HEX value is 100 x the actual temperature
log.info " Raw hex value from pvto = $SHThexData"
SensorValue = hubitat.helper.HexUtils.hexStringToInt(SHThexData)
log.info " integer value = $SensorValue"
Where are you seeing that? Maybe I'm misunderstanding you, but feeding 0x8000 into that function gives me:
32768
Feeding 0x8001 (so over that value) gives me:
32769
...which is exactly what I expect.
Is this not working for you? Feeding 0xFCC9 into this method gives me:
64713
...which is also what I expect (that is the decimal equivalent of that hex). Is your issue just that your sensor wraps value around instead of reporting negative values? If so, you can convert them yourself before or after conversion. Otherwise, I'm not sure what is happening for you.
If you want to experiment more with this conversion yourself, this method is basically a shortcut for Integer.parseInt(<hexString>, 16), so you can try that method directly yourself (substituting <hexString> with your actual string`), but you shouldn't find anything different that way...
My goal was to convert (for instance) 0xFCC6 and receive back -826 decimal.
I thought that the hexStringToInt, 16 would convert to a signed integer. The "signed" part made me think it would handle negatives.
If that is not the case then I can figure out how to do that separate from this function.
I'm not sure if we're looking at different things; I don't see anything about "signed" anywhere in the method name or documentation for the one I am talking about. It does work fine with negative values, though, either "0x-F123" or "-F123" format. This will convert to the negative decimal value.
It sounds like maybe you just need to account for your sensor wrapping data around instead of reporting a negative value? This method isn't going to do that for you; it can't possibly know where your cutoff is. But it should be easy enough to do mathematically before or after (probably more easily after...) the string-to-number conversion.
EDIT:
Thinking about this more: does your device just overflow after the max 16-bit value, 0x8000? If so, would the two's complement work for you after conversion?
Integer number = hexStringToInt(SHThexData)
if (number >= 0x8000) {
number -= 0x10000
}
This is completely untested; I look forward to someone probably correcting this in the morning...
I'm assuming the "normal" way to represent a negative number (16) in hex was two's compliment. I've never run across any "-" hex format ("0x-F123" or "-F123" format).
And the fact that the hexStringToInt did not give an error when exceeding 0x8000 seemed to support that.
When I converted FCC6 using the MS Windows calculator I get a negative value (-826) that matches the approximate value of the sensor. Which is -826/100 or -8.26°C
I'm going to look into the Unary "~" operator and see if that works.
This seems to work: (a little clumsy, will clean up tomorrow.)
if (descMap.cluster == "0402"){
SHThexData = descMap.value // the HEX value is 100 x the actual temperature (determined by ptvo)
log.info " Raw hex value from pvto = $SHThexData"
Temperature = Integer.valueOf(SHThexData, 16).shortValue();
log.info " converted $Temperature"
Sorry to bother you, however I've not been successful with your suggestion. I get a missing Method Exception error.
This is the line that gives me the error:
SensorValue = hubitat.helper.HexUtils.hexStrToSignedInt(SHThexData) // line 72