Closed lhtrevisan closed 4 years ago
Ok... I got further on it by myself but I'm still facing some problems... Here is what I did so far:
1st: I've added a read line to the serial setup, pointing to a callback:
private val broadcastReceiver = object : BroadcastReceiver(){ override fun onReceive(context: Context?, intent: Intent?) { [...] m_serial!!.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF) m_serial!!.read(mCallback) [...]
2nd: Then I wrote the callback to get the data from Serial:
private val mCallback = UsbSerialInterface.UsbReadCallback { MyVariables.receivedText = String(it, Charsets.UTF_8) understandSerial(MyVariables.receivedText) }
3rd: I wrote a function to understand the data received trough the callback:
fun understandSerial(msg: String){ val byteArray = msg.toByteArray(Charsets.UTF_8) var prefix : Char = '0' var readingMSG: Boolean = false var messageRead: String = "" for ((index, bytes) in byteArray.withIndex()){ if (readingMSG){ if (bytes == '>'.toByte()){ readingMSG = false handleCommand(prefix, messageRead) //Handle command/information received here } else { messageRead += bytes.toString() // } } else { if (bytes == 'I'.toByte() || bytes == 'V'.toByte() || bytes == '<'.toByte()) { prefix = bytes.toChar() messageRead = "" readingMSG = true } } } }
4th: Every command/information received will then be handled separately by another function:
fun handleCommand(prefix: Char, msg: String){ if (prefix == 'I'){ // Actions for ID Received trough serial } else if (prefix == 'V'){ // Show/update current poured volume on screen } else if (prefix == '<'){ //Actions for commands received: if (msg == "INCOMPATIBLE_TOKEN"){ } else if (msg == "DOC_AUTH_FAIL"){ } else if (msg == "DOC_READ_FAIL"){ } else if (msg == "ABORT_COMMAND"){ } else if (msg == "ABORT_COMMAND2"){ } else if (msg == "WDOC"){ } else if (msg == "UNDEF_DATA"){ } else if (msg == "MAXVOL_END_SERVICE"){ } else if (msg == "IDLE_END_SERVICE"){ } else { //UNKNOWN COMMAND RECEIVED } } }
Everything seems to work fine like this.
Then I tried to show/update the volume poured, measured by the Arduino:
} else if (prefix == 'V'){ tvPouredCost.text = msg }
- Volume is received in this format: "Vxxxx>", and at this point of the code, the variable data is supposed to be "xxxx", without the prefix and stopbit;
Right after the RFID card is read, the app stops working. By the way, the TextView element is declared and initialized right at "onCreate":
private var tvPouredCost: TextView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) context = this setContentView(R.layout.activity_item_list) tvPouredCost = findViewById<View>(R.id.tvValor) as TextView //tvPouredCost.text = "0mL" m_usbManager = getSystemService(Context.USB_SERVICE) as UsbManager val filter = IntentFilter() filter.addAction(ACTION_USB_PERMISSION) filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED) filter.addAction((UsbManager.ACTION_USB_DEVICE_ATTACHED)) registerReceiver(broadcastReceiver, filter) startUsbConnecting()
- If I uncomment the text setting line right after the initialization, it sets the text correctly.
I tried putting a breakpoint inside the callback and running debug, but I was unable to identify the root of the problem. What may be happening here?
i can recommend you to add text updates in a separate thread.
I tought it'd be better if I posted the update in the same thread because, if someone have the same issue I had, they could benefit from de direct answer that I implemented... Of course I can open another thread for the new problem, but what if the problem is related to the way I made the code? If that's the case, I think it should be solved here.
i am sorry i meant to run textupdates creating a user thread or a timer in the program to update the textview:
private void startTextupdateThread() {
Thread th = new Thread(new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
tvPouredCost.setText();
}
});
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
th.start();
}
i am not sure this will fix, but u can try as you said it was fine when you commented that line out.
It Worked! I created a new thread:
private fun startTextUpdateThread(){ val th = Thread(Runnable { // try to touch View of UI thread this@ItemListActivity.runOnUiThread(java.lang.Runnable { this.tvCreds.text = "R$" + MyVariables.actualCredits this.tvValor.text = "R$" + MyVariables.actualPouredCost this.tvVolume.text = MyVariables.actualPouredVol + "mL" }) }).start() }
And passed reference to it inside the handleCommand function:
else if (prefix == 'V'){ MyVariables.actualPouredVol = msg startTextUpdateThread() // Show/update current poured volume on screen }
- Variables are "MyVariables.___" because I put them inside an object, to have access easily everywhere
MyVariables object looks like this:
object MyVariables{ var tapNum: Int = 1 var receivedText: String = "" var CommandReceived: String = "" var actualPouredCost: String = "" var actualPouredVol: String = "" var actualCredits: String = "" }
Hi friends! Calling myself newbie at Android is too much of a complyment for me, as I don't know Jack s*it about it, but I'm adventuring myself into developing a Self Service Beer Tap sistem using Kotlin language anyways. After struggling a bit, I've managed to make the layout for the app and somewhat setting up the serial communication with an arduino board using this UsbSerial library. At this point I was supposed to code serial reading at the app, but I don't know how to do it. Serial communication is set up in the code exactly as the tutorial made by "Apps in the sky": Part 1: https://www.youtube.com/watch?v=QHa6HWTmQFs Part 2: https://www.youtube.com/watch?v=ICjjG1VsZmw&t
The messages/commands that the android will receive will have the following format: ` Ixxxxxxx> Vxxxxxx>