Sunday 22 July 2012

Aplikasi Pengontrol Lampu Sederhana dengan CGI

Pada kesempatan ini saya akan menuliskan langkah-langkah membuat aplikasi pengontrol lampu menggunakan CGI yang merupakan dokumentasi untuk tugas perkuliahan saya. CGI (Common Gateway Interface) merupakan program yang bisa menghubungkan beberapa program aplikasi pada halaman web, misalnya antara HTML yang menjadi standar pemrograman web dengan database atau yang lain. Bahasa yang sering digunakan dalam CGI adalah C++.
Untuk aplikasi sederhana ini membutuhkan beberapa aplikasi pendukung, yaitu :
  1. Visual C++ sebagai IDE
  2. Mozila Firefox sebagai web browser
  3. XAMPP 1.7.3 sebagai web server
  4. Adobe Dreamweaver sebagai  web page editor
  5. com0com sebagai simulator penghubung 2 port dalam 1 komputer
  6. Hyperterminal untuk komunikasi data melalui serial com port
 Langkah pertama yang harus kita lakukan adalah kita mendesain algoritmanya terlebih dahulu. Kita analogikan user dapat mengakses web server melalui browser untuk menyalakan lampu, perintah akan dikirimkan dari browser ke web server kemudian akan kembali dikirimkan ke browser yang diakses oleh user. Aplikasi pada server bisa digunakan untuk mengontrol kondisi lampu ON atau OFF dan kondisi lampu dikontrol oleh server dengan menggunakan komunikasi serial RS232.
Langkah kedua, adalah melakukan desain web yang digunakan sebagai user untuk mengakses webserver, dalam hal ini saya mendesain secara sederhana saja menggunakan Adobe Dreamweaver sebagai page editor, seperti tampak pada gambar berikut.

dan tampilannya adalah sebagai berikut :

Langkah ketiga, melakukan instalasi simulator com0com yang bisa di download secara gratis. Jangan lupa ketika mendownload simulator ini harus disesuaikan dengan komputer masing-masing agar tidak terjadi error. Setelah melakukan instalasi, langkah selanjutnya adalah membuat simulator port, pada bagian ini saya membuat port COM31 dan port COM1(terserah kita dalam penamaan, catatan : untuk nama port apabila berwarna merah berarti port tersebut telah ada dan digunakan, apabila berwarna biru maka port dalam keadaan free). Berikut ini tampilannya :

Apabila sudah terbuat, maka untuk melakukan pengecekkan bisa dilihat pada device manager komputer kita, seperti pada gambar berikut ini :


Langkah keempat, adalah membuat website yang merespon aplikasi. Saya menggunakan Visual Studio 2010 sebagai editor C++, seperti pada gambar berikut ini 

Dalam percobaan ini saya menggunakan simulator lampu yang sudah dibuatkan oleh dosen saya, dan akan bisa langsung dijalankan pada hardware lampu aslinya. Berikut tampilan simulator lampu.
Untuk bisa menjalankan simulator lampu cukup tekan tombol connect saja. Pada simulator tersebut, port yang digunakan adalah posrt COM31(dari pak dosen yang membuat). Dan untuk memanggilnya perlu file serial.cpp dan header serial.h yang isi kodingnya kurang lebih seperti di bawah ini
script pada file serial.cpp



//    Serial.cpp - Implementation of the CSerial class // //    Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA ////////////////////////////////////////////////////////////////////// // Include the standard header files #define STRICT #include #include #include ////////////////////////////////////////////////////////////////////// // Include module headerfile #include "Serial.h" ////////////////////////////////////////////////////////////////////// // Disable warning C4127: conditional expression is constant, which // is generated when using the _RPTF and _ASSERTE macros. #pragma warning(disable: 4127) ////////////////////////////////////////////////////////////////////// // Enable debug memory manager #ifdef _DEBUG #ifdef THIS_FILE #undef THIS_FILE #endif static const char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Helper methods inline void CSerial::CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const { #ifdef SERIAL_NO_OVERLAPPED     // Check if an overlapped structure has been specified     if (lpOverlapped || (dwTimeout != INFINITE))     {         // Quit application         ::MessageBox(0,_T("Overlapped I/O and time-outs are not supported, when overlapped I/O is disabled."),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);         ::DebugBreak();         ::ExitProcess(0xFFFFFFF);     } #endif #ifdef SERIAL_NO_CANCELIO     // Check if 0 or INFINITE time-out has been specified, because     // the communication I/O cannot be cancelled.     if ((dwTimeout != 0) && (dwTimeout != INFINITE))     {         // Quit application         ::MessageBox(0,_T("Timeouts are not supported, when SERIAL_NO_CANCELIO is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);         ::DebugBreak();         ::ExitProcess(0xFFFFFFF);     } #endif    // SERIAL_NO_CANCELIO     // Avoid warnings     (void) dwTimeout;     (void) lpOverlapped; } inline BOOL CSerial::CancelCommIo (void) { #ifdef SERIAL_NO_CANCELIO     // CancelIo shouldn't have been called at this point     ::DebugBreak();     return FALSE; #else     // Cancel the I/O request     return ::CancelIo(m_hFile); #endif    // SERIAL_NO_CANCELIO } ////////////////////////////////////////////////////////////////////// // Code CSerial::CSerial ()     : m_lLastError(ERROR_SUCCESS)     , m_hFile(0)     , m_eEvent(EEventNone)     , m_dwEventMask(0) #ifndef SERIAL_NO_OVERLAPPED     , m_hevtOverlapped(0) #endif { } CSerial::~CSerial () {     // If the device is already closed,     // then we don't need to do anything.     if (m_hFile)     {         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::~CSerial - Serial port not closed\n");         // Close implicitly         Close();     } } CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice) {     // Try to open the device     HANDLE hFile = ::CreateFile(lpszDevice,                            GENERIC_READ|GENERIC_WRITE,                            0,                            0,                            OPEN_EXISTING,                            0,                            0);     // Check if we could open the device     if (hFile == INVALID_HANDLE_VALUE)     {         // Display error         switch (::GetLastError())         {         case ERROR_FILE_NOT_FOUND:             // The specified COM-port does not exist             return EPortNotAvailable;         case ERROR_ACCESS_DENIED:             // The specified COM-port is in use             return EPortInUse;         default:             // Something else is wrong             return EPortUnknownError;         }     }     // Close handle     ::CloseHandle(hFile);     // Port is available     return EPortAvailable; } LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the port isn't already opened     if (m_hFile)     {         m_lLastError = ERROR_ALREADY_INITIALIZED;         _RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n");         return m_lLastError;     }     // Open the device     m_hFile = ::CreateFile(lpszDevice,                            GENERIC_READ|GENERIC_WRITE,                            0,                            0,                            OPEN_EXISTING,                            fOverlapped?FILE_FLAG_OVERLAPPED:0,                            0);     if (m_hFile == INVALID_HANDLE_VALUE)     {         // Reset file handle         m_hFile = 0;         // Display error         m_lLastError = ::GetLastError();         _RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n");         return m_lLastError;     } #ifndef SERIAL_NO_OVERLAPPED     // We cannot have an event handle yet     _ASSERTE(m_hevtOverlapped == 0);     // Create the event handle for internal overlapped operations (manual reset)     if (fOverlapped)     {         m_hevtOverlapped = ::CreateEvent(0,true,false,0);         if (m_hevtOverlapped == 0)         {             // Obtain the error information             m_lLastError = ::GetLastError();             _RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n");             // Close the port             ::CloseHandle(m_hFile);             m_hFile = 0;             // Return the error             return m_lLastError;         }     } #else         // Overlapped flag shouldn't be specified     _ASSERTE(!fOverlapped); #endif     // Setup the COM-port     if (dwInQueue || dwOutQueue)     {         // Make sure the queue-sizes are reasonable sized. Win9X systems crash         // if the input queue-size is zero. Both queues need to be at least         // 16 bytes large.         _ASSERTE(dwInQueue >= 16);         _ASSERTE(dwOutQueue >= 16);         if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue))         {             // Display a warning             long lLastError = ::GetLastError();             _RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n");             // Close the port             Close();             // Save last error from SetupComm             m_lLastError = lLastError;             return m_lLastError;            }     }     // Setup the default communication mask     SetMask();     // Non-blocking reads is default     SetupReadTimeouts(EReadTimeoutNonblocking);     // Setup the device for default settings      COMMCONFIG commConfig = {0};     DWORD dwSize = sizeof(commConfig);     commConfig.dwSize = dwSize;     if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize))     {         // Set the default communication configuration         if (!::SetCommConfig(m_hFile,&commConfig,dwSize))         {             // Display a warning             _RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n");         }     }     else     {         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n");     }     // Return successful     return m_lLastError; } LONG CSerial::Close (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // If the device is already closed,     // then we don't need to do anything.     if (m_hFile == 0)     {         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::Close - Method called when device is not open\n");         return m_lLastError;     } #ifndef SERIAL_NO_OVERLAPPED     // Free event handle     if (m_hevtOverlapped)     {         ::CloseHandle(m_hevtOverlapped);         m_hevtOverlapped = 0;     } #endif     // Close COM port     ::CloseHandle(m_hFile);     m_hFile = 0;     // Return successful     return m_lLastError; } LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Setup - Device is not opened\n");         return m_lLastError;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::    GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to obtain DCB information\n");         return m_lLastError;     }     // Set the new data     dcb.BaudRate = DWORD(eBaudrate);     dcb.ByteSize = BYTE(eDataBits);     dcb.Parity   = BYTE(eParity);     dcb.StopBits = BYTE(eStopBits);     // Determine if parity is used     dcb.fParity  = (eParity != EParNone);     // Set the new DCB structure     if (!::SetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to set DCB information\n");         return m_lLastError;     }     // Return successful     return m_lLastError; } LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Device is not opened\n");         return m_lLastError;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to obtain DCB information\n");         return m_lLastError;     }     // Set the new event character     dcb.EvtChar = char(bEventChar);     // Adjust the event mask, to make sure the event will be received     if (fAdjustMask)     {         // Enable 'receive event character' event.  Note that this         // will generate an EEventNone if there is an asynchronous         // WaitCommEvent pending.         SetMask(GetEventMask() | EEventRcvEv);     }     // Set the new DCB structure     if (!::SetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to set DCB information\n");         return m_lLastError;     }     // Return successful     return m_lLastError; } LONG CSerial::SetMask (DWORD dwEventMask) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::SetMask - Device is not opened\n");         return m_lLastError;     }     // Set the new mask. Note that this will generate an EEventNone     // if there is an asynchronous WaitCommEvent pending.     if (!::SetCommMask(m_hFile,dwEventMask))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetMask - Unable to set event mask\n");         return m_lLastError;     }     // Save event mask and return successful     m_dwEventMask = dwEventMask;     return m_lLastError; } LONG CSerial::WaitEvent (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) {     // Check if time-outs are supported     CheckRequirements(lpOverlapped,dwTimeout);     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Device is not opened\n");         return m_lLastError;     } #ifndef SERIAL_NO_OVERLAPPED     // Check if an overlapped structure has been specified     if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))     {         // Set the internal error code         m_lLastError = ERROR_INVALID_FUNCTION;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n");         return m_lLastError;     }     // Wait for the event to happen     OVERLAPPED ovInternal;     if (!lpOverlapped && m_hevtOverlapped)     {         // Setup our own overlapped structure         memset(&ovInternal,0,sizeof(ovInternal));         ovInternal.hEvent = m_hevtOverlapped;         // Use our internal overlapped structure         lpOverlapped = &ovInternal;     }     // Make sure the overlapped structure isn't busy     _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));     // Wait for the COM event     if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),lpOverlapped))     {         // Set the internal error code         long lLastError = ::GetLastError();         // Overlapped operation in progress is not an actual error         if (lLastError != ERROR_IO_PENDING)         {             // Save the error             m_lLastError = lLastError;             // Issue an error and quit             _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n");             return m_lLastError;         }         // We need to block if the client didn't specify an overlapped structure         if (lpOverlapped == &ovInternal)         {             // Wait for the overlapped operation to complete             switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))             {             case WAIT_OBJECT_0:                 // The overlapped operation has completed                 break;             case WAIT_TIMEOUT:                 // Cancel the I/O operation                 CancelCommIo();                 // The operation timed out. Set the internal error code and quit                 m_lLastError = ERROR_TIMEOUT;                 return m_lLastError;             default:                 // Set the internal error code                 m_lLastError = ::GetLastError();                 // Issue an error and quit                 _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait until COM event has arrived\n");                 return m_lLastError;             }         }     }     else     {         // The operation completed immediatly. Just to be sure         // we'll set the overlapped structure's event handle.         if (lpOverlapped)             ::SetEvent(lpOverlapped->hEvent);     } #else     // Wait for the COM event     if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0))     {         // Set the internal error code         m_lLastError = ::GetLastError();         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n");         return m_lLastError;     } #endif     // Return successfully     return m_lLastError; } LONG CSerial::SetupHandshaking (EHandshake eHandshake) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Device is not opened\n");         return m_lLastError;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to obtain DCB information\n");         return m_lLastError;     }     // Set the handshaking flags     switch (eHandshake)     {     case EHandshakeOff:         dcb.fOutxCtsFlow = false;                    // Disable CTS monitoring         dcb.fOutxDsrFlow = false;                    // Disable DSR monitoring         dcb.fDtrControl = DTR_CONTROL_DISABLE;        // Disable DTR monitoring         dcb.fOutX = false;                            // Disable XON/XOFF for transmission         dcb.fInX = false;                            // Disable XON/XOFF for receiving         dcb.fRtsControl = RTS_CONTROL_DISABLE;        // Disable RTS (Ready To Send)         break;     case EHandshakeHardware:         dcb.fOutxCtsFlow = true;                    // Enable CTS monitoring         dcb.fOutxDsrFlow = true;                    // Enable DSR monitoring         dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;    // Enable DTR handshaking         dcb.fOutX = false;                            // Disable XON/XOFF for transmission         dcb.fInX = false;                            // Disable XON/XOFF for receiving         dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;    // Enable RTS handshaking         break;     case EHandshakeSoftware:         dcb.fOutxCtsFlow = false;                    // Disable CTS (Clear To Send)         dcb.fOutxDsrFlow = false;                    // Disable DSR (Data Set Ready)         dcb.fDtrControl = DTR_CONTROL_DISABLE;        // Disable DTR (Data Terminal Ready)         dcb.fOutX = true;                            // Enable XON/XOFF for transmission         dcb.fInX = true;                            // Enable XON/XOFF for receiving         dcb.fRtsControl = RTS_CONTROL_DISABLE;        // Disable RTS (Ready To Send)         break;     default:         // This shouldn't be possible         _ASSERTE(false);         m_lLastError = E_INVALIDARG;         return m_lLastError;     }     // Set the new DCB structure     if (!::SetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to set DCB information\n");         return m_lLastError;     }     // Return successful     return m_lLastError; } LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Device is not opened\n");         return m_lLastError;     }     // Determine the time-outs     COMMTIMEOUTS cto;     if (!::GetCommTimeouts(m_hFile,&cto))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to obtain timeout information\n");         return m_lLastError;     }     // Set the new timeouts     switch (eReadTimeout)     {     case EReadTimeoutBlocking:         cto.ReadIntervalTimeout = 0;         cto.ReadTotalTimeoutConstant = 0;         cto.ReadTotalTimeoutMultiplier = 0;         break;     case EReadTimeoutNonblocking:         cto.ReadIntervalTimeout = MAXDWORD;         cto.ReadTotalTimeoutConstant = 0;         cto.ReadTotalTimeoutMultiplier = 0;         break;     default:         // This shouldn't be possible         _ASSERTE(false);         m_lLastError = E_INVALIDARG;         return m_lLastError;     }     // Set the new DCB structure     if (!::SetCommTimeouts(m_hFile,&cto))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to set timeout information\n");         return m_lLastError;     }     // Return successful     return m_lLastError; } CSerial::EBaudrate CSerial::GetBaudrate (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Device is not opened\n");         return EBaudUnknown;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Unable to obtain DCB information\n");         return EBaudUnknown;     }     // Return the appropriate baudrate     return EBaudrate(dcb.BaudRate); } CSerial::EDataBits CSerial::GetDataBits (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Device is not opened\n");         return EDataUnknown;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Unable to obtain DCB information\n");         return EDataUnknown;     }     // Return the appropriate bytesize     return EDataBits(dcb.ByteSize); } CSerial::EParity CSerial::GetParity (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetParity - Device is not opened\n");         return EParUnknown;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetParity - Unable to obtain DCB information\n");         return EParUnknown;     }     // Check if parity is used     if (!dcb.fParity)     {         // No parity         return EParNone;     }     // Return the appropriate parity setting     return EParity(dcb.Parity); } CSerial::EStopBits CSerial::GetStopBits (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Device is not opened\n");         return EStopUnknown;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Unable to obtain DCB information\n");         return EStopUnknown;     }     // Return the appropriate stopbits     return EStopBits(dcb.StopBits); } DWORD CSerial::GetEventMask (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetEventMask - Device is not opened\n");         return 0;     }     // Return the event mask     return m_dwEventMask; } BYTE CSerial::GetEventChar (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Device is not opened\n");         return 0;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Unable to obtain DCB information\n");         return 0;     }     // Set the new event character     return BYTE(dcb.EvtChar); } CSerial::EHandshake CSerial::GetHandshaking (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Device is not opened\n");         return EHandshakeUnknown;     }     // Obtain the DCB structure for the device     CDCB dcb;     if (!::GetCommState(m_hFile,&dcb))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Unable to obtain DCB information\n");         return EHandshakeUnknown;     }     // Check if hardware handshaking is being used     if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE))         return EHandshakeHardware;     // Check if software handshaking is being used     if (dcb.fOutX && dcb.fInX)         return EHandshakeSoftware;     // No handshaking is being used     return EHandshakeOff; } LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) {     // Check if time-outs are supported     CheckRequirements(lpOverlapped,dwTimeout);     // Overlapped operation should specify the pdwWritten variable     _ASSERTE(!lpOverlapped || pdwWritten);     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Use our own variable for read count     DWORD dwWritten;     if (pdwWritten == 0)     {         pdwWritten = &dwWritten;     }     // Reset the number of bytes written     *pdwWritten = 0;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Write - Device is not opened\n");         return m_lLastError;     } #ifndef SERIAL_NO_OVERLAPPED     // Check if an overlapped structure has been specified     if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))     {         // Set the internal error code         m_lLastError = ERROR_INVALID_FUNCTION;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n");         return m_lLastError;     }     // Wait for the event to happen     OVERLAPPED ovInternal;     if (!lpOverlapped && m_hevtOverlapped)     {         // Setup our own overlapped structure         memset(&ovInternal,0,sizeof(ovInternal));         ovInternal.hEvent = m_hevtOverlapped;         // Use our internal overlapped structure         lpOverlapped = &ovInternal;     }     // Make sure the overlapped structure isn't busy     _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));     // Write the data     if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped))     {         // Set the internal error code         long lLastError = ::GetLastError();         // Overlapped operation in progress is not an actual error         if (lLastError != ERROR_IO_PENDING)         {             // Save the error             m_lLastError = lLastError;             // Issue an error and quit             _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");             return m_lLastError;         }         // We need to block if the client didn't specify an overlapped structure         if (lpOverlapped == &ovInternal)         {             // Wait for the overlapped operation to complete             switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))             {             case WAIT_OBJECT_0:                 // The overlapped operation has completed                 if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE))                 {                     // Set the internal error code                     m_lLastError = ::GetLastError();                     _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n");                     return m_lLastError;                 }                 break;             case WAIT_TIMEOUT:                 // Cancel the I/O operation                 CancelCommIo();                 // The operation timed out. Set the internal error code and quit                 m_lLastError = ERROR_TIMEOUT;                 return m_lLastError;             default:                 // Set the internal error code                 m_lLastError = ::GetLastError();                 // Issue an error and quit                 _RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n");                 return m_lLastError;             }         }     }     else     {         // The operation completed immediatly. Just to be sure         // we'll set the overlapped structure's event handle.         if (lpOverlapped)             ::SetEvent(lpOverlapped->hEvent);     } #else     // Write the data     if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0))     {         // Set the internal error code         m_lLastError = ::GetLastError();         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");         return m_lLastError;     } #endif     // Return successfully     return m_lLastError; } LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) {     // Check if time-outs are supported     CheckRequirements(lpOverlapped,dwTimeout);     // Determine the length of the string     return Write(pString,strlen(pString),pdwWritten,lpOverlapped,dwTimeout); } LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) {     // Check if time-outs are supported     CheckRequirements(lpOverlapped,dwTimeout);     // Overlapped operation should specify the pdwRead variable     _ASSERTE(!lpOverlapped || pdwRead);     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Use our own variable for read count     DWORD dwRead;     if (pdwRead == 0)     {         pdwRead = &dwRead;     }     // Reset the number of bytes read     *pdwRead = 0;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Read - Device is not opened\n");         return m_lLastError;     } #ifdef _DEBUG     // The debug version fills the entire data structure with     // 0xDC bytes, to catch buffer errors as soon as possible.     memset(pData,0xDC,iLen); #endif #ifndef SERIAL_NO_OVERLAPPED     // Check if an overlapped structure has been specified     if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))     {         // Set the internal error code         m_lLastError = ERROR_INVALID_FUNCTION;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\n");         return m_lLastError;     }     // Wait for the event to happen     OVERLAPPED ovInternal;     if (lpOverlapped == 0)     {         // Setup our own overlapped structure         memset(&ovInternal,0,sizeof(ovInternal));         ovInternal.hEvent = m_hevtOverlapped;         // Use our internal overlapped structure         lpOverlapped = &ovInternal;     }     // Make sure the overlapped structure isn't busy     _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));         // Read the data     if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped))     {         // Set the internal error code         long lLastError = ::GetLastError();         // Overlapped operation in progress is not an actual error         if (lLastError != ERROR_IO_PENDING)         {             // Save the error             m_lLastError = lLastError;             // Issue an error and quit             _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");             return m_lLastError;         }         // We need to block if the client didn't specify an overlapped structure         if (lpOverlapped == &ovInternal)         {             // Wait for the overlapped operation to complete             switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))             {             case WAIT_OBJECT_0:                 // The overlapped operation has completed                 if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE))                 {                     // Set the internal error code                     m_lLastError = ::GetLastError();                     _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n");                     return m_lLastError;                 }                 break;             case WAIT_TIMEOUT:                 // Cancel the I/O operation                 CancelCommIo();                 // The operation timed out. Set the internal error code and quit                 m_lLastError = ERROR_TIMEOUT;                 return m_lLastError;             default:                 // Set the internal error code                 m_lLastError = ::GetLastError();                 // Issue an error and quit                 _RPTF0(_CRT_WARN,"CSerial::Read - Unable to wait until data has been read\n");                 return m_lLastError;             }         }     }     else     {         // The operation completed immediatly. Just to be sure         // we'll set the overlapped structure's event handle.         if (lpOverlapped)             ::SetEvent(lpOverlapped->hEvent);     } #else         // Read the data     if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0))     {         // Set the internal error code         m_lLastError = ::GetLastError();         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");         return m_lLastError;     } #endif     // Return successfully     return m_lLastError; } LONG CSerial::Purge() {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Purge - Device is not opened\n");         return m_lLastError;     }     if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR))     {         // Set the internal error code         m_lLastError = ::GetLastError();         _RPTF0(_CRT_WARN,"CSerial::Purge - Overlapped completed without result\n");     }         // Return successfully     return m_lLastError; } LONG CSerial::Break (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::Break - Device is not opened\n");         return m_lLastError;     }     // Set the RS-232 port in break mode for a little while     ::SetCommBreak(m_hFile);     ::Sleep(100);     ::ClearCommBreak(m_hFile);     // Return successfully     return m_lLastError; } CSerial::EEvent CSerial::GetEventType (void) { #ifdef _DEBUG     // Check if the event is within the mask     if ((m_eEvent & m_dwEventMask) == 0)         _RPTF2(_CRT_WARN,"CSerial::GetEventType - Event %08Xh not within mask %08Xh.\n", m_eEvent, m_dwEventMask); #endif     // Obtain the event (mask unwanted events out)     EEvent eEvent = EEvent(m_eEvent & m_dwEventMask);     // Reset internal event type     m_eEvent = EEventNone;     // Return the current cause     return eEvent; } CSerial::EError CSerial::GetError (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Check if the device is open     if (m_hFile == 0)     {         // Set the internal error code         m_lLastError = ERROR_INVALID_HANDLE;         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetError - Device is not opened\n");         return EErrorUnknown;     }     // Obtain COM status     DWORD dwErrors = 0;     if (!::ClearCommError(m_hFile,&dwErrors,0))     {         // Set the internal error code         m_lLastError = ::GetLastError();         // Issue an error and quit         _RPTF0(_CRT_WARN,"CSerial::GetError - Unable to obtain COM status\n");         return EErrorUnknown;     }     // Return the error     return EError(dwErrors); } bool CSerial::GetCTS (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Obtain the modem status     DWORD dwModemStat = 0;     if (!::GetCommModemStatus(m_hFile,&dwModemStat))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetCTS - Unable to obtain the modem status\n");         return false;     }     // Determine if CTS is on     return (dwModemStat & MS_CTS_ON) != 0; } bool CSerial::GetDSR (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Obtain the modem status     DWORD dwModemStat = 0;     if (!::GetCommModemStatus(m_hFile,&dwModemStat))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetDSR - Unable to obtain the modem status\n");         return false;     }     // Determine if DSR is on     return (dwModemStat & MS_DSR_ON) != 0; } bool CSerial::GetRing (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Obtain the modem status     DWORD dwModemStat = 0;     if (!::GetCommModemStatus(m_hFile,&dwModemStat))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetRing - Unable to obtain the modem status");         return false;     }     // Determine if Ring is on     return (dwModemStat & MS_RING_ON) != 0; } bool CSerial::GetRLSD (void) {     // Reset error state     m_lLastError = ERROR_SUCCESS;     // Obtain the modem status     DWORD dwModemStat = 0;     if (!::GetCommModemStatus(m_hFile,&dwModemStat))     {         // Obtain the error code         m_lLastError = ::GetLastError();         // Display a warning         _RPTF0(_CRT_WARN,"CSerial::GetRLSD - Unable to obtain the modem status");         return false;     }     // Determine if RLSD is on     return (dwModemStat & MS_RLSD_ON) != 0; }


 
dan Kode pada script header yang ditambahkan pada file serial.h adalah sebagai berikut :



 //    Serial.h - Definition of the CSerial class // //    Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #ifndef __SERIAL_H #define __SERIAL_H ////////////////////////////////////////////////////////////////////// // The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses // overlapped I/O. When overlapped I/O is available (normal Win32 // platforms) it uses overlapped I/O. Windows CE doesn't allow the use // of overlapped I/O, so it is disabled there by default. #ifndef SERIAL_DEFAULT_OVERLAPPED #ifndef SERIAL_NO_OVERLAPPED #define SERIAL_DEFAULT_OVERLAPPED    true #else #define SERIAL_DEFAULT_OVERLAPPED    false #endif #endif ////////////////////////////////////////////////////////////////////// // // CSerial - Win32 wrapper for serial communications // // Serial communication often causes a lot of problems. This class // tries to supply an easy to use interface to deal with serial // devices. // // The class is actually pretty ease to use. You only need to open // the COM-port, where you need to specify the basic serial // communication parameters. You can also choose to setup handshaking // and read timeout behaviour. // // The following serial classes are available: // // CSerial      - Serial communication support. // CSerialEx    - Serial communication with listener thread for events // CSerialSync  - Serial communication with synchronized event handler // CSerialWnd   - Asynchronous serial support, which uses the Win32 //                message queue for event notification. // CSerialMFC   - Preferred class to use in MFC-based GUI windows. // // // Pros: // ----- //    - Easy to use (hides a lot of nasty Win32 stuff) //    - Fully ANSI and Unicode aware // // Cons: // ----- //  - Little less flexibility then native Win32 API, however you can //    use this API at the same time for features which are missing //    from this class. //  - Incompatible with Windows 95 or Windows NT v3.51 (or earlier), //    because CancelIo isn't support on these platforms. Define the //      SERIAL_NO_CANCELIO macro for support of these platforms as //      well. When this macro is defined, then only time-out values of //      0 or INFINITE are valid. // // // Copyright (C) 1999-2003 Ramon de Klein //                         (Ramon.de.Klein@ict.nl) class CSerial { // Class enumerations public:     // Communication event     typedef enum     {         EEventUnknown         = -1,            // Unknown event         EEventNone         = 0,                // Event trigged without cause         EEventBreak        = EV_BREAK,        // A break was detected on input         EEventCTS          = EV_CTS,        // The CTS signal changed state         EEventDSR          = EV_DSR,        // The DSR signal changed state         EEventError        = EV_ERR,        // A line-status error occurred         EEventRing         = EV_RING,        // A ring indicator was detected         EEventRLSD         = EV_RLSD,        // The RLSD signal changed state         EEventRecv         = EV_RXCHAR,        // Data is received on input         EEventRcvEv        = EV_RXFLAG,        // Event character was received on input         EEventSend           = EV_TXEMPTY,    // Last character on output was sent         EEventPrinterError = EV_PERR,        // Printer error occured         EEventRx80Full       = EV_RX80FULL,    // Receive buffer is 80 percent full         EEventProviderEvt1 = EV_EVENT1,        // Provider specific event 1         EEventProviderEvt2 = EV_EVENT2,        // Provider specific event 2     }     EEvent;     // Baudrate     typedef enum     {         EBaudUnknown = -1,            // Unknown         EBaud110     = CBR_110,        // 110 bits/sec         EBaud300     = CBR_300,        // 300 bits/sec         EBaud600     = CBR_600,        // 600 bits/sec         EBaud1200    = CBR_1200,    // 1200 bits/sec         EBaud2400    = CBR_2400,    // 2400 bits/sec         EBaud4800    = CBR_4800,    // 4800 bits/sec         EBaud9600    = CBR_9600,    // 9600 bits/sec         EBaud14400   = CBR_14400,    // 14400 bits/sec         EBaud19200   = CBR_19200,    // 19200 bits/sec (default)         EBaud38400   = CBR_38400,    // 38400 bits/sec         EBaud56000   = CBR_56000,    // 56000 bits/sec         EBaud57600   = CBR_57600,    // 57600 bits/sec         EBaud115200  = CBR_115200,    // 115200 bits/sec         EBaud128000  = CBR_128000,    // 128000 bits/sec         EBaud256000  = CBR_256000,    // 256000 bits/sec     }     EBaudrate;     // Data bits (5-8)     typedef enum     {         EDataUnknown = -1,            // Unknown         EData5       =  5,            // 5 bits per byte         EData6       =  6,            // 6 bits per byte         EData7       =  7,            // 7 bits per byte         EData8       =  8            // 8 bits per byte (default)     }     EDataBits;     // Parity scheme     typedef enum     {         EParUnknown = -1,            // Unknown         EParNone    = NOPARITY,        // No parity (default)         EParOdd     = ODDPARITY,    // Odd parity         EParEven    = EVENPARITY,    // Even parity         EParMark    = MARKPARITY,    // Mark parity         EParSpace   = SPACEPARITY    // Space parity     }     EParity;     // Stop bits     typedef enum     {         EStopUnknown = -1,            // Unknown         EStop1       = ONESTOPBIT,    // 1 stopbit (default)         EStop1_5     = ONE5STOPBITS,// 1.5 stopbit         EStop2       = TWOSTOPBITS    // 2 stopbits     }     EStopBits;     // Handshaking     typedef enum     {         EHandshakeUnknown        = -1,    // Unknown         EHandshakeOff            =  0,    // No handshaking         EHandshakeHardware        =  1,    // Hardware handshaking (RTS/CTS)         EHandshakeSoftware        =  2    // Software handshaking (XON/XOFF)     }     EHandshake;     // Timeout settings     typedef enum     {         EReadTimeoutUnknown        = -1,    // Unknown         EReadTimeoutNonblocking    =  0,    // Always return immediately         EReadTimeoutBlocking    =  1    // Block until everything is retrieved     }     EReadTimeout;     // Communication errors     typedef enum     {         EErrorUnknown = 0,            // Unknown         EErrorBreak   = CE_BREAK,    // Break condition detected         EErrorFrame   = CE_FRAME,    // Framing error         EErrorIOE     = CE_IOE,        // I/O device error         EErrorMode    = CE_MODE,    // Unsupported mode         EErrorOverrun = CE_OVERRUN,    // Character buffer overrun, next byte is lost         EErrorRxOver  = CE_RXOVER,    // Input buffer overflow, byte lost         EErrorParity  = CE_RXPARITY,// Input parity error         EErrorTxFull  = CE_TXFULL    // Output buffer full     }     EError;     // Port availability     typedef enum     {         EPortUnknownError = -1,        // Unknown error occurred         EPortAvailable    =  0,        // Port is available         EPortNotAvailable =  1,        // Port is not present         EPortInUse        =  2        // Port is in use     }     EPort; // Construction public:     CSerial();     virtual ~CSerial(); // Operations public:     // Check if particular COM-port is available (static method).     static EPort CheckPort (LPCTSTR lpszDevice);     // Open the serial communications for a particular COM port. You     // need to use the full devicename (i.e. "COM1") to open the port.     // It's possible to specify the size of the input/output queues.     virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);     // Close the serial port.     virtual LONG Close (void);     // Setup the communication settings such as baudrate, databits,     // parity and stopbits. The default settings are applied when the     // device has been opened. Call this function if these settings do     // not apply for your application. If you prefer to use integers     // instead of the enumerated types then just cast the integer to     // the required type. So the following two initializations are     // equivalent:     //     //   Setup(EBaud9600,EData8,EParNone,EStop1)     //     // or     //     //   Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT))     //     // In the latter case, the types are not validated. So make sure     // that you specify the appropriate values.     virtual LONG Setup (EBaudrate eBaudrate = EBaud9600,                         EDataBits eDataBits = EData8,                         EParity   eParity   = EParNone,                         EStopBits eStopBits = EStop1);     // Set/clear the event character. When this byte is being received     // on the serial port then the EEventRcvEv event is signalled,     // when the mask has been set appropriately. If the fAdjustMask flag     // has been set, then the event mask is automatically adjusted.     virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true);     // Set the event mask, which indicates what events should be     // monitored. The WaitEvent method can only monitor events that     // have been enabled. The default setting only monitors the     // error events and data events. An application may choose to     // monitor CTS. DSR, RLSD, etc as well.     virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv);     // The WaitEvent method waits for one of the events that are     // enabled (see SetMask).     virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);     // Setup the handshaking protocol. There are three forms of     // handshaking:     //     // 1) No handshaking, so data is always send even if the receiver     //    cannot handle the data anymore. This can lead to data loss,     //    when the sender is able to transmit data faster then the     //    receiver can handle.     // 2) Hardware handshaking, where the RTS/CTS lines are used to     //    indicate if data can be sent. This mode requires that both     //    ports and the cable support hardware handshaking. Hardware     //    handshaking is the most reliable and efficient form of     //    handshaking available, but is hardware dependant.     // 3) Software handshaking, where the XON/XOFF characters are used     //    to throttle the data. A major drawback of this method is that     //    these characters cannot be used for data anymore.     virtual LONG SetupHandshaking (EHandshake eHandshake);     // Read operations can be blocking or non-blocking. You can use     // this method to setup wether to use blocking or non-blocking     // reads. Non-blocking reads is the default, which is required     // for most applications.     //     // 1) Blocking reads, which will cause the 'Read' method to block     //    until the requested number of bytes have been read. This is     //    useful if you know how many data you will receive.     // 2) Non-blocking reads, which will read as many bytes into your     //    buffer and returns almost immediately. This is often the     //    preferred setting.     virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout);     // Obtain communication settings     virtual EBaudrate  GetBaudrate    (void);     virtual EDataBits  GetDataBits    (void);     virtual EParity    GetParity      (void);     virtual EStopBits  GetStopBits    (void);     virtual EHandshake GetHandshaking (void);     virtual DWORD      GetEventMask   (void);     virtual BYTE       GetEventChar   (void);     // Write data to the serial port. Note that we are only able to     // send ANSI strings, because it probably doesn't make sense to     // transmit Unicode strings to an application.     virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);     virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);     // Read data from the serial port. Refer to the description of     // the 'SetupReadTimeouts' for an explanation about (non) blocking     // reads and how to use this.     virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);     // Send a break     LONG Break (void);     // Determine what caused the event to trigger     EEvent GetEventType (void);     // Obtain the error     EError GetError (void);     // Obtain the COMM and event handle     HANDLE GetCommHandle (void)        { return m_hFile; }     // Check if com-port is opened     bool IsOpen (void) const        { return (m_hFile != 0); }     // Obtain last error status     LONG GetLastError (void) const    { return m_lLastError; }     // Obtain CTS/DSR/RING/RLSD settings     bool GetCTS (void);     bool GetDSR (void);     bool GetRing (void);     bool GetRLSD (void);     // Purge all buffers     LONG Purge (void); protected:     // Internal helper class which wraps DCB structure     class CDCB : public DCB     {     public:         CDCB() { DCBlength = sizeof(DCB); }     }; // Attributes protected:     LONG    m_lLastError;        // Last serial error     HANDLE    m_hFile;            // File handle     EEvent    m_eEvent;            // Event type     DWORD    m_dwEventMask;        // Event mask #ifndef SERIAL_NO_OVERLAPPED     HANDLE    m_hevtOverlapped;    // Event handle for internal overlapped operations #endif protected:     // Check the requirements     void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const;     // CancelIo wrapper (for Win95 compatibility)     BOOL CancelCommIo (void); }; #endif    // __SERIAL_H


Setelah semua terinstal, jalankan program .cpp yang telah kita buat. Apabila simulato lampu berwarna merah, berarti aplikasi kita berhasil, dan kita tinggal mengkoneksikan pada hardware yang disesuaikan dengan port hardware lampu tersebut. Perlu diingat, kode .cpp di atas hanya untuk menguji apabila ditekan huruf "a" maka lampu merah akan menyala seperti gambar berikut ini
Untuk lampu yang lainnya silahkan di modifikasi sendiri dengan ketentuan a= merah hidup, s = merah mati, d=kuning hidup, f = kuning mati, g=hijau hidup dan h= hijau mati.

catatan : untuk dapat menjalankan file CGI pada web client yang telah kita buat, maka langkah yang harus dilakukan adalah mengubah hasil debug program kita pada visual studio yang berekstensi .exe menjadi .cgi dengan me-rename dan meletakkannya pada direktori folder xampp --> cgi-bin (bila tes lampu menggunakan localhost maka menggunakan xampp).
Apabila sudah selesai, maka file cgi yang tgelah kita buat sudah bisa dipanggil dengan menggunakan URL.
Perhatikan url berikut

Untuk sintak di atas sesuaikan dengan kebutuhan, kebetulan saya mencoba pada komputer saya sendiri jadi menggunakan Localhost, apabila ingin menguji menggunakan client server, maka ubahlah pada bagian url dengan alamat ip yang dibuat (saya telah mencoba dengan menggunakan koneksi adhoc dengan 2 client dan 1 server, dan aplikasi saya bisa dijalankan)
Demikian sedikit sharing dari saya, untuk keterangan lebih lanjut bisa langsung menanyakan pada coment atau melalui email saya.
Selamat mencoba

1 comment:

Toha Mustofa said...

mantabh.. disharing juga dong software simulator lampu bangjo-nya yg dari dosen itu? boleh? lebih baik ijin dulu ke beliau...