Click here to Skip to main content
14,494,237 members

IntelliPort - An Alternative Windows Version to the Famous HyperTerminal

Rate this:
4.74 (33 votes)
Please Sign up or sign in to vote.
4.74 (33 votes)
25 Mar 2020Zlib
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 strMessage;
   switch (theApp.GetInt(_T("Connection"), 0))
   {
      case 0:
      {
         m_pSerialPort.Open(
            (LPCTSTR) theApp.GetString
            (_T("SerialName"), _T("COM1")),
            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);
            strMessage.Format(_T("Serial port %s has been opened."), 
            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");
         const 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");
         const 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
            {
            }

            m_nThreadRunning = TRUE;
            AfxBeginThread(SocketThreadFunc, this);
            strMessage.Format(_T("%s socket %s:%d has been created."), 
            ((theApp.GetInt(_T("Connection"), 0) == 1) ? 
            _T("TCP") : _T("UDP")), strServerIP, nServerPort);
            SetCaptionBarText(strMessage);
         }
         break;
      }
   }
}

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

         if (!m_pSerialPort.IsOpen())
         {
            strMessage.Format(_T("Serial port %s has been closed."), 
            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");
         const UINT nServerPort = theApp.GetInt(_T("ServerPort"), 0);

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

         if (!m_pSocket.IsCreated())
         {
            strMessage.Format(_T("%s socket %s:%d has been closed."), 
            ((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);
            // CString strClientIP = theApp.GetString
            (_T("ClientIP"), _T("127.0.0.1"));
            // if (strClientIP.IsEmpty()) strClientIP = _T("127.0.0.1");
            // const UINT nClientPort = theApp.GetInt(_T("ClientPort"), 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[0x1000] = { 0, };
   CMainFrame* pMainFrame = (CMainFrame*) pParam;
   CRingBuffer& pRingBuffer = pMainFrame->m_pRingBuffer;
   CSerialPort& pSerialPort = pMainFrame->m_pSerialPort;
   CMutex& 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();
      }
      ::Sleep(10);
   }
   return 0;
}

UINT SocketThreadFunc(LPVOID pParam)
{
   char pBuffer[0x1000] = { 0, };
   CMainFrame* pMainFrame = (CMainFrame*) pParam;
   CRingBuffer& pRingBuffer = pMainFrame->m_pRingBuffer;
   CWSocket& pSocket = pMainFrame->m_pSocket;
   CWSocket& pIncomming = pMainFrame->m_pIncomming;
   CMutex& 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
         {
            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
      {
         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();
         }
      }
      ::Sleep(10);
   }
   return 0;
}

Final Words

IntelliPort application uses many components that have been published on The 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

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

Share

About the Author

Mihai MOGA
Software Developer (Senior) 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).

If you like my articles, please visit my website: https://www.mihaimoga.com/

Comments and Discussions

 
QuestionWhy the bloody ribbon! Pin
Galatei31-Mar-20 7:20
MemberGalatei31-Mar-20 7:20 
QuestionCannot show returned output from serial device Pin
uzayim25-Dec-19 6:18
Memberuzayim25-Dec-19 6:18 
QuestionIssue with reading from serial port Pin
V12025-Sep-19 6:05
MemberV12025-Sep-19 6:05 
BugSerial ports > COM9 Pin
Chris in England17-Jul-19 22:50
MemberChris in England17-Jul-19 22:50 
GeneralRe: Serial ports > COM9 Pin
Mihai MOGA27-Jul-19 0:36
professionalMihai MOGA27-Jul-19 0:36 
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
Mihai MOGA22-Jul-19 10:24
professionalMihai 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
Mihai MOGA14-Jun-19 20:25
professionalMihai 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
Mihai MOGA8-Jun-19 12:49
professionalMihai 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
Mihai MOGA13-Sep-14 19:07
professionalMihai 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
Mihai MOGA15-Sep-14 6:19
professionalMihai MOGA15-Sep-14 6:19 
AnswerRe: Where on your site to download exe? Pin
Mihai MOGA8-Jun-19 12:51
professionalMihai MOGA8-Jun-19 12:51 
QuestionFormat issues Pin
Nelek30-Aug-14 3:59
protectorNelek30-Aug-14 3:59 
AnswerRe: Format issues Pin
Mihai MOGA30-Aug-14 6:36
professionalMihai MOGA30-Aug-14 6:36 
GeneralRe: Format issues Pin
Nelek30-Aug-14 7:10
protectorNelek30-Aug-14 7:10 

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

51.6K views
1.7K downloads
69 bookmarked