Need good concat method for a multi-message parse

I am using rawSocket to receive messages from some devices (Kasa Plugs). The return message is an encrypted Hex string sent in two segments to the parse method. I have to concat these two prior to sending to the decrypt routine. My personal developed routine relies on two state; however, the states do not always update properly and the system gets errors on further processing.. The two main related methods are below. They then send the message for decryption and distribution.

Any help on a better routine would be appreciated.
Dave

def parse(response) {
	//	state.concatResp is set to false in installed() and updated().
	//	state response is set to "" in installed() and updated().
	logDebug("parse: length = ${response.length()} // ${state.respConcat}")
	if (response.length() < 2048 && !state.concatResp) {
		//	length less than max and first in sequence. distribute
		distributeResponse(response)
	} else { respConcat(response) }
}

def respConcat(response) {
	//	Using second method in (vain) attempt to get consistent state performance.
	logDebug("respConcat: length = ${response.length()} // ${state.concatResp}")
	if (response.length() == 2048) {
		//	Length is 2048 (max length).  Add to state.response.
		//	set state.concat to true, which means next string will
		//	be added to the existing string.
		state.response = response
		state.concatResp = true
	} else {
		//	length less and a concat is active.  Add then distribute.
		//	set state.response to null and state concat to false.
		def resp = state.response
		resp = resp.concat(response)
		state.response = ""
		state.concatResp = false
		distributeResponse(resp)
	}
}

I've had the problem of the state database updates not making it back from asynchronous packet handling things (like parse) too. It has to do with state's implementation -- my understanding is that it only commits to the persistent state database when execution of the current (process/thread/or whatever apps and handlers run in) finishes.

I worked around it for a while by breaking up my methods and using runInMillis() to build a fake yield() system. Set the state as needed, then schedule the second half of the method for a few hundred milliseconds later. This usually gave the state database time to do the right thing.

However...a couple of days ago, I stumbled across the updateDataValue() and getDataValue() methods:

https://docs.hubitat.com/index.php?title=Driver_Object#Additional_to_be_documented

You can use these to store per-device variables as strings, and they seem to update instantly. I have no idea what the size limitations are. Might be worth a look though.

Thanks. The issue with those is that they take significant processing and (I believe) the items are meant for more persistent (I currently use for deviceIp, plug Id, and other persistent driver data.

That being said, it is my final work-around.

Just fyi, I was curious about exactly how slow updateDataValue() might be. So I tested it by including the code below in the parse function of one of my drivers.

With only the call to device.updateDataValue() commented out, the code runs in about 4ms. Including the call, it averages around 1200ms.

The test loops 1000 times, so a bit over 1ms per call to set a single character string variable. (I changed the value being written every time just in case there was an optimization that bailed out early if the same value was being rewritten.)

Admittedly, this test won't show if using these APIs causes a commit to slow storage when doing a context switch, but still it seems quick enough for occasional use. (And man, would I love it if the Hubitat folks would give us semaphores, and/or a per-device chunk of memory that we could use for "whatever". )

// handle command responses & status updates from bulb 
def parse(String description) {
    
// crazy timing test
  def start = now()
  def j,val
  for (j = 0;j < 1000; j++) {
      val = j.toString()
      device.updateDataValue("test",val)       
  }
  j = now() - start
  logDebug("Timing test took ${j} milliseconds")   
...

Understand. Even global variables would be nice. But I believe they do not work. You can have global constants, but not variables.