#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''  
Serial设备通讯类  
'''

import threading, serial, logging, time, Queue

class SerialHelper(object):  
    def __init__(self, ByteSize="8", Parity="N", Stopbits="1"):
        '''
        串行口初始化函数
        :param ByteSize:数据位
        :param Parity:校验位
        :param Stopbits:停止位
        '''
        self.l_serial = None
        self.alive = False
        self.bytesize = ByteSize
        self.parity = Parity
        self.stopbits = Stopbits
        self.thresholdValue = 64
        self.receive_data = ""

    def start(self, serialPort, baudRate):
        '''
        打开串行口,这里选择只传入两个参数
        :param serialPort: 串口号名称
        :param baudRate: 串口波特率
        :return:
        '''
        self.l_serial = serial.Serial()
        self.l_serial.port = serialPort
        self.l_serial.baudrate = baudRate
        self.l_serial.bytesize = int(self.bytesize)
        self.l_serial.parity = self.parity
        self.l_serial.stopbits = int(self.stopbits)
        self.l_serial.timeout = 2

        try:
            self.l_serial.open()
            if self.l_serial.isOpen():
                self.alive = True
        except Exception as e:
            self.alive = False
            logging.error(e)

    def stop(self):
        '''
        关闭串口
        :return:
        '''
        self.alive = False
        if self.l_serial.isOpen():
            self.l_serial.close()

    def read(self, q):
        '''
        读取串行口数据,传入一个queue对象
        然后串口就会把数据写入队列中
        当收到换行符之后才会把数据写入Queue中
        :param q: Queue对象,由另外一个线程消费
        :return:
        '''
        while self.alive:
            try:
                number = self.l_serial.inWaiting()
                if number:
                    self.receive_data += self.l_serial.read(number)
                    if self.receive_data[-1:] == "\n":
                        q.put(self.receive_data)
                        self.receive_data = ''
            except Exception as e:
                logging.error(e)

    def write(self, data):
        '''
        向串口写入数据
        :param data: 待写入的数据
        :return: 0 写入成功/ -1 写入失败
        '''
        if self.alive:
            if self.l_serial.isOpen():
                self.l_serial.write(data)
                return 0
            else:
                return -1


def QueueTest(q):  
    """ 线程worker函数
    用于处理队列中的元素项
    这些守护线程在一个无限循环中
    只有当主线程结束时才会结束循环
    """
    while True:
        time.sleep(0.001)
        data = q.get()
        print('Queue Get Data: %s' % data)
        q.task_done()


if __name__ == '__main__':  
    '''
    测试程序
    '''
    q = Queue.Queue()
    ser = SerialHelper()
    ser.start('/dev/cu.SLAB_USBtoUART', 9600)
    ser.write("123")
    thread_read = threading.Thread(target=ser.read, args=(q,))
    queueTest = threading.Thread(target=QueueTest, args=(q,))
    thread_read.setDaemon(True)
    thread_read.start()
    queueTest.start()
    q.join()
    time.sleep(25)
    ser.stop()