Using Java.net Socket

That won't catch everything. And it mixes data types for e. I use (and strongly recommend) this construct (shown as if a library script):

from java.lang import Throwable
logger = system.util.getLogger(system.util.getProjectName() + '.' + __name__)

def someTask():
	try:
		someaction()
	except Throwable, t:
		# Throwable is the ultimate superclass of all java exceptions and errors
		logger.warn("some text for java", t)
	except Exception, e
		# Exception is python's superclass (technically BaseException--substitute if you like)
		logger.warn("some text for jython", later.PythonAsJavaException(e))

Note that you cannot use jython exceptions with loggers, and you should always be using loggers (no prints). Which is why the separate except: clause is so important--you have extra work required to log a python exception. (PythonAsJavaException() is available in my later.py.)

If you have common handling needed for both exception cases, move that into another function.

2 Likes

Oh does the throwable catch basically all of the Java errors?

My exception cases for these are starting to look a bit ridiculous with all the different error types I'd been coming across, could never find a general exception as I very rarely want to do anything special based on the error.

try:
    spamEggs()
except java.lang.Exception as e:
    callBack(str(e))
	
except java.io.IOException as e:
	callBack(str(e))

except Exception as e:
	callBack(str(e))

def callBack(e)
	logger.warn("Failed, {0}".format(e))

You're not catching EggsTooCookedException though.

2 Likes

Ahh, that's why my code is always so scrambled, makes sense

2 Likes

Yes. When you specify an exception type, that type and any subtypes are included. All java exceptions and errors inherit from Throwable, so you get them all there.

But it won't catch any jython errors--that's a different inheritance hierarchy.

You really should not be stringifying your exceptions--that drops the backtrace that you really need to debug complex problems. Pass them to the appropriate logger methods (look for the argument of type Throwable), which will include the backtrace in the logs.

2 Likes

Been a while as this was on the back burner...

I've been testing with it and managed to get some data out of the socket using the below code:

remaining_data_len = resp_data_len - len(response_data)
buff_size = 1024 if remaining_data_len > 1024 else remaining_data_len
	
chunk = jarray.zeros(buff_size, 'b')
response_header = in_stream.read(chunk, 0, buff_size) # read response data
	
myLogger.debug("Chunk : {0}".format(chunk))
	
chunk = chunk.tolist()
	
response_data = b"" + str(chunk)
response_data = response_data.decode("utf-8")
	
myLogger.debug("Response Data = {0}".format(response_data))
	
return response_data

When I run the code the values change so I can tell I'm getting the correct stuff out.

Defintely need to adjust my buffer size as most of the returned values are 0, but I get a response out of the socket like the below:

From my logger above...

Chunk : array('b', [34, 97, 117, 116, .....

Now I'm expecting to get a JSON out of this data showing my values. How am I supposed to convert this data into a string or a list of chars at least.

In my above code I naively attempt at just decoding at utf-8, but it just returns those integer values as actual integer values.

I must need to convert them back into a correct byte format then decode right?

No, array('b',...is bytes.

I don't know. How are your messages constructed on the wire? (You'll have to share a lot more code to get effective advice.)

1 Like

This line is where your problems start.

response_header should be called something like length or bytes_read, and you need to use that to determine how many valid bytes were read into the buffer you provided.

1 Like

Okay, how do I convert these bytes into chars and get them out of this array without them just becoming integers?

Something I found is if I take these numbers and convert them to binary, then convert those binary values into utf-8 encoding I start to piece together my JSON I want

Ah okay, but will this also respond with empty bytes, or is this value going to be my good values. And I can ignore anything after these?

Maybe something like:

from java.lang import String

s = String(chunk, 0, bytes_read)

while chunk is still a byte array and you haven't converted it to a list or something.

But I think you have more problems here... you're reading JSON - how do you know when to stop? What is your frame delimiter?

1 Like

In our message we get a 16 byte message header, this contains the length information for the rest of our JSON.

In this example I just have a hard cap on the buffer as 1024. And read that until its full, none of the messages are longer than that. Not a good solution, but workable while I test to see if we can even connect first. I'll come back around to patch that up later on, once I can kind of decode my JSON.

If none of the messages are longer than that you can't read until it's full... you'll just be reading/waiting forever.

1 Like
chunk = jarray.zeros(buff_size, 'b')
bytes_read = in_stream.read(chunk, 0, buff_size) # read response data
	
myLogger.debug("Chunk : {0}".format(chunk))
	
myLogger.debug("Chunk Okay")
	
response_data = String(chunk, 0, bytes_read)
	
return response_data

That worked very well actually getting me the below values:

"auto_charge":false,"battery_cycle":58,"battery_level":0.99,"battery_temp":36.0,"battery_user_data":"0107E623000086DE","charging":true,"create_on":"2023-10-31T22:47:49.181+0800","current":3.81,"manual_charge":false,"max_charge_current":-1.0,"max_charge_voltage":-1.0,"ret_code":0,"voltage":53.602}

I'll need to look into where the buffer is going astray, seem to be missing the first '{' for whatever reason, but some tweaking shoudl sort that out.

Ah, I think I've already got some check in there to unpack that header then. As it seems to send the data properly, I though it wasn't yet implemented.