Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onDataReceived not woking ! #154

Closed
deepakjsr7979 opened this issue Nov 30, 2021 · 50 comments
Closed

onDataReceived not woking ! #154

deepakjsr7979 opened this issue Nov 30, 2021 · 50 comments

Comments

@deepakjsr7979
Copy link

deepakjsr7979 commented Nov 30, 2021

onDataReceived how to Received data from device, can help me i want to received data in my serve file.

I able to connect to device, also write to device but not able to received data from device.

Current code IS ====

import {DeviceEventEmitter} from 'react-native';
import RNBluetoothClassic, {
  BluetoothEventType,
  BluetoothDevice,
} from 'react-native-bluetooth-classic';
import {Peripheral} from '../types';
import BleCommunication from './BLEConnection';

const onSessionConnect = (event: any) => {
  console.log('onSessionConnect', event);
};

DeviceEventEmitter.addListener(
  BluetoothEventType.DEVICE_READ,
  onSessionConnect,
);
DeviceEventEmitter.addListener(
  BluetoothEventType.DEVICE_DISCONNECTED,
  onSessionConnect,
);

export default class BlueFireService {
  // private connection: Subscription;
  // private connectionCommunication: Subscription;
  // private reader: Observable<any>;
  public static readSubscription: any;
  constructor() {}
  static addListener(id: string) {
    DeviceEventEmitter.addListener(
      'DEVICE_READ@AC:67:B2:40:48:E2',
      this.onReceivedData,
    );
    // RNBluetoothClassic.readFromDevice(id).then((data) => {
    //   console.warn(data, 'readFromDevice');
    // });
  }
  static removeListener() {
    // bleManagerEmitter.addListener('DEVICE_READ', this.onReceivedData);
    DeviceEventEmitter.removeAllListeners();
  }
  static async connectDevice(id: string): Promise<boolean | unknown> {
    try {
      const connected = RNBluetoothClassic.connectToDevice(id);
      (await connected).onDataReceived(this.onReceivedData);
      return true;
    } catch (error) {
      console.log('error $$', error);
      return error;
    }
  }

  static onReceivedData = (data: any) => {
    console.log('onReceivedData data', data);
  };
  static async writeData(
    id: string,
    string: string,
  ): Promise<boolean | unknown> {
    try {
      return await RNBluetoothClassic.writeToDevice(id, string);
    } catch (error) {
      console.log('error DEE', error);
      return error;
    }
  }
  static async disconnectFromDevice(id: string): Promise<boolean> {
    try {
      let connectedDevice = await RNBluetoothClassic.disconnectFromDevice(id);
      this.removeListener();
      return true;
    } catch (error) {
      console.log('error Listener', error);
      return false;
    }
  }

}
@kenjdavidson
Copy link
Owner

First of all, you should take a look at the documentation and the sample application. You don't need DeviceEmitter directly, nor is this a BLECommunication library.

Yes, it's in the doc:

https://kenjdavidson.com/react-native-bluetooth-classic/react-native/rn-bluetooth-device/#ondatareceived

And the sample application:

https://github.com/kenjdavidson/react-native-bluetooth-classic-apps/blob/1cba89aaa1181998dbcab7a9549a88a9bb5071a1/BluetoothClassicExample/src/connection/ConnectionScreen.js#L140

You're doing a lot of extra addition of subscriptions. The only code you really nead:

static async connectDevice(id: string): Promise<boolean | unknown> {
    try {
      // You're doing the connected device right
      const connected = RNBluetoothClassic.connectToDevice(id);

      // Once you get a connected device, you just need to create the subscription
      const subscription = await connected.onDataReceived(this.onReceivedData);

      // Then you want to store both so that you can communicate and remove the subscription accordingly
      return { connected, subscription };
    } catch (error) {
      console.log('error $$', error);
      return error;
    }
  }

You may want to play with this function based on the documentation and sample app (above).

@kenjdavidson
Copy link
Owner

If you get things working and you find bugs, please re-open the ticket providing all the information that I've requested in the template:

  • Code
  • Logs
  • Debug assistance

Good luck.

@deepakjsr7979
Copy link
Author

this.onReceivedData

is still not getting called when device send the data,

I can see Received 417 bytes from device is been log but no JS method get called.

Can You please suggest me the process i waking with function components, examples r in class based.

@kenjdavidson
Copy link
Owner

All I can do is reference your code to the sample application code and compare it, which you can also do (I've provided the links). Unless you can provide debugging information (either JS or Native, whichever you believe the problem to be) there isn't much I can do.

If you want to post your full repository I can try (at some point, but not any time soon - like really not any time soon) to clone and reproduce the issue.

  • Where do you see the 417 bytes?
  • What happens after the 417 bytes are received?
  • Does the same code see the listener?
  • Does it attempt to read?
  • Is your delimiter setup correctly? this is one of the biggest issues with the String Delimiter connection. If your delimiter is \n but your device is sending \r then you'll never get messages.

You really need to provide substantially more information if you want any form of assistance.

@deepakjsr7979
Copy link
Author

` static async connectDevice(id: string) {

try {
  this.subScription = await RNBluetoothClassic.connectToDevice(id);
  const subScription = await this.subScription.onDataReceived((event) => {
    console.log(event);
    this.onReceivedData(event);
  });

  // Then you want to store both so that you can communicate and remove the subscription accordingly
  return {connection: true, subScription};
} catch (error) {
  console.log('error $$', error);
  // return error;
}

}

static onReceivedData = (data: any) => {
console.log('onReceivedData data', data);
};
static async writeData(
id: string,
string: string,
): Promise<boolean | unknown> {
try {
// return await RNBluetoothClassic.writeToDevice(id, string);
return this.subScription.write(string);
} catch (error) {
console.log('error DEE', error);
// return error;
}
}
static async disconnectFromDevice(id?: string): Promise {
try {
// let connectedDevice = await RNBluetoothClassic.disconnectFromDevice(id);
this.subScription.disconnect();
this.subScription.clear();
return true;
} catch (error) {
console.log('error Listener', error);
return false;
}
}`

  • Where do you see the 417 bytes? - In Android Studio LOG cat
  • What happens after the 417 bytes are received?
  • Does the same code see the listener?
  • Does it attempt to read?
  • Is your delimiter setup correctly? this is one of the biggest issues with the String Delimiter connection. If your delimiter is \n but your device is sending \r then you'll never get messages.

I can see

2021-11-30 19:29:44.463 32552-32666/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: Received 417 bytes from device AC:67:B2:40:48:E2 2021-11-30 19:29:44.463 32552-32666/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: BluetoothEvent.READ listener is registered, providing data

After that noting being loge;

@kenjdavidson
Copy link
Owner

If you're seeing the log, the next step is to start debugging it on that line and see what happens when it attempts to send data.

@deepakjsr7979
Copy link
Author

Is their any other way around to directly send the data to JS method
From
`public class DelimitedStringDeviceConnectionImpl extends AbstractDeviceConnection {
@OverRide
protected void receivedData(byte[] bytes) {
Log.d(this.getClass().getSimpleName(),
String.format("Received %d bytes from device Deepak99 %s", bytes.length, getDevice().getAddress()));

    mBuffer.append(new String(bytes, mCharset));
    Log.d(this.getClass().getSimpleName(),
            "DATA mBuffer " + mBuffer.toString());

// I can see my data here want to directly emit and event to custom event listener?

    if (mOnDataReceived != null) {
        Log.d(this.getClass().getSimpleName(),
                "BluetoothEvent.READ listener is registered, providing data");

        String message;
        while ((message = read()) != null) {
            mOnDataReceived.accept(getDevice(), message);
        }


    } else {
        Log.d(this.getClass().getSimpleName(),
                "No BluetoothEvent.READ listeners are registered, skipping handling of the event");
    }
}

`
this method to js method ?

@kenjdavidson
Copy link
Owner

There are two ways to receive data:

  • Add a READ listener/subscription
  • Repeatedly call device#read() in an interval

There are no other ways. If you're doing one of those and you're not getting data, then until you can show me otherwise I assume your data is invalid:

  • It doesn't have the correct delimiter

or you're attempting to do both manual and listener reads and that will just mess things up.

You cannot add any other custom listeners, you can only add the READ listener built into the module.

@kenjdavidson
Copy link
Owner

The line you want to debug is

while ((message = read()) != null) {

If this doesn't return data, then it won't send anything to the Javascript side.

  • You might be getting 497 bytes of data.
  • Those bytes will be added to the buffer
  • But unless it finds a delimiter from the read() method you won't get anything

Now I admit, it's not done in the best way, the delimited messsages should be put into a QUEUE based on the incoming messages and that queue should be read from, instead of performing the buffer read each time. But regardless of that you should be able to read data.

@deepakjsr7979
Copy link
Author

deepakjsr7979 commented Nov 30, 2021

2021-11-30 22:21:40.761 9209-9396/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: DATA mBuffer {"Date":"01-01-3000","Time":"00:01:19","DOW":"","DevName":"","TermID":"","TermTyp":"","BuildDt":"2021-08-28","TmpltTyp":"ISO","FwVer":"I","FwID":"icon-A01-104113211541e","UncapRcH":"1","UncapRcI":"2","TrCap":"00","TmpltCnt":"","EnrldUsrCnt":"0/0","SensorTyp":"","TzOffset":"","BattStat":"","Lat":"","Long":"","ssid":"123","TtSleep":""}

AS you can see the log "DATA mBuffer " + mBuffer.toString());

It is giving me Object that i am expecting data,,

@kenjdavidson
Copy link
Owner

That's good, you're getting a String representation of a JSON object. The default delimiter is \n so what happens is:

  • onReceivedData gets called with your bytes
  • Your bytes are conveted into a string (JSON data)
  • Your string is added to the buffer
  • It sees a listener
  • It attempts to READ() from the buffer up until the \n

If your JSON data does not end with a \n then it doesn't think that the message is delimited and therefore doesn't actually find a new message to send to the listener.

Can you confirm that you:

  • Understand the point of the delimiter?
  • Are sending data from your device with the delimiter at the end?
  • Are setting your device.connect({ DELIMITER: \n }) correctly?

@deepakjsr7979
Copy link
Author

Just Now i Comminted
mOnDataReceived.accept(getDevice(), mBuffer.toString());

//            String message;
//            while ((message = read()) != null) {
//                Log.d(this.getClass().getSimpleName(),
//                        "BluetoothEvent.READ listener is registered, providing data");
//                mOnDataReceived.accept(getDevice(), message);
//            }

AND directly send the data
mOnDataReceived.accept(getDevice(), mBuffer.toString());

And i
onDataReceived i get back the data

{data , device, timestamp}

SO do i need to do this way?

@kenjdavidson
Copy link
Owner

kenjdavidson commented Nov 30, 2021

I don't think you understand what a delimiter is. The point of DelimitedStringDeviceConnectionImpl is to be able to handle data that looks like this:

This is a message1\nThis is another message2\n

which will return 2 messages to the application:

  • This is a message1
  • This is another message2

Do you see how the messages are delimited by the \n character?

What you're doing is bipassing the delimiter and just sending the full message. The problem with this, is based on your messaging it is possible that a message is bigger than the amount of data read. This means that you might get partial messages in your application.

At this point in time there is no logic to handle EMPTY/NULL delimiters, which might be a handy option? I don't know.

You have two options:

  1. Actually understand the delimiter logic and use it
  2. Just modify the library in the way you have and suffer whatever happens

Your call, but the library is working as it's intended too and this isn't a bug (per say).

@deepakjsr7979
Copy link
Author

this.subScription = await RNBluetoothClassic.connectToDevice(id, {
        delimiter: '\n',
        charset: Platform.OS === 'ios' ? 1536 : 'utf-8',
      });
SENT Object  ==== '{"ht":"45","hy":58,"gt":"85"}\n'

As You suggested i made the changes?

Yet not

 const subScription = await this.subScription.onDataReceived((event) => {
        console.log(event);
        this.onReceivedData(event);
      });

Not working

@kenjdavidson
Copy link
Owner

Like I said, you need to debug the Android code to see why the read() method isn't finding your delimiter.

Your latest change look good in terms of:

  • Delimited being set on connect
  • Delimiter is available in the sent data

But I cannot debug the read() method for you.

@deepakjsr7979
Copy link
Author

Like I said, you need to debug the Android code to see why the read() method isn't finding your delimiter.

Your latest change look good in terms of:

  • Delimited being set on connect
  • Delimiter is available in the sent data

But I cannot debug the read() method for you.

this.subScription.write(string + '\n');

Can you please point out some of the cases in which read() come null,

in my case i can send the new message with \n linke m doing this.subScription.write(string + '\n'); but device not going to revert me back with JSON string object end with \n

as if now while ((message = read()) != null) { this line of code gating false read() is null

@kenjdavidson
Copy link
Owner

You cant read the code for yourself to find that out?

The line will be null when there is no delimiter found in the buffer. It's pretty straight forward. You need to send a delimiter so it knows when a full message has been sent. That's how that works.

You can write your own device connection to do what you want. I wrote it to be generic and extendable.

I'm not sure why the \n is breaking your json parsing, but why not just remove it before json parsing? I chose to keep it in there because I needed the delimiter. If you don't, remove it in the listener.

But it must be in the data from the device.

I don't know. What to tell you at this point.

@kenjdavidson
Copy link
Owner

Actually. Looking at the ios code it looks like the delimiter isn't included. So ya, this could be a bug on Android, but again most of the time a \n delimiter shouldn't break that much.

I'll fix 5he issue when I get a chance with #152

Regardless. You should send in the \n to make it work. Then chop it off before calling JSON.parse() on the react side.

@deepakjsr7979
Copy link
Author

You cant read the code for yourself to find that out?

The line will be null when there is no delimiter found in the buffer. It's pretty straight forward. You need to send a delimiter so it knows when a full message has been sent. That's how that works.

You can write your own device connection to do what you want. I wrote it to be generic and extendable.

I'm not sure why the \n is breaking your json parsing, but why not just remove it before json parsing? I chose to keep it in there because I needed the delimiter. If you don't, remove it in the listener.

But it must be in the data from the device.

I don't know. What to tell you at this point.

my Point is i can Send data with \n to device but device wont send me data string ending with \n
so if device will only send string object what will happen in that case ? will this will still work ? while ((message = read()) != null) {
in my case i can modify my sending string but wont able to modify response from device end ?

**Really appreciate your support Bro a big thanks for your replies **
After we get this fix will post my full working code so all get benefited.

@kenjdavidson
Copy link
Owner

You don't need to send (react native to device) the \n delimiter. As long as it know how to handle the messages.

If you don't control the device code, and cannot add the delimiter, then you cannot use the Delimited String connection (as that's the whole point). This means you have a few options.

  1. You do what you did and modify the code so that it ignores delimiters.

  2. You create your own implementation of of a device connection and load. I don't know the devices api or message format so I can't help.

  3. We add logic in so that a null or empty delimiter sends the full message. This goes against the naming of delimited string so I'm hesitant to do it. It shouldn't have too many issues, and most people would not notice, but it feels wrong.

What device is this that you use?
Why can't you ass the delimiter?

I need more info before I make a change that I feel is not right. I see both pros and cons for a null/blank delimiter.

@deepakjsr7979
Copy link
Author

I don't know this will help or not but i have done one different application with communication with same device using this plugin

all worked good without any delimiter
it was in ionic angular.

private void sendRawDataToSubscriber(byte[] data) {
        if (data != null && data.length > 0) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, data);
            result.setKeepCallback(true);
            rawDataAvailableCallback.sendPluginResult(result);
        }
    }

    private void sendDataToSubscriber() {
        String data = readUntil(delimiter);
        if (data != null && data.length() > 0) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, data);
            result.setKeepCallback(true);
            dataAvailableCallback.sendPluginResult(result);

            sendDataToSubscriber();
        }
    }
private String readUntil(String c) {
        String data = "";
        int index = buffer.indexOf(c, 0);
        if (index > -1) {
            data = buffer.substring(0, index + c.length());
            buffer.delete(0, index + c.length());
        }
        return data;
    }

What device is this that you use? ---
IT's a Biomatric device which sends the data attendance data using Bluetooth in a string OBJECT
like "{"A":"B"}" --- like this only
Why can't you ass the delimiter?

@deepakjsr7979
Copy link
Author

deepakjsr7979 commented Dec 2, 2021

@kenjdavidson
Copy link
Owner

The code you posted doesnt' make any sense. There has to be a delimiter or else int index = buffer.indexOf(c, 0); would return -1 and then it would return "" which is the default data. If that attempted to read data without a delimiter then nothing would happen, just like you're seeing now.

Why can't I ass the delimiter? I don't understand your question?

@deepakjsr7979
Copy link
Author

deepakjsr7979 commented Dec 2, 2021

The code you posted doesnt' make any sense. There has to be a delimiter or else int index = buffer.indexOf(c, 0); would return -1 and then it would return "" which is the default data. If that attempted to read data without a delimiter then nothing would happen, just like you're seeing now.

Why can't I ass the delimiter? I don't understand your question?

you asked me this two question.

What device is this that you use? -- IT's a Biomatric device which sends the data attendance data using Bluetooth in a string OBJECT
Why can't you ass the delimiter?
--- Because i am responsible for app development cant modify any thing in device end.

The code you posted doesnt' make any sense. There has to be a delimiter or else int index = buffer.indexOf(c, 0); would return -1 and then it would return "" which is the default data. If that attempted to read data without a delimiter then nothing would happen, just like you're seeing now.

IN that case how i am able to receive all data which device is sending... without any issue ??

For Connection with device -------------------------

deviceConnection(id: string): Promise<string> {
   return new Promise((resolve, reject) => {
     // if (this.bluetoothSerial) {
     //   this.connection.unsubscribe();
     // }
     this.connection = this.bluetoothSerial.connect(id).subscribe(
       () => {
         // this.storage.setBluetoothId(id);
         this.connectedDevisees = id;
         this.userService.bluetoothConnectionID = id;
         resolve("BLUETOOTH_CONNECTED");
       },
       (fail) => {
         if (this.connectionCommunication) {
           this.connectionCommunication.unsubscribe();
         }
         if (this.connection) {
           this.connection.unsubscribe();
         }
         // console.log(`[bluetooth.service-88] Error conexión: ${JSON.stringify(fail)}`);
         this.globale.showToast(
           `Error: ${JSON.stringify(fail)}`,
           "bottom",
           "errormessage",
           "danger",
           3000
         );
         reject("BLUETOOTH_CANNOT_CONNECT");
       }
     );
   });
 }

For Receiving data from device

suscrivedatain() {
   return new Promise(async (resolve, reject) => {
     try {
       this.bluetoothSerial.subscribeRawData().subscribe(
         (dt) => {
           this.bluetoothSerial.read().then(
             (dd) => {
               console.log(dd);
            },
             (err) => {
            reject(err?.error);
             }
           );
         },
         (err) => {
         console.warn("subscribeRawData err", JSON.stringify(err));
        }
       );
     } catch (error) {
       console.log(error);
     }
   });
 }
case MESSAGE_READ_RAW:
                    if (rawDataAvailableCallback != null) {
                        byte[] bytes = (byte[]) msg.obj;
                        sendRawDataToSubscriber(bytes);
                    }
                    break;

can see the full code
(https://github.com/don/BluetoothSerial/blob/master/src/android/com/megster/cordova/BluetoothSerial.java)

@kenjdavidson
Copy link
Owner

kenjdavidson commented Dec 2, 2021

I have no idea how you're reading data, I can only read the library code that you posted and it's doing exactly the same thing that this is doing. If there is no delimiter found then it will return a "" (in this case it will return a null). You would need to debug the Cordova app in order to confirm what is actually happening.

I'm looking at the full code:

The original method you posted requires a delimiter to be set from delimiter = args.getString(0); which happens in the SUBSCRIBE block:

    // This method calls `readUntil` with the provided delimiter
    private void sendDataToSubscriber() {
        String data = readUntil(delimiter);
        if (data != null && data.length() > 0) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, data);
            result.setKeepCallback(true);
            dataAvailableCallback.sendPluginResult(result);

            sendDataToSubscriber();
        }
    }

When the read happens it:

    private String readUntil(String c) {
        String data = "";

        // Attempts to look up the delimiter in the StringBuffer, which is exactly what happens 
        int index = buffer.indexOf(c, 0);

        // If no delimiter is found the index will be -1, so it will return back a ""
        if (index > -1) {
            data = buffer.substring(0, index + c.length());
            buffer.delete(0, index + c.length());
        }
        return data;
    }

Looking at the options:

buffer.indexOf("") will return 0, which means it will do buffer.substring(0, 0+0) which is nothing
buffer.indexOf(null) will throw an exception

What exactly are you providing in the Cordova app as a string delimiter?

        } else if (action.equals(SUBSCRIBE)) {

            delimiter = args.getString(0);

However arguments work in Cordova, it's the first argument.

@kenjdavidson
Copy link
Owner

Oh I see, subscribeRawData is bipassing the delimiter.
So it always does both sends on read:

  • Send regular (delimiter)
  • Send raw (no delimiter)

which seems like an odd way to do things.

I've created a branch task/blank-delimiter-messages which I don't have time to test.

if you take the code from DelimitedStringDeviceConnectionImpl and put it into your local file and:

  • It compiles
  • It works

I will pull it and release it.

@deepakjsr7979
Copy link
Author

task/blank-delimiter-messages

Sure Bro I am doing it now ... a special thanks to you ones more...👍

@deepakjsr7979
Copy link
Author

deepakjsr7979 commented Dec 2, 2021

DelimitedStringDeviceConnectionImpl

error: cannot find symbol
                counter = mBuffer.length();
                ^
  symbol:   variable counter
  location: class DelimitedStringDeviceConnectionImpl

it will be count

@deepakjsr7979
Copy link
Author

DelimitedStringDeviceConnectionImpl

error: cannot find symbol
                counter = mBuffer.length();
                ^
  symbol:   variable counter
  location: class DelimitedStringDeviceConnectionImpl

it will be count

2021-12-02 21:04:08.734 20475-20587/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: Received 423 bytes from device AC:67:B2:40:48:E2
2021-12-02 21:04:08.734 20475-20587/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: BluetoothEvent.READ listener is registered, providing data

yet

 this.subScription = await RNBluetoothClassic.connectToDevice(id);
      const subScription = await this.subScription.onDataReceived(
        this.onReceivedData,
      );

this.onReceivedData

not gating called

@deepakjsr7979
Copy link
Author

DelimitedStringDeviceConnectionImpl

error: cannot find symbol
                counter = mBuffer.length();
                ^
  symbol:   variable counter
  location: class DelimitedStringDeviceConnectionImpl

it will be count

2021-12-02 21:04:08.734 20475-20587/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: Received 423 bytes from device AC:67:B2:40:48:E2 2021-12-02 21:04:08.734 20475-20587/com.reactnativeultimatestarter D/DelimitedStringDeviceConnectionImpl: BluetoothEvent.READ listener is registered, providing data

yet

 this.subScription = await RNBluetoothClassic.connectToDevice(id);
      const subScription = await this.subScription.onDataReceived(
        this.onReceivedData,
      );

this.onReceivedData

not gating called

 this.subScription = await RNBluetoothClassic.connectToDevice(id, {
        delimiter: '}',
      });
      const subScription = await this.subScription.onDataReceived(
        this.onReceivedData,
      );

and working with adding this delimiter: '}',

@kenjdavidson
Copy link
Owner

Using the delimiter of } is super shady, and will work when you provide a single json object. But if you provide a Json object with child objects, it will blow things up.

With the changes made, and using this code:

 this.subScription = await RNBluetoothClassic.connectToDevice(id, {
        delimiter: '',  // Send a blank delimieter
      });
      const subScription = await this.subScription.onDataReceived(
        this.onReceivedData,
      );

Does it not send the full content?

@kenjdavidson
Copy link
Owner

It also won't work with the latest change where I'm dropping the delimiter.

"This is a test\n" => "This is a test"
"{ id: 1, name: "Kenneth" } => { id: 1, name: "Kenneth" 

Which is now matching IOS but would blow up what you are doing.

@deepakjsr7979
Copy link
Author

Using the delimiter of } is super shady, and will work when you provide a single json object. But if you provide a Json object with child objects, it will blow things up.

With the changes made, and using this code:

 this.subScription = await RNBluetoothClassic.connectToDevice(id, {
        delimiter: '',  // Send a blank delimieter
      });
      const subScription = await this.subScription.onDataReceived(
        this.onReceivedData,
      );

Does it not send the full content?

Yes Your are write.. i just did this for testing.. and check its work or not.. so that i will be sure about the issue..
`Oh I see, subscribeRawData is bipassing the delimiter.
So it always does both sends on read:

Send regular (delimiter)
Send raw (no delimiter)
which seems like an odd way to do things.

I've created a branch task/blank-delimiter-messages which I don't have time to test.

if you take the code from DelimitedStringDeviceConnectionImpl and put it into your local file and:`

IF you can make this working it will add more user to use this plugin without any knowledge of delimiter.

@deepakjsr7979
Copy link
Author

It also won't work with the latest change where I'm dropping the delimiter.

"This is a test\n" => "This is a test"
"{ id: 1, name: "Kenneth" } => { id: 1, name: "Kenneth" 

Which is now matching IOS but would blow up what you are doing.

Yes, but the point is device can sent data with or without any delimiter and code should work in both the case

@deepakjsr7979 deepakjsr7979 changed the title onDataReceived now woking,,, onDataReceived not woking,,, Dec 2, 2021
@deepakjsr7979 deepakjsr7979 changed the title onDataReceived not woking,,, onDataReceived not woking ! Dec 2, 2021
@kenjdavidson
Copy link
Owner

Yes, but the point is device can sent data with or without any delimiter and code should work in both the case

I would fully agree, if the logic wasn't contained in something called DelimitedStringDeviceConnectionImpl. The original library from which this was taken, was a conversion of the library you provided for Cordova. It looks like that Cordova library added this raw data function as a bandaid for this specific case.

I'm not against having an EMPTY delimiter (now that we've discussed it more), since it's something you'd have to configure manually during the connection process, and shouldn't affect anyone who is already using the library with an actual delimiter.

@kenjdavidson
Copy link
Owner

IF you can make this working it will add more user to use this plugin without any knowledge of delimiter.

I won't be adding the same functionality of rawData where:

  • The delimiter is checked
  • The raw data is sent

as that makes no sense to me. But what I will try to get working is:

let device = await device.connect({ delimiter: '' });

Since it will require the developer to be cognizant that their device does NOT send a delimiter and they are aware that they need to handle the data themselves:

  • By ensuring a full message is returned
  • By stitching messages together in Javascript rather than Java/Swift

I think this will work for all parties.

@kenjdavidson kenjdavidson reopened this Dec 2, 2021
@deepakjsr7979
Copy link
Author

deepakjsr7979 commented Dec 2, 2021

IF you can make this working it will add more user to use this plugin without any knowledge of delimiter.

I won't be adding the same functionality of rawData where:

  • The delimiter is checked
  • The raw data is sent

as that makes no sense to me. But what I will try to get working is:

let device = await device.connect({ delimiter: '' });

Since it will require the developer to be cognizant that their device does NOT send a delimiter and they are aware that they need to handle the data themselves:

  • By ensuring a full message is returned
  • By stitching messages together in Javascript rather than Java/Swift

I think this will work for all parties.

 this.subScription = await RNBluetoothClassic.connectToDevice(id, {
        delimiter: '',
      });

Last byte of data gating lost.
As i am received only like this
data: "{"Date":"02-12-2021""Time":"Time""

@kenjdavidson
Copy link
Owner

Sorry, your messages don't make much sense (language barrier I'm sure).

You're connecting with:

let device = await device.connect({ delimiter: '' });

The device is sending:

"{\"Date\":\"02-12-2021\",\"Time\":\"Time\"}"

And you're only receiving:

"{\"Date\":\"02-12-2021\",\"Time\":\"Time\""

Or are you still using the } delimiter??

@deepakjsr7979
Copy link
Author

Sorry, your messages don't make much sense (language barrier I'm sure).

You're connecting with:

let device = await device.connect({ delimiter: '' });  -- **YES**

The device is sending:

"{\"Date\":\"02-12-2021\",\"Time\":\"Time\"}" ---**YES**

And you're only receiving:

"{\"Date\":\"02-12-2021\",\"Time\":\"Time\"" **YES**

Or are you still using the } delimiter??

Yes But latest bulid its seemas to be solved.. i got full JSON object .
BUT NOW IT keeps ON Coming IN infinity and onReceivedData is gating called

@kenjdavidson
Copy link
Owner

Ya, that makes sense..

"".indexOf("",0) will always return 0 now, so it's stuck in the while loop.

Let me update it so that it checks that !mBuffer.isEmpty() && the read works.

@deepakjsr7979
Copy link
Author

Ya, that makes sense..

"".indexOf("",0) will always return 0 now, so it's stuck in the while loop.

Let me update it so that it checks that !mBuffer.isEmpty() && the read works.


while (!mBuffer.isEmpty() && (message = read()) != null) {
                               ^
  symbol:   method isEmpty()
  location: variable mBuffer of type StringBuffer

@kenjdavidson
Copy link
Owner

Dammit, brackets!!

Sorry, I'm making these changes while trying to get something else working.

@deepakjsr7979
Copy link
Author

Dammit, brackets!!

Sorry, I'm making these changes while trying to get something else working.

Its total fine Bro...

still gating this one ---
while (!mBuffer.isEmpty() && ((message = read()) != null)) { ^ symbol: method isEmpty() location: variable mBuffer of type StringBuffer

@kenjdavidson
Copy link
Owner

Ugh, I'm thinking StringBuilder not StringBuffer, buffer doesn't have an isEmpty method.

@deepakjsr7979
Copy link
Author

Ugh, I'm thinking StringBuilder not StringBuffer, buffer doesn't have an isEmpty method.

StringBuffer.length() ?

@kenjdavidson
Copy link
Owner

Yes, already updated

if ((mBuffer.length() > 0 && ((message = read()) != null))

@deepakjsr7979
Copy link
Author

Yes, already updated

if ((mBuffer.length() > 0 && ((message = read()) != null))

GOOD NEWS 😊

Now working as expected... Thanks Bro!..

will this changes will be available on main branch as will ? after some time ?

@kenjdavidson
Copy link
Owner

kenjdavidson commented Dec 2, 2021

If you can do me a favor and just check that the original functionality works.
Just add in any delimiter other than '' and see if it splits the message up?

If you do that for me, I'll merge and publish it now.

I really have to find time to write some unit tests.

@deepakjsr7979
Copy link
Author

If you can do me a favor and just check that the original functionality works. Just add in any delimiter other than '' and see if it splits the message up?

If you do that for me, I'll merge and publish it now.

I really have to find time to write some unit tests.

I have just tested it with } delimiter and it working fine. as i don't have reserved the '}' at the end of JSON object. its fine at my end. 👍

@kenjdavidson
Copy link
Owner

Welp, here's hoping.

Merged and publishing to NPM.

Hopefully this doesn't break a bunch of peoples work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants