Receiving data back from a BLE embedded device on Android - android

I am working on an Android BLE project. We are using BLE to configure some settings on an embedded device. The embedded device was going to take a long time to come up so I started using BlueSim to emulate the embedded connection.
There are essentially two messages that the Android (I'm requiring KitKat) device sends off to the embedded device. One is to write settings....One is to read the settings.
A Write message is going out to endpoint 0xFFF1 like the following
byte[] data2Send = new byte[11];
data2Send[0] = 0xAA; // signifying this is a write message to device
data2Send[1] = 0x01; // data value
data2Send[2] = 0x38; // data value
data2Send[3] = 0x47; // data value
data2Send[4] = 0x24; // data value
data2Send[5] = 0x01; // data value
data2Send[6] = 0x36; // data value
data2Send[7] = 0x49; // data value
data2Send[8] = 0x0b; // data value
data2Send[9] = 0x63; // data value
data2Send[10] = 0x0D; // CR to indicate the last byte of the packet
characteristic.setValue(data2Send);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
Log.v(TAG,"Status is:" + String.valueOf(status));
I had verified this using BlueSim and we have confirmed that this works when transmitting data to the embedded device. We can successfully change all of the settings.
The other message is a Read request of the device so I can know what settings are already in there or to confirm that the settings actually changed.......
byte[] data3Send = new byte[3];
data3Send[0] = 0x55; // Signify this is a start of a READ message
data3Send[1] = 0x42; // Second part of the read designator
data3Send[2] = 0x0d; // Carriage return saying this is the last bit
characteristic.setValue(data3Send);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
Log.v(TAG,"Status is:" + String.valueOf(status))
When I send this message over to BlueSim, I see the message on my iPhone and immediately send the settings back out. On Android I see the 11 bytes that are coming back informing me of all the settings! This almost happens instantaneously. Great!
But when we do this on the embedded device I see one byte come back. That's it. Using a debugger on the embedded side we can see all 11 bytes going into the BLE module on the embedded device. If we use a PC rather than my Android device we can see all 11 bytes show up on the PC (the manufacturer of the BLE module has a terminal like app that you can 'sniff' the data with).
The embedded device is an 8 bit micro that is hooked up to a BLE module (TI CC2540 chipset) via a UART so it's obviously SLOWER than the iPhone where BlueSim is running. The embedded device is going to need some time to receive the BLE message, process the request, and shove data back out the BLE module. Is there some setting I have to set in my Android program to allow for a slower response to come back?
I tried downloading LightBlue on iOS and sending that read request out, and we get the same results. We see the first byte of the data packet show up in LightBlue. But only that one.
Any help would be greatly appreciated as always.

It sounds like you are experiencing an issue with the TI Module, not Android. Not sure if its the same issue, but it seems others have been getting headaches from trying to establish connections from Android to the CC254X. See here: https://e2e.ti.com/support/wireless_connectivity/f/538/t/401240

Related

Android BLE connection breaks when sending many packets with WRITE_TYPE_NO_RESPONSE

I am getting crazy with a project where I need to send firmware files from an Android device to a STM32F4 chip using Bluetooth LE.
I have already implemented BLE on both ends successfully and I am working with it with several characteristics for a long period without any problem.
Now a file transfer ought to be implemented that shall be able to send files in size of about 250K. My implementation seem to work but only in one of 10 cases. It does start sending packets in chunks of 20 bytes but then it
stops communication in 90% of the test cases on an undetermined point. I need to disconnect/reset and restart to get things up again.
Characteristic for file transger on the STM32F4 are defined as:
ret = aci_gatt_add_char(fileServiceHandle,
UUID_TYPE_128, // File xfer UUID
uuid, // Char UUID
FILEIO_RECORD_LEN, // Maximum length of the characteristic value (20)
CHAR_PROP_WRITE|CHAR_PROP_WRITE_WITHOUT_RESP|CHAR_PROP_NOTIFY, // WRITE NOTIFY me
ATTR_PERMISSION_NONE, // Nothing special
GATT_NOTIFY_ATTRIBUTE_WRITE, // The application will be notified when a client writes to this attribute.
// An #ref EVT_BLUE_GATT_ATTRIBUTE_MODIFIED will be issued.
16, // Encryption key size
0, // is fixed length (1== variable size)
&fileRequestHandle); // ReturnValue als handle
In Andoid I am setting the WRITE_TYPE_NO_RESPONSE flag in the service characteristic to
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
... aServiceCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
Writing the packets is done in the onCharacteristicWrite call back function for a FIFO of maximum 8 packets.
Build up to 8 fragments of file data and queue it to a fifo
wrtCharacteristic.setValue(firstQueueItem);
in onCharacteristicWrite call back: if queue not empy { wrtCharacteristic.setValue(nextQueueItem); }
If the last packet is received in the STM32F4, all packets in that group are verified and an acknowledge is send back causing an event in the APP.
The event then triggers sending the next 8 packets.
This looks pretty straight forward to me and seem to work sometimes. It works always though if I am setting the number of consecutive blocks to 1. All other sizes do not complete sending the in files in almost all cases.
There is no evidence of when the transfer is broken, sometimes immediately, sometimes after sending more than 80% of the data.
I have also tried to skip writing the received data on the STM32F4 to the flash storage to avoid SPI interferences without any changes in behavior.
Is there anything that I am missing here? Where could I check for errors. Any help wouldbe very much appreciated.
For unknown reasons, this problem does occur any longer. My implementation has not changed compared to what I stated on top. I tried to request a BLE response for the last packet of each group but that does not seem to make any difference.
I thank everybody who read and commented on this entry.

How to receive files programmatically using bluetooth

I am trying to receive data (strings) from a Bluetooth enabled device whose MAC_ID is known.
I have searched many examples ,but each article is pointing to Bluetooth Chat example, I think in Bluetooth Chat example, application need to be installed on both the devices for them to be connected and exchange strings.Correct me if I am wrong.
But I need to install application only on Receiver device.I have tried installing the application only on one device and tried connecting to the sender device, without success.
Bluetooth is a peer to peer protocol where you need to have application running on both sides. Hence if you want to exchange data very good example would be Bluetooth chat. If you want to download or transfer a file you should either implement obex or FTP profile based applications.
Yes you need to deploy an application on both sides. If you are really restricted in a way that you only can deploy on one side, you have to figure out which standard protocols/bluetooth profiles the other side is capable of. You can figure that out by doing a SDP lookup. For a device, you will then get a list of UUIDs identifying these services. See the bluetooth spec for well known UUIDs. As #7383 pointed out, your are most probably looking for OBEX or FTP.
If you can deploy on both sides, you can write your own app using Blaubot (disclaimer: I wrote it). A simple Blaubot program would do this:
UUID MY_UUID = UUID.fromString("33bb1246-1472-11e5-b60b-1697f925ec7b");
// onCreate() or in a service, we create a blaubot instance
// using Bluetooth to form a network and Bluetooth + NFC to find devices
IBlaubotDevice ownDevice = new BlaubotDevice();
BlaubotUUIDSet uuidSet = new BlaubotUUIDSet(MY_UUID);
BlaubotBluetoothAdapter bluetoothAdapter = new BlaubotBluetoothAdapter(uuidSet, ownDevice);
BlaubotNFCBeacon nfcBeacon = new BlaubotNFCBeacon();
BlaubotBluetoothBeacon bluetoothBeacon = new BlaubotBluetoothBeacon();
this.mBlaubot = BlaubotAndroidFactory.createBlaubot(MY_UUID, ownDevice, adapter, nfcBeacon, bluetoothBeacon);
// start and wait until connected
this.mBlaubot.startBlaubot();
// create a channel and send your file
IBlaubotChannel fileChannel = this.mBlaubot.createChannel(1);
// convert your file to its bytes
File yourFile = // ... however you get it
byte[] fileBytes = ...// ... see http://stackoverflow.com/questions/858980/file-to-byte-in-java
// send it to all connected devices
fileChannel.publish(fileBytes, true);
// to receive it on the other device, do this:
// subscribe to the channel
fileChannel.subscribe(new IBlaubotMessageListener() {
#Override
public void onMessage(BlaubotMessage message) {
// extract your bytes from the message
byte[] fileBytes = message.getPayload();
// .. do something useful or write it to a file again
// to write it to a file
File file = new File(yourFilePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(fileBytes);
bos.flush();
bos.close();
}
});
This should be all you need. To allow the devices to connect, you have to pair them before or use NFC (just hold them together, when Blaubot is started). If you go with Blaubot let me know if you have problems that can't be solved with the documentation or the android quickstart guide.
I can only guess what your actual scenario looks like. If you have two android phones, this should work. If that is not the case, you should add more informations about the involved devices. Are we really talking about (classic) Bluetooth connections or are you trying to get data from a Bluetooth Low Energy device?
In this case the famous chat example will not help you either.

How to check at one phone whether the other phone is getting an incoming call?

I have two phones which are paired and connected via bluetooth. How to programmatically check at one phone's end whether the other phone is getting an incoming call? Should I use a particular profile for this, that is, PBAP or HFP? If yes, how I am to do this?
Once I detect this, if I want to receive the incoming call via the connected phone, how should I implement that?
Download Hands Free Profile pdf. It is available easily. It provides you all details about how HFP works and AT commands supported by HFP for communication. No APIs available for this.
As eliasj said, you need to implement HFP and when two phones get connected, you can communicate between them via AT commands.
Suppose you have 1st phone which is Android device and 2nd phone Android or any device and they both are connected over HFP.
I don't have complete code but I can suggest you some AT commands -
1. Using AT+CIND? command you can read indicator status of other phone.
2. To enable reporting for Indicator status change, you need to use AT+CMER=3,0,0,1 command.
3. Once you get valid response from 'AT+CMER' command, you can use AlarmManager that will start a service which continuously reads the input stream of Bluetooth Socket.
4. Because of step 2., if the 2nd phone is having any incoming call, the input stream of Bluetooth Socket will contains RING as an alert.
I have used service implementing a Runnable. Here is a sample code for step 4.-
public void run()
{
try
{
// Get input and output streams from Bluetooth socket.
m_oInputStream = m_oBluetoothSocket.getInputStream();
m_oOutputStream = m_oBluetoothSocket.getOutputStream();
// Read input stream for +CIEV response is given or not.
byte[] buffer = new byte[200];
int nNumberOfBytesRead = m_oInputStream.read(buffer);
String strResponse = new String(buffer).trim();
if(true == strResponse.contains("RING"))
{
// Contains RING Alert. Answer the call.
// Start Activity for handling Incoming Call.
Intent oIncomingCallActivityIntent = new Intent(getApplicationContext(), IncomingCallActivity.class);
oIncomingCallActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
getApplicationContext().startActivity(oIncomingCallActivityIntent);
// Stop service.
stopSelf();
}
}
catch(Exception e)
{
// Log the error.
}
}
You need to implement acivity that handles incoming call. It will accept or reject call. To accept incoming call AT+ATA command is used. You will receive "OK" as a response from 2nd phone.
I hope this will help you.
You should implement HFP (the hands-free side). When I looked at this problem over a year ago it was not possible to send the audio between to phones (Android) but it could have change now.
Look at the Q/A in How to send AT commands based on BT Hands-Free profile in android? (hit on how to connect) and in the HFP spec https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=238193 (for how the profile works (incoming call on page 36))

Connecting B4A Android Application to Desktop using VB6

I am using basic4android and have created an application which simply stores and pushes all mobile phone keystrokes. This is functioning when I storing and dumping the data remotely online, however I am attempting to store the data to display on a listening vb6 form application. Basically each time a new record of X number of words is triggered, it should simply display that text block on my running VB form label. Please note I am using a usb cable from the device to the PC. Sorry about the noob question.
How can I push data from my android device to my listening VB6 form app via USB?
Thanks.
This is a tricky one, since it is not obvious what is the driver that is talking to the android phone. If you are lucky, the driver maps itself to a COM port. For instance, on my box, the "Samsung Mobile USB Modem #2" device maps itself to COM4.
If your device is using a COM port mapping, then add the Microsoft Comm Control to your Components list. Simple code which waits for input forever, and writes to Debug.Print is as follows:
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
MSComm1.CommPort = "4" ' <=== "1" = COM1, "2" = COM2, "3" = COM3, "4" = COM4
MSComm1.Settings = "1200,n,8,1" ' You can probably replace 1200 with a much higher value, e.g. 230400
MSComm1.RThreshold = 1
MSComm1.InputLen = 1
MSComm1.PortOpen = True
Do
DoEvents
Debug.Print MSComm1.Input
Loop Until False
If the driver uses other mechanisms, this will be a lot more complicated, and require messing around with drivers and the Windows API - not for the faint-hearted.
Like Mark Bertenshaw said, although I wouldn't loop to obtain the data but use the OnComm() event:
Private Sub MSComm1_OnComm()
Dim strInput As String
Select Case MSComm1.CommEvent
Case comEvReceive
strInput = MSComm1.Input
Debug.Print strInput
End Select
End Sub

Asynchronous bulk data transfer

I am working on USB communication between an Android Galaxy S III smartphone and a device which does not conform to Android Open Accessory device definition. I want to transfer asynchronously bulk data from the device to the host. The connection between the host and device works correctly, what has been verified by sending control commands to the device.
Can this transfer be done with an endpoint of the bulk type (USB_ENDPOINT_XFER_BULK) or it has to be the interrupt type (USB_ENDPOINT_XFER_INT) as it is specified in the MissileLauncher app sample?
Does the request.queue call fill the data buffer after the connection.requestWait returns or some other conditions need to be checked?
You must do your bulk transfer with your bulk endpoints either you do asynchronous or synchronous transfer(USB_ENDPOINT_XFER_BULK).
I can not give clear answer for you second question because I have too problem about this subject. I can fill my buffer with below code. Generally connection.requestWait() method is calling after request.queu(...) method. But I have problem in this state
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.order(ByteOrder.LITTLE_ENDIAN);
UsbRequest request = new UsbRequest();
request.initialize(usbDeviceModel.getConnection(), usbEndpoint2);
request.queue(buffer, 512);
if(request == usbDeviceModel.getConnection().requestWait()){
Message msg = imageViewFragment.usbDataHandler.obtainMessage();
msg.obj = buffer.array();
imageViewFragment.usbDataHandler.sendMessage(msg);
}
I want to send data to my activity with handler after if condition but I can not send when my device plugged in to android device. Only when I plugged out my device if condition is working and I can send data to activity with handler. (https://stackoverflow.com/questions/35350251/android-asynchronous-bulk-transfer-with-usb-host-api#)

Categories

Resources