Skip to content

Commit 2f4cc83

Browse files
author
AndyEveritt
committed
Merge branch 'dev' of github.com:AndyEveritt/DuetWebAPI into dev
2 parents caed31d + 3cb2462 commit 2f4cc83

3 files changed

Lines changed: 280 additions & 23 deletions

File tree

DuetWebAPI/DuetWebAPI.py

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222

2323

2424
class DuetWebAPIFactory:
25-
def __init__(self):
25+
def __init__(self) -> None:
2626
self._creators = {}
27+
28+
def __call__(self, base_url: str) -> DuetAPI:
29+
self.get_api(base_url)
2730

28-
def register_api(self, name: str, creator: object, url_suffix: str):
31+
def register_api(self, name: str, creator: object, url_suffix: str) -> None:
2932
self._creators[name] = {'creator': creator, 'url_suffix': url_suffix}
3033

31-
def get_api(self, base_url):
34+
def get_api(self, base_url) -> DuetAPI:
3235
for api in self._creators.values():
3336
url = base_url + api['url_suffix']
3437
try:
@@ -114,14 +117,29 @@ def put_file(self, file: str, directory: str = 'gcodes'):
114117
raise ValueError
115118
return r.json()
116119

117-
def get_fileinfo(self, filename):
118-
pass
120+
def get_fileinfo(self, filename: str = None, directory: str = 'gcodes'):
121+
url = f'{self._base_url}/rr_fileinfo'
122+
if filename:
123+
r = requests.get(url, {'name': f'/{directory}/{filename}'})
124+
else:
125+
r = requests.get(url)
126+
if not r.ok:
127+
raise ValueError
128+
return r.json()
119129

120-
def delete_file(self, filename):
121-
pass
130+
def delete_file(self, filename: str, directory: str = 'gcodes'):
131+
url = f'{self._base_url}/rr_delete'
132+
r = requests.get(url, {'name': f'/{directory}/{filename}'})
133+
if not r.ok:
134+
raise ValueError
135+
return r.json()
122136

123-
def move_file(self, from_path, to_path, force=False):
124-
pass
137+
def move_file(self, from_path, to_path, **_ignored):
138+
url = f'{self._base_url}/rr_move'
139+
r = requests.get(url, {'old': f'{from_path}', 'new': f'{to_path}'})
140+
if not r.ok:
141+
raise ValueError
142+
return r.json()
125143

126144
def get_directory(self, directory) -> List[Dict]:
127145
url = f'{self._base_url}/rr_filelist'
@@ -131,7 +149,11 @@ def get_directory(self, directory) -> List[Dict]:
131149
return r.json()['files']
132150

133151
def put_directory(self, directory):
134-
pass
152+
url = f'{self._base_url}/rr_mkdir'
153+
r = requests.get(url, {'dir': f'/{directory}'})
154+
if not r.ok:
155+
raise ValueError
156+
return r.json()
135157

136158

137159
class DSFAPI(DuetAPI):
@@ -146,14 +168,14 @@ def post_code(self, code) -> str:
146168
r = requests.post(url, data=code)
147169
return r.text
148170

149-
def get_file(self, filename, directory):
171+
def get_file(self, filename: str, directory: str = 'gcodes') -> str:
150172
"""
151173
filename: name of the file you want to download including extension
152174
directory: the folder that the file is in, options are ['gcodes', 'macros', 'sys']
153175
154176
returns the file as a string
155177
"""
156-
url = f'{self._base_url}/machine/file/{directory}'
178+
url = f'{self._base_url}/machine/file/{directory}/{filename}'
157179
r = requests.get(url)
158180
if not r.ok:
159181
raise ValueError
@@ -175,14 +197,26 @@ def put_file(self, file: str, directory: str = 'gcodes'):
175197
raise ValueError
176198
return r.ok
177199

178-
def get_fileinfo(self, filename):
179-
pass
200+
def get_fileinfo(self, filename: str, directory: str = 'gcodes'):
201+
url = f'{self._base_url}/machine/fileinfo/{directory}/{filename}'
202+
r = requests.get(url)
203+
if not r.ok:
204+
raise ValueError
205+
return r.json()
180206

181-
def delete_file(self, filename):
182-
pass
207+
def delete_file(self, filename: str, directory: str = 'gcodes'):
208+
url = f'{self._base_url}/machine/file/{directory}/{filename}'
209+
r = requests.delete(url)
210+
if not r.ok:
211+
raise ValueError
212+
return r.text
183213

184214
def move_file(self, from_path, to_path, force=False):
185-
pass
215+
url = f'{self._base_url}/machine/file/move'
216+
r = requests.post(url, {'from': f'{from_path}', 'to': f'{to_path}', 'force': force})
217+
if not r.ok:
218+
raise ValueError
219+
return r.text
186220

187221
def get_directory(self, directory) -> List[Dict]:
188222
url = f'{self._base_url}/machine/directory/{directory}'
@@ -192,16 +226,20 @@ def get_directory(self, directory) -> List[Dict]:
192226
return r.json()
193227

194228
def put_directory(self, directory):
195-
pass
229+
url = f'{self._base_url}/machine/directory/{directory}'
230+
r = requests.put(url)
231+
if not r.ok:
232+
raise ValueError
233+
return r.text
196234

197235

198-
factory = DuetWebAPIFactory()
199-
factory.register_api('DWC', DWCAPI, '/rr_model')
200-
factory.register_api('DSF', DSFAPI, '/machine/status')
236+
DuetWebAPI = DuetWebAPIFactory()
237+
DuetWebAPI.register_api('DWC', DWCAPI, '/rr_model')
238+
DuetWebAPI.register_api('DSF', DSFAPI, '/machine/status')
201239

202240

203-
riley = factory.get_api('http://riley')
204-
force_rig = factory.get_api('http://forcerig')
241+
riley = DuetWebAPI('http://riley')
242+
force_rig = DuetWebAPI('http://forcerig')
205243
force_rig.put_file('test.gcode')
206244
riley.put_file('test.gcode')
207245
pass

DuetWebAPI/tmp.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
class OldDuetWebAPI:
2+
3+
pt = 0
4+
5+
6+
####
7+
# The following methods are a more atomic, reading/writing basic data structures in the printer.
8+
####
9+
10+
11+
def printerType(self):
12+
return(self.pt)
13+
14+
def baseURL(self):
15+
return(self._base_url)
16+
17+
18+
19+
def getCoords(self):
20+
if (self.pt == 2):
21+
URL = (f'{self._base_url}'+'/rr_status?type=2')
22+
r = self.requests.get(URL)
23+
j = self.json.loads(r.text)
24+
jc = j['coords']['xyz']
25+
an = j['axisNames']
26+
ret = self.json.loads('{}')
27+
for i in range(0, len(jc)):
28+
ret[an[i]] = jc[i]
29+
return(ret)
30+
if (self.pt == 3):
31+
URL = (f'{self._base_url}'+'/machine/status')
32+
r = self.requests.get(URL)
33+
j = self.json.loads(r.text)
34+
ja = j['result']['move']['axes']
35+
# d=j['result']['move']['drives']
36+
# ad=self.json.loads('{}')
37+
# for i in range(0,len(ja)):
38+
# ad[ ja[i]['letter'] ] = ja[i]['drives'][0]
39+
ret = self.json.loads('{}')
40+
for i in range(0, len(ja)):
41+
ret[ja[i]['letter']] = ja[i]['userPosition']
42+
return(ret)
43+
44+
def getLayer(self):
45+
if (self.pt == 2):
46+
URL = (f'{self._base_url}'+'/rr_status?type=3')
47+
r = self.requests.get(URL)
48+
j = self.json.loads(r.text)
49+
s = j['currentLayer']
50+
return (s)
51+
if (self.pt == 3):
52+
URL = (f'{self._base_url}'+'/machine/status')
53+
r = self.requests.get(URL)
54+
j = self.json.loads(r.text)
55+
s = j['result']['job']['layer']
56+
if (s == None):
57+
s = 0
58+
return(s)
59+
60+
def getG10ToolOffset(self, tool):
61+
if (self.pt == 3):
62+
URL = (f'{self._base_url}'+'/machine/status')
63+
r = self.requests.get(URL)
64+
j = self.json.loads(r.text)
65+
ja = j['result']['move']['axes']
66+
jt = j['result']['tools']
67+
ret = self.json.loads('{}')
68+
to = jt[tool]['offsets']
69+
for i in range(0, len(to)):
70+
ret[ja[i]['letter']] = to[i]
71+
return(ret)
72+
return({'X': 0, 'Y': 0, 'Z': 0}) # Dummy for now
73+
74+
def getNumExtruders(self):
75+
if (self.pt == 2):
76+
URL = (f'{self._base_url}'+'/rr_status?type=2')
77+
r = self.requests.get(URL)
78+
j = self.json.loads(r.text)
79+
jc = j['coords']['extr']
80+
return(len(jc))
81+
if (self.pt == 3):
82+
URL = (f'{self._base_url}'+'/machine/status')
83+
r = self.requests.get(URL)
84+
j = self.json.loads(r.text)
85+
return(len(j['result']['move']['extruders']))
86+
87+
def getNumTools(self):
88+
if (self.pt == 2):
89+
URL = (f'{self._base_url}'+'/rr_status?type=2')
90+
r = self.requests.get(URL)
91+
j = self.json.loads(r.text)
92+
jc = j['tools']
93+
return(len(jc))
94+
if (self.pt == 3):
95+
URL = (f'{self._base_url}'+'/machine/status')
96+
r = self.requests.get(URL)
97+
j = self.json.loads(r.text)
98+
return(len(j['result']['tools']))
99+
100+
def getStatus(self):
101+
if (self.pt == 2):
102+
URL = (f'{self._base_url}'+'/rr_status?type=2')
103+
r = self.requests.get(URL)
104+
j = self.json.loads(r.text)
105+
s = j['status']
106+
if ('I' in s):
107+
return('idle')
108+
if ('P' in s):
109+
return('processing')
110+
if ('S' in s):
111+
return('paused')
112+
if ('B' in s):
113+
return('canceling')
114+
return(s)
115+
if (self.pt == 3):
116+
URL = (f'{self._base_url}'+'/machine/status')
117+
r = self.requests.get(URL)
118+
j = self.json.loads(r.text)
119+
return(j['result']['state']['status'])
120+
121+
# def gCode(self, command):
122+
# if (self.pt == 2):
123+
# URL = (f'{self._base_url}'+'/rr_gcode?gcode='+command)
124+
# r = self.requests.get(URL)
125+
# if (self.pt == 3):
126+
# URL = (f'{self._base_url}'+'/machine/code/')
127+
# r = self.requests.post(URL, data=command)
128+
# if (r.ok):
129+
# return(0)
130+
# else:
131+
# print("gCode command return code = ", r.status_code)
132+
# print(r.reason)
133+
# return(r.status_code)
134+
135+
# def getFilenamed(self, filename):
136+
# if (self.pt == 2):
137+
# URL = (f'{self._base_url}'+'/rr_download?name='+filename)
138+
# if (self.pt == 3):
139+
# URL = (f'{self._base_url}'+'/machine/file/'+filename)
140+
# r = self.requests.get(URL)
141+
# return(r.text.splitlines()) # replace('\n',str(chr(0x0a))).replace('\t',' '))
142+
143+
# def getDirectory(self, directory):
144+
# if (self.pt == 2):
145+
# URL = (f'{self._base_url}'+'/rr_download?name='+directory)
146+
# if (self.pt == 3):
147+
# URL = (f'{self._base_url}'+'/machine/directory/'+directory)
148+
# r = self.requests.get(URL)
149+
# return(r.text.splitlines()) # replace('\n',str(chr(0x0a))).replace('\t',' '))
150+
151+
def putFile(self, filepath, file):
152+
153+
if (self.pt == 2):
154+
URL = (f'{self._base_url}'+'/rr_upload?name='+filepath) # lol, probably not correct, fix welcome
155+
if (self.pt == 3):
156+
URL = (f'{self._base_url}'+'/machine/file/'+filepath)
157+
r = self.requests.put(URL, data=file)
158+
if (r.ok):
159+
return(0)
160+
else:
161+
print("gCode command return code = ", r.status_code)
162+
print(r.reason)
163+
164+
def getTemperatures(self):
165+
if (self.pt == 2):
166+
URL = (f'{self._base_url}'+'/rr_status?type=2')
167+
r = self.requests.get(URL)
168+
j = self.json.loads(r.text)
169+
return('Error: getTemperatures not implemented (yet) for RRF V2 printers.')
170+
if (self.pt == 3):
171+
URL = (f'{self._base_url}'+'/machine/status')
172+
r = self.requests.get(URL)
173+
j = self.json.loads(r.text)
174+
jsa = j['result']['sensors']['analog']
175+
return(jsa)
176+
177+
178+
####
179+
# The following methods provide services built on the atomics above.
180+
####
181+
182+
# Given a line from config g that defines an endstop (N574) or Z probe (M558),
183+
# Return a line that will define the same thing to a "nil" pin, i.e. undefine it
184+
185+
186+
def _nilEndstop(self, configLine):
187+
ret = ''
188+
for each in [word for word in configLine.split()]:
189+
ret = ret + (each if (not (('P' in each[0]) or ('p' in each[0]))) else 'P"nil"') + ' '
190+
return(ret)
191+
192+
def clearEndstops(self):
193+
c = self.getFilenamed('/sys/config.g')
194+
for each in [line for line in c if (('M574 ' in line) or ('M558 ' in line))]:
195+
self.gCode(self._nilEndstop(each))
196+
197+
def resetEndstops(self):
198+
c = self.getFilenamed('/sys/config.g')
199+
for each in [line for line in c if (('M574 ' in line) or ('M558 ' in line))]:
200+
self.gCode(self._nilEndstop(each))
201+
for each in [line for line in c if (('M574 ' in line) or ('M558 ' in line) or ('G31 ' in line))]:
202+
self.gCode(each)
203+
204+
def resetAxisLimits(self):
205+
c = self.getFilenamed('/sys/config.g')
206+
for each in [line for line in c if 'M208 ' in line]:
207+
self.gCode(each)
208+
209+
def resetG10(self):
210+
c = self.getFilenamed('/sys/config.g')
211+
for each in [line for line in c if 'G10 ' in line]:
212+
self.gCode(each)
213+
214+
def yeetJob(self, filename, file):
215+
path = f"gcodes/{filename}"
216+
ret = self.putFile(path, file)
217+
if ret == 0:
218+
print('YAY WE DID THE THING')

test.gcode

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
G1 X10

0 commit comments

Comments
 (0)