Closed MobileTallent closed 9 months ago
Non lossy is the default now, so maybe don't add it to the connection options?
It's possible the logic for parsing the Charset doesn't like the non lossy value. Did you always pass in non lossy? Or did you just add this to try and resolve with an older version?
Thank you. In the old version, even if I didn't add any options, and it worked fine on iOS 16. On iOS 17, I faced the issue of onDataReceived() not working.
I heard that the Charset non lossy option should be added to resolve the iOS 17 issue, so I added the Charset option. But still failed.
What kind of info do you need to resolve this problem?
Best case scenerio is you debug it an dope a pr.
I was working with another user who resolved their issue with this fix, you can see his pr in the list, and follow the last issue.
Previously the issue was that ios17 changed how ascii was parsed and it wasn't able to find limiters anymore. Hence why read and listen aren't working, it thinks there's no messages.
You can try utf8 maybe and see if that keeps the newline characters. From my understanding it's now working and the other user has released a working app.
@jim-at-jibba
the lines here are probably way wrong in how they attempt to convert the .nonLossyASCII
string into the CFStringEncoding
type, which looks like it's wrong. My lack of experience with Swift is the main culprit, and it looks like only .utf8
will work this way (ha/oops).
If you are more comfortable with swift, feel free to update that block so that the Encoding enum is parsed correctly.
The default encoding is .nonLossyASCII ?
Yes, it was changed as a fix to https://github.com/kenjdavidson/react-native-bluetooth-classic/issues/278
What was the older default value?
The original value was .ascii
.
Which in IOS17 would do something funky with the \n
character.
Hey,
Yep Ken is correct, I could not get it to work with the \n
delimiter without it being .nonLossyASCII
, It was not parsed correctly in the previous state.
We are not using it in production with the current implementation and all seems fine
But when I use this code, the connection itself did not work.
let device = await RNBluetoothClassic.getBondedDevices(); await device.connect({charset: ".nonLossyASCII"});
Ya, that's because the code for parsing the connect property is wrong:
if let value = self.properties["DEVICE_CHARSET"] { self.encoding = String.Encoding.from(value as! CFStringEncoding) }
else if let value = self.properties["device_charset"] { self.encoding = String.Encoding.from(value as! CFStringEncoding) }
else if let value = self.properties["charset"] { self.encoding = String.Encoding.from(value as! CFStringEncoding) }
else { self.encoding = String.Encoding.from(CFStringBuiltInEncodings.nonLossyASCII.rawValue) }
Looking at this it looks like CFStringEncoding
is just a remap of utf8
which makes sense as to why those don't actually work. My bad. Looking at some of the Enums in question though:
String.Encoding.init(rawValue: UInt)
so that won't work with String.Encoding(rawValue: 'nonLossyASCII')
Essentially I have no idea how to get from
string
toString.Encoding
in Swift? Maybe it's just:
if let value = self.properties["DEVICE_CHARSET"] { self.encoding = String.Encoding.from(value as! String) }
else if let value = self.properties["device_charset"] { self.encoding = String.Encoding.from(value as! String) }
else if let value = self.properties["charset"] { self.encoding = String.Encoding.from(value as! String) }
else { self.encoding = String.Encoding.from(CFStringBuiltInEncodings.nonLossyASCII.rawValue) }
instead?
Or maybe
if let value = self.properties["DEVICE_CHARSET"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value)) }
else if let value = self.properties["device_charset"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value)) }
else if let value = self.properties["charset"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value) }
else { self.encoding = String.Encoding.from(CFStringBuiltInEncodings.nonLossyASCII.rawValue) }
Would be cool if you could give it a go.
Should I make above changes on this file? - DelimitedStringDeviceConnectionImpl.swift
Feel free to go for it and let me know. The world is your oyster my friend!
My Swift version is 5, but sorry the above code not working on my side
So you're saying:
You cannot provide the charset
parameter in the connect({})
options? If you do, you get an error? What error? The screenshot above doesn't have a specific error (or else I'm blind, which is possible).
When you remove charset
from the connect({})
parameters and just have the default .nonLossyASCII
pickup, it still doesn't work? What errors do you get?
If you get passed the connect()
issue using (1) or (2) above then what happens when you debug the string connection? Are you seeing data coming in through the Stream? Is it the same issue as #278 or is it something new?
You're going to need to do some debugging for me in order to help.
On iOS 17, the DELIMITER is changed into "\n" , or still "\n" ?
When I use only this ({charset: ".nonLossyASCII"}), DelimitedStringDeviceConnectionImpl.init function returns error and crashed.
when I didn't use any options, so the default options will be used, then DelimitedStringDeviceConnectionImpl.read function returns error and crashed.
stream data couldn't be shown, because the read function throws error. I think its a bit similar with the issue https://github.com/kenjdavidson/react-native-bluetooth-classic/issues/278
The delimiter hasn't changed unless you asked it to change. The default delimiter is \n
but you can override this with the connection property connect({ delimiter: "::" })
if you so choose. But chances are you haven't so it's most likely still \n
.
read
you're talking about. I still need to get a stack trace in order to see what the actual error is.~If read
is throwing an error, can you post what the error is in text? Not just a screenshot that doesn't actually show the error.~ The line in question is:
let numBytesRead = stream.read(buffer, maxLength: readSize)
which is being called when data is present. There are limited posibilities for this:
stream.read
buffer
readSize
Need to know which it is. You should be able to debug this and provide more info.
Hey @MobileTallent any follow up on this?
@kenjdavidson hey bud, I will pick this up. Can't promise ETA but will do it as soon as I can
@jim-at-jibba Is it still not working for you either with the fix you put in for .nonLossyAscii
? I thought you said it was working with that last change?
Ah no, it's working fine! Been in production and used daily since we merged. It was more the bit about how we set the encoding type in the initialiser, that you thought might be wrong and had asked the other guy to have a stab at.
If you don't think it's worth it I won't do it but happy to have a look if needed.
Ah, that thing. That does probably need to be fixed, since it's definitely a bug due to my complete lack of swift enum experience! I don't think there's any rush with it, not too many people use the IOS side of this, I think it's only enterprise level, since most others don't have access to MFi devices (in general).
OK, well I am happy to fix but busy with Christmas fast approaching so it wont be for a while.
Probably gonna create an updated example app too. Will let you know when its done.
Take it easy
Hi, Ken. Merry Christmas! I have the same error with @MobileTallent. So I tried to follow your guides, but my app is still crashing or the build is failing.
if let value = self.properties["DEVICE_CHARSET"] { self.encoding = String.Encoding.from(value as! String) } else if let value = self.properties["device_charset"] { self.encoding = String.Encoding.from(value as! String) } else if let value = self.properties["charset"] { self.encoding = String.Encoding.from(value as! String) } else { self.encoding = String.Encoding.from(CFStringBuiltInEncodings.nonLossyASCII.rawValue) }
if let value = self.properties["DEVICE_CHARSET"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value)) } else if let value = self.properties["device_charset"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value)) } else if let value = self.properties["charset"] { self.encoding = String.Encoding.from(CFStringBuiltInEncodings(rawValue: value) } else { self.encoding = String.Encoding.from(CFStringBuiltInEncodings.nonLossyASCII.rawValue) }
Can you help me on how to fix this error?
Thank you
If you've been following the thread youll see that there are two issue here.
The first and I think qhta you're experiencing is that you are attempting to set the Charset on connection. There is a bug with this code that has never worked.
The second is that the original issue has to do with the delimiter and how ascii decoded the /n. This was resolved by changing the default to nonLossyAscii.
So the question is, what exactly is your issue?
Are you setting the Charset during connection? If so don't. Are you removing the Charset, and still not seeing data? I need you to debug to see why. Do you need to be able to change the Charset from nonLossyAscii? If so, the bug needs to get fixed, which you can either open a pr for or wait for me to figure eit out.
You're specific error is a null pointer while attempting to unwrap an optional.
0 AccuPin 0x0000000102dd3c4c Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value + 0 (<compiler-generated>:0)
1 AccuPin 0x0000000102dd3c4c DelimitedStringDeviceConnectionImpl.read() + 1052 (DelimitedStringDeviceConnectionImpl.swift:176)
2 AccuPin 0x0000000102dd4118 DelimitedStringDeviceConnectionImpl.readDataFromStream(_:) + 280 (DelimitedStringDeviceConnectionImpl.swift:256)
3 AccuPin 0x0000000102dd3fe0 @objc DelimitedStringDeviceConnectionImpl.stream(_:handle:) + 68 (<compiler-generated>:0)
Looking at the code
Line 256 shows that data came in and was added to the buffer Line 176 is
let content = String(data: inBuffer, encoding: self.encoding)!
Which looks to me like the conversation to string is returning null. You'll have to debug this line and see what the result is of
Inbuffer Encoding The string, why's it null?
I'm assuming that you actually need utf or something else is up with the data you have in the buffer. But this seems very specific to the GPS device you're using.
You'll need to provide specifics, and maybe I can help.
Looking at the bad elf sdk, it doesn't look like they use a delimiter that I can see. But they definitely use nonlossyascii. This is super confusing how this library even worked originally with no delimiter sent by the device.
Thank you for your reply. Let me explain in detail. My app was working well under iOS 16. But on iOS 17, an error occurred - GPS data was not captured. My app was using "react-native-bluetooth-classic": "^1.60.0-rc.29". After researching, I upgraded the version to "^1.60.0-rc.30". After upgrading, my app crashed when captured the GPS data. I didn't use any connection option - badElfDevice.connect(). I already attached the error log. Here is how my app crashed.
Yup I fully understand. But you'll need to debug it. I've given you line numbers and background details. I cannot do anything more than this until you provide the debugging. You should have enough details to debug and see what is going on.
Ok. I'll debug and let you know. Thank you
Hello @MobileTallent. I have the same error as you. Were you successful in fixing your issue?
Any word on this? If there is more information, feel free to re-open when available.
hi @leon-915 I didn't fix the issue. please share the list of debugged datasets
Fixed the issue finally. I changed the code like this: connect({ delimiter: "\r\n" })
Thank you
Feel free to send me some Cash for this. Nothing big. Just something that shows how. Much I helped for it only to be the first thing I asked. Thanks.
Mobile Device Environment Provide a list of operating systems on which this issue is relevant.
Application Environment Provide information about your development environment:
device.connect({charset: ".nonLossyASCII"}); when I used above option for the connection. I faced this error:
device.connect(); when I didn't use the "charset" option for the connection. I faced this error:
It seems device.onDataReceived() function not working on iOS 17