B4J Question Convert Hex 13 bits to integer

Philip Prins

Active Member
Licensed User
Longtime User
Hello,

I have a GPS tracker that sends the following message in HEX
/ First 32 bits is floating number for Latitude or Temperature
// Next 32 bits is floating number for Longitude or Pressure
// Next 13 bits is integer number for altitude (0-8191m)
// Next 7 bits is integer number for battery level in percent
// Next 7 bits is integer number for speed with S = (S-60)*3 if S > 90
// Next 2 bits is integer number for direction "N","E","S","W"
// Last 3 bits is integer number for operating mode or message composition

Data bd534f4287228a40610d0800

I get the longtitude and latitude with the hex to float with byteconverter but how do i get the 13 bits and 7 bits value?

Thanks in advance for your help.
Philip
 

Philip Prins

Active Member
Licensed User
Longtime User
Short = 16 bits
To read the battery you need to read two bytes starting from byte 9 (72 - 87 bits).
You are only interested in bits 77 to 83 so you need to shift right the number 5 bits and then AND it with 0x7F = 1111111 in binary.
Tnx
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Hello Erel, somehow i don't get the right results;
B4X:
        Dim b() As Byte = BC.HexToBytes(cFrame)
        Dim raf As RandomAccessFile
        raf.Initialize3(b, True) 'or false depending on the endianess
        Dim Alti As Int = raf.ReadShort(8)
        Alti = Bit.And(0x1fff, Alti)
        Log(Alti)
'        Short = 16 bits
'        To read the battery you need To read two bytes starting from byte 9 (72 - 87 bits).
'        You are only interested in bits 77 To 83 so you need To shift right the number 5 bits And Then And it with 0x7F = 1111111 in binary.
        Dim Batt As Int = raf.ReadShort(9)
        Batt = Bit.And(0x7f, Batt)
        Log("Batt "&Batt)

This will give me a battery percentage of 121 and a altitude of 6518.
Data = 2dc7874162cd7d447679b000
This is temperature of 16.972253799438477 and pressure 1017.4476318359375
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Maybe I am wrong , but
initializing RAF true gives you raf.ReadShort(8) = 0D61
So, try
raf.Initialize3(b, false)
this will give you raf.ReadShort(8) = x610D (0110000100001101b)
shift it right 3 places to keep just the 13 bits you need --> 0000110000100001b (x0C21)
now, since altitude is an int (4 bytes) you need to mask it with 00FF
and that will finally yeld 33meters (battery 80%)

B4X:
   Dim bc As ByteConverter
   Dim b() As Byte = bc.HexToBytes("bd534f4287228a40610d0800")
   Dim raf As RandomAccessFile
   raf.Initialize3(b, False) 'big endian
   Dim altitude As Int = raf.ReadShort(8)
   Log(altitude) '24845 or 610D
   altitude = Bit.ShiftRight(altitude, 3)
   Log(altitude) '3105 or C21
   altitude = Bit.And(0x00ff, altitude)
   Log(altitude) '33 meters


udg
 
Last edited:
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
Maybe I am wrong , but
initializing RAF true gives you raf.ReadShort(8) = 0D61
So, try
raf.Initialize3(b, false)
this will give you raf.ReadShort(8) = x610D (0110000100001101b)
shift it right 3 places to keep just the 13 bits you need --> 0000110000100001b (x0C21)
now, since altitude is an int (4 bytes) you need to mask it with 00FF
and that will finally yeld 33meters (battery 80%)

B4X:
   Dim bc As ByteConverter
   Dim b() As Byte = bc.HexToBytes("bd534f4287228a40610d0800")
   Dim raf As RandomAccessFile
   raf.Initialize3(b, False) 'big endian
   Dim altitude As Int = raf.ReadShort(8)
   Log(altitude) '24845 or 610D
   altitude = Bit.ShiftRight(altitude, 3)
   Log(altitude) '3105 or C21
   altitude = Bit.And(0x00ff, altitude)
   Log(altitude) '33 meters


udg

B4X:
Dim Batt As Int = raf.ReadShort(9)
        Log(Batt)
        Batt= Bit.ShiftRight(Batt, 5)
        Batt = Bit.And(0x00ff, Batt)
        Log("Batt "&Batt)

I do not get 80 percent battery value,can you post me the code to get :
Next 7 bits is integer number for battery level in percent 1 byte
// Next 7 bits is integer number for speed with S = (S-60)*3 if S > 90
// Next 2 bits is integer number for direction "N","E","S","W"
// Last 3 bits is integer number for operating mode or message composition

I am getting stuck,
Tnx in advance
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Philip
please find in bold the reason why the following code is slightly different from yours. BTW, it leads to 80%..
0000110100001000 --> 0000000011010000
When you mask it, you don't want first two bytes (so you have 0x00), you want the 3 right-most bits from third byte (so x7) and the whole fourth byte (so xF).

B4X:
Dim battery As Int = raf.ReadShort(9)
Log(battery) '3336 or 0D08 or 0000110100001000
battery= Bit.ShiftRight(battery,4)
Log(battery) '208 or D0 or 0000000011010000
battery= Bit.And(0x007f, battery)
Log(battery) '80%

udg
 
Upvote 0

Philip Prins

Active Member
Licensed User
Longtime User
T
Hi Philip
please find in bold the reason why the following code is slightly different from yours. BTW, it leads to 80%..
0000110100001000 --> 0000000011010000
When you mask it, you don't want first two bytes (so you have 0x00), you want the 3 right-most bits from third byte (so x7) and the whole fourth byte (so xF).

B4X:
Dim battery As Int = raf.ReadShort(9)
Log(battery) '3336 or 0D08 or 0000110100001000
battery= Bit.ShiftRight(battery,4)
Log(battery) '208 or D0 or 0000000011010000
battery= Bit.And(0x007f, battery)
Log(battery) '80%

udg
Tnx UDG and Erel,
 
Upvote 0
Top