BLE sends junk data on onLeScan - android

Working on Bluetooth communication using https://github.com/GitGarage/BLEMingleDroid
While receiving data I am getting some junk Char appended to my real message, below is my code for sending and receiving message
AdvertiseData
byte[] data = message.getBytes();
ParcelUuid pu = ParcelUuid.fromString("0000" + asHex(message.substring(0,2).getBytes()) + "-0000-1000-8000-00805F9B34FB");
AdvertiseData.Builder builder = new AdvertiseData.Builder();
builder.addServiceData(pu, data);
builder.addServiceUuid(pu);
Receive Data
#Override
public void onLeScan(final BluetoothDevice newDevice, final int newRssi,
final byte[] newScanRecord) {
String message = new String(newScanRecord);
TextView textViewToChange = (TextView) findViewById(R.id.textView);
String oldText = textViewToChange.getText().toString();
String device = newDevice.getAddress();
String rssi = "" + newRssi;
}
I am not sure for what reason this junk appended to my real message, any idea?

That's not junk data. The scanRecord is an array of bytes, so you can't just convert it to a String.
void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
The scanRecord often contains strings, like the advertised device name, but it also contains service uuids, and other data that needs to be parsed. You need to manually parse this data. The scanRecord will have a byte indicating the length, a byte indicating the data type, then the data. Additional length, type, value bytes can follow the first one. The type codes are listed in the Generic Access Profile documentation.

Related

Sending a large string via NFC

I'm trying to send large string from device to device with NFC. I understand that is possible in specs? But how to do it?
At the moment I have this kind of solution
NdefRecord data = NdefRecord.createExternal("A", "ROW2", selected.substring(0, 4000).getBytes(Charset.forName("UTF-8")));
NdefMessage msg = new NdefMessage(new NdefRecord[]{
data
});
Log.d(TAG, msg.getByteArrayLength() + " Byte array");
nfcAdapter.setNdefPushMessage(msg, this, this);
I try to send string from 0 to 4000 but it don't work.

Sending Arduino ADC Data to Android Tablet via USB Serial

I'm trying to send Arduino ADC data to android tablet using USB serial Communication. I'm using Serial.println() at arduino side. My Issue is that I'm not able to Decode the data received at the android end.
For Eg. Suppose I send Serial.println(768) from arduino, I check my android receive buffer and it Shows (55,54,56,13,10).
How can i decode this data back to 768 value?
Looking into an ASCII table you'll find that
55,54,56,13,10
represents
"768\n\r"
Most programming languages provide means for conversion between byte values and characters/strings with their string libraries. So you don't have to implement the decoding yourself.
Refer to https://howtodoinjava.com/array/convert-byte-array-string-vice-versa/
or UTF-8 byte[] to String
or anything else you find online for "byte to string Android"
String rawdata = " " ;
String finaldata = " ";
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
#Override
public void onReceivedData(byte[] arg0) {
byte[] buffer = arg0;
for (i =0;i <=(buffer.length-1);i++) {
if(buffer[i]!= 13) {
if(buffer[i]== 10){
finaldata = rawdata;
rawdata = "";
}else {
chdata = (char) buffer[i];
rawdata += chdata;
}
}
}
data = Integer.parseInt(finaldata);
}

Get temperature data from SensorTag as an advertisement

I am doing some works with Texas Instruments SensorTag CC2541. I am trying to show the temperature data in the advertising packets.
First, I implemented the temperature service UUID in the advertising data packet. This is done in the SensorTag.c firmware (using IAR Workbench for 8051).
static uint8 advertData[] =
{
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
0x03,
GAP_ADTYPE_16BIT_MORE,
LO_UINT16(IRTEMPERATURE_SERV_UUID),
HI_UINT16(IRTEMPERATURE_SERV_UUID)
};
And here is the Scan Response Array:
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8 scanRspData[] =
{
// complete name
0x0A, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
0x53, // 'S'
0x65, // 'e'
0x6E, // 'n'
0x73, // 's'
0x6F, // 'o'
0x66, // 'f'
0x74, // 't'
0x69, // 'i'
0x61, // 'a'
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),
HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),
0x03,
GAP_ADTYPE_16BIT_MORE,
LO_UINT16(IRTEMPERATURE_SERV_UUID),
HI_UINT16(IRTEMPERATURE_SERV_UUID)
};
Then, I use a sample Bluetooth Low Energy GAT application and modify it to show the data when it is scanning. The original app was used for another beacon device and it showed the beacon name + RSSI + thermometer service when scanning.
Here is the original code:
class TemperatureBeacon {
/* Full Bluetooth UUID that defines the Health Thermometer Service */
public static final ParcelUuid THERM_SERVICE = ParcelUuid.fromString("00001809-0000-1000-8000-00805f9b34fb");
/* Short-form UUID that defines the Health Thermometer service */
private static final int UUID_SERVICE_THERMOMETER = 0x1809;
private String mName;
private float mCurrentTemp;
//Device metadata
private int mSignal;
private String mAddress;
/* Builder for Lollipop+ */
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TemperatureBeacon(ScanRecord record, String deviceAddress, int rssi) {
mSignal = rssi;
mAddress = deviceAddress;
mName = record.getDeviceName();
byte[] data = record.getServiceData(THERM_SERVICE);
if (data != null) {
mCurrentTemp = parseTemp(data);
} else {
mCurrentTemp = 0f;
}
}
/* Builder for pre-Lollipop */
public TemperatureBeacon(List<AdRecord> records, String deviceAddress, int rssi) {
mSignal = rssi;
mAddress = deviceAddress;
for(AdRecord packet : records) {
//Find the device name record
if (packet.getType() == AdRecord.TYPE_NAME) {
mName = AdRecord.getName(packet);
}
//Find the service data record that contains our service's UUID
if (packet.getType() == AdRecord.TYPE_SERVICEDATA
&& AdRecord.getServiceDataUuid(packet) == UUID_SERVICE_THERMOMETER) {
byte[] data = AdRecord.getServiceData(packet);
mCurrentTemp = parseTemp(data);
}
}
}
private float parseTemp(byte[] serviceData) {
/*
* Temperature data is two bytes, and precision is 0.5degC.
* LSB contains temperature whole number
* MSB contains a bit flag noting if fractional part exists
*/
float temp = (serviceData[0] & 0xFF);
if ((serviceData[1] & 0x80) != 0) {
temp += 0.5f;
}
return temp;
}
public String getName() {
return mName;
}
public int getSignal() {
return mSignal;
}
public float getCurrentTemp() {
return mCurrentTemp;
}
public String getAddress() {
return mAddress;
}
#Override
public String toString() {
return String.format("%s (%ddBm): %.1fC", mName, mSignal, mCurrentTemp);
}
}
As you can see, the program uses the THERM_SERVICE UUID (00001809-0000-1000-8000-00805f9b34fb) and its short form (0x1809). I tried to modify it with the SensorTag IR Temperature UUID service (F000AA00-0451-4000-B000-000000000000). And the result is that, it cannot show neither the name of the scanned device nor the temperature data.
Can you give some suggestions for this problem? Thank you!
The missing part in your question is the scan response structure in your modified SensorTag code. The advertData only notifies the central (iOS) of it's presence and available services (temperature). The scan response may carry more information, such as the value of the temperature. Could you post the scan response array?

Android bluetooth communication with 2 Activities

I'm can send data from the phone to the arduino and get a response in the phone, but just in the same activity, for practical reasons I need to show the data received in the phone in another activity, so I try to pass the received data using the put extras option but I get an error and te aplication crashed, because the data is receiving in other thread I think that that could cause problems if the received data isn't complete before launch the second activity, any sugestions?
ok i have done this a really long time ago and i don't remember exactly what changes i made in the bluetooth sample so just follow these steps and you will be sending and receiving strings from any class.
if you are using the bluetooth chat example in android sdk samples, then do the following:
-in the bluetoothchat class:
*change "private" BluetoothChatService mChatService into "public".
then in the activity you want to send a string from do this
BluetoothChat.mChatService.write(byteArray);
where byteArray is as it sounds an array of bytes, so you need a a string to byte array converter to make things easy:
public static byte[] convertStringToByteArray(String s)
{
byte[] byteArray = null;
if(s!=null)
{
if(s.length()>0)
{
try
{
byteArray = s.getBytes();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
return byteArray;
}
that's for sending, and as for receiving:
what i did is make a Boolean for entering and exiting a specific class so for example when i enter a class i would make this Boolean true and forward the string i receive in the Bluetoothchat class to the class i want, like for example you will go to the bluetooth chat class at these code lines:
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
where readMessage is the string message you recieve , but instead you will make it "readMessage" a public static variable.....so you would say if i'm in activity for example number one then set the static boolean value to true and you would make a function for example called update which checks if the boolean was true then get the readMessage string and do whatever you want with it , like set text for example:
if(Bluetoothchat.one==true)
tv.settext(Bluetoothchat.readMessage);
then you need to change this boolean to false when you exit the current activity you are in so the application won't crash, so you can do something like this:
#Override
public void onBackPressed() {
BluetoothChatone.one=false;
super.onBackPressed();
}
and if you get errors tell me so i can see what i have missed to tell you.

Buffer and value filter

I'm running trough a curious bug where I receive bad values from a serial connection. I created a post earlier but no one have responded yet.
[other problem] : Bluetooth SPP (serial) glitchs (Android)
Because I would like to finish this project soon I think I will have to implement a "patch" that will filter all the values. If the new value is around +/- 15% to my previous value I will keep it and if it exceed this cutoff range I will discard it. Here is the code where I receive the values :
hBluetooth = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECEIVE_MESSAGE: // If we receive a message
byte[] readBuf = (byte[]) msg.obj;
String stringIncome = new String(readBuf, 0, msg.arg1); // Create string from byte array
stringBuilder.append(stringIncome);
int endOfLineIndex = stringBuilder.indexOf("\r\n"); // Determine the end-of-line
Log.e(TAG, "Line"+endOfLineIndex);
if (endOfLineIndex > 0) { // If we are at the end-of-line we parsed all the data that was sent
rmsgBluetooth = stringBuilder.substring(0, endOfLineIndex); // The string is extracted in a string object rmsgBluetooth
stringBuilder.setLength(0);
Could some one help me to implement a filter that will output the retained value in a string ? Thanks.
Here is my solution :
sensorReading = Float.parseFloat(rmsgBluetooth);
if(Math.abs(sensorReadingOld - sensorReading)<10 || sensorReadingOld == 0 ){
sensorReadingOld = sensorReading;
}
else {
sensorReading = sensorReadingOld;
}

Categories

Resources