28
28
* Author(s): Dan Halbert for Adafruit Industries
29
29
30
30
"""
31
- from bleio import Characteristic , Central
32
- from .uart import UART
31
+ from bleio import Central , CharacteristicBuffer
32
+ from .uart import NUS_SERVICE_UUID , NUS_RX_CHAR_UUID , NUS_TX_CHAR_UUID
33
33
34
- class UARTClient ( UART ) :
34
+ class UARTClient :
35
35
"""
36
36
Provide UART-like functionality via the Nordic NUS service.
37
37
@@ -58,27 +58,88 @@ class UARTClient(UART):
58
58
"""
59
59
60
60
def __init__ (self , * , timeout = 5.0 , buffer_size = 64 ):
61
- # Since we're remote we receive on tx and send on rx. The names
62
- # are from the point of view of the server.
63
- super ().__init__ (read_characteristic = Characteristic (UART .NUS_TX_CHAR_UUID ),
64
- write_characteristic = Characteristic (UART .NUS_RX_CHAR_UUID ),
65
- timeout = timeout , buffer_size = buffer_size )
66
-
61
+ self ._buffer_size = buffer_size
62
+ self ._timeout = timeout
63
+ self ._read_char = self ._write_char = self ._read_buffer = None
67
64
self ._central = Central ()
68
65
69
- @property
70
- def connected (self ):
71
- """True if we are connected to a peripheral."""
72
- return self ._central .connected
73
-
74
66
def connect (self , address , timeout ):
75
67
"""Try to connect to the peripheral at the given address.
76
68
77
69
:param bleio.Address address: The address of the peripheral to connect to
78
70
:param float/int timeout: Try to connect for timeout seconds.
79
71
"""
80
- self ._central .connect (address , timeout , service_uuids = (UART .NUS_SERVICE_UUID ,))
72
+ self ._central .connect (address , timeout , service_uuids = (NUS_SERVICE_UUID ,))
73
+
74
+ # Connect succeeded. Get the remote characteristics we need, which were
75
+ # found during discovery.
76
+
77
+ for characteristic in self ._central .remote_services [0 ].characteristics :
78
+ # Since we're remote we receive on tx and send on rx.
79
+ # The names are from the point of view of the server.
80
+ if characteristic .uuid == NUS_RX_CHAR_UUID :
81
+ self ._write_char = characteristic
82
+ elif characteristic .uuid == NUS_TX_CHAR_UUID :
83
+ self ._read_char = characteristic
84
+ if not self ._write_char or not self ._read_char :
85
+ raise OSError ("Remote UART missing needed characteristic" )
86
+ self ._read_buffer = CharacteristicBuffer (self ._read_char ,
87
+ timeout = self ._timeout ,
88
+ buffer_size = self ._buffer_size )
81
89
82
90
def disconnect (self ):
83
91
"""Disconnect from the peripheral."""
84
92
self ._central .disconnect ()
93
+ self ._read_char = self ._write_char = self ._read_buffer = None
94
+
95
+ @property
96
+ def connected (self ):
97
+ """True if we are connected to a peripheral."""
98
+ return self ._central .connected
99
+
100
+ def read (self , nbytes = None ):
101
+ """
102
+ Read characters. If ``nbytes`` is specified then read at most that many bytes.
103
+ Otherwise, read everything that arrives until the connection times out.
104
+ Providing the number of bytes expected is highly recommended because it will be faster.
105
+
106
+ :return: Data read
107
+ :rtype: bytes or None
108
+ """
109
+ return self ._read_buffer .read (nbytes )
110
+
111
+ def readinto (self , buf , nbytes = None ):
112
+ """
113
+ Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
114
+ that many bytes. Otherwise, read at most ``len(buf)`` bytes.
115
+
116
+ :return: number of bytes read and stored into ``buf``
117
+ :rtype: int or None (on a non-blocking error)
118
+ """
119
+ return self ._read_buffer .readinto (buf , nbytes )
120
+
121
+ def readline (self ):
122
+ """
123
+ Read a line, ending in a newline character.
124
+
125
+ :return: the line read
126
+ :rtype: int or None
127
+ """
128
+ return self ._read_buffer .readline ()
129
+
130
+ @property
131
+ def in_waiting (self ):
132
+ """The number of bytes in the input buffer, available to be read."""
133
+ return self ._read_buffer .in_waiting
134
+
135
+ def reset_input_buffer (self ):
136
+ """Discard any unread characters in the input buffer."""
137
+ self ._read_buffer .reset_input_buffer ()
138
+
139
+ def write (self , buf ):
140
+ """Write a buffer of bytes."""
141
+ # We can only write 20 bytes at a time.
142
+ offset = 0
143
+ while offset < len (buf ):
144
+ self ._write_char .value = buf [offset :offset + 20 ]
145
+ offset += 20
0 commit comments