hexStringToInt(SHThexData) doesn't handle negative numbers

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:
image

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...

1 Like

Thank you for your reply.

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.

John

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... :smiley:

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.

The signed part I found in the Zigbee spec:

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"

Use hexStrToSignedInt for signed values

5 Likes

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

Is what I'm doing wrong obvious to you?

Thanks
John

This works

Temperature = Integer.valueOf(SHThexData, 16).shortValue();
import hubitat.helper.HexUtils
-
-
-
// ---- parse --------------------------------------------------------------------------------------------------
def parse(String description){
   
    if (logEnable)  log.info "  Raw Description=  $description"

    if (description?.startsWith('read attr -')){        // in testing all messages are 'read attr -''
        Map descMap = zigbee.parseDescriptionAsMap(description)

        if (logEnable) log.info "   descMap=  $descMap"

        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"
           
            SensorValue = hubitat.helper.HexUtils.hexStrToSignedInt(SHThexData)  // line 72

            if (displayUnits == "0"){   // 0 = °F
                SensorValue = SensorValue * 9/5 + 3200
                SensorValue = Math.round(SensorValue / 10)
                SensorValue = SensorValue / 10
                sendEvent(name: "temperature", value: SensorValue , unit:"°F")
            }
            else{
                SensorValue = Math.round(SensorValue / 10)
                SensorValue = SensorValue / 10
                float dewSensorTempC = SensorValue
                sendEvent(name: "temperature", value: SensorValue , unit:"°C")
            }
            updateMaxMin(SensorValue)
        }  // if 0402        

That method does not require the path you added.
It is simply SensorValue = hexStrToSignedInt(SHThexData)

1 Like