Click here to Skip to main content
14,603,097 members

IntelliPort - An Alternative Windows Version to the Famous HyperTerminal

Rate this:
4.73 (39 votes)
Please Sign up or sign in to vote.
4.73 (39 votes)
31 Jul 2020GPL3
You can use IntelliPort to transfer large files from a computer onto your portable computer using a serial port rather than going through the process of setting up your portable computer on a network.
The main purpose of this MFC application is to get logs via serial port or UDP socket from embedded systems, such as EFTPOS devices, and it is based on PJ Naughter's CSerialPort and CWSocket classes.

HyperTerminal

Introduction

As you already know, Microsoft has dropped the development of HyperTerminal starting with Windows 7. IntelliPort is a program that you can use to connect to other computers, using either your null modem cable or Ethernet connection. IntelliPort records the messages passed to and from the computer on the other end of your connection. Therefore, it can serve as a valuable troubleshooting tool when setting up and using your modem. To make sure that your modem is connected properly or to view your modem's settings, you can send commands through IntelliPort and check the results. IntelliPort has scroll functionality that allows you to look at received text that has scrolled off the screen. You can use IntelliPort to transfer large files from a computer onto your portable computer using a serial port rather than going through the process of setting up your portable computer on a network. IntelliPort is designed to be an easy-to-use tool and is not meant to replace other full-feature tools available on the market. You can use IntelliPort to perform the specific tasks described above, but do not attempt to use IntelliPort for more complex communication needs.

Background

The main purpose of this MFC application is to get logs via serial port or UDP socket from embedded systems, such as EFTPOS devices, and it is based on PJ Naughter's CSerialPort and CWSocket classes. For those who do not know, EFTPOS is the method for paying for goods or services without needing to carry cash. On making a purchase, the EFTPOS customer gives an EFTPOS card to the cashier who inserts it into an on-site EFTPOS machine. When the EFTPOS customer confirms the purchase, either by signature or security PIN, the EFTPOS equipment contacts the store's bank electronically about the transaction. A message is also sent to the customer's bank. Unless there is reason for the EFTPOS transaction not to be completed, the funds will then be transferred between the two accounts. The EFTPOS transaction takes a matter of only a few seconds. Before the EFTPOS customer has had the goods put into a bag, the EFTPOS transaction will be complete. Confirmation of the EFTPOS transaction is sent to the store and passed on to the customer in the form of a printed EFTPOS transaction record.

How Do I Get Started?

First, configure the MFC application to get logs from either serial port or TCP/UDP socket connection. Please check the CConfigureDlg class for implementation details.

Configure serial port or TCP/UDP socket

Next, now you can connect/disconnect from your data source. Please check the OnOpenSerialPort and OnCloseSerialPort functions for implementation details.

Reading/Writing data to serial port or TCP/UDP socket

void CMainFrame::OnOpenSerialPort()
{
  CString strFormat, strMessage;
  switch (theApp.GetInt(_T("Connection"), 0))
  {
  case 0:
  {
    CString strFullPortName;
    strFullPortName.Format(_T("\\\\.\\%s"), theApp.GetString(_T("SerialName"), _T("COM1")));
    m_pSerialPort.Open(
      strFullPortName,
      theApp.GetInt(_T("BaudRate"), CBR_115200),
      (CSerialPort::Parity) theApp.GetInt(_T("Parity"), CSerialPort::NoParity),
      (BYTE)theApp.GetInt(_T("DataBits"), 8),
      (CSerialPort::StopBits) theApp.GetInt(_T("StopBits"), CSerialPort::OneStopBit),
      (CSerialPort::FlowControl) theApp.GetInt(_T("FlowControl"), CSerialPort::NoFlowControl),
      FALSE);

    if (m_pSerialPort.IsOpen())
    {
      m_nThreadRunning = TRUE;
      AfxBeginThread(SerialPortThreadFunc, this);
      strFormat.LoadString(IDS_SERIAL_PORT_OPENED);
      strMessage.Format(strFormat, theApp.GetString(_T("SerialName"), _T("COM1")));
      SetCaptionBarText(strMessage);
    }
    break;
  }
  case 1:
  case 2:
  {
    CString strServerIP = theApp.GetString(_T("ServerIP"), _T("127.0.0.1"));
    if (strServerIP.IsEmpty()) strServerIP = _T("127.0.0.1");
    UINT nServerPort = theApp.GetInt(_T("ServerPort"), 0);
    CString strClientIP = theApp.GetString(_T("ClientIP"), _T("127.0.0.1"));
    if (strClientIP.IsEmpty()) strClientIP = _T("127.0.0.1");
    UINT nClientPort = theApp.GetInt(_T("ClientPort"), 0);

    m_pSocket.SetBindAddress(strClientIP);
    m_pSocket.CreateAndBind(nClientPort, 
    ((theApp.GetInt(_T("Connection"), 0) == 1) ? SOCK_STREAM : SOCK_DGRAM), AF_INET);

    if (m_pSocket.IsCreated())
    {
      if (theApp.GetInt(_T("Connection"), 0) == 1) // TCP Socket
      {
        if (theApp.GetInt(_T("SocketType"), 0) == 1) // Client
        {
          m_pSocket.Connect(strServerIP, nServerPort);
        }
        else // TCP Server
        {
          m_dlgIncoming.ShowWindow(SW_SHOW);
          m_dlgIncoming.CenterWindow(this);
          m_dlgIncoming.Invalidate();
          m_dlgIncoming.UpdateWindow();
          m_pSocket.Listen();
          m_pSocket.Accept(m_pIncomming);
          m_dlgIncoming.ShowWindow(SW_HIDE);
        }
      }
      else // UDP Socket
      {
        strServerIP = strClientIP;
        nServerPort = nClientPort;
      }

      m_nThreadRunning = TRUE;
      AfxBeginThread(SocketThreadFunc, this);
      strFormat.LoadString(IDS_SOCKET_CREATED);
      strMessage.Format(strFormat, ((theApp.GetInt(_T("Connection"), 0) == 1) ? 
                        _T("TCP") : _T("UDP")), strServerIP, nServerPort);
      SetCaptionBarText(strMessage);
    }
    break;
  }
  }
}

void CMainFrame::OnCloseSerialPort()
{
  CString strFormat, strMessage;
  m_nThreadRunning = FALSE;
  ::Sleep(1000);
  switch (theApp.GetInt(_T("Connection"), 0))
  {
  case 0:
  {
    m_pSerialPort.Close();

    if (!m_pSerialPort.IsOpen())
    {
      strFormat.LoadString(IDS_SERIAL_PORT_CLOSED);
      strMessage.Format(strFormat, theApp.GetString(_T("SerialName"), _T("COM1")));
      SetCaptionBarText(strMessage);
    }
    break;
  }
  case 1:
  case 2:
  {
    CString strServerIP = theApp.GetString(_T("ServerIP"), _T("127.0.0.1"));
    if (strServerIP.IsEmpty()) strServerIP = _T("127.0.0.1");
    UINT nServerPort = theApp.GetInt(_T("ServerPort"), 0);
    CString strClientIP = theApp.GetString(_T("ClientIP"), _T("127.0.0.1"));
    if (strClientIP.IsEmpty()) strClientIP = _T("127.0.0.1");
    UINT nClientPort = theApp.GetInt(_T("ClientPort"), 0);

    m_pSocket.Close();
    m_pIncomming.Close();

    if (!m_pSocket.IsCreated())
    {
      if (theApp.GetInt(_T("Connection"), 0) == 1) // TCP Socket
      {
        if (theApp.GetInt(_T("SocketType"), 0) == 1) // Client
        {
        }
        else // TCP Server
        {
        }
      }
      else // UDP Socket
      {
        strServerIP = strClientIP;
        nServerPort = nClientPort;
      }

      strFormat.LoadString(IDS_SOCKET_CLOSED);
      strMessage.Format(strFormat, ((theApp.GetInt(_T("Connection"), 0) == 1) ? 
                        _T("TCP") : _T("UDP")), strServerIP, nServerPort);
      SetCaptionBarText(strMessage);
    }
    break;
  }
  }
}

void CMainFrame::OnSendReceive()
{
  CInputDlg dlgInput(this);
  if (dlgInput.DoModal() == IDOK)
  {
    CStringA pBuffer(dlgInput.m_strSendData);
    const int nLength = pBuffer.GetLength();

    switch (theApp.GetInt(_T("Connection"), 0))
    {
    case 0:
    {
      m_pMutualAccess.lock();
      m_pSerialPort.Write(pBuffer.GetBufferSetLength(nLength), nLength);
      m_pMutualAccess.unlock();
      pBuffer.ReleaseBuffer();
      break;
    }
    case 1:
    case 2:
    {
      CString strServerIP = theApp.GetString(_T("ServerIP"), _T("127.0.0.1"));
      if (strServerIP.IsEmpty()) strServerIP = _T("127.0.0.1");
      const UINT nServerPort = theApp.GetInt(_T("ServerPort"), 0);

      if (theApp.GetInt(_T("Connection"), 0) == 1) // TCP Socket
      {
        if (theApp.GetInt(_T("SocketType"), 0) == 1) // Client
        {
          if (m_pSocket.IsWritable(1000))
          {
            m_pMutualAccess.lock();
            m_pSocket.Send(pBuffer.GetBufferSetLength(nLength), nLength, 0);
            pBuffer.ReleaseBuffer();
            m_pMutualAccess.unlock();
          }
        }
        else
        {
          if (m_pIncomming.IsWritable(1000))
          {
            m_pMutualAccess.lock();
            m_pIncomming.Send(pBuffer.GetBufferSetLength(nLength), nLength, 0);
            pBuffer.ReleaseBuffer();
            m_pMutualAccess.unlock();
          }
        }
      }
      else
      {
        if (m_pSocket.IsWritable(1000))
        {
          m_pMutualAccess.lock();
          m_pSocket.SendTo(pBuffer.GetBufferSetLength(nLength), 
                           nLength, nServerPort, strServerIP, 0);
          pBuffer.ReleaseBuffer();
          m_pMutualAccess.unlock();
        }
      }
      break;
    }
    }
  }
}

Points of Interest

In order to be GUI responsive, the MFC application does the reading in separate working threads:

UINT SerialPortThreadFunc(LPVOID pParam)
{
  COMSTAT status = { 0, };
  char pBuffer[0x10000] = { 0, };
  CMainFrame* pMainFrame = (CMainFrame*)pParam;
  CRingBuffer& pRingBuffer = pMainFrame->m_pRingBuffer;
  CSerialPort& pSerialPort = pMainFrame->m_pSerialPort;
  std::mutex& pMutualAccess = pMainFrame->m_pMutualAccess;

  while (pMainFrame->m_nThreadRunning)
  {
    memset(&status, 0, sizeof(status));
    pSerialPort.GetStatus(status);
    if (status.cbInQue > 0)
    {
      memset(pBuffer, 0, sizeof(pBuffer));
      const int nLength = pSerialPort.Read(pBuffer, sizeof(pBuffer));
      pMutualAccess.lock();
      pRingBuffer.WriteBinary(pBuffer, nLength);
      pMutualAccess.unlock();
    }
    else
    {
      ::Sleep(10);
    }
  }
  return 0;
}

UINT SocketThreadFunc(LPVOID pParam)
{
  char pBuffer[0x10000] = { 0, };
  CMainFrame* pMainFrame = (CMainFrame*)pParam;
  CRingBuffer& pRingBuffer = pMainFrame->m_pRingBuffer;
  CWSocket& pSocket = pMainFrame->m_pSocket;
  CWSocket& pIncomming = pMainFrame->m_pIncomming;
  std::mutex& pMutualAccess = pMainFrame->m_pMutualAccess;
  BOOL bIsTCP = (theApp.GetInt(_T("Connection"), 0) == 1);
  BOOL bIsClient = (theApp.GetInt(_T("SocketType"), 0) == 1);

  CString strServerIP = theApp.GetString(_T("ServerIP"), _T("127.0.0.1"));
  if (strServerIP.IsEmpty()) strServerIP = _T("127.0.0.1");
  UINT nServerPort = theApp.GetInt(_T("ServerPort"), 0);

  while (pMainFrame->m_nThreadRunning)
  {
    if (bIsTCP)
    {
      if (bIsClient)
      {
        if (pSocket.IsReadible(1000))
        {
          memset(pBuffer, 0, sizeof(pBuffer));
          const int nLength = pSocket.Receive(pBuffer, sizeof(pBuffer), 0);
          pMutualAccess.lock();
          pRingBuffer.WriteBinary(pBuffer, nLength);
          pMutualAccess.unlock();
        }
        else
        {
          ::Sleep(10);
        }
      }
      else
      {
        if (pIncomming.IsReadible(1000))
        {
          memset(pBuffer, 0, sizeof(pBuffer));
          const int nLength = pIncomming.Receive(pBuffer, sizeof(pBuffer), 0);
          pMutualAccess.lock();
          pRingBuffer.WriteBinary(pBuffer, nLength);
          pMutualAccess.unlock();
        }
        else
        {
          ::Sleep(10);
        }
      }
    }
    else
    {
      if (pSocket.IsReadible(1000))
      {
        memset(pBuffer, 0, sizeof(pBuffer));
        const int nLength = pSocket.ReceiveFrom(pBuffer, sizeof(pBuffer), 
                            strServerIP, nServerPort, 0);
        pMutualAccess.lock();
        pRingBuffer.WriteBinary(pBuffer, nLength);
        pMutualAccess.unlock();
      }
      else
      {
        ::Sleep(10);
      }
    }
  }
  return 0;
}

Final Words

IntelliPort application uses many components that have been published on Code Project. Many thanks to:

  • PJ Naughter for his EnumSerialPorts class
  • Larry Antram for his CRingBuffer class
  • PJ Naughter for his CSerialPort class
  • PJ Naughter for his CWSocket class
  • PJ Naughter for his CVersionInfo class

Further plans: I would like to add Telnet and SSH support as soon as possible.

History

  • Version 1.3 (20th July, 2014)
    • Initial release
  • Version 1.5 (28th July, 2014)
    • Fixed several bugs regarding logging functions for serial port and UDP socket
  • Version 1.6 (30th August, 2015)
    • Fix for Microsoft Windows 10 64bit
  • Version 1.7 (03rd April, 2019)
    • Performance and security fixes
  • Version 1.8 (15th June, 2019)
    • Added Romanian translation; could anyone add German/French/Spanish/etc. translations?
    • Added PJ Naughter's CInstanceChecker class;
  • Version 1.9 (27th July, 2019)
    • Bugfix for serial port name - please see the article mentioned in the comments
  • Moved source code from CodeProject to GitLab (7th December, 2019)
  • Version 1.10 (25th March, 2020)
    • Changed font size for main and input dialogs
  • Version 1.11 (9th May, 2020)
    • Added French translation, thanks to Stefan Gaftoniuc
  • Version 1.12 (6th June, 2020)
  • Version 1.13 (13th June, 2020)
    • Added German translation, thanks to InterLingua
  • Version 1.14 (20th June, 2020)
    • Added Spanish translation, thanks to InterLingua
  • Version 1.15 (19th July, 2020)
    • Added Russian translation, thanks to InterLingua
  • Version 1.16 (31st July, 2020)
    • Added Greek translation, thanks to InterLingua

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Ștefan-Mihai MOGA
Architect Printec Group Romania SRL
Romania Romania
My professional background includes knowledge of analyst programmer for Microsoft Visual C++, Microsoft Visual C#, Microsoft Visual Basic, Sun Java, assembly for Intel 80x86 microprocessors, assembly for PIC microcontrollers (produced by Microchip Inc.), relational databases (MySQL, Oracle, SQL Server), concurrent version systems, bug tracking systems, web design (HTML5, CSS3, XML, PHP/MySQL, JavaScript, Flash).

Comments and Discussions

 
QuestionCommented out code and sleeps. Pin
Mike Diack17-Jun-20 2:32
MemberMike Diack17-Jun-20 2:32 
AnswerRe: Commented out code and sleeps. Pin
Ștefan-Mihai MOGA17-Jun-20 5:56
professionalȘtefan-Mihai MOGA17-Jun-20 5:56 
QuestionLine endings Pin
Gisle Vanem13-May-20 23:00
MemberGisle Vanem13-May-20 23:00 
AnswerRe: Line endings Pin
Ștefan-Mihai MOGA19-May-20 7:06
professionalȘtefan-Mihai MOGA19-May-20 7:06 
QuestionWhy the bloody ribbon! Pin
Galatei31-Mar-20 7:20
MemberGalatei31-Mar-20 7:20 
AnswerRe: Why the bloody ribbon! Pin
DavidPendleton22-Jun-20 7:09
MemberDavidPendleton22-Jun-20 7:09 
QuestionCannot show returned output from serial device Pin
uzayim25-Dec-19 6:18
Memberuzayim25-Dec-19 6:18 
AnswerRe: Cannot show returned output from serial device Pin
Ștefan-Mihai MOGA19-May-20 7:45
professionalȘtefan-Mihai MOGA19-May-20 7:45 
QuestionIssue with reading from serial port Pin
V12025-Sep-19 6:05
MemberV12025-Sep-19 6:05 
AnswerRe: Issue with reading from serial port Pin
Ștefan-Mihai MOGA19-May-20 7:45
professionalȘtefan-Mihai MOGA19-May-20 7:45 
BugSerial ports > COM9 Pin
Chris in England17-Jul-19 22:50
MemberChris in England17-Jul-19 22:50 
GeneralRe: Serial ports > COM9 Pin
Ștefan-Mihai MOGA27-Jul-19 0:36
professionalȘtefan-Mihai MOGA27-Jul-19 0:36 
I've made a bug fix as you suggested (in version 1.9 of IntelliPort)!
Please have a look and let me know if you have any questions or would like any changes.
QuestionVS2013 Platform toolset error fix: set to what you have in VS Pin
studleylee17-Jun-19 11:50
Memberstudleylee17-Jun-19 11:50 
AnswerRe: VS2013 Platform toolset error fix: set to what you have in VS Pin
Ștefan-Mihai MOGA22-Jul-19 10:24
professionalȘtefan-Mihai MOGA22-Jul-19 10:24 
QuestionChange COM Port? Pin
Member 1078424214-Jun-19 8:03
MemberMember 1078424214-Jun-19 8:03 
AnswerRe: Change COM Port? Pin
Ștefan-Mihai MOGA14-Jun-19 20:25
professionalȘtefan-Mihai MOGA14-Jun-19 20:25 
GeneralMy vote of 2 Pin
Country Man10-Jun-19 22:15
MemberCountry Man10-Jun-19 22:15 
GeneralMy vote of 4 Pin
TimDwg16-Dec-15 8:34
MemberTimDwg16-Dec-15 8:34 
GeneralRe: My vote of 4 Pin
Ștefan-Mihai MOGA8-Jun-19 12:49
professionalȘtefan-Mihai MOGA8-Jun-19 12:49 
QuestionWhere on your site to download exe? Pin
Len20209-Sep-14 16:07
MemberLen20209-Sep-14 16:07 
AnswerRe: Where on your site to download exe? Pin
Ștefan-Mihai MOGA13-Sep-14 19:07
professionalȘtefan-Mihai MOGA13-Sep-14 19:07 
GeneralRe: Where on your site to download exe? Pin
Len202015-Sep-14 5:32
MemberLen202015-Sep-14 5:32 
GeneralRe: Where on your site to download exe? Pin
Ștefan-Mihai MOGA15-Sep-14 6:19
professionalȘtefan-Mihai MOGA15-Sep-14 6:19 
AnswerRe: Where on your site to download exe? Pin
Ștefan-Mihai MOGA8-Jun-19 12:51
professionalȘtefan-Mihai MOGA8-Jun-19 12:51 
QuestionFormat issues Pin
Nelek30-Aug-14 3:59
protectorNelek30-Aug-14 3:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 21 Jul 2014

Stats

74.6K views
79 bookmarked