Convert hex-string to number

Hi guys,

I've been using BluetoothLE extension to communicate with my device through BLE1.
I successfully receive and send data without problem.

Now I am stuck trying to find a way to convert my data into number

My device sends a string of data like this {152, 55, 48, 48, 70, 47}

If I receive as StringValue, it will be "(?700F/)" . '?' is unknow character not a question mark.
If I receive as BytesValue, it will be "(152 55 48 48 70 47)" also as a string.

The first byte defines what kind of message it is, the next 4 bytes is 16 bit number formatted in HEX.

If receiving as StringValue, I cannot compare that single character with a decimal value.

image

Those conditions never true.

If receiving as BytesValue, ie. "152".

The condition does work, but I am stuck at converting the rest to a 16 bit number. I cannot find a way to do this.

If it is in C, I can write a function to do so in less than 5 minutes without using any library.

uint16_t uchar_to_uint16(const uint8_t* in_uchar)
{
  uint8_t b0 = in_uchar[0], b1 = in_uchar[1], b2 = in_uchar[2], b3 = in_uchar[3];

  if (b0 >=48 && b0 <=57) b0 -= 48; // 0 -- 9
  if (b0 >=65 && b0 <=70) b0 -= -55;  // A -- F, or b0 = b0 -65 +10

  if (b1 >=48 && b1 <=57) b1 -= 48; // 0 -- 9
  if (b1 >=65 && b1 <=70) b1 -= -55;  // A -- F, or b0 = b0 -65 +10

  if (b2 >=48 && b2 <=57) b2 -= 48; // 0 -- 9
  if (b2 >=65 && b2 <=70) b2 -= -55;  // A -- F, or b0 = b0 -65 +10

  if (b3 >=48 && b3 <=57) b3 -= 48; // 0 -- 9
  if (b3 >=65 && b3 <=70) b3 -= -55;  // A -- F, or b0 = b0 -65 +10

  if (b0>15 || b1>15 || b2>15 || b3>15) return 0; // fail to convert, return 0;

  return (uint16_t) (b0) | (b1<<3) | (b2<<7) | (b3<<11);
}

But I am unable to do this using language blocks.

Could someone shed some light on this for me?

Thanks

Edit:
I've tried this procedure to convert from ascii to decimal value https://gallery.appinventor.mit.edu/?galleryid=6407304567324672
But it just return 0 instead of 152.

Hello Simon

First and foremost, what exactly is the device sending the data? You appear to have influence with respect to what it sends in terms of data type.

Hi Chris,

The device sending data is an ARM cortex M4 from ST. through a BTLE module RN4871 via UART.

Because it comes down to UART hence, it is byte (unsigned char) on basis.

Yes I also wrote the code for my device so that I can change the data format. I can also change '\152' into something like "98" in 0x98 (one single byte value into 2 chars)

But that is not the point.

So for now I find it very difficult (or impossible for me)

  1. to compare an extended ascii character with a decimal value which represents that character.
  2. to write a simple function to do such a simple conversion like that.

Btw, something like "98700F/" is more like human readable format than data communication between MCUs or between 2 computers.

Note: character '/' in the message is just like a separator only for AI app for easier to split each message if transfer rate is too high. I rather not to have that character in the message.

You could try something like this, which will parse the message structure you've described and return a dictionary with keys type and value:

You may need to change the order of the for range loop to account for endianness. There are also bitwise operator blocks in the math drawer if you'd want to code to read more like the C code.

On the contrary, you are reporting a problem of your App receiving data from the device, so that is of great importance.

What exactly data are you sending to uart? Are you sending text or bytes (numerical data)? You use serial.print() or serial.write()?

Thank so much ewpatton, this should do the trick. I thought I had to go back wrestling with android studio. :+1:

That's not true. ReadBytes receives data as a byte list. It is not a string.

I don't use Arduino SDK. I use STM32CUBEIDE and HAL drivers. Hence, I don't have the luxury of Serial.Write(). I pretty much write some bytes to an array like uint8_t TX_buffer[6];
Then I call DMA to handle UART transmission for me.

My data likes this

struct mydata
{ 
  uint8_t msg_id; // I have about 50 types of data
  uint16_t value;  
}

Data exchange over UART is just informational mostly to user. My application requires intensive CPU power (@72Mhz) so that even the time lag when an interrupt pop / push on the stack (around 40 us) could cause problem if it happened in the wrong time. Hence, I rather not to transmit / receive lengthy data and certainly not like "152 28687" for {0x98, 0xF007} or "152 1" for {0x98, 0x0001}. This could be very very trouble for MCU to receive data like this.

So I pack the message like what I described. 16 bit number into a string "FFFF" . This to avoid the the confusion of somehow 1 byte of the value coincide with 1 byte of the type. Eg: {152, 175, 152} or {0x98, 0xAF, 0x98} or {msg_id=152, value=44952 or 0xAF98}

If you have a better way, please enlighten me.

That's not true. ReadBytes receives data as a byte list. It is not a string.

I didn't know that. Please excuse me for being an idiot. I don't have a way to halt the AI app and read the memory of ReadBytes like how a real debugger can do. All I did was to put it on a static label and it showed "(152 55 48 48 70 47)" as a string.

That's a perfectly legitimate way to inspect received data - App Inventor is flexible on data types in that way, numbers in strings can be used with Math functions too.

1 Like

Well, this is off topic but it would give you better view!

I started my career from win32 app in C++. Tasted the forbidden fruits of the real debugger of visual studio and third party like ollydbg. Recently, I've tinkered a bit with arduino but then immediately moved on to ESP32 using Jtag debugger. Now my work mostly on Arm M0 or similar because I can use SWD interface.

I know I ask too much from AI.

Just saying, once you took a bite out of the real debugger you hardly could resist the sweetness of it.

Keep up the good work. Thanks!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.