Android Question How to create and parse Tag, Length, Value (TLV) in .b4a and encode it in Base64

alktab

New Member
Hello, I have this code in vb net

B4X:
    Public Function encodeQrText(ByVal sallerName As String, ByVal sallerTRN As String, ByVal invoiceDateTime As String, ByVal totalWithVAT As String, ByVal VATTotal As String) As String
        Dim bytes As Byte() = Encoding.UTF8.GetBytes(sallerName)
        Dim L1 As String = bytes.Length.ToString("X")
        Dim tag1Hex As String = BitConverter.ToString(bytes)
        tag1Hex = tag1Hex.Replace("-", "")
        Dim L2 As String = sallerTRN.Length.ToString("X")
        Dim L3 As String = invoiceDateTime.Length.ToString("X")
        Dim L4 As String = totalWithVAT.Length.ToString("X")
        Dim L5 As String = VATTotal.Length.ToString("X")

        Dim hex As String = "01" & (If((L1.Length = 1), ("0" & L1), L1)) & tag1Hex & "02" & (If((L2.Length = 1), ("0" & L2), L2)) & ToHexString(sallerTRN) & "03" & (If((L3.Length = 1), ("0" & L3), L3)) + ToHexString(invoiceDateTime) & "04" & (If((L4.Length = 1), ("0" & L4), L4)) + ToHexString(totalWithVAT) & "05" & (If((L5.Length = 1), ("0" & L5), L5)) + ToHexString(VATTotal)
        Texthex.Text = hex


        Return HexToBase64(hex)
    End Function

B4X:
    Private Function HexToBase64(ByVal strInput As String) As String
        Try
            Dim bytes = New Byte(strInput.Length / 2 - 1) {}
            For i = 0 To bytes.Length - 1
                bytes(i) = Convert.ToByte(strInput.Substring(i * 2, 2), 16)
            Next
            Return Convert.ToBase64String(bytes)
        Catch __unusedException1__ As Exception
            Return "-1"
        End Try
    End Function

Outputs :
AQRURVNUAg8zMDAyNTQyMzU0NTg0NTYDFDIwMjQtMDItMTdUMDM6MDA6NDJaBAMxMDAFAjE1
010454455354020F3330303235343233353435383435360314323032342D30322D31375430333A30303A34325A040331303005023135


How can it be converted to B4A

The code depends on five variables that I want to deal with inside B4A
 

emexes

Expert
Licensed User
This might be a useful starting point:

B4X:
Dim Base64Input As String = "AQRURVNUAg8zMDAyNTQyMzU0NTg0NTYDFDIwMjQtMDItMTdUMDM6MDA6NDJaBAMxMDAFAjE1"

Log("base64" & TAB & Base64Input)

Dim su As StringUtils
Dim B() As Byte = su.DecodeBase64(Base64Input)

Dim bc As ByteConverter
Log("hex" & TAB & bc.HexFromBytes(B))

Log("tag" & TAB & "length" & TAB & "value")

Dim NumDone As Int = 0
Do While NumDone + 2 <= B.Length    'expecting at least tag and length bytes
    Dim FieldTag As Byte = B(NumDone)
    NumDone = NumDone + 1
  
    Dim FieldLength As Int = Bit.And(B(NumDone), 0xFF)    'translate signed -128..127 to unsigned 0..255
    NumDone = NumDone + 1
  
    If NumDone + FieldLength > B.Length Then Exit    'expecting at least FieldLength bytes

    Dim V(FieldLength) As Byte
    bc.ArrayCopy(B, NumDone, V, 0, FieldLength)
    NumDone = NumDone + FieldLength

    Dim FieldValue As String = bc.StringFromBytes(V, "UTF-8")

    'if we get to here then FieldTag+Length+Value are ok
    Log(FieldTag & TAB & FieldLength & TAB & FieldValue)
Loop

Log output:
Waiting for debugger to connect...
Program started.
base64    AQRURVNUAg8zMDAyNTQyMzU0NTg0NTYDFDIwMjQtMDItMTdUMDM6MDA6NDJaBAMxMDAFAjE1
hex       010454455354020F3330303235343233353435383435360314323032342D30322D31375430333A30303A34325A040331303005023135
tag   length   value
1     4        TEST
2     15       300254235458456
3     20       2024-02-17T03:00:42Z
4     3        100
5     2        15
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
This might be a useful starting point:

Maybe this too:
B4X:
Dim EncodedQrText As String = encodeQrText( _
    "TEST", _
    "300254235458456", _
    "2024-02-17T03:00:42Z", _
    "100", _
    "15" _
)

Log(EncodedQrText)


Sub encodeQrText(sallerName As String, sallerTRN As String, invoiceDateTime As String, totalWithVAT As String, VATTotal As String) As String

    Dim hex As String = _
        StringToTagLengthValueHex(1, sallerName) & _
        StringToTagLengthValueHex(2, sallerTRN) & _
        StringToTagLengthValueHex(3, invoiceDateTime) & _
        StringToTagLengthValueHex(4, totalWithVAT) & _
        StringToTagLengthValueHex(5, VATTotal)

    Dim bc As ByteConverter
    Dim B() As Byte = bc.HexToBytes(hex)

    Dim su As StringUtils
    Return su.EncodeBase64(B)
 
End Sub


Sub StringToTagLengthValueHex(Tag As Int, Value As String) As String

    Dim bc As ByteConverter
 
    For L = Value.Length To 0 Step -1    'ensure not too long for 8-bit (unsigned) length byte 0..255
        Dim V() As Byte = bc.StringToBytes(Value.SubString2(0, L), "UTF-8")
        If V.Length <= 255 Then Exit
    Next

    Dim TL() As Byte = Array As Byte(Tag, V.Length)
 
    Return bc.HexFromBytes(TL) & bc.HexFromBytes(V)

End Sub
Log output:
Waiting for debugger to connect...
Program started.
AQRURVNUAg8zMDAyNTQyMzU0NTg0NTYDFDIwMjQtMDItMTdUMDM6MDA6NDJaBAMxMDAFAjE1
 
Last edited:
Upvote 0

alktab

New Member
Thank you emexes
It took me a lot of time how creative you are in thinking and thank you once again and to brother Ariel I came up with a very wonderful project God bless you
 
Upvote 0
Top