2 |
2 |
3 # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
3 # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
4 # |
4 # |
5 |
5 |
6 """ |
6 """ |
7 Module implementing a QSerialPort with additional functionality. |
7 Module implementing a QSerialPort with additional functionality for |
|
8 MicroPython devices. |
8 """ |
9 """ |
9 |
10 |
10 from __future__ import unicode_literals |
11 from __future__ import unicode_literals |
11 |
12 |
12 from PyQt5.QtCore import QIODevice |
13 from PyQt5.QtCore import QIODevice, QTime |
13 from PyQt5.QtSerialPort import QSerialPort |
14 from PyQt5.QtSerialPort import QSerialPort |
14 |
15 |
15 |
16 |
16 class MicroPythonSerialPort(QSerialPort): |
17 class MicroPythonSerialPort(QSerialPort): |
17 """ |
18 """ |
18 Class implementing a QSerialPort with additional functionality |
19 Class implementing a QSerialPort with additional functionality for |
|
20 MicroPython devices. |
19 """ |
21 """ |
20 def __init__(self, parent=None): |
22 def __init__(self, timeout=10000, parent=None): |
21 """ |
23 """ |
22 Constructor |
24 Constructor |
23 |
25 |
|
26 @param timeout timout in milliseconds to be set |
|
27 @type int |
24 @param parent reference to the parent object |
28 @param parent reference to the parent object |
25 @type QObject |
29 @type QObject |
26 """ |
30 """ |
27 super(MicroPythonSerialPort, self).__init__(parent) |
31 super(MicroPythonSerialPort, self).__init__(parent) |
28 |
32 |
29 self.__connected = False |
33 self.__connected = False |
|
34 self.__timeout = timeout # 10s default timeout |
|
35 |
|
36 def setTimeout(self, timeout): |
|
37 """ |
|
38 Public method to set the timeout for device operations. |
|
39 |
|
40 @param timeout timout in milliseconds to be set |
|
41 @type int |
|
42 """ |
|
43 self.__timeout = timeout |
30 |
44 |
31 def openSerialLink(self, port): |
45 def openSerialLink(self, port): |
32 """ |
46 """ |
33 Public method to open a serial link to a given serial port. |
47 Public method to open a serial link to a given serial port. |
34 |
48 |
68 @rtype bool |
82 @rtype bool |
69 """ |
83 """ |
70 return self.__connected |
84 return self.__connected |
71 |
85 |
72 def readUntil(self, expected=b"\n", size=None): |
86 def readUntil(self, expected=b"\n", size=None): |
73 """ |
87 r""" |
74 Public method to read data until an expected sequence is found |
88 Public method to read data until an expected sequence is found |
75 (default: \n) or a specific size is exceeded. |
89 (default: \n) or a specific size is exceeded. |
76 |
90 |
77 @param expected expected bytes sequence |
91 @param expected expected bytes sequence |
78 @type bytes |
92 @type bytes |
79 @param size maximum data to be read |
93 @param size maximum data to be read |
80 @type int |
94 @type int |
81 @return bytes read from the device including the expected sequence |
95 @return bytes read from the device including the expected sequence |
82 @rtype bytes |
96 @rtype bytes |
83 """ |
97 """ |
|
98 from PyQt5.QtCore import QCoreApplication, QEventLoop |
84 data = bytearray() |
99 data = bytearray() |
|
100 |
|
101 t = QTime() |
|
102 t.start() |
85 while True: |
103 while True: |
86 if self.waitForReadyRead(): |
104 # TODO: check if this is still needed when used with a QThread |
87 c = bytes(self.read(1)) |
105 QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents) |
88 if c: |
106 ## if self.waitForReadyRead(self.__timeout): |
89 data += c |
107 c = bytes(self.read(1)) |
90 if data.endswith(expected): |
108 if c: |
91 break |
109 data += c |
92 if size is not None and len(data) >= size: |
110 if data.endswith(expected): |
93 break |
|
94 else: |
|
95 break |
111 break |
96 else: |
112 if size is not None and len(data) >= size: |
|
113 break |
|
114 # else: |
|
115 # break |
|
116 if t.elapsed() > self.__timeout: |
97 break |
117 break |
|
118 ## else: |
|
119 ## break |
98 |
120 |
99 return bytes(data) |
121 return bytes(data) |