meerk40t 0.9.2000__py2.py3-none-any.whl → 0.9.3001__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerk40t/balormk/balor_params.py +1 -43
- meerk40t/balormk/controller.py +1 -41
- meerk40t/balormk/device.py +16 -22
- meerk40t/balormk/driver.py +4 -4
- meerk40t/balormk/gui/balorconfig.py +2 -2
- meerk40t/balormk/gui/balorcontroller.py +13 -5
- meerk40t/balormk/gui/baloroperationproperties.py +0 -46
- meerk40t/balormk/gui/gui.py +17 -17
- meerk40t/camera/gui/camerapanel.py +18 -11
- meerk40t/core/cutcode/rastercut.py +3 -1
- meerk40t/core/cutplan.py +145 -14
- meerk40t/core/elements/clipboard.py +18 -9
- meerk40t/core/elements/element_treeops.py +320 -180
- meerk40t/core/elements/element_types.py +7 -2
- meerk40t/core/elements/elements.py +53 -27
- meerk40t/core/elements/geometry.py +8 -0
- meerk40t/core/elements/offset_clpr.py +129 -4
- meerk40t/core/elements/offset_mk.py +3 -1
- meerk40t/core/elements/shapes.py +28 -25
- meerk40t/core/laserjob.py +7 -0
- meerk40t/core/node/bootstrap.py +4 -0
- meerk40t/core/node/effect_hatch.py +85 -96
- meerk40t/core/node/effect_wobble.py +309 -0
- meerk40t/core/node/elem_image.py +49 -19
- meerk40t/core/node/elem_line.py +60 -0
- meerk40t/core/node/elem_rect.py +5 -3
- meerk40t/core/node/image_processed.py +766 -0
- meerk40t/core/node/image_raster.py +113 -0
- meerk40t/core/node/node.py +120 -1
- meerk40t/core/node/op_cut.py +2 -8
- meerk40t/core/node/op_dots.py +0 -8
- meerk40t/core/node/op_engrave.py +2 -18
- meerk40t/core/node/op_image.py +22 -35
- meerk40t/core/node/op_raster.py +0 -9
- meerk40t/core/planner.py +32 -2
- meerk40t/core/svg_io.py +699 -461
- meerk40t/core/treeop.py +191 -0
- meerk40t/core/undos.py +15 -1
- meerk40t/core/units.py +14 -4
- meerk40t/device/dummydevice.py +3 -2
- meerk40t/device/gui/defaultactions.py +43 -55
- meerk40t/device/gui/formatterpanel.py +58 -49
- meerk40t/device/gui/warningpanel.py +12 -12
- meerk40t/device/mixins.py +13 -0
- meerk40t/dxf/dxf_io.py +9 -5
- meerk40t/extra/ezd.py +28 -26
- meerk40t/extra/imageactions.py +300 -308
- meerk40t/extra/lbrn.py +19 -2
- meerk40t/fill/fills.py +6 -6
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +2 -6
- meerk40t/grbl/controller.py +168 -52
- meerk40t/grbl/device.py +23 -18
- meerk40t/grbl/driver.py +39 -0
- meerk40t/grbl/emulator.py +79 -19
- meerk40t/grbl/gcodejob.py +10 -0
- meerk40t/grbl/gui/grblconfiguration.py +2 -2
- meerk40t/grbl/gui/grblcontroller.py +24 -8
- meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
- meerk40t/grbl/gui/gui.py +17 -14
- meerk40t/grbl/mock_connection.py +15 -34
- meerk40t/grbl/plugin.py +0 -4
- meerk40t/grbl/serial_connection.py +2 -1
- meerk40t/gui/about.py +8 -5
- meerk40t/gui/alignment.py +10 -6
- meerk40t/gui/basicops.py +27 -17
- meerk40t/gui/bufferview.py +2 -2
- meerk40t/gui/choicepropertypanel.py +101 -13
- meerk40t/gui/consolepanel.py +12 -9
- meerk40t/gui/devicepanel.py +38 -25
- meerk40t/gui/executejob.py +6 -4
- meerk40t/gui/help_assets/help_assets.py +13 -10
- meerk40t/gui/hersheymanager.py +8 -6
- meerk40t/gui/icons.py +1951 -3065
- meerk40t/gui/imagesplitter.py +14 -7
- meerk40t/gui/keymap.py +3 -3
- meerk40t/gui/laserpanel.py +151 -84
- meerk40t/gui/laserrender.py +61 -70
- meerk40t/gui/lasertoolpanel.py +8 -7
- meerk40t/gui/materialtest.py +3 -3
- meerk40t/gui/mkdebug.py +254 -1
- meerk40t/gui/navigationpanels.py +321 -180
- meerk40t/gui/notes.py +3 -3
- meerk40t/gui/opassignment.py +12 -12
- meerk40t/gui/operation_info.py +13 -13
- meerk40t/gui/plugin.py +5 -0
- meerk40t/gui/position.py +20 -18
- meerk40t/gui/preferences.py +21 -6
- meerk40t/gui/propertypanels/attributes.py +70 -22
- meerk40t/gui/propertypanels/blobproperty.py +2 -2
- meerk40t/gui/propertypanels/consoleproperty.py +2 -2
- meerk40t/gui/propertypanels/groupproperties.py +3 -3
- meerk40t/gui/propertypanels/hatchproperty.py +11 -18
- meerk40t/gui/propertypanels/imageproperty.py +4 -3
- meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
- meerk40t/gui/propertypanels/pathproperty.py +2 -2
- meerk40t/gui/propertypanels/pointproperty.py +2 -2
- meerk40t/gui/propertypanels/propertywindow.py +4 -4
- meerk40t/gui/propertypanels/textproperty.py +3 -3
- meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
- meerk40t/gui/ribbon.py +367 -259
- meerk40t/gui/scene/scene.py +31 -5
- meerk40t/gui/scenewidgets/elementswidget.py +12 -4
- meerk40t/gui/scenewidgets/gridwidget.py +2 -2
- meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
- meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
- meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
- meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
- meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
- meerk40t/gui/simpleui.py +95 -8
- meerk40t/gui/simulation.py +44 -36
- meerk40t/gui/spoolerpanel.py +124 -26
- meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
- meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
- meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
- meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
- meerk40t/gui/themes.py +78 -0
- meerk40t/gui/toolwidgets/toolcircle.py +2 -1
- meerk40t/gui/toolwidgets/toolellipse.py +2 -1
- meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
- meerk40t/gui/toolwidgets/toolline.py +144 -0
- meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
- meerk40t/gui/toolwidgets/toolpoint.py +1 -1
- meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
- meerk40t/gui/toolwidgets/toolrect.py +2 -1
- meerk40t/gui/usbconnect.py +2 -2
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
- meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
- meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
- meerk40t/gui/wordlisteditor.py +33 -18
- meerk40t/gui/wxmeerk40t.py +166 -66
- meerk40t/gui/wxmmain.py +236 -157
- meerk40t/gui/wxmribbon.py +49 -25
- meerk40t/gui/wxmscene.py +49 -38
- meerk40t/gui/wxmtree.py +216 -85
- meerk40t/gui/wxutils.py +62 -4
- meerk40t/image/imagetools.py +443 -15
- meerk40t/internal_plugins.py +2 -10
- meerk40t/kernel/kernel.py +12 -4
- meerk40t/lihuiyu/controller.py +7 -7
- meerk40t/lihuiyu/device.py +3 -1
- meerk40t/lihuiyu/driver.py +3 -0
- meerk40t/lihuiyu/gui/gui.py +8 -8
- meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
- meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
- meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
- meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
- meerk40t/main.py +6 -1
- meerk40t/moshi/controller.py +5 -5
- meerk40t/moshi/device.py +5 -2
- meerk40t/moshi/driver.py +4 -0
- meerk40t/moshi/gui/gui.py +8 -8
- meerk40t/moshi/gui/moshicontrollergui.py +24 -8
- meerk40t/moshi/gui/moshidrivergui.py +2 -2
- meerk40t/newly/controller.py +2 -0
- meerk40t/newly/device.py +9 -2
- meerk40t/newly/driver.py +4 -0
- meerk40t/newly/gui/gui.py +16 -17
- meerk40t/newly/gui/newlyconfig.py +2 -2
- meerk40t/newly/gui/newlycontroller.py +13 -5
- meerk40t/rotary/gui/gui.py +2 -2
- meerk40t/rotary/gui/rotarysettings.py +2 -2
- meerk40t/ruida/device.py +3 -0
- meerk40t/ruida/driver.py +4 -0
- meerk40t/ruida/gui/gui.py +6 -6
- meerk40t/ruida/gui/ruidaconfig.py +2 -2
- meerk40t/ruida/gui/ruidacontroller.py +13 -5
- meerk40t/svgelements.py +9 -9
- meerk40t/tools/geomstr.py +849 -153
- meerk40t/tools/kerftest.py +8 -4
- meerk40t/tools/livinghinges.py +15 -8
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
- test/test_core_elements.py +8 -24
- test/test_file_svg.py +88 -0
- test/test_fill.py +9 -9
- test/test_geomstr.py +258 -8
- test/test_kernel.py +4 -0
- test/test_tools_rasterplotter.py +29 -0
- meerk40t/extra/embroider.py +0 -56
- meerk40t/extra/pathoptimize.py +0 -249
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
meerk40t/fill/patterns.py
CHANGED
@@ -154,12 +154,8 @@ class LivingHinges:
|
|
154
154
|
if outer_path is None:
|
155
155
|
return
|
156
156
|
self.path = Geomstr()
|
157
|
-
|
158
|
-
|
159
|
-
pts = list(sp.as_interpolated_points(interpolate=100))
|
160
|
-
# pts = [Path(sp).point(i / 100.0, error=1e4) for i in range(101)]
|
161
|
-
clip.polyline(pts)
|
162
|
-
# clip.end()
|
157
|
+
|
158
|
+
clip = outer_path
|
163
159
|
|
164
160
|
q = Clip(clip)
|
165
161
|
subject = Geomstr()
|
meerk40t/grbl/controller.py
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
GRBL Controller
|
3
3
|
|
4
4
|
Tasked with sending data to the different connection.
|
5
|
+
|
6
|
+
Validation Stages.
|
7
|
+
Stage 0, we are disconnected and invalid.
|
8
|
+
Stage 1, we are connected and need to check if we are GRBL send $
|
9
|
+
Stage 2, we parsed $ and need to try $$ $G
|
10
|
+
Stage 3, we successfully parsed $$
|
11
|
+
Stage 4, we successfully parsed $G, send ?
|
12
|
+
Stage 5, we successfully parsed ?
|
5
13
|
"""
|
6
14
|
import re
|
7
15
|
import threading
|
@@ -12,6 +20,83 @@ from meerk40t.kernel import signal_listener
|
|
12
20
|
SETTINGS_MESSAGE = re.compile(r"^\$([0-9]+)=(.*)")
|
13
21
|
|
14
22
|
|
23
|
+
def hardware_settings(code):
|
24
|
+
"""
|
25
|
+
Given a $# code returns the parameter and the units.
|
26
|
+
|
27
|
+
@param code: $$ code.
|
28
|
+
@return: parameter, units
|
29
|
+
"""
|
30
|
+
if code == 0:
|
31
|
+
return 10, "step pulse time", "microseconds"
|
32
|
+
if code == 1:
|
33
|
+
return 25, "step idle delay", "milliseconds"
|
34
|
+
if code == 2:
|
35
|
+
return 0, "step pulse invert", "bitmask"
|
36
|
+
if code == 3:
|
37
|
+
return 0, "step direction invert", "bitmask"
|
38
|
+
if code == 4:
|
39
|
+
return 0, "invert step enable pin", "boolean"
|
40
|
+
if code == 5:
|
41
|
+
return 0, "invert limit pins", "boolean"
|
42
|
+
if code == 6:
|
43
|
+
return 0, "invert probe pin", "boolean"
|
44
|
+
if code == 10:
|
45
|
+
return 255, "status report options", "bitmask"
|
46
|
+
if code == 11:
|
47
|
+
return 0.010, "Junction deviation", "mm"
|
48
|
+
if code == 12:
|
49
|
+
return 0.002, "arc tolerance", "mm"
|
50
|
+
if code == 13:
|
51
|
+
return 0, "Report in inches", "boolean"
|
52
|
+
if code == 20:
|
53
|
+
return 0, "Soft limits enabled", "boolean"
|
54
|
+
if code == 21:
|
55
|
+
return 0, "hard limits enabled", "boolean"
|
56
|
+
if code == 22:
|
57
|
+
return 0, "Homing cycle enable", "boolean"
|
58
|
+
if code == 23:
|
59
|
+
return 0, "Homing direction invert", "bitmask"
|
60
|
+
if code == 24:
|
61
|
+
return 25.000, "Homing locate feed rate", "mm/min"
|
62
|
+
if code == 25:
|
63
|
+
return 500.000, "Homing search seek rate", "mm/min"
|
64
|
+
if code == 26:
|
65
|
+
return 250, "Homing switch debounce delay", "ms"
|
66
|
+
if code == 27:
|
67
|
+
return 1.000, "Homing switch pull-off distance", "mm"
|
68
|
+
if code == 30:
|
69
|
+
return 1000, "Maximum spindle speed", "RPM"
|
70
|
+
if code == 31:
|
71
|
+
return 0, "Minimum spindle speed", "RPM"
|
72
|
+
if code == 32:
|
73
|
+
return 1, "Laser mode enable", "boolean"
|
74
|
+
if code == 100:
|
75
|
+
return 250.000, "X-axis steps per millimeter", "steps"
|
76
|
+
if code == 101:
|
77
|
+
return 250.000, "Y-axis steps per millimeter", "steps"
|
78
|
+
if code == 102:
|
79
|
+
return 250.000, "Z-axis steps per millimeter", "steps"
|
80
|
+
if code == 110:
|
81
|
+
return 500.000, "X-axis max rate", "mm/min"
|
82
|
+
if code == 111:
|
83
|
+
return 500.000, "Y-axis max rate", "mm/min"
|
84
|
+
if code == 112:
|
85
|
+
return 500.000, "Z-axis max rate", "mm/min"
|
86
|
+
if code == 120:
|
87
|
+
return 10.000, "X-axis acceleration", "mm/s^2"
|
88
|
+
if code == 121:
|
89
|
+
return 10.000, "Y-axis acceleration", "mm/s^2"
|
90
|
+
if code == 122:
|
91
|
+
return 10.000, "Z-axis acceleration", "mm/s^2"
|
92
|
+
if code == 130:
|
93
|
+
return 200.000, "X-axis max travel", "mm"
|
94
|
+
if code == 131:
|
95
|
+
return 200.000, "Y-axis max travel", "mm"
|
96
|
+
if code == 132:
|
97
|
+
return 200.000, "Z-axis max travel", "mm"
|
98
|
+
|
99
|
+
|
15
100
|
def grbl_error_code(code):
|
16
101
|
long = ""
|
17
102
|
short = f"Error #{code}"
|
@@ -156,53 +241,14 @@ class GrblController:
|
|
156
241
|
def __init__(self, context):
|
157
242
|
self.service = context
|
158
243
|
self.connection = None
|
244
|
+
self._validation_stage = 0
|
159
245
|
|
160
246
|
self.update_connection()
|
161
247
|
|
162
248
|
self.driver = self.service.driver
|
163
|
-
self.grbl_settings = {
|
164
|
-
0: 10, # step pulse microseconds
|
165
|
-
1: 25, # step idle delay
|
166
|
-
2: 0, # step pulse invert
|
167
|
-
3: 0, # step direction invert
|
168
|
-
4: 0, # invert step enable pin, boolean
|
169
|
-
5: 0, # invert limit pins, boolean
|
170
|
-
6: 0, # invert probe pin
|
171
|
-
10: 255, # status report options
|
172
|
-
11: 0.010, # Junction deviation, mm
|
173
|
-
12: 0.002, # arc tolerance, mm
|
174
|
-
13: 0, # Report in inches
|
175
|
-
20: 0, # Soft limits enabled.
|
176
|
-
21: 0, # hard limits enabled
|
177
|
-
22: 0, # Homing cycle enable
|
178
|
-
23: 0, # Homing direction invert
|
179
|
-
24: 25.000, # Homing locate feed rate, mm/min
|
180
|
-
25: 500.000, # Homing search seek rate, mm/min
|
181
|
-
26: 250, # Homing switch debounce delay, ms
|
182
|
-
27: 1.000, # Homing switch pull-off distance, mm
|
183
|
-
30: 1000, # Maximum spindle speed, RPM
|
184
|
-
31: 0, # Minimum spindle speed, RPM
|
185
|
-
32: 1, # Laser mode enable, boolean
|
186
|
-
100: 250.000, # X-axis steps per millimeter
|
187
|
-
101: 250.000, # Y-axis steps per millimeter
|
188
|
-
102: 250.000, # Z-axis steps per millimeter
|
189
|
-
110: 500.000, # X-axis max rate mm/min
|
190
|
-
111: 500.000, # Y-axis max rate mm/min
|
191
|
-
112: 500.000, # Z-axis max rate mm/min
|
192
|
-
120: 10.000, # X-axis acceleration, mm/s^2
|
193
|
-
121: 10.000, # Y-axis acceleration, mm/s^2
|
194
|
-
122: 10.000, # Z-axis acceleration, mm/s^2
|
195
|
-
130: 200.000, # X-axis max travel mm.
|
196
|
-
131: 200.000, # Y-axis max travel mm
|
197
|
-
132: 200.000, # Z-axis max travel mm.
|
198
|
-
}
|
199
249
|
|
200
250
|
# Welcome message into, indicates the device is initialized.
|
201
251
|
self.welcome = self.service.setting(str, "welcome", "Grbl")
|
202
|
-
self._requires_validation = self.service.setting(
|
203
|
-
bool, "requires_validation", True
|
204
|
-
)
|
205
|
-
self._connection_validated = not self._requires_validation
|
206
252
|
|
207
253
|
# Sending variables.
|
208
254
|
self._sending_thread = None
|
@@ -321,6 +367,8 @@ class GrblController:
|
|
321
367
|
self.log("Could not connect.", type="event")
|
322
368
|
return
|
323
369
|
self.log("Connecting to GRBL...", type="event")
|
370
|
+
self._validation_stage = 1
|
371
|
+
self.realtime("$\r\n")
|
324
372
|
|
325
373
|
def close(self):
|
326
374
|
"""
|
@@ -331,8 +379,8 @@ class GrblController:
|
|
331
379
|
if not self.connection.connected:
|
332
380
|
return
|
333
381
|
self.connection.disconnect()
|
334
|
-
self._connection_validated = not self._requires_validation
|
335
382
|
self.log("Disconnecting from GRBL...", type="event")
|
383
|
+
self._validation_stage = 0
|
336
384
|
|
337
385
|
def write(self, data):
|
338
386
|
"""
|
@@ -386,6 +434,7 @@ class GrblController:
|
|
386
434
|
self.add_watcher(self._channel_log)
|
387
435
|
|
388
436
|
if self._sending_thread is None:
|
437
|
+
self._sending_thread = True # Avoid race condition.
|
389
438
|
self._sending_thread = self.service.threaded(
|
390
439
|
self._sending,
|
391
440
|
thread_name=f"sender-{self.service.location()}",
|
@@ -393,6 +442,7 @@ class GrblController:
|
|
393
442
|
daemon=True,
|
394
443
|
)
|
395
444
|
if self._recving_thread is None:
|
445
|
+
self._recving_thread = True # Avoid race condition.
|
396
446
|
self._recving_thread = self.service.threaded(
|
397
447
|
self._recving,
|
398
448
|
thread_name=f"recver-{self.service.location()}",
|
@@ -454,6 +504,7 @@ class GrblController:
|
|
454
504
|
if line is not None:
|
455
505
|
self._send(line)
|
456
506
|
if "\x18" in line:
|
507
|
+
self._paused = False
|
457
508
|
with self._forward_lock:
|
458
509
|
self._forward_buffer.clear()
|
459
510
|
|
@@ -476,9 +527,7 @@ class GrblController:
|
|
476
527
|
@return:
|
477
528
|
"""
|
478
529
|
with self._loop_cond:
|
479
|
-
self.service.signal("pipe;running", False)
|
480
530
|
self._loop_cond.wait()
|
481
|
-
self.service.signal("pipe;running", True)
|
482
531
|
|
483
532
|
def _send_resume(self):
|
484
533
|
"""
|
@@ -497,21 +546,24 @@ class GrblController:
|
|
497
546
|
@return:
|
498
547
|
|
499
548
|
"""
|
500
|
-
self.service.signal("pipe;running", True)
|
501
549
|
while self.connection.connected:
|
502
550
|
if self._realtime_queue:
|
503
551
|
# Send realtime data.
|
504
552
|
self._sending_realtime()
|
505
553
|
continue
|
506
|
-
if self._paused or not self.
|
507
|
-
# We are paused. We do not send anything other than realtime commands.
|
554
|
+
if self._paused or not self.fully_validated():
|
555
|
+
# We are paused or invalid. We do not send anything other than realtime commands.
|
508
556
|
time.sleep(0.05)
|
509
557
|
continue
|
510
558
|
if not self._sending_queue:
|
511
559
|
# There is nothing to write/realtime
|
560
|
+
self.service.laser_status = "idle"
|
512
561
|
self._send_halt()
|
513
562
|
continue
|
514
563
|
buffer = len(self._forward_buffer)
|
564
|
+
if buffer:
|
565
|
+
self.service.laser_status = "active"
|
566
|
+
|
515
567
|
if self.service.buffer_mode == "sync":
|
516
568
|
if buffer:
|
517
569
|
# Any buffer is too much buffer. Halt.
|
@@ -525,7 +577,7 @@ class GrblController:
|
|
525
577
|
continue
|
526
578
|
# Go for send_line
|
527
579
|
self._sending_single_line()
|
528
|
-
self.service.
|
580
|
+
self.service.laser_status = "idle"
|
529
581
|
|
530
582
|
####################
|
531
583
|
# GRBL RECV ROUTINES
|
@@ -616,6 +668,9 @@ class GrblController:
|
|
616
668
|
self._process_feedback_message(response)
|
617
669
|
continue
|
618
670
|
elif response.startswith("$"):
|
671
|
+
if self._validation_stage == 2:
|
672
|
+
self.log("Stage 3: $$ was successfully parsed.", type="event")
|
673
|
+
self._validation_stage = 3
|
619
674
|
self._process_settings_message(response)
|
620
675
|
continue
|
621
676
|
elif response.startswith("ALARM"):
|
@@ -631,11 +686,15 @@ class GrblController:
|
|
631
686
|
elif response.startswith(">"):
|
632
687
|
self.log(f"STARTUP: {response}", type="event")
|
633
688
|
elif response.startswith(self.welcome):
|
634
|
-
self.log("
|
635
|
-
self.
|
689
|
+
self.log("Device Reset, revalidation required", type="event")
|
690
|
+
if self.fully_validated():
|
691
|
+
self._validation_stage = 1
|
692
|
+
self.realtime("$\r\n")
|
636
693
|
else:
|
637
694
|
self._assembled_response.append(response)
|
638
|
-
|
695
|
+
|
696
|
+
def fully_validated(self):
|
697
|
+
return self._validation_stage == 5
|
639
698
|
|
640
699
|
def _process_status_message(self, response):
|
641
700
|
message = response[1:-1]
|
@@ -655,6 +714,39 @@ class GrblController:
|
|
655
714
|
f, s = info.split(",")
|
656
715
|
self.service.signal("grbl:speed", float(f))
|
657
716
|
self.service.signal("grbl:power", float(s))
|
717
|
+
elif name == "MPos":
|
718
|
+
coords = info.split(",")
|
719
|
+
try:
|
720
|
+
nx = float(coords[0])
|
721
|
+
ny = float(coords[1])
|
722
|
+
|
723
|
+
if not self.fully_validated():
|
724
|
+
# During validation, we declare positions.
|
725
|
+
self.driver.declare_position(nx, ny)
|
726
|
+
ox = self.driver.mpos_x
|
727
|
+
oy = self.driver.mpos_y
|
728
|
+
|
729
|
+
x, y = self.service.view_mm.position(f"{nx}mm", f"{ny}mm")
|
730
|
+
|
731
|
+
(
|
732
|
+
self.driver.mpos_x,
|
733
|
+
self.driver.mpos_y,
|
734
|
+
) = self.service.view_mm.scene_position(f"{x}mm", f"{y}mm")
|
735
|
+
|
736
|
+
if len(coords) >= 3:
|
737
|
+
self.driver.mpos_z = float(coords[2])
|
738
|
+
self.service.signal(
|
739
|
+
"status;position",
|
740
|
+
(ox, oy, self.driver.mpos_x, self.driver.mpos_y),
|
741
|
+
)
|
742
|
+
except ValueError:
|
743
|
+
pass
|
744
|
+
elif name == "WPos":
|
745
|
+
coords = info.split(",")
|
746
|
+
self.driver.wpos_x = coords[0]
|
747
|
+
self.driver.wpos_y = coords[1]
|
748
|
+
if len(coords) >= 3:
|
749
|
+
self.driver.wpos_z = coords[2]
|
658
750
|
# See: https://github.com/grbl/grbl/blob/master/grbl/report.c#L421
|
659
751
|
# MPos: Coord values. Machine Position.
|
660
752
|
# WPos: MPos but with applied work coordinates. Work Position.
|
@@ -664,6 +756,9 @@ class GrblController:
|
|
664
756
|
# Lim: limits states
|
665
757
|
# Ctl: control pins and mask (binary).
|
666
758
|
self.service.signal(f"grbl:status:{name}", info)
|
759
|
+
if self._validation_stage in (2, 3, 4):
|
760
|
+
self.log("Connection Confirmed.", type="event")
|
761
|
+
self._validation_stage = 5
|
667
762
|
|
668
763
|
def _process_feedback_message(self, response):
|
669
764
|
if response.startswith("[MSG:"):
|
@@ -671,11 +766,29 @@ class GrblController:
|
|
671
766
|
self.log(message, type="event")
|
672
767
|
self.service.channel("console")(message)
|
673
768
|
elif response.startswith("[GC:"):
|
769
|
+
# Parsing $G
|
674
770
|
message = response[4:-1]
|
771
|
+
states = list(message.split(" "))
|
772
|
+
if not self.fully_validated():
|
773
|
+
self.log("Stage 4: $G was successfully parsed.", type="event")
|
774
|
+
self.driver.declare_modals(states)
|
775
|
+
self._validation_stage = 4
|
776
|
+
self.realtime("?\r\n")
|
675
777
|
self.log(message, type="event")
|
676
|
-
self.service.signal("grbl:states",
|
778
|
+
self.service.signal("grbl:states", states)
|
677
779
|
elif response.startswith("[HLP:"):
|
780
|
+
# Parsing $
|
678
781
|
message = response[5:-1]
|
782
|
+
if self._validation_stage == 1:
|
783
|
+
self.log("Stage 2: $ was successfully parsed.", type="event")
|
784
|
+
self._validation_stage = 2
|
785
|
+
if "$$" in message:
|
786
|
+
self.realtime("$$\r\n")
|
787
|
+
if "$G" in message:
|
788
|
+
self.realtime("$G\r\n")
|
789
|
+
elif "?" in message:
|
790
|
+
# No $G just request status.
|
791
|
+
self.realtime("?\r\n")
|
679
792
|
self.log(message, type="event")
|
680
793
|
elif response.startswith("[G54:"):
|
681
794
|
message = response[5:-1]
|
@@ -782,6 +895,9 @@ class GrblController:
|
|
782
895
|
match = SETTINGS_MESSAGE.match(response)
|
783
896
|
if match:
|
784
897
|
try:
|
785
|
-
|
898
|
+
key = int(match.group(1))
|
899
|
+
value = float(match.group(2))
|
900
|
+
self.service.hardware_config[key] = value
|
901
|
+
self.service.signal(f"grbl:hwsettings", key, value)
|
786
902
|
except ValueError:
|
787
903
|
pass
|
meerk40t/grbl/device.py
CHANGED
@@ -10,22 +10,25 @@ from meerk40t.kernel import CommandSyntaxError, Service
|
|
10
10
|
|
11
11
|
from ..core.laserjob import LaserJob
|
12
12
|
from ..core.spoolers import Spooler
|
13
|
-
from ..core.units import
|
13
|
+
from ..core.units import MM_PER_INCH, Length
|
14
14
|
from ..core.view import View
|
15
|
+
from ..device.mixins import Status
|
15
16
|
from .controller import GrblController
|
16
17
|
from .driver import GRBLDriver
|
17
18
|
|
18
19
|
|
19
|
-
class GRBLDevice(Service):
|
20
|
+
class GRBLDevice(Service, Status):
|
20
21
|
"""
|
21
22
|
GRBLDevice is driver for the Gcode Controllers
|
22
23
|
"""
|
23
24
|
|
24
25
|
def __init__(self, kernel, path, *args, choices=None, **kwargs):
|
26
|
+
self.hardware_config = {}
|
25
27
|
self.permit_tcp = True
|
26
28
|
self.permit_serial = True
|
27
29
|
|
28
30
|
Service.__init__(self, kernel, path)
|
31
|
+
Status.__init__(self)
|
29
32
|
self.name = "GRBLDevice"
|
30
33
|
self.extension = "gcode"
|
31
34
|
if choices is not None:
|
@@ -232,6 +235,12 @@ class GRBLDevice(Service):
|
|
232
235
|
dpi_x=1000.0,
|
233
236
|
dpi_y=1000.0,
|
234
237
|
)
|
238
|
+
self.view_mm = View(
|
239
|
+
self.bedwidth,
|
240
|
+
self.bedheight,
|
241
|
+
dpi_x=MM_PER_INCH,
|
242
|
+
dpi_y=MM_PER_INCH,
|
243
|
+
)
|
235
244
|
self.realize()
|
236
245
|
self.settings = dict()
|
237
246
|
self.state = 0
|
@@ -451,17 +460,6 @@ class GRBLDevice(Service):
|
|
451
460
|
"conditional": (self, "use_red_dot"),
|
452
461
|
"section": "_10_Red Dot",
|
453
462
|
},
|
454
|
-
{
|
455
|
-
"attr": "requires_validation",
|
456
|
-
"object": self,
|
457
|
-
"default": True,
|
458
|
-
"type": bool,
|
459
|
-
"label": _("Require validation for device"),
|
460
|
-
"tip": _(
|
461
|
-
"Ensure device is completely initialized before sending data. This is usually known to be valid at the 'Grbl xx.x' version message."
|
462
|
-
),
|
463
|
-
"section": "_40_Validation",
|
464
|
-
},
|
465
463
|
{
|
466
464
|
"attr": "welcome",
|
467
465
|
"object": self,
|
@@ -471,7 +469,6 @@ class GRBLDevice(Service):
|
|
471
469
|
"tip": _(
|
472
470
|
"If for some reason the device needs a different welcome validator than 'Grbl' (default), for example, somewhat custom grbl-like firmware"
|
473
471
|
),
|
474
|
-
"conditional": (self, "requires_validation"),
|
475
472
|
"section": "_40_Validation",
|
476
473
|
},
|
477
474
|
]
|
@@ -523,7 +520,7 @@ class GRBLDevice(Service):
|
|
523
520
|
)
|
524
521
|
def soft_reset(command, channel, _, data=None, remainder=None, **kwgs):
|
525
522
|
self.driver.reset()
|
526
|
-
self.
|
523
|
+
self.laser_status = "idle"
|
527
524
|
|
528
525
|
@self.console_command(
|
529
526
|
"estop",
|
@@ -532,8 +529,7 @@ class GRBLDevice(Service):
|
|
532
529
|
)
|
533
530
|
def estop(command, channel, _, data=None, remainder=None, **kwgs):
|
534
531
|
self.driver.reset()
|
535
|
-
self.
|
536
|
-
self.signal("pause")
|
532
|
+
self.laser_status = "idle"
|
537
533
|
|
538
534
|
@self.console_command(
|
539
535
|
"clear_alarm",
|
@@ -542,7 +538,7 @@ class GRBLDevice(Service):
|
|
542
538
|
)
|
543
539
|
def clear_alarm(command, channel, _, data=None, remainder=None, **kwgs):
|
544
540
|
self.driver.clear_alarm()
|
545
|
-
self.
|
541
|
+
self.laser_status = "idle"
|
546
542
|
|
547
543
|
@self.console_command(
|
548
544
|
"pause",
|
@@ -755,6 +751,15 @@ class GRBLDevice(Service):
|
|
755
751
|
flip_y=self.flip_y,
|
756
752
|
swap_xy=self.swap_xy,
|
757
753
|
)
|
754
|
+
self.view_mm.set_dims(self.bedwidth, self.bedheight)
|
755
|
+
self.view_mm.transform(
|
756
|
+
user_scale_x=self.scale_x,
|
757
|
+
user_scale_y=self.scale_y,
|
758
|
+
flip_x=self.flip_x,
|
759
|
+
flip_y=self.flip_y,
|
760
|
+
swap_xy=self.swap_xy,
|
761
|
+
)
|
762
|
+
|
758
763
|
# rotary_active=self.rotary_active,
|
759
764
|
# rotary_scale_x=self.rotary_scale_x,
|
760
765
|
# rotary_scale_y=self.rotary_scale_y,
|
meerk40t/grbl/driver.py
CHANGED
@@ -34,6 +34,15 @@ class GRBLDriver(Parameters):
|
|
34
34
|
self.paused = False
|
35
35
|
self.native_x = 0
|
36
36
|
self.native_y = 0
|
37
|
+
|
38
|
+
self.mpos_x = 0
|
39
|
+
self.mpos_y = 0
|
40
|
+
self.mpos_z = 0
|
41
|
+
|
42
|
+
self.wpos_x = 0
|
43
|
+
self.wpos_y = 0
|
44
|
+
self.wpos_z = 0
|
45
|
+
|
37
46
|
self.stepper_step_size = UNITS_PER_MIL
|
38
47
|
|
39
48
|
self.plot_planner = PlotPlanner(
|
@@ -254,6 +263,8 @@ class GRBLDriver(Parameters):
|
|
254
263
|
self(f"M4{self.line_end}")
|
255
264
|
for q in self.queue:
|
256
265
|
while self.hold_work(0):
|
266
|
+
if self.service.kernel.is_shutdown:
|
267
|
+
return
|
257
268
|
time.sleep(0.05)
|
258
269
|
x = self.native_x
|
259
270
|
y = self.native_y
|
@@ -517,6 +528,7 @@ class GRBLDriver(Parameters):
|
|
517
528
|
"""
|
518
529
|
self.paused = True
|
519
530
|
self(f"!{self.line_end}", real=True)
|
531
|
+
self.service.signal("pause")
|
520
532
|
|
521
533
|
def resume(self, *args):
|
522
534
|
"""
|
@@ -529,6 +541,7 @@ class GRBLDriver(Parameters):
|
|
529
541
|
"""
|
530
542
|
self.paused = False
|
531
543
|
self(f"~{self.line_end}", real=True)
|
544
|
+
self.service.signal("pause")
|
532
545
|
|
533
546
|
def clear_states(self):
|
534
547
|
self.power_dirty = True
|
@@ -562,6 +575,7 @@ class GRBLDriver(Parameters):
|
|
562
575
|
self.units_dirty = True
|
563
576
|
|
564
577
|
self.paused = False
|
578
|
+
self.service.signal("pause")
|
565
579
|
|
566
580
|
def clear_alarm(self):
|
567
581
|
"""
|
@@ -571,6 +585,31 @@ class GRBLDriver(Parameters):
|
|
571
585
|
"""
|
572
586
|
self(f"$X{self.line_end}", real=True)
|
573
587
|
|
588
|
+
def declare_modals(self, modals):
|
589
|
+
self.move_mode = 0 if "G0" in modals else 1
|
590
|
+
if "G90" in modals:
|
591
|
+
self._g90_absolute()
|
592
|
+
self.absolute_dirty = False
|
593
|
+
if "G91" in modals:
|
594
|
+
self._g91_relative()
|
595
|
+
self.absolute_dirty = False
|
596
|
+
if "G94" in modals:
|
597
|
+
self._g94_feedrate()
|
598
|
+
self.feedrate_dirty = False
|
599
|
+
if "G93" in modals:
|
600
|
+
self._g93_feedrate()
|
601
|
+
self.feedrate_dirty = False
|
602
|
+
if "G20" in modals:
|
603
|
+
self._g20_units_inch()
|
604
|
+
self.units_dirty = False
|
605
|
+
if "G21" in modals:
|
606
|
+
self._g21_units_mm()
|
607
|
+
self.units_dirty = False
|
608
|
+
|
609
|
+
def declare_position(self, x, y):
|
610
|
+
self.native_x = x * self.unit_scale
|
611
|
+
self.native_y = y * self.unit_scale
|
612
|
+
|
574
613
|
####################
|
575
614
|
# PROTECTED DRIVER CODE
|
576
615
|
####################
|