-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathneatoserialbasic.py
238 lines (209 loc) · 7.73 KB
/
neatoserialbasic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
"""Serial interface for Neato."""
from config import settings
import serial
import os
import time
import RPi.GPIO as GPIO
import logging
class NeatoSerial:
"""Serial interface to Neato."""
def __init__(self):
"""Initialize serial connection to Neato."""
self.log = logging.getLogger(__name__)
self.isConnected = self.connect()
def connect(self):
"""Connect to serial port."""
devices = settings['serial']['serial_device'].split(',')
for dev in devices:
try:
self.ser = serial.Serial(dev, 115200,
serial.EIGHTBITS, serial.PARITY_NONE,
serial.STOPBITS_ONE,
settings['serial']['timeout_seconds'])
self.open()
self.log.debug("Connected to Neato at "+dev)
print("Connected to Neato at "+dev)
return True
except:
self.log.error("Could not connect to device "+dev+". "
+ "Trying next device.")
print("Could not connect to device "+dev+". "
+ "Trying next device.")
return False
def getIsConnected(self):
"""Return if connected."""
return self.isConnected
def open(self):
"""Open serial port and flush the input."""
print("Entering OPEN()")
if self.ser is None:
return
else:
self.ser.isOpen()
self.ser.flushInput()
print("Leaving OPEN()")
def close(self):
"""Close serial port."""
print("Entering CLOSE()")
self.ser.close()
self.isConnected = False
print("Leaving CLOSE, isConnected= "+str(self.isConnected))
def read_all(self, port, chunk_size=200):
"""Read all characters on the serial port and return them."""
if not port.timeout:
raise TypeError('Port needs to have a timeout set!')
read_buffer = b''
while True:
# Read in chunks. Each chunk will wait as long as specified by
# timeout. Increase chunk_size to fail quicker
byte_chunk = port.read(size=chunk_size)
read_buffer += byte_chunk
if not len(byte_chunk) == chunk_size:
break
return read_buffer
def reconnect(self):
"""Close and reconnect connection to Neato."""
print("Entering RECONNECT()")
self.log.debug("Reconnecting to Neato")
print("Reconnecting to Neato")
self.isConnected = False
time.sleep(5)
self.close()
self.isConnected = self.connect()
self.open()
print("Leaving RECONNECT(), isConnected = "+str(self.isConnected))
def raw_write(self,msg):
"""Write message to serial and return output."""
print("Entering RAW_WRITE(), msg = "+str(msg))
out = ''
if self.isConnected:
inp = msg+"\n"
self.ser.write(inp.encode('utf-8'))
time.sleep(1)
while self.ser.inWaiting() > 0:
out += self.read_all(self.ser).decode('utf-8')
print("Leaving RAW_WRITE()")
return out
def write(self, msg):
"""Write message to serial and return output. Handles Clean message."""
print("Entering WRITE, msg = "+msg)
self.log.debug("Message received for writing: "+msg)
if self.isConnected:
# wake up neato by sending something random
try:
print("Sending Wake-up msg.")
out = self.raw_write("wake-up")
# now send the real message
out = self.raw_write(msg)
if out is not '':
print("Leaving WRITE(), out = "+str(out)[:10])
return out
except OSError as ex:
self.log.error("Exception in 'write' method: "+str(ex))
print("Exception in WRITE(): "+str(ex))
print("Calling RECONNECT()")
self.reconnect()
else:
print("Not connected in WRITE() - calling CONNECT()")
self.isConnected = self.connect()
def getError(self):
"""Return error message if available."""
print("Entering GETERROR()")
output = self.write("GetErr")
if output is not None:
outputsplit = output.split('\r\n')
if len(outputsplit) == 3:
err = outputsplit[1]
if ' - ' in err:
errsplit = err.split(' - ')
print("Leaving GETERROR(), errsplit = "+str(errsplit))
return errsplit[0], errsplit[1]
else:
print("Leaving GETERROR(), return None since no output split.")
return None
else:
print("Leaving GETERROR(), return None since Output is None.")
return None
def getBatteryLevel(self):
"""Return battery level."""
charger = self.getCharger()
if charger:
return int(charger.get("FuelPercent", 0))
else:
return 0
def getChargingActive(self):
"""Return true if device is currently charging."""
charger = self.getCharger()
if charger:
return bool(int(charger.get("ChargingActive", False)))
else:
return False
def getExtPwrPresent(self):
"""Return true if device is currently docked."""
charger = self.getCharger()
if charger:
return bool(int(charger.get("ExtPwrPresent", False)))
else:
return False
def getAccel(self):
"""Get accelerometer info."""
return self.parseOutput(self.write("GetAccel"))
def getAnalogSensors(self):
"""Get analog sensor info."""
return self.parseOutput(self.write("GetAnalogSensors"))
def getButtons(self):
"""Get button info."""
return self.parseOutput(self.write("GetButtons"))
def getCalInfo(self):
"""Get calibration info."""
return self.parseOutput(self.write("GetCalInfo"))
def getCharger(self):
"""Get charger info."""
return self.parseOutput(self.write("GetCharger"))
def getDigitalSensors(self):
"""Get digital sensor info."""
return self.parseOutput(self.write("GetDigitalSensors"))
def getLDSScan(self):
"""Get lidar scan."""
return self.parseOutput(self.write("GetLDSScan"))
def getMotors(self):
"""Get motor info."""
return self.parseOutput(self.write("GetMotors"))
def getVersion(self):
"""Get version info."""
return self.parseOutput(self.write("GetVersion"))
def getVacuumRPM(self):
"""Get vacuum RPM."""
motors = self.getMotors()
if motors:
return int(motors.get("Vacuum_RPM", 0))
else:
return 0
def getCleaning(self):
"""Return true is device is currently cleaning."""
return self.getVacuumRPM() > 0
def parseOutput(self, output):
"""Parse the raw output of the serial port into a dictionary."""
if output is None:
return None
else:
lines = output.splitlines()
dict = {}
for l in lines:
lsplit = l.split(',')
if len(lsplit) > 1:
dict[lsplit[0]] = lsplit[1]
return dict
if __name__ == '__main__':
ns = NeatoSerial()
print("Enter commands. Enter 'exit' to quit")
while 1:
inp = input("? ")
if inp == 'exit':
ns.close()
exit()
else:
try:
print(">> "+ns.write(inp))
except:
print("No result returned.")