Long HEX Value Split to 2bytes Hex values or 4bytes Hex Values and convert it to decimal (float) values Using VB.Net - vb.net

I want to split my long array to 2bytes (4 digit HEX) or 4bytes(8 digit HEX). If c value is 1, I want to get 2bytes (4 digit HEX) HEX array and if c value is 0, I want to get 4bytes(8 digit HEX) HEX array from a long HEX string.
After that, I want to convert while converting 2byte or 4byte to floating number( decimal number).
I have code for 4byte to a decimal value.
Dim bytes() As Byte = {&H43, &H62, &HD3, &HE}
If BitConverter.IsLittleEndian Then
Array.Reverse(bytes)
End If
Dim myFloat As Decimal = BitConverter.ToSingle(bytes, 0)
txt4.Text = myFloat
Please provide me the code for this function.
Example:
Long Hex value - 4362D30EFFC00000FFC00000FFFFFFFF
If C is 1, split 4 digit HEX values.
4362
Then convert to decimal.
17250
Again split 4 digit HEX values.
D30E
Then convert to decimal
-11506
If c is 0, split 8 digit HEX values.
4362D30E
Then convert to decimal
226.824432
Please help with this. I don't not know much about VB.Net

I'm going to give this a shot as well, but do consider what I said on your newer question.
To read a certain amount of bytes and turn them into a number best is to use the BitConverter and its To*** methods.
This is how many bytes each numeric data type uses:
Double: 8 bytes
Int16 / UInt16 / Short / UShort: 2 bytes
Int32 / UInt32 / Integer / UInteger: 4 bytes
Int64 / UInt64 / Long / ULong: 8 bytes
Single: 4 bytes
With this in mind, all you need is to decide on a data type based on the number of bytes you want to read, and then specify an index in your array where to start reading from.
Remember that if you reverse your array you have to start reading from the end of the array instead.
Dim StartIndex As Integer = 0
Dim EndIndex As Integer = bytes.Length - 1
'How many bytes to read: 2 or 4.
Dim BytesPerStep As Integer = If(C = 1, 2, 4)
'If the system uses little endianness we need to reverse the array and loop backwards.
If BitConverter.IsLittleEndian Then
'Reverse the array.
Array.Reverse(bytes)
'Swap start and end index.
StartIndex = EndIndex
EndIndex = 0
'Negate BytesPerStep: Go backwards.
BytesPerStep = -BytesPerStep
End If
'Iterate the array <BytesPerStep> bytes at a time.
For i = StartIndex To EndIndex Step BytesPerStep
If C = 1 Then
'Read two bytes = Short (Int16).
ListBox1.Items.Add(BitConverter.ToInt16(bytes, i))
Else
'Read four bytes = Single (Float)
ListBox1.Items.Add(BitConverter.ToSingle(bytes, i))
End If
Next

Related

VB .NET Convert string to array of bytes without converting the characters

I'm trying to split a string of 32 numerical characters into a 16 length Array of Byte and each value has to stay numerical
from "70033023311330000000004195081460" to array {&H_70, &H_03, &H_30, &H_23, ..}
I've tried multiple stuff but each time either it's the conversion that's wrong or I can't find the appropriate combination of functions to implement it.
'it splits but per 1 character only instead of two
str.Select(Function(n) Convert.ToByte(n, 10)).ToArray
'I also tried looping but then the leading zero disappears and the output is a string converted to HEX which is also not what I want.
Function ConvertStringToHexBinary(str As String) As Byte()
Dim arr(15) As Byte
Dim k = 0
For i As Integer = 0 To str.Length - 1
arr(k) = str(i) & str(i + 1)
k += 1
i += 1
Next
Return arr
End Function
Anyone got any suggestion what to do?
G3nt_M3caj's use of LINQ might be.. er.. appealing to the LINQ lovers but it's horrifically inefficient. LINQ is a hammer; not everything is a nail.
This one is about 3 times faster than the LINQ version:
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length/2) as Byte
For i = 0 to str.Length - 1 Step 2
byt(i/2) = Convert.ToByte(str.Substring(i, 2))
Next i
And this one, which does it all with math and doesn't do any new stringing at all is just under 3 times faster than the above (making it around 9 times faster than the LINQ version):
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length / 2) As Byte
For i = 0 To str.Length - 1
If i Mod 2 = 0 Then
byt(i / 2) = (Convert.ToByte(str(i)) - &H30) * &HA
Else
byt(i / 2) += Convert.ToByte(str(i)) - &H30
End If
Next i
Of the two, I prefer the stringy version because it's easier to read and work out what's going on - another advantage loops approaches often have over a LINQ approach
Do you need something like this?
Dim str As String = "70033023311330000000004195081460"
Dim mBytes() As Byte = str.
Select(Function(x, n) New With {x, n}).
GroupBy(Function(x) x.n \ 2, Function(x) x.x).
Select(Function(y) Convert.ToByte(New String(y.ToArray()), 10)).ToArray

signed result of Val function in VBA

I use vba in ms access,and found that ,if my parameter greater than 0x8000
less than 0x10000, the result is minus number
eg. Val("&H8000") = -32768 Val("&HFFFF")= -1
how can i get the unsigned number?
thanks!
There's a problem right here:
?TypeName(&HFFFF)
Integer
The Integer type is 16-bit, and 65,535 overflows it. This is probably overkill, but it was fun to write:
Function ConvertHex(ByVal value As String) As Double
If Left(value, 2) = "&H" Then
value = Right(value, Len(value) - 2)
End If
Dim result As Double
Dim i As Integer, j As Integer
For i = Len(value) To 1 Step -1
Dim digit As String
digit = Mid$(value, i, 1)
result = result + (16 ^ j) * Val("&H" & digit)
j = j + 1
Next
ConvertHex = result
End Function
This function iterates each digit starting from the right, computing its value and adding it to the result as it moves to the leftmost digit.
?ConvertHex("&H10")
16
?ConvertHex("&HFF")
255
?ConvertHex("&HFFFF")
65535
?ConvertHex("&HFFFFFFFFFFFFF")
281474976710655
UPDATE
As I suspected, there's a much better way to do this. Credits to #Jonbot for this one:
Function ConvertHex(ByVal value As String) As Currency
Dim result As Currency
result = CCur(value)
If result < 0 Then
'Add two times Int32.MaxValue and another 2 for the overflow
'Because the hex value is apparently parsed as a signed Int64/Int32
result = result + &H7FFFFFFF + &H7FFFFFFF + 2
End If
ConvertHex = result
End Function
Append an ampersand to the hex literal to force conversion to a 32bit integer:
Val("&HFFFF" & "&") == 65535
Val("&H8000&") == +32768
Don't use Val. Use one of the built-in conversion functions instead:
?CCur("&HFFFF")
65535
?CDbl("&HFFFF")
65535
Prefer Currency over Double in this case, to avoid floating-point issues.

How can I get packets of data from a HEX string in VB.NET?

I'm getting a hexadecimal string from a PLC. The data comes from 3 sensors and the string is 12 characters long. For example 00150C950137 so the data for the sensors is 0015, 0C95 and 0137.
I converted the first 4 easily but it gives me an error when I try to convert the 2nd and 3rd. This is what I'm using:
ResData.Text = strRes & ": " & strRes.Substring(0, 4) & " - " & strRes.Substring(4, 4) & " - " & strRes.Substring(8, 4)
Dim lbl1 = strRes.Substring(0, 4).ToString
lbl1 = Convert.ToByte(lbl1, 16)
Dim lbl2 = strRes.Substring(4, 4).ToString
lbl2 = Convert.ToByte(lbl2, 16)
Dim prg1 = strRes.Substring(8, 4).ToString
prg1 = Convert.ToByte(prg1, 16)
Label1.Text = "Plug Catcher: " & lbl1 & " psi"
Label3.Text = "Manifold: " & lbl2 & " psi"
MyVerticalProgessBar1.Value = prg1
The first line is there to show the whole string and also the 3 different groups of data and it works fine in HEX.
The lbl1 convertion also works. For example 0015 gives me 21. The problem comes with the lbl2 and the prg1. It says:
An unhandled exception of type 'System.OverflowException' occurred in
mscorlib.dll
Additional information: Value was either too large or too small for an
unsigned byte.
Any ideas? Thanks in advance!
The problem is that you are trying to convert it to a four digit hexadecimal number into a single Byte. Each digit in a hexadecimal number has a range of 0 to F (0 to 15). So a two decimal hexadecimal number can range from 0 to FF (0 to 255). The Byte type only allows for values ranging from 0 to 255. In other words, each two-digit pair in a hexadecimal string represents one byte. So, in your example, the number 00150C950137 represents six bytes:
00 15 0C 95 01 37
When you are converting from a hexadecimal string to a Byte, only values up to FF will be allowed. Anything larger than FF will throw an OverflowException. If you need to get the numeric value of a four digit hexadecimal string, that's not a Byte, that's a 16-bit integer (a byte is 8 bits). In VB.NET, the types for 16-bit integers are called Short and UShort. So, for instance:
Console.WriteLine(Convert.ToByte("00FF", 16)) ' Writes 255
Console.WriteLine(Convert.ToUInt16("00FF", 16)) ' Writes 255
Console.WriteLine(Convert.ToUInt16("0100", 16)) ' Writes 256
Console.WriteLine(Convert.ToByte("0100", 16)) ' Throws an OverflowException
So, if you need all four digits, you probably want it as an unsigned 16-bit UShort, like this:
Dim val1 As UShort = Convert.ToUInt16(strRes.Substring(0, 4), 16)
Dim val2 As UShort = Convert.ToUInt16(strRes.Substring(4, 4), 16)
Dim val3 As UShort = Convert.ToUInt16(strRes.Substring(8, 4), 16)
When reading multiple bytes, however, you may very well need to care about the endianness (byte-order) of both your current platform and the platform that is sending the data.

Force an integer to be two digits - VB

I have a variable that holds a string "02100030000000000000000000D5010008D501000804" and I'm byte separating the string using
For i As Integer = 1 To (stringReader.Length - 1) Step 2
'Get the successive 2-character substrings, parse as bytes and add to total
Dim b As Byte = Byte.Parse(stringReader.Substring(i, 2), NumberStyles.AllowHexSpecifier)
sum = sum + CInt(b)
Next
I'm converting the strings to direct integers.e.g:(string"10" to Integer10 and ). That works fine. But Whenever I convert the string"02" to Integer, I get only Integer(2) and I need Integer(02). How can I proceed with?
My code is:
stringReader = fileReader.ReadLine()
byt = stringReader(1) + stringReader(2)
stringreader contains something like "100030000000000000000000D5010008D501000804"
Byte separation
For i As Integer = 1 To (stringReader.Length - 1) Step 2
'Get the successive 2-character substrings, parse as bytes and add to total
Dim b As Byte = Byte.Parse(stringReader.Substring(i, 2), NumberStyles.AllowHexSpecifier)
sum = sum + CInt(b)
Next
You can use
number.ToString("D2")
where number is an integral type like System.Int32(Integer).
Further reading: Standard Numeric Format Strings: The Decimal ("D") Format Specifier
If you have a String instead you could also use String.PadLeft:
"2".PadLeft(2, "0"c) ' -> "02"

Get two's complement for a byte

Two's compliment is when each bit in the byte is flipped and then a '1' is added to the result.
I don't want to extract each bit and flip it. Is there an easy way to do this?
You can convert the byte to a negative value (after you convert it to integer):
b = CByte(-CSHort(b) And &HFF)
You can simply XOR the byte with 255, then add one.
Dim myByte1 As Byte = 5
Dim myByte2 As Byte = 255
Dim MyTwosComplement As Byte
MyTwosComplement = myByte1 Xor myByte2
MyTwosComplement = CByte(MyTwosComplement + 1)
You can use the other definition for two's complement: 2^n - b where n is the number of bits.
Function TwosComplement(b As Byte) As Byte
Return CByte((256 - b) And &HFF)
End Function
How about
Dim b as Byte = 5
Dim twosCompliment As Byte = (Not b) + 1
Option Explicit On
Option Strict On
...
Public Function TwosComplement(value As Byte) As Byte
If value = 0 Then Return 0 Else Return CByte(CByte(value Xor Byte.MaxValue) + 1)
End Function