dcsimg
Results 1 to 9 of 9

Thread: Should vb6 Strings be converted to byte arrays when using Com port communication?

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jan 2020
    Posts
    16

    Question Should vb6 Strings be converted to byte arrays when using Com port communication?

    Is it good practice to always convert a vb6 string to a byte array when using Com.output?

    Would a string that was converted to a byte array like this:
    Code:
    Dim Sometext As String
    Dim b() As Byte
    
    Sometext = "Hello World"
    
    b = StrConv(Sometext ,vbFromUnicode)
    Be a better approach than simply do this:
    Code:
    Dim Sometext As String
    Sometext = "Hello World"
    
    Com.output =  Sometext

    The problem i'm facing is that 98% of commands work. But the device i send commands to, also has an 'internal hardware' that commands can be sent to, to do specific operations. These 'Specifics' dont work, or fail 99.8% of the time (specific number, but kinda accurate)


    It doesn't work on my machine using vb6, but it does work on the manufacturer's machine, using .net

    If we 'sniff' the data (using a 3rd party serial port monitor), everything seems to be exactly as we are sending it. ( Although it doesn't work here, and it DOES work over there.)

    So to exclude the hardware being the problem, we've sent the whole package to the manufacturer. And using our hardware it works there, while it didn't over here.


    I've found a thread ,where this was sort of discussed and it sparked the idea to me: http://www.vbforums.com/showthread.p...-mscomm-output


    Since i'm new to Vb6 but really into it, and it's 'Part of the job', i need to learn myself a consistent way of doing this.
    I don't want to run into incompatibility issues in the future. Especially when i'm working with newer hardware, that might internally not be able to handle a vb6 string variable if sent in unicode as per example 2.

    Which way would be the most reliable way, and could my issue be related to it?

  2. #2
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    2,149

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Endianness?
    One System to rule them all, One IDE to find them,
    One Code to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    For health reasons i try to avoid reading unformatted Code

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Jan 2020
    Posts
    16

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    There is no endianess at question here. or is there? it's confusing..

    Literally the same command that is sent over the output is working for an .net application but isn't in my vb6 application.

    This string for example (in hex for readability): "530008000460EBAA"

    is sent to the output as follows:

    Code:
    str$ = chr(53) & chr(00)& chr(08)& chr(00)& chr(04)& chr(60)& chr(EB)& chr(AA)
    com.output = str$
    Can the result on the other end be different when it was sent like this, in other words, will it be more true to the actual data:

    Code:
    dim b() as byte
    str$ = chr(&h53) & chr(&h00) & chr(&h08) & chr(&h00) & chr(&h04) & chr(&h60) & chr(&hEB) & chr(&hAA)
    b = StrConv(str$ ,vbFromUnicode)
    com.output = b

    Can Unicode mess it up, but make it look like the same characters were communicated when 'sniffed'
    Last edited by rikdol; Feb 18th, 2020 at 08:47 AM. Reason: forgot '()' as byte

  4. #4
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    2,149

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Quote Originally Posted by rikdol View Post
    Literally the same command that is sent over the output is working for an .net application but isn't in my vb6 application.
    It's not, at least acc. to your description.

    Your statement, that it works with dot Crap specifically mentiones manufacturer's machine --> and not your own.

    Maybe the "receiving" device has different endianness, and the manufacturer would know that.
    It would be my first point of "debugging"
    One System to rule them all, One IDE to find them,
    One Code to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    For health reasons i try to avoid reading unformatted Code

  5. #5
    PowerPoster
    Join Date
    Feb 2006
    Posts
    20,956

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    It depends entirely on the application layer protocol used.

    Most text protocols including "squirt plain text" presume 7-bit ASCII with CRLF line delimiters. You can see that in one Internet RFC after another. Sending a String that hasn't been cluttered with values outside that subset of Unicode results in the Winsock control handling that automagically. A side-effect is that characters outside that range get converted using the current ANSI codepage, and that isn't portable internationally.

    To expand on that UTF-8 can be used. Newer RFCs often specify UTF-8 or include options for using it. VB6 and the Winsock contyrol do not support conversion from Unicode to UTF-8 and back though. To use this you'd have to do the conversions using an external library.

    Just schlepping a Unicode String into a Byte array copies Unicode bytes (UTF-16LE) and in theory that is ever acceptable because Network Byte Order should always be observed in any Internet protocols. That would mean UTF-16BE instead, which again doesn't have any direct support in VB6.

    Binary data is another thing entirely. However it should NEVER be passed through a String because of the chances of distortion due to Unicode to ANSI conversion (and back) implied in so many VB6 String operations (mainly text I/O and control properties).

  6. #6
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,882

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Quote Originally Posted by dilettante View Post
    Binary data is another thing entirely. However it should NEVER be passed through a String because of the chances of distortion due to Unicode to ANSI conversion (and back) implied in so many VB6 String operations (mainly text I/O and control properties).
    Yep, whilst "Binary-Stream-representations" (as a Hex-String) are entirely valid to use,
    one should not convert such "HexStream-StringLiterals" via the method shown by the OP (using Chr() or StrConv()).

    @the OP:
    Instead one should use ones own converter-routine for such Hex-Stream-Inputs, like the one below:
    Code:
    Private Sub Form_Load()
      DumpBytesHex HexStrToByteArr("530008000460EBAA")
      DumpBytesHex HexStrToByteArr("53 00 08 00 04 60 EB AA")
    End Sub
    
    Public Function HexStrToByteArr(strHex As String) As Byte()
      Dim B() As Byte, i As Long, j As Long, B15 As Byte
          B = Replace(strHex, " ", "")  'remove potential SpaceChars beforehand
          For i = 0 To UBound(B) Step 2 'B contains a WChar-Stream, so we step with 2
              Select Case B(i) + 256& * B(i + 1) 'and re-construct the WChar-Value as Select-Case-Input
                Case 48 To 57:  B15 = B(i) - 48
                Case 65 To 70:  B15 = B(i) - 55
                Case 97 To 102: B15 = B(i) - 87
                Case Else: Err.Raise vbObjectError, , "invalid char in hex-stream"
              End Select
              If i Mod 4 Then B(j) = B(j) * 16 + B15: j = j + 1 Else B(j) = B15
          Next
          If j Then ReDim Preserve B(j - 1)
      HexStrToByteArr = B
    End Function
    
    Public Sub DumpBytesHex(B() As Byte) 'to visualize content of short ByteArrays
      Dim i As Long
      For i = 0 To UBound(B)
        Debug.Print Right("0" & Hex(B(i)), 2); IIf(i = UBound(B), vbLf, " ");
      Next
    End Sub
    HTH

    Olaf

  7. #7
    Frenzied Member wqweto's Avatar
    Join Date
    May 2011
    Posts
    1,974

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Here is a simple trick that will get rid of most locale issues. Just *always* pass 3-rd parameter to StrConv and *always* read/write byte-arrays from/to the serial port.
    Code:
        Const LOCALE_ID As Long = 1033
        
        Dim b() As Byte
        b = StrConv("this is a test - това е проба", vbFromUnicode, LOCALE_ID)
    Another (better) option would be to use conversion from/to UTF-8 not just en-US locale 1033 with some helper functions like these:

    Code:
    '--- for MultiByteToWideChar
    Private Const CP_UTF8                       As Long = 65001
    
    Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, lpMultiByteStr As Any, ByVal cbMultiByte As Long, lpWideCharStr As Any, ByVal cchWideChar As Long) As Long
    Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
    
    Public Function ToUtf8Array(sText As String) As Byte()
        Dim baRetVal()      As Byte
        Dim lSize           As Long
        
        lSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), 0, 0, 0, 0)
        If lSize > 0 Then
            ReDim baRetVal(0 To lSize - 1) As Byte
            Call WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), VarPtr(baRetVal(0)), lSize, 0, 0)
        Else
            baRetVal = vbNullString
        End If
        ToUtf8Array = baRetVal
    End Function
    
    Public Function FromUtf8Array(baText() As Byte) As String
        Dim lSize           As Long
        
        If UBound(baText) >= 0 Then
            FromUtf8Array = String$(2 * UBound(baText), 0)
            lSize = MultiByteToWideChar(CP_UTF8, 0, baText(0), UBound(baText) + 1, ByVal StrPtr(FromUtf8Array), Len(FromUtf8Array))
            FromUtf8Array = Left$(FromUtf8Array, lSize)
        End If
    End Function
    Just *always* read/write byte-arrays from/to the serial port again.

    cheers,
    </wqw>

  8. #8
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Quote Originally Posted by rikdol View Post
    There is no endianess at question here. or is there? it's confusing..

    Literally the same command that is sent over the output is working for an .net application but isn't in my vb6 application.

    This string for example (in hex for readability): "530008000460EBAA"

    is sent to the output as follows:

    Code:
    str$ = chr(53) & chr(00)& chr(08)& chr(00)& chr(04)& chr(60)& chr(EB)& chr(AA)
    com.output = str$
    Can the result on the other end be different when it was sent like this, in other words, will it be more true to the actual data:

    Code:
    dim b() as byte
    str$ = chr(&h53) & chr(&h00) & chr(&h08) & chr(&h00) & chr(&h04) & chr(&h60) & chr(&hEB) & chr(&hAA)
    b = StrConv(str$ ,vbFromUnicode)
    com.output = b

    Can Unicode mess it up, but make it look like the same characters were communicated when 'sniffed'
    Try Using ChrW() instead of Chr(). Chr() converts any code from 128-255 to Unicode depending on the OS code page, even in US English systems some characters in this range are converted to 16-Bit. ChrW on the other hand doesn't do that. See this post for more details, which shows output illustrating differences between Chr and ChrW on US-English system.
    Last edited by qvb6; Feb 18th, 2020 at 01:55 PM.

  9. #9
    PowerPoster
    Join Date
    Jun 2013
    Posts
    4,882

    Re: Should vb6 Strings be converted to byte arrays when using Com port communication?

    Quote Originally Posted by qvb6 View Post
    Try Using ChrW() instead of Chr()...
    Nononono... please don't...

    When we look again, what the OP is apparently after (with a "Hex-Input-Literal" like "530008000460EBAA"),
    then he obviously wants to find a way, to send such "Hex-Literals" over the COM-interface as binary (in a ByteArray).

    Not sure, where these Hex-(String)-Literals came from (maybe defined as the OPs own "protocol-helper-consts",
    or maybe from the DeviceVendor-documentation, or from somewhere else).

    Let's play the OPs idea through with a simpler Hex-Input Literal
    (with the single Binary-Value 128 == "80")

    The OP is now trying to convert this Hex-Input "80" to a ByteArray (with a single Byte and the value 128).
    And he does this via:
    Code:
      Dim S As String, B() As Byte
      S = Chr(&H80) 'implicit ANSI to Unicode-conversion
      B = StrConv(S, vbFromUnicode) 'explicit Unicode to ANSI conversion
      Debug.Print B(0) '<- Prints out decimal 128 == &H80
    This ANSI-Unicode + Unicode-ANSI backconversion works (although still risky),
    because both parts use the same (default-)locale for the ANSI-mapping-table.

    But if we introduce ChrW as the first conversion-function:
    Code:
      Dim S As String, B() As Byte
      S = ChrW(&H80) 'UTF16-UnicodeValue to Unicode-WChar-conversion
      B = StrConv(S, vbFromUnicode) 'explicit Unicode to ANSI conversion
      Debug.Print B(0) '<- Prints out decimal 63 <> &H80
    Of course the task would be quite easy, when the OP would just do:
    Redim B(0) As Byte
    B(0) = &H80

    Or when the whole thing is part of a (Step 2)-loop over the HexLiteral-InputString, then:
    Redim B(0 to Len(HexInput) \ 2 - 1) As Byte
    B(i \ 2) = CByte("&H" & Mid$(HexInput, i, 2))

    Or alternatively just using the function I've shown in my first post here...

    Olaf
    Last edited by Schmidt; Feb 18th, 2020 at 04:15 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width