Getting Response for Android BLE Write Characteristic - android

I am invoking the writeCharacteristic both using the WRITE_TYPE_NO_RESPONSE and without it.Am I supposed to get the response out of both or one or none?
Is there any callback to catch this response?
Does onReliableWriteCompleted callBack ensures the successful delivery of the Message at the BLE device side(from the Phone) or does it implies that the message has been sent to the device(From the Phone) successfully and has been released in air.

If you use the WRITE_TYPE_NO_RESPONSE, you will get the onCharacteristicWrite callback as soon as the stack is ready and has space to accept a new request. This does not mean the other side has received it.
If you don't use WRITE_TYPE_NO_RESPONSE, you will get the onCharacteristicWrite callback as soon as the remote device has sent back a Write Response.
The onReliableWriteCompleted will be called when the remote side has acknowledged everything.

Related

android BLE write command with response, no response receive

i'm developping an android app that communicate with a BLE device(in kotlin).
i'm sending a command to the ble device, the device usually give the following response:
-OK(confirming the command was received and valid)
-one or multiple line of data
-Done
in onCharacteristicWrite i tryed to show this.value to read the response but look like it's not the way to do it. i googled a lot without lot of success.
so my question is how could i get the data from the response.the device send?
i try to call a readCharateristic without success either.
thank you for your help
GATT does not have any protocol feature of a request - response transaction where both messages embed data.
For Write Request - Write Response, only the request can contain data. The response can only be empty or an error code.
For Read Request - Read Response, the request contain only what characteristic is to be read and the response contains some data or an error code.
To implement a request - response mechanism using GATT, one usually follows one of the following strategies:
Use Write Request or Write Without Response for the request message and Notification for the response message.
Use Write Request or Write Without Response for the request message. When the GATT server produces a response message, it is put in a characteristic that the client will then read using a Read Request.
The first method has lowest overhead and best throughput.
What you should do is to investigate what method your peripheral actually uses. If it sends its responses in notifications, you must enable these and implement the onCharacteristicChanged callback.

How to handle a connection issue during a .GET request?

I have an android app which do some .GET calls by using Ion library.
The server on each call returns a web page which i will then format and transform in real object data.
When the server receive the .GET request it locks the access to that request.
So if i make the .GET to /example/?PAGE=1 the first request will return all needed data while if i will try to get it again i will receive a string like LOCKED until i will send another request like /example/?UNLOCKPAGE=1
The main issue of that is that the content of the page coult be very large and the device which is trying to fetch it could have a very bad network connection from which he could be disconnected at any time.
So if i make the .GET request and the device immediatly goes offline the server will lock the page but in facts the device didn't received that data.
How could a situation like this be solved?
I tought about a situation where on the .GET request the content is not locked until the device didn't send another request that confirms that he get all the data, but at this point what will happen if two devices will try to get both the same data and one of them get it first, will both of them get the data? Is that the right way?

Response from readCharacteristic is not always as expected after issue writeCharacteristic

I'm working on an android BLE app. I have a BLE device which storing the coordinates of where the device went.
In order to get the data from the device after connected, we will need to send several commands and read its response. The steps are as follow:
Send first command to device
Read response (some data..)
Send second command to device
Read response (coordinates)
And this is how I did
After connected, sending a command to the device by using writeCharacteristic
When receiving GATT_SUCCESS in onCharacteristicWrite callback, call readCharacteristic to read its response
When receiving GATT_SUCCESS in onCharacteristicRead callback, continue to send second command to the device by using writeCharacteristic
When receiving GATT_SUCCESS in onCharacteristicWrite callback, call readCharacteristic to read its response
So here's the problem, when I issued readCharacteristic after write operation succeeded, the response is not expected as always and sometime it return the same command that I wrote. However, if I put some delay (e.g. 1 second) after I write, the response is correct when I read but the delay may different every time.
I am wondering if anyone having the same issue like this or anyone can explain to me why is this happening? Is that possible that we can know when is the correct time to read the characteristic?
Note: The device does not provide any notification/indication.

Lost messages with aSmack

i'm using aSmack in my Android app to receive messages from my Desktop-Jabber-client. This works fine and even if my android phone is offline (after the connection was closed properly) it will receive the offline messages after the next login.
But when i enter the airplane-mode on the phone or shutdown the phone so that the connection is abruptly closed (without calling disconnect() on the Connection-object) the phone stays "online" in the contact-list of my Desktop-Jabber-client for a while and i can send messages to it. However these messages never arrive. Even though the phone logs in to the server again. These messages are lost.
Does anyone know how to fix this issue? Losing messages in a chat is not an option. :)
EDIT: Added Test-Code
BroadcastReceiver: http://pastebin.com/cFLzGXgy
Service: http://pastebin.com/wLpQCQfT
The first one is a BroadcastReceiver starting the service (second URL) each time the phone is connected to a network.
PS: This is only a test-code! You must change the server/username/password if you want to use/test it.
You can try to send delivered message from client b to client A when the message arrival. The problem is if the client A is offline (no connection break) the delivered confirm don't send until the user receives the message and the client B can't re-send the message.
you can try to send acknowledgement of receiving the message using Smackx Message Events
this will assure the message is delivered else you take corrective action.
this problem occurs when your connection broke.
You need "Stream Management" XEP-198 enabled connections to achieve this messages. refer to this blog : http://op-co.de/blog/posts/XEP-0198/ Basically it allows for stanza acknowledgement and stream resumption, which is exactly what you want to do in case.so you should wait till smack will 4.1 release.

Doing something just BEFORE wifi disconnection

I understand that on a wifi network there are sudden disconnections which prevent me from sending messages to my server.
But sometimes there's still one last chance before the disconnection, for example if the signal is low or the user is trying to turn off the wifi. On those occasions I would like to send a logout message to my server.
How do I detect disconnections like those?
I tried to retrieve changes of connectivity by registering a broadcast listener:
registerReceiver(this,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
...
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if( (info.getState()== State.DISCONNECTING) && (info.getType() == ConnectivityManager.TYPE_WIFI) ) {
//send logout
}
But it looks like at that time it's already too late. My logout message doesn't go through.
Is there a better way?
[Update 1]
I also tried:
if( (info.getDetailedState()== DetailedState.DISCONNECTING) && connectionTypeOK ) {
[Update 2 - SOLUTION]
The solution is, as stated below, using a combination of receiving the RSSI_CHANGED_ACTION and WIFI_STATE_CHANGED_ACTION broadcasts to monitor the signal strength and the WIFI_STATE_DISABLING events respectively. When this happens, I send my logout request. This works exactly as I needed. Thanks!!
You could try to implement a variable "heartbeat" function, by using WifiManager to detect changes in signal strength. Here you can find some related code, btw.
Now, once you receive a RSSI_CHANGED notification, according to the corresponding signal strength, you will update the frequency of your app's "heartbeats" to the server: if the signal is strong, you will only need to notify the server infrequently that the app is alive. Once the signal becomes week, however, just like adrenaline kicking in for a real live being, so should your app notify the server more frequently. If the signal's strength recovers, you'll send a specific message to let the server know everything is all right again; if, however, the server does not receive this message in a certain period of time and the "heartbeat" stops - your app ceases notifications for that amount of time - then the server logs it out until receiving from it again.
If you're based on TCP connections, the server should know when a session disconnects unexpectedly - it will get an RST or FIN packet, depending on the router configuration between the client and server.
There's no need to do anything from the client's point of view - TCP connections are designed so you can know when they're interrupted.
Why don't you have the server regularly ping the client, at certain intervals, and just log out if it doesn't get a response? Trying to make this happen through client side will be cumbersome.
A better way is not to have sessions at all, if possible.
Why is it a problem if the user doesn't log out?
Maybe this is a long shot.. but why don't you use Google push notifications to start an activity if wifi is on. That would tell the server that the phone is "online". If that doesn't happen in X seconds or 1 minute ou whatever, redirect it to somewhere else.
I would implement a handler on the server that handles when the client is not able to receive a message. After each message the phone could send a message back to the server saying it successfully received the message.
are you looking for a good way for users to send / receive data after a disconnection?
HTML5 has a local storage (with a good file size too) so if a user is attempting a huge form, you first save it locally and then attempt to send it to server. if failed when the user loads the page again, you can first check if the file has some content, and if so, you can send that data, clear the content and proceed accordingly.
may be this will help you out http://www.html5rocks.com/tutorials/appcache/beginner/
or look at the local storage tutorial: http://www.youtube.com/watch?v=h0uZIljjElo
using this you could save frequent status data and modify it on the fly.
and Android should support HTML5 too.

Categories

Resources