Problem receiving data from bluetooth at very high speeds - flutter

I'm using the flutter_bluetooth_serial 0.4.0 package, it has a listen function that receives a function that returns the reading of the sending of a string (List Uint8), but for my case I need to carry out the communication at a very high speed, and when that it happens it does not understand where the end of a string is and it joins it until it overflows with 230 bytes and shows it as if it were a single string, I tried to solve this in several ways, but I can only receive the complete string (18 bytes) when I reduce the transmission speed, I've tried using some characters like '\n', to see if it understands where a string ends and another begins, but I wasn't successful either. If I could read character by character for me it would also solve it, because the messages have a sending pattern.
Do you have an idea how I could be solving this? Some package that works better than this one for this purpose or some way to determine where the end of the string is. I thank!
Here is the code snippet I get the data:
_dataSubscription = connection.input!.listen(_onDataReceived);
void _onDataReceived(Uint8List data) {
print('Data incoming: ${ascii.decode(data)}');
// Allocate buffer for parsed data
var backspacesCounter = 0;
for (var byte in data) {
if (byte == 8 || byte == 127) backspacesCounter++;
}
var buffer = Uint8List(data.length - backspacesCounter);
var bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
// print(backspacesCounter);
// print(buffer);
// print(bufferIndex);
}
I've tried using some characters like '\n', to see if it understands where a string ends and another begins, read character per character, but doesn't have function to do this.

Related

Getting substring of a string in flutter that contain and emoji can cause a render failure

As part of the app I am shortening a user-given string to 40 characters and appending ellipses at the end if the string is longer than 40 characters. The users are allowed/able to use emoji in their strings.
If a string that is cut off has an emoji at the 40-character mark it causes it to fail to render and renders as a "�".
Is there a way to reliably get a sub-string of a text but without running into this issue?
Current code:
if (useStr.length > 40) {
useStr = useStr.substring(0, 40) + "...";
}
You should use package:characters and truncate strings based on graphemes (human-perceived characters) and not on (UTF-16) code units.
import 'package:characters/characters.dart';
void main() {
final originalString = '\u{1F336}\uFE0F' * 3; // 🌶️🌶️🌶️
const ellipsis = '\u2026';
for (var i = 1; i < 4; i += 1) {
var s = originalString;
var characters = s.chararacters;
if (characters.length > i) {
s = '${characters.take(i)}$ellipsis';
}
print(s);
}
}
which prints:
🌶️…
🌶️🌶️…
🌶️🌶️🌶️

Problem receiving data from bluetooth at very high speeds with Bluetooth Serial

I'm using the flutter_bluetooth_serial 0.4.0 package, it has a listen function that receives a function that returns the reading of the sending of a string (List Uint8), but for my case I need to carry out the communication at a very high speed, and when this happens it does not understand where the end of a string is and joins overflow with 230 bytes and shows as if it was a single string, I tried to solve this in several ways, but I only managed to receive a complete string (18 bytes) when I slow down of transmission. I would need to read 40 bytes at a time regardless of '\n' or anything, I would have for this case maybe read byte by byte to validate the message and not a Uint8. In this case the input is a Stream and I would have to transform it into a Stream or something that makes me receive 40 bytes at a time regardless of the speed. Most of the time, a message comes together with another, and this could not happen in this transmission.
Here is the code snippet I get the data:
_dataSubscription = connection.input!.listen(_onDataReceived);
void _onDataReceived(Uint8List data) {
print('Data incoming: ${ascii.decode(data)}');
// Allocate buffer for parsed data
var backspacesCounter = 0;
for (var byte in data) {
if (byte == 8 || byte == 127) backspacesCounter++;
}
var buffer = Uint8List(data.length - backspacesCounter);
var bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
// print(backspacesCounter);
// print(buffer);
// print(bufferIndex);
}

TCP/.NET: Reading length prefixed buffer or fixed buffer size

I'm currently in the progress of writing my own TCP network library in C# and I want to make sure I'm doing things right.
Currently, I have every packet that gets sent through a socket prefixed with the length. The receiving end will read 4 bytes, convert that to an int, and read that many bytes afterward.
I'm not sure if that's the best approach. Would it be better to just read a fixed amount of bytes and process from there?
In the end, I would just extract 4 bytes from the fixed length buffer and read ahead however much I need.
Here is the code that I currently have to demonstrate my thought process.
internal void BeginReceive()
{
ReceiveImpl();
}
protected virtual void ReceiveImpl()
{
// Should we rather receive a bigger buffer (e.g. 8KB) immediately and then grab the length from that?
// It would require an internal buffer to store whatever we've already read ahead.
var recvState = new ReceiveState(new byte[4]);
Socket.BeginReceive(recvState.Buffer, 0, 4, SocketFlags.None, OnReceiveLength, recvState);
}
private void OnReceiveLength(IAsyncResult ar)
{
var recvState = (ar.AsyncState as ReceiveState)!;
var bytesRead = Socket.EndReceive(ar, out var errorCode);
if (errorCode != SocketError.Success)
{
// we ain't good fam!
return;
}
if (bytesRead > 0) // should we rather check if we read the 4 bytes we wanted?
{
var length = LengthFromBuffer(recvState.Buffer);
recvState.Buffer = new byte[length];
#if DEBUG
Console.WriteLine($"Receiving a packet with length of {length}.");
#endif
// what if the packet is absolutely massive? should we limit the buffer size?
Socket.BeginReceive(recvState.Buffer, 0, length, SocketFlags.None, OnReceive, recvState);
}
}
private void OnReceive(IAsyncResult ar)
{
var recvState = (ar.AsyncState as ReceiveState)!;
var bytesRead = Socket.EndReceive(ar, out var errorCode);
if (errorCode != SocketError.Success)
{
// we ain't good fam!
return;
}
if (bytesRead > 0)
{
recvState.BytesReceived += bytesRead;
if (recvState.BytesReceived < recvState.Buffer.Length)
{
Socket.BeginReceive(recvState.Buffer, recvState.BytesReceived,
recvState.Buffer.Length - recvState.BytesReceived, SocketFlags.None, OnReceive, recvState);
return;
}
OnDataReceived(recvState.Buffer); // this will call BeginReceive again.
}
}

Swift Type 'string.index' has no subscript members

I'm currently converting C++ code to Swift and I've gotten stuck on one part. The parameter passed into the function is a string and the area where I'm stuck is when attempting to set a variable based on the second to last character of a string to check for a certain character.
The error shows up on this line:
line[i-1]
I've tried casting this value to an Int but this didn't work:
Int(line[i - 1])
I've also tried to see if the string's startIndex function which takes a Int would work but it didn't:
line.startIndex[i - 1]
Here is the full function:
func scanStringForSpecificCharacters(line: String){
var maxOpen: Int = 0;
var minOpen: Int = 0;
minOpen = 0;
maxOpen = 0;
var i = 0
while i < line.characters.count {
for character in line.characters {
//var c: Character = line[i];
if character == "(" {
maxOpen += 1;
if i == 0 || line[i - 1] != ":" {
minOpen += 1;
}
}
else if character == ")"{
minOpen = max(0,minOpen-1);
if i == 0 || line[i-1] != ":"{
maxOpen -= 1;
}
if maxOpen < 0{
break;
}
}
}
if maxOpen >= 0 && minOpen == 0{
print("YES")
}else{
print("NO")
}
}
}
Strings in Swift aren't indexed collections and instead you can access one of four different views: characters, UTF8, UTF16, or unicodescalars.
This is because Swift supports unicode, where an individual characters may actually be composed of multiple unicode scalars.
Here's a post that really helped me wrap my head around this: https://oleb.net/blog/2016/08/swift-3-strings/
Anyway, to answer you question you'll need to create an index using index(after:), index(before:), or index(_, offsetBy:).
In your case you'd want to do something like this:
line.index(line.endIndex, offsetBy: -2) // second to last character
Also, you'll probably find it easier to iterate directly using a String.Index type rather than Int:
let line = "hello"
var i = line.startIndex
while i < line.endIndex {
print(line[i])
i = line.index(after: i)
}
// prints ->
// h
// e
// l
// l
// o
Working with Strings in Swift was changed several times during it's evolution and it doesn't look like C++ at all. You cannot subscript string to obtain individual characters, you should use index class for that. I recommend you read this article:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
As already pointed out in the other answers, the compiler error
is caused by the problem that you cannot index a Swift String with
integers.
Another problem in your code is that you have a nested loop which is
probably not intended.
Actually I would try to avoid string indexing at all and only
enumerate the characters, if possible. In your case, you can
easily keep track of the preceding character in a separate variable:
var lastChar: Character = " " // Anything except ":"
for char in line.characters {
if char == "(" {
maxOpen += 1;
if lastChar != ":" {
minOpen += 1;
}
}
// ...
lastChar = char
}
Or, since you only need to know if the preceding character is
a colon:
var lastIsColon = false
for char in string.characters {
if char == "(" {
maxOpen += 1;
if !lastIsColon {
minOpen += 1;
}
}
// ...
lastIsColon = char == ":"
}
Another possible approach is to iterate over the string and a shifted
view of the string in parallel:
for (lastChar, char) in zip([" ".characters, line.characters].joined(), line.characters) {
// ...
}
As others have already explained, trying to index into Swift strings is a pain.
As a minimal change to your code, I would recommend that you just create an array of the characters in your line up front:
let linechars = Array(line.characters)
And then anywhere you need to index into the line, use linechars:
This:
if i == 0 || line[i-1] != ":" {
becomes:
if i == 0 || linechars[i-1] != ":" {

how to Insert multiple columns using PQputCopyData

I am trying to insert two columns using PQputCopyData with following code. But once it checks for the final result it shows error invalid byte sequence for encoding UTF8 and data is not getting inserted into the database.
Both columns type is character varying. What am I doing wrong here ?
const char *buffer = "john,doe";
PGresult *res;
res=PQexec(conn,"COPY john FROM STDIN DELIMITER ',';");
cout<<buffer;
if(PQresultStatus(res) != PGRES_COPY_IN)
{
cout<<"copy in not ok";
}
else
{
if(PQputCopyData(conn,buffer,400) == 1)
{
if(PQputCopyEnd(conn,NULL) == 1)
{
PGresult *res = PQgetResult(conn);
if(PQresultStatus(res) == PGRES_COMMAND_OK)
{
cout<<"done";
}
else
{
cout<<PQerrorMessage(conn); Here I get the error invalid byte sequence for encoding "UTF8"
}
}
else
{
cout<<PQerrorMessage(conn);
}
}
}
if(PQputCopyData(conn,buffer,400) == 1)
What's wrong is passing 400 instead of the actual size of the contents in buffer, making it send unallocated garbage after the real data. Use strlen(buffer) instead.
Also you want each line to finish with a newline, so buffer should be :
const char *buffer = "john,doe\n";