-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathebb_serial.py
153 lines (143 loc) · 5.06 KB
/
ebb_serial.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
# ebb_serial.py
# Serial connection utilities for EiBotBoard
# https://github.com/evil-mad/plotink
#
# Intended to provide some common interfaces that can be used by
# EggBot, WaterColorBot, AxiDraw, and similar machines.
#
# Version 0.3, Dated June 28, 2016.
#
# Thanks to Shel Michaels for bug fixes and helpful suggestions.
#
# The MIT License (MIT)
#
# Copyright (c) 2016 Evil Mad Scientist Laboratories
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import serial
import inkex
import gettext
def version():
return "0.3" # Version number for this document
def findPort():
#Find a single EiBotBoard connected to a USB port.
try:
from serial.tools.list_ports import comports
except ImportError:
comports = None
return None
if comports:
comPortsList = list(comports())
EBBport = None
for port in comPortsList:
#inkex.debug(port[1])
if port[1].startswith("EiBotBoard") or port[1].startswith("//dev") or port[1].startswith("Arduino"):
EBBport = port[0] #Success; EBB found by name match.
break #stop searching-- we are done.
if EBBport is None:
for port in comPortsList:
if port[2].startswith("USB VID:PID=04D8:FD92"):
EBBport = port[0] #Success; EBB found by VID/PID match.
break #stop searching-- we are done.
return EBBport
def testPort( comPort ):
'''
Return a SerialPort object
for the first port with an EBB (EiBotBoard; EggBot controller board).
YOU are responsible for closing this serial port!
'''
if comPort is not None:
try:
serialPort = serial.Serial( comPort, timeout=1.0 ) # 1 second timeout!
serialPort.write( 'v\r' )
strVersion = serialPort.readline()
if strVersion and strVersion.startswith( 'EBB' ):
return serialPort
serialPort.write( 'v\r' )
strVersion = serialPort.readline()
if strVersion and strVersion.startswith( 'EBB' ):
return serialPort
serialPort.close()
except serial.SerialException:
pass
return None
else:
return None
def openPort():
foundPort = findPort()
serialPort = testPort( foundPort )
if serialPort:
return serialPort
return None
def closePort(comPort):
if comPort is not None:
try:
comPort.close()
except serial.SerialException:
pass
def query( comPort, cmd ):
if (comPort is not None) and (cmd is not None):
response = ''
try:
comPort.write( cmd )
response = comPort.readline()
nRetryCount = 0
while ( len(response) == 0 ) and ( nRetryCount < 100 ):
# get new response to replace null response if necessary
response = comPort.readline()
nRetryCount += 1
if cmd.strip().lower() not in ["v","i","a", "mr","pi","qm"]:
#Most queries return an "OK" after the data requested.
#We skip this for those few queries that do not return an extra line.
unused_response = comPort.readline() #read in extra blank/OK line
nRetryCount = 0
while ( len(unused_response) == 0 ) and ( nRetryCount < 100 ):
# get new response to replace null response if necessary
unused_response = comPort.readline()
nRetryCount += 1
except:
inkex.errormsg( gettext.gettext( "Error reading serial data." ) )
return response
else:
return None
def command( comPort, cmd ):
if (comPort is not None) and (cmd is not None):
try:
comPort.write( cmd )
response = comPort.readline()
nRetryCount = 0
while ( len(response) == 0 ) and ( nRetryCount < 100 ):
# get new response to replace null response if necessary
response = comPort.readline()
nRetryCount += 1
inkex.errormsg("Retry" + str(nRetryCount))
if response.strip().startswith("OK"):
pass # inkex.errormsg( 'OK after command: ' + cmd ) #Debug option: indicate which command.
else:
if ( response != '' ):
inkex.errormsg( 'Error: Unexpected response from EBB.')
inkex.errormsg( ' Command: ' + cmd.strip() )
inkex.errormsg( ' Response: ' + str( response.strip() ) )
else:
inkex.errormsg( 'EBB Serial Timeout after command: ' + cmd )
# except Exception,e:
# inkex.errormsg( str(e)) #For debugging: one may wish to display the error.
except:
inkex.errormsg( 'Failed after command: ' + cmd )
pass