Wed, 20 Jan 2021 10:15:13 +0100
updated and added new files for printrun
46 | 1 | # This file is part of the Printrun suite. |
2 | # | |
3 | # Printrun is free software: you can redistribute it and/or modify | |
4 | # it under the terms of the GNU General Public License as published by | |
5 | # the Free Software Foundation, either version 3 of the License, or | |
6 | # (at your option) any later version. | |
7 | # | |
8 | # Printrun is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | # GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the GNU General Public License | |
14 | # along with Printrun. If not, see <http://www.gnu.org/licenses/>. | |
15 | # | |
16 | # Copyright 2017 Rock Storm <rockstorm@gmx.com> | |
17 | ||
18 | # This module indirectly depends of pronsole and settings but it does not | |
19 | # import them | |
20 | ||
21 | class SpoolManager(): | |
22 | """ | |
23 | Back-end for the Spool Manager. | |
24 | ||
25 | It is expected to be called from an object which has the contents of | |
26 | settings.py and pronsole.py. This way the class is able to '_add' and | |
27 | 'set' settings. | |
28 | ||
29 | This class basically handles a single variable called '_spool_list'. It is | |
30 | a list of spool_items. A spool_item is in turn a list three elements: a | |
31 | string, a float and an integer. Namely: the name of the spool, the | |
32 | remaining length of filament and the extruder it is loaded to. E.g.: | |
33 | ||
34 | spool_item = [string name, float length, int extruder] | |
35 | ||
36 | _spool_list = [spool_item spool_1, ... , spool_item spool_n ] | |
37 | ||
38 | '_spool_list' is somehow a Nx3 matrix where N is the number of recorded | |
39 | spools. The first column contains the names of the spools, the second the | |
40 | lengths of remaining filament and the third column contains which extruder | |
41 | is the spool loaded for. | |
42 | ||
43 | The variable '_spool_list' is saved in the configuration file using a | |
44 | setting with the same name: 'spool_list'. It is saved as a single string. | |
45 | It concatenates every item from the list and separates them by a comma and | |
46 | a space. For instance, if the variable '_spool_list' was: | |
47 | ||
48 | _spool_list = [["spool_1", 100.0, 0], ["spool_2", 200.0, -1]] | |
49 | ||
50 | The 'spool_list' setting will look like: | |
51 | ||
52 | "spool_1, 100.0, 0, spool_2, 200.0, -1" | |
53 | """ | |
54 | ||
55 | def __init__(self, parent): | |
56 | self.parent = parent | |
57 | self.refresh() | |
58 | ||
59 | def refresh(self): | |
60 | """ | |
61 | Read the configuration file and populate the list of recorded spools. | |
62 | """ | |
63 | self._spool_list = self._readSetting(self.parent.settings.spool_list) | |
64 | ||
65 | def add(self, spool_name, spool_length): | |
66 | """Add the given spool to the list of recorded spools.""" | |
67 | self._spool_list.append([spool_name, spool_length, -1]) | |
68 | self._save() | |
69 | ||
70 | def load(self, spool_name, extruder): | |
71 | """Set the extruder field of the given spool item.""" | |
72 | ||
73 | # If there was a spool already loaded for this extruder unload it | |
74 | previous_spool = self._findByColumn(extruder, 2) | |
75 | if previous_spool != -1: | |
76 | self.unload(extruder) | |
77 | ||
78 | # Load the given spool | |
79 | new_spool = self._findByColumn(spool_name, 0) | |
80 | self.remove(spool_name) | |
81 | self._spool_list.append([new_spool[0], new_spool[1], extruder]) | |
82 | self._save() | |
83 | ||
84 | def remove(self, spool_name): | |
85 | """Remove the given spool item from the list of recorded spools.""" | |
86 | spool_item = self._findByColumn(spool_name, 0) | |
87 | self._spool_list.remove(spool_item) | |
88 | self._save() | |
89 | ||
90 | def unload(self, extruder): | |
91 | """Set to -1 the extruder field of the spool item currently on.""" | |
92 | ||
93 | spool_item = self._findByColumn(extruder, 2) | |
94 | if spool_item != -1: | |
95 | self.remove(spool_item[0]) | |
96 | self._spool_list.append([spool_item[0], spool_item[1], -1]) | |
97 | self._save() | |
98 | ||
99 | def isLoaded(self, spool_name): | |
100 | """ | |
101 | int isLoaded( string name ) | |
102 | ||
103 | Return the extruder that the given spool is loaded to. -1 if it is | |
104 | not loaded for any extruder or None if the given name does not match | |
105 | any known spool. | |
106 | """ | |
107 | ||
108 | spool_item = self._findByColumn(spool_name, 0) | |
109 | if spool_item != -1: | |
110 | return spool_item[2] | |
111 | else: | |
112 | return None | |
113 | ||
114 | def isListed(self, spool_name): | |
115 | """Return 'True' if the given spool is on the list.""" | |
116 | ||
117 | spool_item = self._findByColumn(spool_name, 0) | |
118 | if not spool_item == -1: | |
119 | return True | |
120 | else: | |
121 | return False | |
122 | ||
123 | def getSpoolName(self, extruder): | |
124 | """ | |
125 | string getSpoolName( int extruder ) | |
126 | ||
127 | Return the name of the spool loaded for the given extruder. | |
128 | """ | |
129 | ||
130 | spool_item = self._findByColumn(extruder, 2) | |
131 | if spool_item != -1: | |
132 | return spool_item[0] | |
133 | else: | |
134 | return None | |
135 | ||
136 | def getRemainingFilament(self, extruder): | |
137 | """ | |
138 | float getRemainingFilament( int extruder ) | |
139 | ||
140 | Return the name of the spool loaded for the given extruder. | |
141 | """ | |
142 | ||
143 | spool_item = self._findByColumn(extruder, 2) | |
144 | if spool_item != -1: | |
145 | return spool_item[1] | |
146 | else: | |
147 | return float("NaN") | |
148 | ||
149 | def editLength(self, increment, spool_name = None, extruder = -1): | |
150 | """ | |
151 | int editLength ( float increment, string spool_name, int extruder ) | |
152 | ||
153 | Add the given 'increment' amount to the length of filament of the | |
154 | given spool. Spool can be specified either by name or by the extruder | |
155 | it is loaded to. | |
156 | """ | |
157 | ||
158 | if spool_name != None: | |
159 | spool_item = self._findByColumn(spool_name, 0) | |
160 | elif extruder != -1: | |
161 | spool_item = self._findByColumn(extruder, 2) | |
162 | else: | |
163 | return -1 # Not enough arguments | |
164 | ||
165 | if spool_item == -1: | |
166 | return -2 # No spool found for the given name or extruder | |
167 | ||
168 | length = spool_item[1] + increment | |
169 | self.remove(spool_item[0]) | |
170 | self.add(spool_item[0], length) | |
171 | if spool_item[2] > -1: | |
172 | self.load(spool_item[0], spool_item[2]) | |
173 | self._save() | |
174 | ||
175 | return 0 | |
176 | ||
177 | def getExtruderCount(self): | |
178 | """int getExtruderCount()""" | |
179 | return self.parent.settings.extruders | |
180 | ||
181 | def getSpoolCount(self): | |
182 | """ | |
183 | int getSpoolCount() | |
184 | ||
185 | Return the number of currently recorded spools. | |
186 | """ | |
187 | return len(self._spool_list) | |
188 | ||
189 | def getSpoolList(self): | |
190 | """ | |
191 | [N][2] getSpoolList () | |
192 | ||
193 | Returns a list of the recorded spools. Returns a Nx2 matrix where N is | |
194 | the number of recorded spools. The first column contains the names of | |
195 | the spools and the second the lengths of remaining filament. | |
196 | """ | |
197 | ||
198 | slist = [] | |
199 | for i in range(self.getSpoolCount()): | |
200 | item = [self._spool_list[i][0], self._spool_list[i][1]] | |
201 | slist.append(item) | |
202 | return slist | |
203 | ||
204 | def _findByColumn(self, data, col = 0): | |
205 | """ | |
206 | Find which spool_item from the list contains certain data. | |
207 | ||
208 | The 'col' argument specifies in which field from the spool_item to | |
209 | look for. For instance, with the following list: | |
210 | ||
211 | _spool_list = [["spool_1", 100.0, 1], | |
212 | ["spool_2", 200.0, 0], | |
213 | . | |
214 | . | |
215 | . | |
216 | ["spool_10", 1000.0, 0]] | |
217 | ||
218 | A call like: _findByColumn("spool_2", 0) | |
219 | ||
220 | Will produce: ["spool_2", 200.0, 0] | |
221 | ||
222 | col = 0, would look into the "name's column" | |
223 | col = 1, would look into the "length's column" | |
224 | col = 2, would look into the "extruder's column" | |
225 | """ | |
226 | ||
227 | for spool_item in self._spool_list: | |
228 | if data == spool_item[col]: | |
229 | return spool_item | |
230 | ||
231 | return -1 | |
232 | ||
233 | def _save(self): | |
234 | """Update the list of recorded spools in the configuration file.""" | |
235 | self._setSetting(self._spool_list, "spool_list") | |
236 | ||
237 | def _setSetting(self, variable, setting): | |
238 | """ | |
239 | Write the given variable to the given setting of the configuration | |
240 | file. | |
241 | """ | |
242 | n = 3 # number of fields in spool_item | |
243 | string_list = [] | |
244 | for i in range(len(variable)): | |
245 | for j in range(n): | |
246 | string_list.append(str(variable[i][j])) | |
247 | separator = ", " | |
248 | self.parent.set(setting, separator.join(string_list)) | |
249 | ||
250 | def _readSetting(self, setting): | |
251 | """ | |
252 | Return the variable read. | |
253 | """ | |
254 | n = 3 # number of fields in spool_item | |
255 | string_list = setting.split(", ") | |
256 | variable = [] | |
257 | for i in range(len(string_list)//n): | |
258 | variable.append( | |
259 | [string_list[n*i], | |
260 | float(string_list[n*i+1]), | |
261 | int(string_list[n*i+2])]) | |
262 | return variable |