HexUtils hexStringToInt sometimes fails

I have code that generates a random byte array (4 bytes) that I am encoding Hex and then using the HexUtils hexTringToInt to convert to a number. I get frequent failures.

Example responses:

  • [byteArray:[82, -102, 89, 6], hexValue:529a5906, integerValue:1385847046]
  • [byteArray:[-55, -51, 114, -100], hexValue:c9cd729c, ERROR:java.lang.NumberFormatException: For input string: "c9cd729c"]
  • [byteArray:[95, 13, -16, -13], hexValue:5f0df0f3, integerValue:1594749171]
  • [byteArray:[51, 69, -53, 60], hexValue:3345cb3c, integerValue:860212028]
  • [byteArray:[-81, -10, -75, -117], hexValue:aff6b58b, ERROR:java.lang.NumberFormatException: For input string: "aff6b58b"]

Code:

byteArray is the byte arrray received as part of a byte response from an external Server.
	String hexSeq = byteSeq.encodeHex()
	Integer seqNo = state.seqNo
	Map errorResp = [byteArray: byteSeq, hexValue: hexSeq]
	try {
		seqNo = hubitat.helper.HexUtils.hexStringToInt(hexSeq)
		errorResp <<  [integerValue: seqNo]
	} catch (error) {
		errorResp << [ERROR: error]
	}

Interestingly, the common feature is that all the failures have a negative number as the first number.

I think that means that it will not parse the hexString representing a negative integer. It would be nice if this "feature" were documented in the developer documents.

I am converting to another method that returns the same value as above when positive and also successfully returns a negative value when calculated.

int byteArrayToInteger(byte[] byteArr) {
	try {
		arrayAsInteger = ((byteArr[0] & 0xFF) << 24) + ((byteArr[1] & 0xFF) << 16) +
			((byteArr[2] & 0xFF) << 8) + (byteArr[3] & 0xFF)
	} catch (error) {
		Map errLog = [byteArr: byteArr, ERROR: error]
		logWarn("byteArrayToInteger: ${errLog}")
	}
	return arrayAsInteger
}

It's using Integer.parseInt(value, 16) behind the scenes, and its behavior is consistent with that Java call. The hex value passed is greater than Integer.MAX_VALUE, thus an error.

I can add hexStringToLong if you need it, though.

Let me see if the method I am using works for the Tapo encryption code. If not, then....