While String doesnt start with MF; manipulate output

Hy, I would need to repeat this code in the library if String data doesnt start with MF

String DFRobot_BT401::getFilename(){
  delay(50);
  sendCMD("MF", NULL);
  String filename = "";
  String data = readAck(0);
  for(uint8_t i = 0;i < data.length()-3;i++){
      filename += data[3+i];
  }
return filename;
}

I was thinking something like:

String DFRobot_BT401::getFilename(){
while(data != MF){
  delay(50);
  sendCMD("MF", NULL);
  String filename = "";
  String data = readAck(0);
}

  for(uint8_t i = 0;i < data.length()-3;i++){
      filename += data[3+i];
  }
return filename;
}

But how can I impelement this? I need this to ensure that I get correct message returned, correct message always starts with MF.

Second thing is the output (filename)...

In my loop I have:

inputText = nowPlaying;

filename gets returned to nowPlaying.

What I want:
YOU_ARE_NOT_ALONE_(REMIX)

What I get:
Y O U _ A R E _ N O T _ A L O N E _ ( R E M I X ) . mp3 (there are some spaces after that)

How can I remove all spaces from the string and end string before .mp3?

Any suggestions would be appreciated.

use a do {...} while construct

String data = "";
do {
  sendCMD("MF", NULL);
  data = readAck(0); // assuming this returns what you want
} while (! data.startsWith("MF")); // https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/startswith/

Note this might be an infinite loop and you can get stuck there

Thank you very much... It wont get stuck because sendCMD ("MF", NULL ); demands awser with MF at the start, but sometimes some other message gets captured idk why. Ussualy after 3 -5 attempts message with MF gets captured.

OK


the spaces you see is likely due to data encoding (unicode / UTF16, ....) in the device. would be interesting to see exactly what's in memory by printing each byte of the filename

Yes, spaces are due to unicode.

so you need to process those to go back to UTF8 (or just ignore one byte out of two is you know it's pure ASCII)

It there like a function for that?
I searched and didnt find anything useful.

I tryed with filename.Replace(" ", "");
But it doesn't work for some reason, if I declare string on my own like String filename = "A B C D E F G " and comment out the code for declaring filename out of data it works....

Also do while !data.startsWith("MF") doesn't work, but I solved this problem with turning auto query on playback start on the board ...

There is no built in function for that. You need to write one for this (assuming you get only ASCII characters should be within reach )

If the startsWith does not work it would be interesting to verify that you don’t get UTF16 in the answer too


Thats everything about filename query from datasheet.... Broken english translated from chinesse.

I think those bytes my indicate what is going on.

However the code bellow does "see" the characters and forwards them to display....

void getColumns(char c, uint8_t columns[numColumns]) {
  switch (c) {
    case 'A'...'Z':
      memcpy_P(&columns[0], &upperCase[c - 'A'][0], numColumns); 
      break;

EDIT: Ok I see now, that there is 0x00 byte after every char byte.... how can I remove them? I tried filename.replace(0x00, ""); but it doesnt work.

@0212995500229 Hey, it's you again! So you decided to stick with weird filenames instead of pure ASCII, but your MP3 board doesn't support them. This doesn't surprise me, and I think that the board (or it's firmware, rather) is of dubious quality: how can an MP3 decoder not support ID3 tags in our day and age?

However, since Unicode is not working, you may try another encoding for your filenames, such as Latin-1. This one will fit in 8 bits (ASCII only needs 7), so you are going to have fixed width. You can always convert from Latin-1 to UTF-8 downstream, if you need to. What language are your filenames written in?

Another solution — or a hack, really — would be to pre-generate a lookup table with filenames and titles (you do that programmatically on your computer, of course). So, for example, the file que_tal_los_ninos.mp3 corresponds to ¿Qué tal los niños? Or, you could make the file que_tal_los_ninos.45.mp3 (or even just 45.mp3, but you lose human readability) if the song is member 45 of an array of titles and all you have to do is parse that number. You get the idea.

Hy, yes, it was hard to find usb mp3 player board that forwards the information about file via uart, this is the best I was abled to get.

My solution to get names to display is to use normal characters, but _ instead of spaces...
Now it works, I will correct _ to be shown as space in my lcd code, but I need to remove whitespaces and .mp3
Will do some research on how to convert to latin-1.

Pre-generating is not the thing I would do, will solve the problem somehow....

So you don't have foreign languages in your filenames? Why are you messing with Unicode then?

This is easy enough. Consider this (tested on PC only, needs some porting):

#include <stdio.h>

void filenameParser (char* buf);

char my_buffer[]  = "My_Favourite_Song.mp3";
char weird_name[] = "I_Like_Song.mp3_Songs.mp3"; 

int main (void)
{
    printf ("%s -> ", my_buffer);
    filenameParser (my_buffer);
    printf ("%s\n", my_buffer);
    
    printf ("%s -> ", weird_name);
    filenameParser (weird_name);
    printf ("%s\n", weird_name);

    return 0;
}

void filenameParser (char* buf)
{
    int i = 0;
    
    for (i; buf[i] != '\0'; ++i)
    {
        if (buf[i] == '_') buf[i] = 32;
        
        if ( buf[i]   == '.' &&
             buf[1+i] == 'm' &&
             buf[2+i] == 'p' &&
             buf[3+i] == '3' &&
             buf[4+i] == '\0' ) buf[i] = '\0';
    }
    
    return;
}

Output is:

My_Favourite_Song.mp3 -> My Favourite Song
I_Like_Song.mp3_Songs.mp3 -> I Like Song.mp3 Songs

As you can see, only the .mp3 at the very end of the string is removed.

Thank you for that. Will try it when I get home...
I hope that it will work as string.Replace also doesnt.

I tought that unicode was sent by the board...

Forget about String and use c-strings. My example parses c-strings and will work everywhere.

Forget about that too; do it the hard way.

Digging into Unicode opens up a can of worms of it's own. You may want to read this. If you can, try to have the board send ASCII.

I read it, but I still dont know what coding does the board output. Is there any way to find it out?

So basicly I would need to convert string (output from the library) to char with:

inputText.toCharArray(inputArray, len)

and then use your code from there?

You probably have UTF-16

so your string "YOU_ARE_NOT_ALONE_(REMIX)" which would be coded in ASCII as

0x59 0x4f 0x55 0x5f 0x41 0x52 0x45 0x5f 0x4e 0x4f 0x54 0x5f 0x41 0x4c 0x4f 0x4e 0x45 0x5f 0x28 0x52 0x45 0x4d 0x49 0x58 0x29

is likely coded as

0x0059 0x004f 0x0055 0x005f 0x0041 0x0052 0x0045 0x005f 0x004e 0x004f 0x0054 0x005f 0x0041 0x004c 0x004f 0x004e 0x0045 0x005f 0x0028 0x0052 0x0045 0x004d 0x0049 0x0058 0x0029

so you don't have spaces but every other byte that is 0x00, that's why replace does not work.

But the good news is that the LSB in UTF16 does match the ASCII byte for ASCII so if you get rid of the extra 0x00 then you get back to the ASCII (or UTF-8) representation.

➜ iterate over each byte of the cString buffer representation of your String and get rid of the 0x00 (you'll need to keep the last one)

(it would be interesting to actually print each byte's value to see if it is really UTF-16)


side note, the doc you show in translated Chinese has a few bugs but would show UTF-16 for the file name in big endian

Sorry for my noobnes. But If I undersand correctly I need to convert my string (nowPlaying) to cString

Would this be correct method?

nowPlaying = (bt.getFilename());

char Playing[nowPlaying.length() + 1] = {};
strcpy(Playing, nowPlaying.c_str());

If this is correct now I must convert value of char Playing into bytes in order to find and remove 0x00 bytes?

After that I must convert bytes back to text string.

I don't see why you need to convert it back to String. What do you want to do with this newly formed string ?

Board sends 0x00yy for one character istead of 0xyy, this results in 0x00 and 0xyy, I need to remove 0x00 bytes

Copying it to a c_string should cast each letter of the string to char, which should get rid of the extra byte.
What's your output now if you
Serial.println(Playing);
?
Edit.
Nevermind I'm wrong.