How can a 1 byte int conversion of a QByteArray fail? - qt

So here is the thing, I'm receiving 1 byte from Bluetooth transmission. When using QDebug I get this message:
The array with error has "\x06"
The line that fails is this:
bool ok = true;
int v = value.toInt(&ok,0);
Because ok has false. But I'm trying to wrap my head around the fact that, How can the conversion fail in the first place if the data represented in that byte (as a sequence of zeros and ones) will always have a valid integer representation. (one byte can always be represented as a int between -127 and 128). So I'm left with the question, how can the conversion fail?
Reading the documentation does not provide many clues as it does not say how the byte array will be interpreted.

QByteArray::toInt converts a string representation in the default C locale to an integer. That means to successfully convert the value in your example, your byte array must contain the string "0x06", which consists of 4 bytes.
To convert a single byte to an int, just extract it:
int i = value[0];
Type promotion will widen the char to an int

Related

Read MyCharNotify as a character instead of a HEX value

I am programming an STM32WB board using the following tutorial (https://www.youtube.com/watch?v=Zgw3wRpGSRQ&list=PLnMKNibPkDnG9JRe2fbOOpVpWY7E4WbJ-&index=18&ab_channel=STMicroelectronics)
I am able to send a hex value to the phone using the ST BLE Toolbox, however I would like to send a char to start, end goal would be to send a string. how could I go about displaying the hex value as a char?
Would CHAR_PROP_BROADCAST or CHAR_PROP_READ be more appropriate for this? I could not find any tutorials on this unfortunately.
enter image description here
followed this tutorial.
https://www.youtube.com/watch?v=Zgw3wRpGSRQ&list=PLnMKNibPkDnG9JRe2fbOOpVpWY7E4WbJ-&index=18&ab_channel=STMicroelectronics
the tutorial only sends one hex number, to send more you can change the "Value length" on CubeMX,
UpdateCharData[n] = some_data;
You need to understand how a character is stored in the microcontroller/PC memory. Read about ASCII table. For example:
#include <stdio.h>
int main() {
unsigned num = 0x41; // two byte variable
printf("%0x\n", num);// output: 41
printf("%d\n", num);// output: 65
printf("%c\n", num);// output: A
//because ASCII code 65 it's 'A' character
return 0;
}
As you can see, the same data are interpreted differently.
If you want to convert a integer to a character, just do the following ->
int a = 65;
char c = (char) a;
Or you can use itoa() function to convert the integer to a string.

How to create an array of references to arrays?

I'm having some syntax troubles with my code. A bit of context...
My program has a schedule, it's an array of 24 bytes. There's one schedule per day, so 7 arrays.
I want to have a single array of 7 elements storing references to the above 7 arrays. This way, by calling schedules[1], I get schedule1[24], which is Monday.
// One schedule per day (0 = sunday)
byte schedule0[24];
byte schedule1[24];
byte schedule2[24];
byte schedule3[24];
byte schedule4[24];
byte schedule5[24];
byte schedule6[24];
byte * schedules[7] = {&schedule0, &schedule1};
The problem comes from the last line, the error being "a value of type "byte (*)[24]" cannot be used to initialize an entity of type "byte *" ".
I tried inserting [24] before or after the star/pointer character, with no luck.
Could any of you please show me the correct syntax to do this?
In C++, name of the array is the pointer to the first element in the array. So in your case schedule0 is a pointer to &schedule0[0] not &schedule0.
You can change the last line as
byte * schedules[2] = {&schedule0[0], &schedule1[0]}; or byte * schedules[2] = {schedule0, schedule1};
This will create a pointer array containing the base address of the scheduleX arrays.
I want to have a single array of 7 elements storing references to the above 7 arrays. This way, by calling schedules[1], I get schedule1[24], which is Monday.
A different approach is needed to index across days. This can be done using a two dimensional array and some pointer arithmetic.
Declare a two dimensional array for your schedules:
byte schedulesArray[7][24];
Declare pointers that point to the schedules for each day:
byte *schedule0 = &schedulesArray[0][0];
byte *schedule1 = &schedulesArray[1][0];
byte *schedule2 = &schedulesArray[2][0];
byte *schedule3 = &schedulesArray[3][0];
byte *schedule4 = &schedulesArray[4][0];
byte *schedule5 = &schedulesArray[5][0];
byte *schedule6 = &schedulesArray[6][0];
Declare a pointer to the first element of the two dimensional array:
byte *schedules = &schedulesArray[0][0];
So if we seed some data:
schedule0[0] = 1;
schedule1[0] = 11;
schedule1[1] = 12;
schedule2[0] = 21;
schedule2[1] = 22;
Then you can use the schedules pointer to index across days:
schedules[0]; // = 1
schedules[24]; // = 11
schedules[25]; // = 12
schedules[48]; // = 21
schedules[49]; // = 22
This works because multidimensional arrays are laid out as a contiguous block of memory.
Simply, you can't do it.
And here is explanation why:
Basically, a reference is an alias to an existing variable. This means, if you apply any operation on a reference, it will behave as if you were using the original variable name. And there are no references at a reference or pointer at references, references don't allocate any memory so there is nothing that you can use to put in an array.
What you can do is create an array of pointers and it will work.

How to retrieve data size larger than Qt Modbus InputRegisters?

From what I understand, the range of QModbusDataUnit::InputRegisters is range 0-65535 which is unsigned short.
The method to read 1 unit of inputregisters is as follows:
QModbusDataUnit readUnit(QModbusDataUnit::InputRegisters, 40006, 1);
The value of that will be in the reply, i.e : int value = result.value(0);
My question is that what if I have to read a value of unsigned int which is much larger of the range of 0 to 4,294,967,295.
How can I retrieve that value?
As you stated, Modbus input registers are 16 bit unsigned integers. So without some type of conversion they are limited to the range: 0 - 65535. For 32-bit unsigned values it is typical (in Modbus) to combine two registers.
For example, the high 16-bits could be stored at 40006 and the low 16-bits at 40007.
So, if you were reading the value ‭2271560481‬ (0x87654321 hex), you would read ‭34661‬ (0x8765) from address 40006 and 17185 (0x4321 hex) from location 40007. You would then combine them to give you the actual value.
I don't know the Qt Modbus code, but expanding on your example code you can probably read both values at the same time by doing something like this:
readUnit(QModbusDataUnit::InputRegisters, 40006, 2);
and combine them
quint32 value = result.value(0);
value = (value << 16) | result.value(1);

Does it make sense to store byte values in Map or it will still use 4 bytes?

In Java in-memory there is no difference between byte or int - both will be represented as 4 bytes.
Does for Chronicle Map the difference exist, i.e. does Chronicle Map store byte values as 8 bits or still use 32?
Same question if byte is an object property.
In primitive map implementations (fastutil, koloboke, gs, hppc) byte values are implemented as a separate byte[] array, so they actually take only 1 byte. If a byte is a field of another on-heap Java object (which is a Map value), indeed, the object size is rounded up to 8-byte boundary, so a single byte field could "take" 8 bytes. But more often, it "takes" 0 bytes, because the field is placed in the already existing alignment holes.
For Chronicle Map, a value could freely be 1 byte in size. (And even 0 bytes, this is how ChronicleSet is currently implmeneted -- a ChronicleMap with 0-byte dummy values.) This is true for all Chronicle Map versions (2, 3).
Edit -- answer to the comment.
If you have a constantly sized structure e. g. 6 byte fields, easiest and efficient way - to use data value generation mechanishm:
interface MyValue {
byte getA(); void setA(byte a);
byte getB(); void setB(byte b);
byte getC(); void setC(byte c);
byte getD(); void setD(byte d);
byte getE(); void setE(byte e);
byte getF(); void setF(byte f);
}
map = ChronicleMapBuilder.of(Key.class, MyValue.class).entries(1000).create();
// Chronicle Map 2 syntax
MyValue value = DataValueClasses.newDirectReference(MyValue.class);
try (Closeable handle = map.getUsingLocked(key, value)) {
// access the value here
System.out.println(value);
}
// Chronicle Map 3 syntax
try (ExternalMapQueryContext<Key, MyValue, ?> q = map.queryContext(key)) {
// if not sure the key is present in the map, check q.entry() != null
MyValue value = q.entry().value().get();
// access the value here
System.out.println(value);
}
It will take exactly 6 bytes per value.
I think I know the response. At least at the version 2.3.8 offheap value will be 1 byte for a byte (work done in SerializationBuilder class).

Conversion with Pointsers in C

I need to implement but I am not sure how can I as I am completely new into this. A function called get_values that has the prototype:
void get_values(unsigned int value, unsigned int *p_lsb, unsigned int *p_msb,
unsigned int *p_combined)
The function computes the least significant byte and the most significant byte of the value
parameter. In addition, both values are combined. For this problem:
a. You may not use any loop constructs.
b. You may not use the multiplication operator (* or *=).
c. Your code must work for unsigned integers of any size (4 bytes, 8 bytes, etc.).
d. To combine the values, append the least significant byte to the most significant one.
e. Your implementation should be efficient.
The following driver (and associated output) provides an example of using the function you are
expected to write. Notice that in this example an unsigned int is 4 bytes, but your function
needs to work with an unsigned int of any size.
Driver
int main() {
unsigned int value = 0xabcdfaec, lsb, msb, combined;
get_values(value, &lsb, &msb, &combined);
printf("Value: %x, lsb: %x, msb: %x, combined: %x\n", value, lsb, msb, combined);
return 0;
}
Output
Value: abcdfaec, lsb: ec, msb: ab, combined: abec
I think you want to look into bitwise and and bit shifting operators. The last piece of the puzzle might be the sizeof() operator if the question is asking that the code should work with platforms with different sized int types.

Resources