Example #1
0
    def SetMode(self, mode):
        """
        Sets the serial port mode setting from a string.

        See :meth:`Open` for a complete description of the mode string.
        """
        dcb = self.dcb
        dcb.ByteSize = int(mode[0])
        dcb.Parity = PARITY_S2V_DICT[mode[1].upper()]
        dcb.StopBits = STOPBITS_S2V_DICT[mode[2:]]
        SetCommState(self.hFile, byref(dcb))
Example #2
0
    def Open(self, port=0, baudrate=9600, mode="8N1"):
        """
        Opens the serial port. After the port is opened, you have to call
        :meth:`Start` to start the actual event processing of this class.

        :Arguments:
            port
                The port to open as an integer starting at one (0 = COM1)
            baudrate
                The baudrate to use as an integer. Defaults to 9600.
            mode
                The serial port mode settings to use. This should be a
                string created by the joining of the following parts:

                #. byte size
                    '5', '6', '7' or '8'
                #. parity mode
                    * 'N' for no parity,
                    * 'E' for even parity,
                    * 'O' for odd parity,
                    * 'M' for mark parity,
                    * 'S' for space parity
                #. stop bits
                    * '1' for one stop bit
                    * '1.5' for one and a half stop bit
                    * '2' for two stop bits

                Example values: '8N1' (default), '8E1', '7N1.5'
        """
        #the "//./COMx" format is required for devices >= 9
        #not all versions of windows seem to support this properly
        #so that the first few ports are used with the DOS device name
        if port < 9:
            deviceStr = 'COM%d' % (port + 1)
        else:
            deviceStr = '\\\\.\\COM%d' % (port + 1)
        try:
            self.hFile = self._CreateFile(
                deviceStr,
                GENERIC_READ | GENERIC_WRITE,
                0,  # exclusive access
                None,  # default security attributes
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                0)
        except Exception:
            self.hFile = None  # cause __del__ is called anyway
            raise eg.Exceptions.SerialOpenFailed()
        if self.hFile == INVALID_HANDLE_VALUE:
            self.hFile = None
            raise eg.Exceptions.SerialOpenFailed()
        dcb = self.dcb
        GetCommState(self.hFile, byref(dcb))
        dcb.fBinary = True
        dcb.fParity = False
        dcb.fOutxCtsFlow = False
        dcb.fOutxDsrFlow = False
        dcb.fDtrControl = DTR_CONTROL_DISABLE
        dcb.fDsrSensitivity = False
        dcb.fTXContinueOnXoff = True
        dcb.fOutX = False
        dcb.fInX = False
        dcb.fErrorChar = False
        dcb.fNull = False
        dcb.fRtsControl = False
        dcb.fAbortOnError = False
        dcb.BaudRate = baudrate
        dcb.ByteSize = int(mode[0])
        dcb.Parity = PARITY_S2V_DICT[mode[1].upper()]
        dcb.StopBits = STOPBITS_S2V_DICT[mode[2:]]
        SetCommState(self.hFile, byref(dcb))
        GetCommTimeouts(self.hFile, byref(self.oldCommTimeouts))
        commTimeouts = COMMTIMEOUTS(0, 0, 0, 100, 100)
        SetCommTimeouts(self.hFile, byref(commTimeouts))
Example #3
0
 def SetBaudrate(self, baudrate):
     """
     Sets the baud rate to an integer value.
     """
     self.dcb.BaudRate = baudrate
     SetCommState(self.hFile, byref(self.dcb))
Example #4
0
class SerialThread(Thread):
    """
    Eased handling of serial port communication.
    """
    # These functions are bound to the class, so instances or subclasses
    # can replace them. This is needed for code that uses the FTDI.DLL
    # driver for example.
    _ReadFile = ReadFile
    _WriteFile = WriteFile
    _ClearCommError = ClearCommError
    _CreateFile = CreateFile
    _CloseHandle = CloseHandle
    # Cache list for GetAllPorts
    _serialPortList = None
    SerialError = SerialError

    @classmethod
    def GetAllPorts(cls):
        """
        Returns a list with all available serial ports.
        """
        serialPortList = cls._serialPortList
        if serialPortList is not None:
            return serialPortList
        serialPortList = []
        commconfig = COMMCONFIG()
        commconfig.dwSize = sizeof(COMMCONFIG)
        lpCC = pointer(commconfig)
        dwSize = DWORD(0)
        lpdwSize = byref(dwSize)
        for i in range(0, 255):
            name = 'COM%d' % (i+1)
            res = GetDefaultCommConfig(name, lpCC, lpdwSize)
            if res == 1 or (res == 0 and GetLastError() == 122):
                serialPortList.append(i)
        cls._serialPortList = serialPortList
        return serialPortList


    def __init__(self, hFile=0):
        Thread.__init__(self, target=self.ReceiveThreadProc)
        self.hFile = int(hFile)
        self.osWriter = OVERLAPPED()
        self.osWriter.hEvent = CreateEvent(None, 0, 0, None)
        self.osReader = OVERLAPPED()
        self.osReader.hEvent = CreateEvent(None, 1, 0, None)
        self.dwRead = DWORD()
        self.comstat = COMSTAT()
        self.dcb = DCB()
        self.dcb.DCBlength = sizeof(DCB)
        self.oldCommTimeouts = COMMTIMEOUTS()

        self.readEventCallback = None
        self.readEventLock = Lock()
        self.readEventLock.acquire()
        self.readCondition = Condition()
        self.buffer = ""
        self.keepAlive = True
        self.stopEvent = CreateEvent(None, 1, 0, None)
        self.callbackThread = Thread(
            target=self.CallbackThreadProc,
            name="SerialReceiveThreadProc"
        )


    def __enter__(self):
        self.SuspendReadEvents()
        return self


    def __exit__(self, dummyExcType, dummyExcValue, dummyTraceback):
        self.ResumeReadEvents()
        return False


    def Open(self, port=0, baudrate=9600, mode="8N1"):
        """
        Opens the serial port. After the port is opened, you have to call
        :meth:`Start` to start the actual event processing of this class.

        :Arguments:
            port
                The port to open as an integer starting at one (0 = COM1)
            baudrate
                The baudrate to use as an integer. Defaults to 9600.
            mode
                The serial port mode settings to use. This should be a
                string created by the joining of the following parts:

                #. byte size
                    '5', '6', '7' or '8'
                #. parity mode
                    * 'N' for no parity,
                    * 'E' for even parity,
                    * 'O' for odd parity,
                    * 'M' for mark parity,
                    * 'S' for space parity
                #. stop bits
                    * '1' for one stop bit
                    * '1.5' for one and a half stop bit
                    * '2' for two stop bits

                Example values: '8N1' (default), '8E1', '7N1.5'
        """
        #the "//./COMx" format is required for devices >= 9
        #not all versions of windows seem to support this properly
        #so that the first few ports are used with the DOS device name
        if port < 9:
            deviceStr = 'COM%d' % (port + 1)
        else:
            deviceStr = '\\\\.\\COM%d' % (port + 1)
        try:
            self.hFile = self._CreateFile(
                deviceStr,
                GENERIC_READ | GENERIC_WRITE,
                0, # exclusive access
                None, # default security attributes
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                0
            )
        except Exception, exc:
            self.hFile = None    # cause __del__ is called anyway
            raise eg.Exceptions.SerialOpenFailed()
        if self.hFile == INVALID_HANDLE_VALUE:
            self.hFile = None
            raise eg.Exceptions.SerialOpenFailed()
        dcb = self.dcb
        GetCommState(self.hFile, byref(dcb))
        dcb.fBinary = True
        dcb.fParity = False
        dcb.fOutxCtsFlow = False
        dcb.fOutxDsrFlow = False
        dcb.fDtrControl = DTR_CONTROL_DISABLE
        dcb.fDsrSensitivity = False
        dcb.fTXContinueOnXoff = True
        dcb.fOutX = False
        dcb.fInX = False
        dcb.fErrorChar = False
        dcb.fNull = False
        dcb.fRtsControl = False
        dcb.fAbortOnError = False
        dcb.BaudRate = baudrate
        dcb.ByteSize = int(mode[0])
        dcb.Parity = PARITY_S2V_DICT[mode[1].upper()]
        dcb.StopBits = STOPBITS_S2V_DICT[mode[2:]]
        SetCommState(self.hFile, byref(dcb))
        GetCommTimeouts(self.hFile, byref(self.oldCommTimeouts))
        commTimeouts = COMMTIMEOUTS(0, 0, 0, 100, 100)
        SetCommTimeouts(self.hFile, byref(commTimeouts))