Hello folks,
I am trying to see if I can improve my inflight experience and get my hands dirty building an Android app. I choose Infinite Flight’s connect API to get started.
Honestly, I am using help from this library to rewrite in Kotlin. Thank you @paodekuai for the repo.
Note: The debug only works when I test this using a device and NOT with the emulator (for folks reading this infuture)
Current status:
- I have a working version of code that discovers and connect to Infinite Sessions and share the IP of the device.
- I am able to fetch the Manifest and parse the data.
- I am trying to get state of the aircraft with multiple getState calls, here’s where the problem exists.
Issue
- My first request to get state data comes through and I can interpret the data, but any subsequent request doesn’t get answered from IF, and is stuck trying to receive data.
- Added some debug to check if the socket connection is open or there are any unread bytes, did not find any lead to investigate there.
Code
// StateID and datatype are fetched from manifest list for each command.
private fun getState(stateId: Int, dataType: Int): Any {
val request =
ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putInt(stateId)
.put(if (false) 1 else 0).array()
try {
conn.outputStream.write(request)
conn.outputStream.flush()
} catch (e: IOException) {
throw IOException("Error sending getState request for id $stateId: ${e.message}", e)
}
val returnIdBytes = ConnectClientHelper.receive(conn, 4)
val returnId = ConnectClientHelper.unpack(returnIdBytes, 1) as Int
val returnLengthBytes = ConnectClientHelper.receive(conn, 4)
val returnLength = ByteBuffer.wrap(returnLengthBytes).order(ByteOrder.LITTLE_ENDIAN).int
val payload = ConnectClientHelper.receive(conn, returnLength)
val value = ConnectClientHelper.unpack(payload, dataType)
Log.d(TAG, "payload (${String(payload, Charsets.UTF_8)}): $value")
return value
}
// below are the methods from ConnectClientHelper class
fun receive(socket: Socket, length: Int): ByteArray {
val buffer = ByteArray(length)
var bytesRead = 0
while (bytesRead < length) {
val read = socket.getInputStream().read(buffer, bytesRead, length - bytesRead)
if (read == -1) {
throw IOException("End of stream reached before reading all bytes")
}
bytesRead += read
}
Log.d(TAG, "Received bytes: ${buffer.contentToString()}")
return buffer
}
fun unpack(bytes: ByteArray, dataType: Int): Any {
val buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN)
return when (dataType) {
0 -> buffer.get() != 0.toByte() // Boolean
1 -> buffer.int // Int
2 -> buffer.float // Float
3 -> buffer.double // Double
4 -> { // String
val length = buffer.int
Log.i(TAG, "Length of string $length")
// Check if there's enough data left for the string
if (buffer.remaining() < length) {
Log.e(TAG, "Not enough data for string $length: ${buffer.remaining()}")
throw Exception("Not enough data for string $length: ${buffer.remaining()}")
}
val stringBytes = ByteArray(length.toInt())
Log.i(TAG, "String Bytes $stringBytes")
buffer.get(stringBytes)
String(stringBytes, Charsets.UTF_8)
}
5 -> buffer.long // Long
else -> throw IllegalArgumentException("Unsupported data type: $dataType")
}
}
Logs
get state for "aircraft/0/systems/fuel/fuel_remaining"
Identifier - Received bytes: [0, 0, 0, 0]
Packet length - Received bytes: [4, 0, 0, 0]
Payload content - Received bytes: [32, 0, 0, 0]
Question
Coding Aviators expert here: Can you help me find the issue or improvement to the code?
I am unable to get past the second getState call. I am not yet sure if the data I received for the first call is accurate.
Thanks in advance form a Lame kotlin coder.