Results 1 to 7 of 7

Thread: Feature request: Add timeout to COMM_Send()

Hybrid View

  1. #1

    Feature request: Add timeout to COMM_Send()

    I have a UI based TB app which presents the user with a pull-down menu of all of the available COM ports on their PC to pick from. I then open the port they choose and use it to communicate.

    Everything works fine unless they pick the wrong port. Some PCs (Lenovo laptops in this case) have a COM port which comes up as an 'available' com port in the list but is actually internal to the PC and is used to communicate with "Intel(R) Active Management Technology", whatever the heck that is.

    Here's the problem: If the user picks the "Intel Active Management Technology" port by accident, TB will open up that COM port just fine, but will hang on the first COMM_Send() call.

    Here's a short program demonstrating the problem:

    Uses "console"
    Uses "COMM" 
    
    Function TBMain() As Long
      Local hComm  As Long
      
      Console_WriteLine("Starting test")
    
      hComm = COMM_FreeFile
      If COMM_Open("\\.\COM3", hComm) = 0 Then
        If Err = 0 Then
          COMM_Send(hComm, "A")
        Else
          Console_WriteLine("Err not zero")
        End If
      Else
        Console_WriteLine("Failed to open port")
      End If
    
      Console_WriteLine("Ending test")
      
      WaitKey
      
    End Function
    
    Now, on my machine, COM3 happens to be this 'special' (and evil) COM port. On other people's PCs it is different.

    If I run the above test program on my machine, I get "Starting test" in the console, and then nothing else. The program hangs at COMM_Send(). I can ctrl-C out of it in this console based version.

    If I change the com port to COM2 in the above code and run it (my PC does not have a COM2), then I get "Starting test", then "Failed to open port", then "Ending test".

    If I change the com port to COM4 in the above code and run it (my PC has a USB to serial adapter in COM4), then I get "Starting test" then "Ending test".

    If I open up COM4 with another application first, then run the above program on COM4 (to test what happens if TB tries to open a COM port that's already open) I get "Starting test" and that's it - program hangs.

    So I'm pretty sure what's going on here is that the list of COM ports doesn't exclude ones that are already opened by another application. So if the user tries to open one that's already open in another application, the COMM_Open() call doesn't fail (shouldn't it??), and when we get to the COMM_Send(), we get the hang.

    Would it be possible to:

    A) Make COMM_Open() fail if another app is already using the port?

    or

    B) Make COMM_Send() return an error code or something in this case rather than just hanging?

    Either would be preferable to what it does now.

    Thanks!

    *Brian

  2. #2
    While both of the above suggestions still stand as good ideas, another way to solve the problem is to be able to filter out the COM ports that are available on the PC, but are already in use.

    Is that possible somehow?

    This is the code I use to populate the 'available' COM ports:

          ' Get the com ports, and add them to the list of available com ports
          Local vData()       As String
          Local nItems        As Long
          Local Counter       As Long
          Local Position      As Long
          Local ComputerName  As String   Value OS_GetComputerName
          Local sBuffer       As String
          Local Ports()       As String
      
          sBuffer = WMI_GetData(ComputerName, "", "", "", "Win32_PnPEntity", "", "Name" )
            
          '---Parse returned data into single lines
          nItems = Parse( sBuffer, vData(), $CRLF)
            
          '---Print lines
          For Counter = 1 To nItems
            Position = InStr(Ucase$(vData(Counter)),"(COM")
            If Position Then
              ReDim Preserve Ports(UBound(Ports)+1)
              PortS(UBound(Ports)) = Extract$(Position+1,vData(Counter),")")
            End If
          Next
           
          COMBOBOX Reset CBHNDL, %ID_CommandSerialCombobox
          If UBound(Ports) >= LBound(Ports) Then
            For Counter = LBound(Ports) To UBound(Ports)
              COMBOBOX Add CBHNDL, %ID_CommandSerialCombobox, Ports(Counter)
            Next            
            COMBOBOX Select CBHNDL, %ID_CommandSerialCombobox, 1
          End If
          Control Redraw CBHNDL, %ID_CommandSerialCombobox
    
    I don't know much about WMI_GetData(). Is there another call that could be made to detect which COM ports are already opened in other applications?

    *Brian

  3. #3
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    51
    Posts
    8,343
    Blog Entries
    2
    Rep Power
    10
    Ciao,

    let's start from TimeOut function.
    Attached to this post new thinBasic_COMM.dll module.
    Please unzip thinBasic_COMM.dll into \thinBasic\Lib\ substituing yout current one.

    I've added function
    COMM_TimeOut(hCom, TimeOutInMillisec)
    
    You can call this function just after COMM_Open(...) function open communication without error.
    TimeOut will effect both Send/Receive functions.

    I've also added few TRY/CATCH zones inside COMM_Open to see if I can catch GPF

    Let me know if it does some difference.

    In the meantime I will check the other points you mentioned. I do not have serial ports in my development computer but I will try to install some virtual serial port and see what I can do.

    Eros

    *ADDED: attached file removed because an improved one attached some posts later
    Last edited by ErosOlmi; 07-02-2018 at 22:53.
    www.thinbasic.com | www.thinbasic.com/community/ | psch.thinbasic.com
    Win10Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

  4. #4
    That, my friend, works PERFECTLY. Thank you so much!

    Now, when I open a COM port that is already in use by another program, the COMM_Send() call exits after the timeout period (I used 1000ms) and the program terminates normally.

    Thanks!

    By the way, I've got _plenty_ of extra FTDI USB to serial cables lying around here. Could I send you a couple so that you'd have some COM ports to play with on your PC? Just send me your address . . .

    *Brian

  5. #5
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    51
    Posts
    8,343
    Blog Entries
    2
    Rep Power
    10
    Great, I will add into next thinBasic version.
    I've also some more ideas on how to improve COMM module error handling, will see what I can do.

    Thanks for the cables, I also have a lot at office, I will get from there.
    www.thinbasic.com | www.thinbasic.com/community/ | psch.thinbasic.com
    Win10Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

  6. #6
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    51
    Posts
    8,343
    Blog Entries
    2
    Rep Power
    10
    Dear Brian,

    regarding listing serial communication ports (modem, physical serials, USB, virtual, ....there are many types) I think I've found a solution using SetupApi.DLL that is a standard Windows DLL present in all Windows versions.
    Please get attached new version of thinBasic_COMM.dll and copy into \thinBasic\Lib\ directory replacing your current one.

    I've added two new functions:

    • COMM_GetDevices that enumerates all devices of some types and store an internal array of info returning the number of devices found
    • COMM_DeviceInfo(n).XXX that returns info XXX of device n where n is device number from 1 to number of devices returned by COMM_GetDevices and XXX con be one of the following:


    1. Class
    2. Guid
    3. FriendlyName
    4. Description
    5. Manufacturer
    6. Driver
    7. Port


    I'm not 100% sure it can work in all the situations. I've done some test but you have much more different kind of serial devices to test so let me know.

    Here an example on how to use:
    #MinVersion 1.10.4
    
    
    uses "COMM"
    uses "Console"
    
    
    printl "--- Hardware devices enumeration  ---" in %CCOLOR_BYELLOW
    PrintL "--- Uses SetupApi.DLL to get info ---" in %CCOLOR_BWHITE
    PrintL
    
    
    '---Always COMM_GetDevices FIRST!
    '---This function collect and store devices info and return number of devices found
    local nDevices = COMM_GetDevices
    printl "Number of devices:", nDevices in %CCOLOR_FYELLOW
    
    
    '---List all devices and devices info
    for n as long = 1 to nDevices
      printl " - Device", n in %CCOLOR_FINTENSEWHITE
      printl "     Class.............", COMM_DeviceInfo(n).Class      
      printl "     Guid..............", COMM_DeviceInfo(n).Guid
      printl "     FriendlyName......", COMM_DeviceInfo(n).FriendlyName
      printl "     Description.......", COMM_DeviceInfo(n).Description
      printl "     Manufacturer......", COMM_DeviceInfo(n).Manufacturer
      printl "     Driver............", COMM_DeviceInfo(n).Driver         
      printl "     Port..............", COMM_DeviceInfo(n).Port           
    Next
    
    
    PrintL
    printl "All done, press a key to end" in %CCOLOR_FLIGHTRED
    
    
    WaitKey
    
    Attached Files Attached Files
    Last edited by ErosOlmi; 07-02-2018 at 23:05.
    www.thinbasic.com | www.thinbasic.com/community/ | psch.thinbasic.com
    Win10Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

Similar Threads

  1. thinBasic 1.10.5 help on testing a new feature
    By ErosOlmi in forum thinBasic Beta testing
    Replies: 11
    Last Post: 30-11-2017, 00:00
  2. Request: Ignore feature for forum
    By Michael Hartlef in forum General
    Replies: 3
    Last Post: 29-09-2008, 05:21

Posting Permissions

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