rusel1989 / react-native-bluetooth-serial

Port of https://github.com/don/BluetoothSerial for react native
476 stars 291 forks source link

Unable to set a READ listener #87

Open dittmarconsulting opened 6 years ago

dittmarconsulting commented 6 years ago

Hi there,

First of all I love this library and it works like a treat.

I'm able to easily pair, connect, write and read data of 2 BT devices but I'm not able to set a listener for reading data asynchronously after the connection has been established.

So far I read through most of the threads here and found that snippet that supposed to be used to set up the reading listener but it doesn't work

BluetoothSerial.withDelimiter('\r\n').then((res)=>{
    BluetoothSerial.on('read', (data) => {
        console.log('Reading data: ', data)
    })
})

I also tried the event namesdata and rawData but the listener doesn't get invoked.

If I invoke BluetoothSerial.readFromDevice() after some time I can read any message but I don't want to poll it all the time.

Can you please let me know how it set the listener correctly?

Thank you, Thomas

eth-n commented 5 years ago

Did you ever find a way to do this without polling? We're thinking of using readEvery and checking whether any data came in but it's not a great solution.

kenjdavidson commented 5 years ago

Does the data you're looking for have the delimiter within each message? For example, when I'm requested data from my device > "ri\r" the data comes back in streams, with multiple lines separated by \r\n. Because of this, I only get the first line back - and now I'm in a loop of always being X lines behind my expected data. For example, if there are 10 lines/delimiters in the buffer then when I actually scan something I'll get the next line of info, instead of my scanned data.

To resolve this I had to update the onData to:

This way my javascript listener stays current. Otherwise I was getting some funky issues where the application was not reading properly. Anyhow, if this isn't your particular symptom, I apologize for hijacking.

krogank9 commented 3 years ago
    /**
     * Handle read
     * @param data Message
     */
    void onData (String data) {
        mBuffer.append(data);
        String completeData = readUntil(this.delimiter);
        if (completeData != null && completeData.length() > 0) {
            WritableMap params = Arguments.createMap();
            params.putString("data", completeData);
            sendEvent(DEVICE_READ, params);
        }
    }

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

Read events weren't working for me either so I took a look at the code and it only sends events when a delimiter is set, otherwise readUntil will just return "" and data length will be 0 so read event won't get triggered. My data had no delimiter but was prefixed with a length byte. I just ended up adding this to the top of the readUntil function:

        if(delimiter == "") {
            String data = mBuffer.toString();
            mBuffer.delete(0, mBuffer.length());
            return data;
        }

So either will need to do something like this for Android/iOS code or make sure delimiter is set to the correct character for your data.

MariwanJ commented 3 years ago

Thanks for your help. was good to mention the location of this function .. anyway it is here : ..\node_modules\react-native-bluetooth-serial\android\src\main\java\com\rusel\RCTBluetoothSerial\RCTBluetoothSerialModule.java This solves the problem but what is the default delimiter ? And the String data is already defined .. so the corrector one is as bellow :

   if(delimiter == "") {
        data = mBuffer.toString();
        mBuffer.delete(0, mBuffer.length());
        return data;
    }

put this code after definition of the data .