Convert string byte to decimal value

I read a string from serial port. Each byte of the string represents device status.
If I do it this way it works fine:

int status
  covx u[0],va3.txt,0,0
  covx va3.txt,status,0,0
  n1.val=status
  covx u[1],va3.txt,0,0
  covx va3.txt,status,0,0
  n2.val=status
 
  ucopy status,0,1,0
  n3.val=status
  ucopy status,1,1,0
  n4.val=status

For example if the string send is “123”, I get results in
n1 49, n2 50
n3 49, n4 50
Note, the sting bytes can have any value from 0 to 129.

But the problem is that I want to store this string in the variable and access the different byte of this string depending on the displayed page.
I tried this code but it doesn’t work:

  ucopy va3.txt,0,3,0
  substr va3.txt,va4.txt,0,1
  covx va4.txt,status,0,0
  n5.val=status

for the same string as in the example above “123”, I get n5 1 not 49.
If the string is “abc” n5 is 0
How can I do it?
It is amazing that basic operation on the bytes/unsigned char is not available.

It might help if you gave examples of serial input variables and what you expect each of the other variables to be

Hi Bobj,
I don’t think it matters what the string is going to be. I just want to read the decimal value of the byte - i.e. if I send and ASCII char ‘a’ I want to read/get value 97.
But I will give you an example.
I have 25 Zigbee devices and depending on the device type I can get the status which will show for example the light is on/off, the light works with delay on/off timer, Air conditioner is ON, the mode is COOLING, and the fan speed is LOW.
So for example:
Light ON with delay off timer will give me status byte in hex 0x21
The same light with delay on timer and delay off timer will have hex value 0x61
For the Air con for example the low 4bits of the byte show the the mode and power on/off, the 4 high bits will be the same as for the light - i.e. the timer.
After I get the status, depending on which page I am on I will show the status of the device by checking if the bit is set.
for example if((status &= 1)== 1) → device is on visibility of the image will on or off
If I do the if((status &= 0x20) == 0x20) → device delay off timer is active, and appropriate image or text will show this.
To get the status of all devices I will send from MCU either:
unsigned char data[40];

  1. where data will have bytes - ‘var1.txt="–status bytes"FFFFFF’
    and status bytes will be hex values like 0x01, 0x00, 0x21, 0x65… up to 25 bytes.
    Status data will be stored in a global variable var1 and each byte will be accessed depending on the screen.
  2. or using reparse mode
    data[0] will be character ‘s’ and the rest of the data will be status data as above.
    When the data is received by Nextion it will be converted to a string variable var1.
    And accessed the same way as in point 1.
    You can see from my first post what works and what doesn’t.

So I need the way to read a decimal value of each byte in a string. Which is simple (basic) operation in any programming language.
I would appreciate your help. I have already wasted a lot of time trying different things and couldn’t get it to work.

I could of course define 25 global int variable - st1, st2,… st25.
And send the status of each variable separately - st1.val=33 etc
But this is a waste of resources, instead of sending once 25 bytes of data (plus variable name), I would have to send 25 times 4 bytes of data (plus variable name) and store 25 bytes in 25 integers (25 bytes stored in 100bytes!). Just an unnecessary waste in my opinion.
I would appreciate your help.

Hi,
Unfortunately, I think your problem is way above my pay grade. However, it seems you are trying to get the ASCII value of a string character. Whilst the following is a workaround it is quite simple and tested.

The following function splits the ASCII code string up to the character in question then assigns the length of that string ‘t2.txt’ to ‘n0.val’ and then adds 48 to give you the ASCII value.
I have used text and number boxes for clarity but of course you can use variables.
The following is the 3 line code in a hotspot ‘m0’ used as a function and called with button press ‘click m0,1’
Hope this helps
Bob

//assign ‘t1.txt’ as character to evaluate eg “8”
//split the ASCII set at that character & assign to ‘t2.txt’ ( “-” used to avoid possible escape codes)
spstr “0123456789-------ABCDFGHIJKLMNOPQRSTUVWXYZ-------abcdfghijklmnopqrstuvwxyz”,t2.txt,t1.txt,0
//eg, for “8” will return “01234567”
//assign ‘n0.val’ with the length of ‘t2.txt’
strlen t2.txt,n0.val // assigns ‘n0.val’ with length of ‘t2.txt’ content
//now add 48 for unused first block of ASCII codes
n0.val=n0.val+48

Why not simply copy blocks of 4 bytes from the serial buffer into an integer variable? Or, if you have 6 bytes into 2 integer variables? Think binary!

// check if 6 bytes are in the buffer:
if(usize>=6)
{
ucopy n0.val,0,4,0
udelete 4 // delete the read bytes, so that the next block can be read
ucopy n1.val,0,2,0
udelete 2 // same as above
}

Now, you have the first 4 bytes in n0 and the last 2 bytes in the lower bytes of n1 and you can use bit mask and shift operations to evaluate the data.
The advantage over the covx method is that even bytes which contain non-printable characters (in the Sexton’s eyes) can be used and processed while covx would swallow these.

Hi Fjodor,
I know I can do it this way, it is much easier to use an array of unsigned char (that’s what really a string can be) and address it by index 0 to 25. It is basic way of programming.
Why what I showed in first post - this works
first byte is for example decimal 49 - ASCII ‘1’, but works for any value!

  covx u[0],va3.txt,0,0
  t2.txt=va3.txt     
  covx va3.txt,status,0,0
  n1.val=status

but this one, where I copy all bytes from serial to variable va3.txt and then read 1 byte to var4.txt and use covx on var4.txt doesn’t work?

  ucopy va3.txt,0,3,0
  substr va3.txt,va4.txt,0,1
  t3.txt=va3.txt
  status=0
  covx va4.txt,status,0,0
  n5.val=status

What is the difference?
if I use for example ASCII 1
n1.val = 49 - which is correct
n5.val = 1 - which is not correct.
Ok, I did another test:
The first method gives me:
t2.txt = 49 - after covx u[0],va3.txt ***Edit: after covx va3 length is 2.
status = 49 - after covx va3.txt
So it looks like u[0] is treated as int (1 byte)
I did this:
status=u[0]
n1.txt=status
It shows me that status is 49 - which is correct and there is no need to use covx (twice) in this method.

So I don’t think there is a way to do it using substr (to get a byte from a string) and covx to convert.

I have wasted enough time on this and I will use 25 global int variables and use only 1 byte in each variable. This in a way, may be better, since I can send via serial/update only the variable that has changed - not all variables every time.
Is there a limit how many global variables can be defined in program.s?

Just to finalize this thread.
I have came to the conclusion that Nextion is not suitable for what I am doing.
If I want to read a byte from serial it has to be a printable ASCII character.
If I want to use a global int variable - to send the value of it - it still has to be sent as a ASCII. so for value 123 I have to convert in MCU 1 byte to 3 ASCII bytes, and send 3 bytes.
I can read decimal value of a byte sent via serial if I do reading of serial via u[0] or ucopy - i…e I control reading of the serial data in the timer, and the code in the timer:

doevents
while(usize > 1{
{
status=u[0]
......
...,,,
udelete 1
}

But this won’t work because the global timer is not so global. It stops when you change the page, so the serial data is not processed any more. I could of course start another time on next page and do the same thing with reading serial - but I may lose data depending when I change page.
By the way this other issue with serial I had error “serial buffer overflow”, which I don’t believe was correct. I didn’t send that much data.
So for me this is it with Nextion.

Hi,
Why not direct typecasting like: String(val,DEC) ?

I am controlling my inverters directly with the nextion I send a command with calculated CRC done with my code and receive bytes back with CRC and I use decimal values from the string to calculate the CRC so it can be done code is here Inverter Remote Screen with a Nextion - AEVA Forums

With global variables you can access them from any page

Thanks Paul. I will have a look at what you are doing.
Edit:
I had a look and it is not going to work for me. As I wrote before, I need to read a decimal value of the byte.
This can be anything from 0 to 250 - so it is not necessary a printable ASCII character. In a lot of cases it will be 0 if the device status is OFF
As I wrote above, I could read a byte status=u[0] (where status is int) in a while loop in timer, but the timer will stop.
Anyway, Thanks for your help.