meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7010__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/__init__.py +1 -1
- meerk40t/balormk/balor_params.py +167 -167
- meerk40t/balormk/clone_loader.py +457 -457
- meerk40t/balormk/controller.py +1566 -1512
- meerk40t/balormk/cylindermod.py +64 -0
- meerk40t/balormk/device.py +966 -1959
- meerk40t/balormk/driver.py +778 -591
- meerk40t/balormk/galvo_commands.py +1195 -0
- meerk40t/balormk/gui/balorconfig.py +237 -111
- meerk40t/balormk/gui/balorcontroller.py +191 -184
- meerk40t/balormk/gui/baloroperationproperties.py +116 -115
- meerk40t/balormk/gui/corscene.py +845 -0
- meerk40t/balormk/gui/gui.py +179 -147
- meerk40t/balormk/livelightjob.py +466 -382
- meerk40t/balormk/mock_connection.py +131 -109
- meerk40t/balormk/plugin.py +133 -135
- meerk40t/balormk/usb_connection.py +306 -301
- meerk40t/camera/__init__.py +1 -1
- meerk40t/camera/camera.py +514 -397
- meerk40t/camera/gui/camerapanel.py +1241 -1095
- meerk40t/camera/gui/gui.py +58 -58
- meerk40t/camera/plugin.py +441 -399
- meerk40t/ch341/__init__.py +27 -27
- meerk40t/ch341/ch341device.py +628 -628
- meerk40t/ch341/libusb.py +595 -589
- meerk40t/ch341/mock.py +171 -171
- meerk40t/ch341/windriver.py +157 -157
- meerk40t/constants.py +13 -0
- meerk40t/core/__init__.py +1 -1
- meerk40t/core/bindalias.py +550 -539
- meerk40t/core/core.py +47 -47
- meerk40t/core/cutcode/cubiccut.py +73 -73
- meerk40t/core/cutcode/cutcode.py +315 -312
- meerk40t/core/cutcode/cutgroup.py +141 -137
- meerk40t/core/cutcode/cutobject.py +192 -185
- meerk40t/core/cutcode/dwellcut.py +37 -37
- meerk40t/core/cutcode/gotocut.py +29 -29
- meerk40t/core/cutcode/homecut.py +29 -29
- meerk40t/core/cutcode/inputcut.py +34 -34
- meerk40t/core/cutcode/linecut.py +33 -33
- meerk40t/core/cutcode/outputcut.py +34 -34
- meerk40t/core/cutcode/plotcut.py +335 -335
- meerk40t/core/cutcode/quadcut.py +61 -61
- meerk40t/core/cutcode/rastercut.py +168 -148
- meerk40t/core/cutcode/waitcut.py +34 -34
- meerk40t/core/cutplan.py +1843 -1316
- meerk40t/core/drivers.py +330 -329
- meerk40t/core/elements/align.py +801 -669
- meerk40t/core/elements/branches.py +1844 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4561 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4329 -3617
- meerk40t/core/elements/files.py +117 -64
- meerk40t/core/elements/geometry.py +473 -224
- meerk40t/core/elements/grid.py +467 -316
- meerk40t/core/elements/materials.py +158 -94
- meerk40t/core/elements/notes.py +50 -38
- meerk40t/core/elements/offset_clpr.py +933 -912
- meerk40t/core/elements/offset_mk.py +963 -955
- meerk40t/core/elements/penbox.py +339 -267
- meerk40t/core/elements/placements.py +300 -83
- meerk40t/core/elements/render.py +785 -687
- meerk40t/core/elements/shapes.py +2618 -2092
- meerk40t/core/elements/trace.py +651 -563
- meerk40t/core/elements/tree_commands.py +415 -409
- meerk40t/core/elements/undo_redo.py +116 -58
- meerk40t/core/elements/wordlist.py +319 -200
- meerk40t/core/exceptions.py +9 -9
- meerk40t/core/laserjob.py +220 -220
- meerk40t/core/logging.py +63 -63
- meerk40t/core/node/blobnode.py +83 -86
- meerk40t/core/node/bootstrap.py +105 -103
- meerk40t/core/node/branch_elems.py +40 -31
- meerk40t/core/node/branch_ops.py +45 -38
- meerk40t/core/node/branch_regmark.py +48 -41
- meerk40t/core/node/cutnode.py +29 -32
- meerk40t/core/node/effect_hatch.py +375 -257
- meerk40t/core/node/effect_warp.py +398 -0
- meerk40t/core/node/effect_wobble.py +441 -309
- meerk40t/core/node/elem_ellipse.py +404 -309
- meerk40t/core/node/elem_image.py +1082 -801
- meerk40t/core/node/elem_line.py +358 -292
- meerk40t/core/node/elem_path.py +259 -201
- meerk40t/core/node/elem_point.py +129 -102
- meerk40t/core/node/elem_polyline.py +310 -246
- meerk40t/core/node/elem_rect.py +376 -286
- meerk40t/core/node/elem_text.py +445 -418
- meerk40t/core/node/filenode.py +59 -40
- meerk40t/core/node/groupnode.py +138 -74
- meerk40t/core/node/image_processed.py +777 -766
- meerk40t/core/node/image_raster.py +156 -113
- meerk40t/core/node/layernode.py +31 -31
- meerk40t/core/node/mixins.py +135 -107
- meerk40t/core/node/node.py +1427 -1304
- meerk40t/core/node/nutils.py +117 -114
- meerk40t/core/node/op_cut.py +462 -335
- meerk40t/core/node/op_dots.py +296 -251
- meerk40t/core/node/op_engrave.py +414 -311
- meerk40t/core/node/op_image.py +755 -369
- meerk40t/core/node/op_raster.py +787 -522
- meerk40t/core/node/place_current.py +37 -40
- meerk40t/core/node/place_point.py +329 -126
- meerk40t/core/node/refnode.py +58 -47
- meerk40t/core/node/rootnode.py +225 -219
- meerk40t/core/node/util_console.py +48 -48
- meerk40t/core/node/util_goto.py +84 -65
- meerk40t/core/node/util_home.py +61 -61
- meerk40t/core/node/util_input.py +102 -102
- meerk40t/core/node/util_output.py +102 -102
- meerk40t/core/node/util_wait.py +65 -65
- meerk40t/core/parameters.py +709 -707
- meerk40t/core/planner.py +875 -785
- meerk40t/core/plotplanner.py +656 -652
- meerk40t/core/space.py +120 -113
- meerk40t/core/spoolers.py +706 -705
- meerk40t/core/svg_io.py +1836 -1549
- meerk40t/core/treeop.py +534 -445
- meerk40t/core/undos.py +278 -124
- meerk40t/core/units.py +784 -680
- meerk40t/core/view.py +393 -322
- meerk40t/core/webhelp.py +62 -62
- meerk40t/core/wordlist.py +513 -504
- meerk40t/cylinder/cylinder.py +247 -0
- meerk40t/cylinder/gui/cylindersettings.py +41 -0
- meerk40t/cylinder/gui/gui.py +24 -0
- meerk40t/device/__init__.py +1 -1
- meerk40t/device/basedevice.py +322 -123
- meerk40t/device/devicechoices.py +50 -0
- meerk40t/device/dummydevice.py +163 -128
- meerk40t/device/gui/defaultactions.py +618 -602
- meerk40t/device/gui/effectspanel.py +114 -0
- meerk40t/device/gui/formatterpanel.py +253 -290
- meerk40t/device/gui/warningpanel.py +337 -260
- meerk40t/device/mixins.py +13 -13
- meerk40t/dxf/__init__.py +1 -1
- meerk40t/dxf/dxf_io.py +766 -554
- meerk40t/dxf/plugin.py +47 -35
- meerk40t/external_plugins.py +79 -79
- meerk40t/external_plugins_build.py +28 -28
- meerk40t/extra/cag.py +112 -116
- meerk40t/extra/coolant.py +403 -0
- meerk40t/extra/encode_detect.py +198 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +835 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +630 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +284 -0
- meerk40t/extra/param_functions.py +1542 -1556
- meerk40t/extra/potrace.py +257 -253
- meerk40t/extra/serial_exchange.py +118 -0
- meerk40t/extra/updater.py +602 -453
- meerk40t/extra/vectrace.py +147 -146
- meerk40t/extra/winsleep.py +83 -83
- meerk40t/extra/xcs_reader.py +597 -0
- meerk40t/fill/fills.py +781 -335
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +614 -567
- meerk40t/grbl/control.py +87 -87
- meerk40t/grbl/controller.py +990 -903
- meerk40t/grbl/device.py +1081 -768
- meerk40t/grbl/driver.py +989 -771
- meerk40t/grbl/emulator.py +532 -497
- meerk40t/grbl/gcodejob.py +783 -767
- meerk40t/grbl/gui/grblconfiguration.py +373 -298
- meerk40t/grbl/gui/grblcontroller.py +485 -271
- meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
- meerk40t/grbl/gui/grbloperationconfig.py +105 -0
- meerk40t/grbl/gui/gui.py +147 -116
- meerk40t/grbl/interpreter.py +44 -44
- meerk40t/grbl/loader.py +22 -22
- meerk40t/grbl/mock_connection.py +56 -56
- meerk40t/grbl/plugin.py +294 -264
- meerk40t/grbl/serial_connection.py +93 -88
- meerk40t/grbl/tcp_connection.py +81 -79
- meerk40t/grbl/ws_connection.py +112 -0
- meerk40t/gui/__init__.py +1 -1
- meerk40t/gui/about.py +2042 -296
- meerk40t/gui/alignment.py +1644 -1608
- meerk40t/gui/autoexec.py +199 -0
- meerk40t/gui/basicops.py +791 -670
- meerk40t/gui/bufferview.py +77 -71
- meerk40t/gui/busy.py +170 -133
- meerk40t/gui/choicepropertypanel.py +1673 -1469
- meerk40t/gui/consolepanel.py +706 -542
- meerk40t/gui/devicepanel.py +687 -581
- meerk40t/gui/dialogoptions.py +110 -107
- meerk40t/gui/executejob.py +316 -306
- meerk40t/gui/fonts.py +90 -90
- meerk40t/gui/functionwrapper.py +252 -0
- meerk40t/gui/gui_mixins.py +729 -0
- meerk40t/gui/guicolors.py +205 -182
- meerk40t/gui/help_assets/help_assets.py +218 -201
- meerk40t/gui/helper.py +154 -0
- meerk40t/gui/hersheymanager.py +1430 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +892 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2917 -0
- meerk40t/gui/materialtest.py +1722 -1694
- meerk40t/gui/mkdebug.py +646 -359
- meerk40t/gui/mwindow.py +163 -140
- meerk40t/gui/navigationpanels.py +2605 -2467
- meerk40t/gui/notes.py +143 -142
- meerk40t/gui/opassignment.py +414 -410
- meerk40t/gui/operation_info.py +310 -299
- meerk40t/gui/plugin.py +494 -328
- meerk40t/gui/position.py +714 -669
- meerk40t/gui/preferences.py +901 -650
- meerk40t/gui/propertypanels/attributes.py +1461 -1131
- meerk40t/gui/propertypanels/blobproperty.py +117 -114
- meerk40t/gui/propertypanels/consoleproperty.py +83 -80
- meerk40t/gui/propertypanels/gotoproperty.py +77 -0
- meerk40t/gui/propertypanels/groupproperties.py +223 -217
- meerk40t/gui/propertypanels/hatchproperty.py +489 -469
- meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
- meerk40t/gui/propertypanels/inputproperty.py +59 -58
- meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
- meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
- meerk40t/gui/propertypanels/outputproperty.py +59 -58
- meerk40t/gui/propertypanels/pathproperty.py +389 -380
- meerk40t/gui/propertypanels/placementproperty.py +1214 -383
- meerk40t/gui/propertypanels/pointproperty.py +140 -136
- meerk40t/gui/propertypanels/propertywindow.py +313 -181
- meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
- meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
- meerk40t/gui/propertypanels/textproperty.py +770 -755
- meerk40t/gui/propertypanels/waitproperty.py +56 -55
- meerk40t/gui/propertypanels/warpproperty.py +121 -0
- meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
- meerk40t/gui/ribbon.py +2468 -2210
- meerk40t/gui/scene/scene.py +1100 -1051
- meerk40t/gui/scene/sceneconst.py +22 -22
- meerk40t/gui/scene/scenepanel.py +439 -349
- meerk40t/gui/scene/scenespacewidget.py +365 -365
- meerk40t/gui/scene/widget.py +518 -505
- meerk40t/gui/scenewidgets/affinemover.py +215 -215
- meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
- meerk40t/gui/scenewidgets/bedwidget.py +120 -97
- meerk40t/gui/scenewidgets/elementswidget.py +137 -107
- meerk40t/gui/scenewidgets/gridwidget.py +785 -745
- meerk40t/gui/scenewidgets/guidewidget.py +765 -765
- meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
- meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
- meerk40t/gui/scenewidgets/nodeselector.py +28 -28
- meerk40t/gui/scenewidgets/rectselectwidget.py +589 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2952 -2756
- meerk40t/gui/simpleui.py +357 -333
- meerk40t/gui/simulation.py +2431 -2094
- meerk40t/gui/snapoptions.py +208 -203
- meerk40t/gui/spoolerpanel.py +1227 -1180
- meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
- meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
- meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
- meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
- meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
- meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
- meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
- meerk40t/gui/themes.py +200 -78
- meerk40t/gui/tips.py +591 -0
- meerk40t/gui/toolwidgets/circlebrush.py +35 -35
- meerk40t/gui/toolwidgets/toolcircle.py +248 -242
- meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
- meerk40t/gui/toolwidgets/tooldraw.py +97 -90
- meerk40t/gui/toolwidgets/toolellipse.py +219 -212
- meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
- meerk40t/gui/toolwidgets/toolline.py +39 -144
- meerk40t/gui/toolwidgets/toollinetext.py +79 -236
- meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
- meerk40t/gui/toolwidgets/toolmeasure.py +160 -216
- meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
- meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
- meerk40t/gui/toolwidgets/toolparameter.py +754 -668
- meerk40t/gui/toolwidgets/toolplacement.py +108 -108
- meerk40t/gui/toolwidgets/toolpoint.py +68 -59
- meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
- meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
- meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
- meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
- meerk40t/gui/toolwidgets/toolrect.py +211 -207
- meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
- meerk40t/gui/toolwidgets/toolribbon.py +598 -113
- meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
- meerk40t/gui/toolwidgets/tooltext.py +98 -89
- meerk40t/gui/toolwidgets/toolvector.py +213 -204
- meerk40t/gui/toolwidgets/toolwidget.py +39 -39
- meerk40t/gui/usbconnect.py +98 -91
- meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
- meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
- meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
- meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
- meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
- meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
- meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
- meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
- meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
- meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
- meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
- meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
- meerk40t/gui/wordlisteditor.py +985 -931
- meerk40t/gui/wxmeerk40t.py +1444 -1169
- meerk40t/gui/wxmmain.py +5578 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1635 -1453
- meerk40t/gui/wxmtree.py +2410 -2089
- meerk40t/gui/wxutils.py +1769 -1099
- meerk40t/gui/zmatrix.py +102 -102
- meerk40t/image/__init__.py +1 -1
- meerk40t/image/dither.py +429 -0
- meerk40t/image/imagetools.py +2778 -2269
- meerk40t/internal_plugins.py +150 -130
- meerk40t/kernel/__init__.py +63 -12
- meerk40t/kernel/channel.py +259 -212
- meerk40t/kernel/context.py +538 -538
- meerk40t/kernel/exceptions.py +41 -41
- meerk40t/kernel/functions.py +463 -414
- meerk40t/kernel/jobs.py +100 -100
- meerk40t/kernel/kernel.py +3809 -3571
- meerk40t/kernel/lifecycles.py +71 -71
- meerk40t/kernel/module.py +49 -49
- meerk40t/kernel/service.py +147 -147
- meerk40t/kernel/settings.py +383 -343
- meerk40t/lihuiyu/controller.py +883 -876
- meerk40t/lihuiyu/device.py +1181 -1069
- meerk40t/lihuiyu/driver.py +1466 -1372
- meerk40t/lihuiyu/gui/gui.py +127 -106
- meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
- meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
- meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
- meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
- meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
- meerk40t/lihuiyu/interpreter.py +53 -53
- meerk40t/lihuiyu/laserspeed.py +450 -450
- meerk40t/lihuiyu/loader.py +90 -90
- meerk40t/lihuiyu/parser.py +404 -404
- meerk40t/lihuiyu/plugin.py +101 -102
- meerk40t/lihuiyu/tcp_connection.py +111 -109
- meerk40t/main.py +231 -165
- meerk40t/moshi/builder.py +788 -781
- meerk40t/moshi/controller.py +505 -499
- meerk40t/moshi/device.py +495 -442
- meerk40t/moshi/driver.py +862 -696
- meerk40t/moshi/gui/gui.py +78 -76
- meerk40t/moshi/gui/moshicontrollergui.py +538 -522
- meerk40t/moshi/gui/moshidrivergui.py +87 -75
- meerk40t/moshi/plugin.py +43 -43
- meerk40t/network/console_server.py +102 -57
- meerk40t/network/kernelserver.py +10 -9
- meerk40t/network/tcp_server.py +142 -140
- meerk40t/network/udp_server.py +103 -77
- meerk40t/network/web_server.py +390 -0
- meerk40t/newly/controller.py +1158 -1144
- meerk40t/newly/device.py +874 -732
- meerk40t/newly/driver.py +540 -412
- meerk40t/newly/gui/gui.py +219 -188
- meerk40t/newly/gui/newlyconfig.py +116 -101
- meerk40t/newly/gui/newlycontroller.py +193 -186
- meerk40t/newly/gui/operationproperties.py +51 -51
- meerk40t/newly/mock_connection.py +82 -82
- meerk40t/newly/newly_params.py +56 -56
- meerk40t/newly/plugin.py +1214 -1246
- meerk40t/newly/usb_connection.py +322 -322
- meerk40t/rotary/gui/gui.py +52 -46
- meerk40t/rotary/gui/rotarysettings.py +240 -232
- meerk40t/rotary/rotary.py +202 -98
- meerk40t/ruida/control.py +291 -91
- meerk40t/ruida/controller.py +138 -1088
- meerk40t/ruida/device.py +672 -231
- meerk40t/ruida/driver.py +534 -472
- meerk40t/ruida/emulator.py +1494 -1491
- meerk40t/ruida/exceptions.py +4 -4
- meerk40t/ruida/gui/gui.py +71 -76
- meerk40t/ruida/gui/ruidaconfig.py +239 -72
- meerk40t/ruida/gui/ruidacontroller.py +187 -184
- meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
- meerk40t/ruida/loader.py +54 -52
- meerk40t/ruida/mock_connection.py +57 -109
- meerk40t/ruida/plugin.py +124 -87
- meerk40t/ruida/rdjob.py +2084 -945
- meerk40t/ruida/serial_connection.py +116 -0
- meerk40t/ruida/tcp_connection.py +146 -0
- meerk40t/ruida/udp_connection.py +73 -0
- meerk40t/svgelements.py +9671 -9669
- meerk40t/tools/driver_to_path.py +584 -579
- meerk40t/tools/geomstr.py +5583 -4680
- meerk40t/tools/jhfparser.py +357 -292
- meerk40t/tools/kerftest.py +904 -890
- meerk40t/tools/livinghinges.py +1168 -1033
- meerk40t/tools/pathtools.py +987 -949
- meerk40t/tools/pmatrix.py +234 -0
- meerk40t/tools/pointfinder.py +942 -942
- meerk40t/tools/polybool.py +940 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +989 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/METADATA +150 -139
- meerk40t-0.9.7010.dist-info/RECORD +445 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/zip-safe +1 -1
- meerk40t/balormk/elementlightjob.py +0 -159
- meerk40t-0.9.3001.dist-info/RECORD +0 -437
- test/bootstrap.py +0 -63
- test/test_cli.py +0 -12
- test/test_core_cutcode.py +0 -418
- test/test_core_elements.py +0 -144
- test/test_core_plotplanner.py +0 -397
- test/test_core_viewports.py +0 -312
- test/test_drivers_grbl.py +0 -108
- test/test_drivers_lihuiyu.py +0 -443
- test/test_drivers_newly.py +0 -113
- test/test_element_degenerate_points.py +0 -43
- test/test_elements_classify.py +0 -97
- test/test_elements_penbox.py +0 -22
- test/test_file_svg.py +0 -176
- test/test_fill.py +0 -155
- test/test_geomstr.py +0 -1523
- test/test_geomstr_nodes.py +0 -18
- test/test_imagetools_actualize.py +0 -306
- test/test_imagetools_wizard.py +0 -258
- test/test_kernel.py +0 -200
- test/test_laser_speeds.py +0 -3303
- test/test_length.py +0 -57
- test/test_lifecycle.py +0 -66
- test/test_operations.py +0 -251
- test/test_operations_hatch.py +0 -57
- test/test_ruida.py +0 -19
- test/test_spooler.py +0 -22
- test/test_tools_rasterplotter.py +0 -29
- test/test_wobble.py +0 -133
- test/test_zingl.py +0 -124
- {test → meerk40t/cylinder}/__init__.py +0 -0
- /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7010.dist-info}/entry_points.txt +0 -0
meerk40t/lihuiyu/device.py
CHANGED
@@ -1,1069 +1,1181 @@
|
|
1
|
-
"""
|
2
|
-
Lihuiyu Device
|
3
|
-
|
4
|
-
Registers the Device service for M2 Nano (and family), registering the relevant commands and provides the viewport for
|
5
|
-
the given device type.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from hashlib import md5
|
9
|
-
|
10
|
-
from meerk40t.core.laserjob import LaserJob
|
11
|
-
from meerk40t.core.spoolers import Spooler
|
12
|
-
from meerk40t.core.view import View
|
13
|
-
from meerk40t.kernel import CommandSyntaxError, Service, signal_listener
|
14
|
-
|
15
|
-
from ..core.units import UNITS_PER_MIL, Length
|
16
|
-
from ..device.mixins import Status
|
17
|
-
from .controller import LihuiyuController
|
18
|
-
from .driver import LihuiyuDriver
|
19
|
-
from .tcp_connection import TCPOutput
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
self
|
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
|
-
"attr": "
|
66
|
-
"object": self,
|
67
|
-
"default":
|
68
|
-
"type":
|
69
|
-
"label": _("
|
70
|
-
"tip": _(
|
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
|
-
"attr": "
|
133
|
-
"object": self,
|
134
|
-
"default":
|
135
|
-
"type":
|
136
|
-
"label": _("
|
137
|
-
"tip": _("
|
138
|
-
"section": "
|
139
|
-
"
|
140
|
-
"signals": "
|
141
|
-
},
|
142
|
-
{
|
143
|
-
"attr": "
|
144
|
-
"object": self,
|
145
|
-
"default":
|
146
|
-
"type":
|
147
|
-
"label": _("
|
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
|
-
"section": "_10_" + _("Configuration"),
|
174
|
-
"subsection": "
|
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
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
"
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
"
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
"
|
287
|
-
"
|
288
|
-
|
289
|
-
|
290
|
-
"
|
291
|
-
"
|
292
|
-
"
|
293
|
-
|
294
|
-
|
295
|
-
"
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
"
|
314
|
-
|
315
|
-
|
316
|
-
"
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
"
|
325
|
-
|
326
|
-
|
327
|
-
"
|
328
|
-
"
|
329
|
-
"
|
330
|
-
|
331
|
-
|
332
|
-
"
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
"
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
"
|
344
|
-
"
|
345
|
-
"
|
346
|
-
"
|
347
|
-
"
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
"section": "_00_" + _("
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
"
|
359
|
-
"
|
360
|
-
"
|
361
|
-
"
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
),
|
366
|
-
"
|
367
|
-
},
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
"
|
374
|
-
"
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
"
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
"
|
389
|
-
|
390
|
-
|
391
|
-
"
|
392
|
-
"
|
393
|
-
"
|
394
|
-
"
|
395
|
-
|
396
|
-
|
397
|
-
"
|
398
|
-
"
|
399
|
-
|
400
|
-
|
401
|
-
"
|
402
|
-
"
|
403
|
-
"
|
404
|
-
"
|
405
|
-
"
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
"
|
411
|
-
"
|
412
|
-
"
|
413
|
-
"
|
414
|
-
"
|
415
|
-
"tip": _(
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
"
|
426
|
-
"
|
427
|
-
"
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
self.
|
474
|
-
|
475
|
-
|
476
|
-
self.setting(bool, "
|
477
|
-
|
478
|
-
|
479
|
-
self.setting(
|
480
|
-
|
481
|
-
|
482
|
-
self.setting(
|
483
|
-
|
484
|
-
|
485
|
-
self.setting(
|
486
|
-
|
487
|
-
|
488
|
-
self.
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
self.
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
)
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
)
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
@self.
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
@self.
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
if
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
"
|
707
|
-
|
708
|
-
)
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
@self.
|
723
|
-
"
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
self.
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
@self.console_argument(
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
)
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
f
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
except (PermissionError, OSError):
|
835
|
-
channel(_("Could not
|
836
|
-
|
837
|
-
@self.
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
)
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
channel(_("Usb Connection
|
913
|
-
|
914
|
-
@self.console_command("
|
915
|
-
def
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
@self.
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
)
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
@self.console_command("
|
943
|
-
def
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
""
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
self.
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
@
|
1042
|
-
def
|
1043
|
-
|
1044
|
-
|
1045
|
-
@
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
@
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
@
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1
|
+
"""
|
2
|
+
Lihuiyu Device
|
3
|
+
|
4
|
+
Registers the Device service for M2 Nano (and family), registering the relevant commands and provides the viewport for
|
5
|
+
the given device type.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from hashlib import md5
|
9
|
+
import meerk40t.constants as mkconst
|
10
|
+
from meerk40t.core.laserjob import LaserJob
|
11
|
+
from meerk40t.core.spoolers import Spooler
|
12
|
+
from meerk40t.core.view import View
|
13
|
+
from meerk40t.kernel import CommandSyntaxError, Service, signal_listener
|
14
|
+
|
15
|
+
from ..core.units import UNITS_PER_MIL, Length
|
16
|
+
from ..device.mixins import Status
|
17
|
+
from .controller import LihuiyuController
|
18
|
+
from .driver import LihuiyuDriver
|
19
|
+
from .tcp_connection import TCPOutput
|
20
|
+
from meerk40t.device.devicechoices import get_effect_choices
|
21
|
+
|
22
|
+
|
23
|
+
class LihuiyuDevice(Service, Status):
|
24
|
+
"""
|
25
|
+
LihuiyuDevice is driver for the M2 Nano and other classes of Lihuiyu boards.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(self, kernel, path, *args, choices=None, **kwargs):
|
29
|
+
Service.__init__(self, kernel, path)
|
30
|
+
Status.__init__(self)
|
31
|
+
self.name = "LihuiyuDevice"
|
32
|
+
_ = kernel.translation
|
33
|
+
self.extension = "egv"
|
34
|
+
if choices is not None:
|
35
|
+
for c in choices:
|
36
|
+
attr = c.get("attr")
|
37
|
+
default = c.get("default")
|
38
|
+
if attr is not None and default is not None:
|
39
|
+
setattr(self, attr, default)
|
40
|
+
choices = [
|
41
|
+
{
|
42
|
+
"attr": "bedwidth",
|
43
|
+
"object": self,
|
44
|
+
"default": "310mm",
|
45
|
+
"type": Length,
|
46
|
+
"label": _("Width"),
|
47
|
+
"tip": _("Width of the laser bed."),
|
48
|
+
"section": "_30_" + _("Laser Parameters"),
|
49
|
+
"nonzero": True,
|
50
|
+
# _("Bed Dimensions")
|
51
|
+
"subsection": "_10_Dimensions",
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"attr": "bedheight",
|
55
|
+
"object": self,
|
56
|
+
"default": "210mm",
|
57
|
+
"type": Length,
|
58
|
+
"label": _("Height"),
|
59
|
+
"tip": _("Height of the laser bed."),
|
60
|
+
"section": "_30_" + _("Laser Parameters"),
|
61
|
+
"nonzero": True,
|
62
|
+
"subsection": "_10_Dimensions",
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"attr": "laserspot",
|
66
|
+
"object": self,
|
67
|
+
"default": "0.3mm",
|
68
|
+
"type": Length,
|
69
|
+
"label": _("Laserspot"),
|
70
|
+
"tip": _("Laser spot size"),
|
71
|
+
"section": "_30_" + _("Laser Parameters"),
|
72
|
+
"subsection": "_10_Dimensions",
|
73
|
+
"nonzero": True,
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"attr": "user_scale_x",
|
77
|
+
"object": self,
|
78
|
+
"default": 1.000,
|
79
|
+
"type": float,
|
80
|
+
"label": _("X Scale Factor"),
|
81
|
+
"tip": _(
|
82
|
+
"Scale factor for the X-axis. Board units to actual physical units."
|
83
|
+
),
|
84
|
+
"section": "_30_" + _("Laser Parameters"),
|
85
|
+
# _("User Scale Factor")
|
86
|
+
"subsection": "_20_User Scale Factor",
|
87
|
+
"nonzero": True,
|
88
|
+
},
|
89
|
+
{
|
90
|
+
"attr": "user_scale_y",
|
91
|
+
"object": self,
|
92
|
+
"default": 1.000,
|
93
|
+
"type": float,
|
94
|
+
"label": _("Y Scale Factor"),
|
95
|
+
"tip": _(
|
96
|
+
"Scale factor for the Y-axis. Board units to actual physical units."
|
97
|
+
),
|
98
|
+
"section": "_30_" + _("Laser Parameters"),
|
99
|
+
"subsection": "_20_User Scale Factor",
|
100
|
+
"nonzero": True,
|
101
|
+
},
|
102
|
+
{
|
103
|
+
"attr": "user_margin_x",
|
104
|
+
"object": self,
|
105
|
+
"default": "0",
|
106
|
+
"type": str,
|
107
|
+
"label": _("X-Margin"),
|
108
|
+
"tip": _(
|
109
|
+
"Margin for the X-axis. This will be a kind of unused space at the left side."
|
110
|
+
),
|
111
|
+
"section": "_30_" + _("Laser Parameters"),
|
112
|
+
# _("User Offset")
|
113
|
+
"subsection": "_30_User Offset",
|
114
|
+
},
|
115
|
+
{
|
116
|
+
"attr": "user_margin_y",
|
117
|
+
"object": self,
|
118
|
+
"default": "0",
|
119
|
+
"type": str,
|
120
|
+
"label": _("Y-Margin"),
|
121
|
+
"tip": _(
|
122
|
+
"Margin for the Y-axis. This will be a kind of unused space at the top."
|
123
|
+
),
|
124
|
+
"section": "_30_" + _("Laser Parameters"),
|
125
|
+
"subsection": "_30_User Offset",
|
126
|
+
},
|
127
|
+
]
|
128
|
+
self.register_choices("bed_dim", choices)
|
129
|
+
|
130
|
+
choices = [
|
131
|
+
{
|
132
|
+
"attr": "label",
|
133
|
+
"object": self,
|
134
|
+
"default": "lihuiyu-device",
|
135
|
+
"type": str,
|
136
|
+
"label": _("Device Name"),
|
137
|
+
"tip": _("The internal label to be used for this device"),
|
138
|
+
"section": "_00_" + _("General"),
|
139
|
+
"priority": "10",
|
140
|
+
"signals": "device;renamed",
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"attr": "board",
|
144
|
+
"object": self,
|
145
|
+
"default": "M2",
|
146
|
+
"type": str,
|
147
|
+
"label": _("Board"),
|
148
|
+
"style": "combosmall",
|
149
|
+
"choices": ["M2", "M3", "B2", "M", "M1", "A", "B", "B1"],
|
150
|
+
"tip": _(
|
151
|
+
"Select the board to use. This affects the speedcodes used."
|
152
|
+
),
|
153
|
+
"section": "_10_" + _("Configuration"),
|
154
|
+
"subsection": _("Board Setup"),
|
155
|
+
},
|
156
|
+
{
|
157
|
+
"attr": "flip_x",
|
158
|
+
"object": self,
|
159
|
+
"default": False,
|
160
|
+
"type": bool,
|
161
|
+
"label": _("Flip X"),
|
162
|
+
"tip": _("Flip the X axis for the device"),
|
163
|
+
"section": "_10_" + _("Configuration"),
|
164
|
+
"subsection": "_10_Axis corrections",
|
165
|
+
},
|
166
|
+
{
|
167
|
+
"attr": "flip_y",
|
168
|
+
"object": self,
|
169
|
+
"default": False,
|
170
|
+
"type": bool,
|
171
|
+
"label": _("Flip Y"),
|
172
|
+
"tip": _("Flip the Y axis for the device"),
|
173
|
+
"section": "_10_" + _("Configuration"),
|
174
|
+
"subsection": "_10_Axis corrections",
|
175
|
+
},
|
176
|
+
{
|
177
|
+
"attr": "swap_xy",
|
178
|
+
"object": self,
|
179
|
+
"default": False,
|
180
|
+
"type": bool,
|
181
|
+
"label": _("Swap X and Y"),
|
182
|
+
"tip": _(
|
183
|
+
"Swaps the X and Y axis. This happens before the FlipX and FlipY."
|
184
|
+
),
|
185
|
+
"section": "_10_" + _("Configuration"),
|
186
|
+
"subsection": "_10_" + _("Axis corrections"),
|
187
|
+
},
|
188
|
+
{
|
189
|
+
"attr": "home_corner",
|
190
|
+
"object": self,
|
191
|
+
"default": "auto",
|
192
|
+
"type": str,
|
193
|
+
"style": "combo",
|
194
|
+
"choices": [
|
195
|
+
"auto",
|
196
|
+
"top-left",
|
197
|
+
"top-right",
|
198
|
+
"bottom-left",
|
199
|
+
"bottom-right",
|
200
|
+
"center",
|
201
|
+
],
|
202
|
+
"label": _("Force Declared Home"),
|
203
|
+
"tip": _("Override native home location"),
|
204
|
+
"section": "_10_" + _("Configuration"),
|
205
|
+
"subsection": "_50_" + _("Home position"),
|
206
|
+
},
|
207
|
+
{
|
208
|
+
"attr": "signal_updates",
|
209
|
+
"object": self,
|
210
|
+
"default": True,
|
211
|
+
"type": bool,
|
212
|
+
"label": _("Device Position"),
|
213
|
+
"tip": _(
|
214
|
+
"Do you want to see some indicator about the current device position?"
|
215
|
+
),
|
216
|
+
"section": "_95_" + _("Screen updates"),
|
217
|
+
"signals": "restart",
|
218
|
+
},
|
219
|
+
]
|
220
|
+
self.register_choices("bed_orientation", choices)
|
221
|
+
choices = [
|
222
|
+
{
|
223
|
+
"attr": "device_coolant",
|
224
|
+
"object": self,
|
225
|
+
"default": "",
|
226
|
+
"type": str,
|
227
|
+
"style": "option",
|
228
|
+
"label": _("Coolant"),
|
229
|
+
"tip": _(
|
230
|
+
"Does this device has a method to turn on / off a coolant associated to it?"
|
231
|
+
),
|
232
|
+
"section": "_99_" + _("Coolant Support"),
|
233
|
+
"dynamic": self.cool_helper,
|
234
|
+
"signals": "coolant_changed",
|
235
|
+
},
|
236
|
+
]
|
237
|
+
self.register_choices("coolant", choices)
|
238
|
+
|
239
|
+
choices = [
|
240
|
+
{
|
241
|
+
"attr": "autolock",
|
242
|
+
"object": self,
|
243
|
+
"default": True,
|
244
|
+
"type": bool,
|
245
|
+
"label": _("Automatically lock rail"),
|
246
|
+
"tip": _("Lock rail after operations are finished."),
|
247
|
+
"section": "_00_" + _("General Options"),
|
248
|
+
},
|
249
|
+
{
|
250
|
+
"attr": "plot_phase_type",
|
251
|
+
"object": self,
|
252
|
+
"default": 0,
|
253
|
+
"type": int,
|
254
|
+
"label": _("Phase Type"),
|
255
|
+
"style": "option",
|
256
|
+
"display": [
|
257
|
+
_("Sequential"),
|
258
|
+
_("Random"),
|
259
|
+
_("Progressive"),
|
260
|
+
_("Static"),
|
261
|
+
],
|
262
|
+
"choices": (0, 1, 2, 3),
|
263
|
+
"tip": "\n".join(
|
264
|
+
[
|
265
|
+
_(
|
266
|
+
"The PPI carry-forward algorithm is ambiguous when it comes to shifting from one location, typically it just maintained the count. However, in some rare cases this may artifact if the PPI is low enough to see individual dots. This feature allows very fine-grained control."
|
267
|
+
),
|
268
|
+
"",
|
269
|
+
_("Sequential: maintain phase between cuts"),
|
270
|
+
_("Random: set the phase to a random value between cuts"),
|
271
|
+
_("Progressive: linearly progress the phase between cuts"),
|
272
|
+
_(
|
273
|
+
"Static: always set the phase to the exact value between cuts"
|
274
|
+
),
|
275
|
+
]
|
276
|
+
),
|
277
|
+
"section": "_01_" + _("Plot Planner"),
|
278
|
+
},
|
279
|
+
{
|
280
|
+
"attr": "plot_phase_value",
|
281
|
+
"object": self,
|
282
|
+
"default": 0,
|
283
|
+
"type": int,
|
284
|
+
"label": _("Phase Value"),
|
285
|
+
"tip": _("Value for progressive or static phase type"),
|
286
|
+
"section": "_01_" + _("Plot Planner"),
|
287
|
+
"trailer": _("/1000"),
|
288
|
+
},
|
289
|
+
{
|
290
|
+
"attr": "plot_shift",
|
291
|
+
"object": self,
|
292
|
+
"default": False,
|
293
|
+
"type": bool,
|
294
|
+
"label": _("Pulse Grouping"),
|
295
|
+
"tip": "\n".join(
|
296
|
+
[
|
297
|
+
_(
|
298
|
+
"Pulse Grouping is an alternative means of reducing the incidence of stuttering, allowing you potentially to burn at higher speeds."
|
299
|
+
),
|
300
|
+
"",
|
301
|
+
_(
|
302
|
+
"It works by swapping adjacent on or off bits to group on and off together and reduce the number of switches."
|
303
|
+
),
|
304
|
+
"",
|
305
|
+
_(
|
306
|
+
'As an example, instead of X_X_ it will burn XX__ - because the laser beam is overlapping, and because a bit is only moved at most 1/1000", the difference should not be visible even under magnification.'
|
307
|
+
),
|
308
|
+
_(
|
309
|
+
"Whilst the Pulse Grouping option in Operations are set for that operation before the job is spooled, and cannot be changed on the fly, this global Pulse Grouping option is checked as instructions are sent to the laser and can turned on and off during the burn process. Because the changes are believed to be small enough to be undetectable, you may wish to leave this permanently checked."
|
310
|
+
),
|
311
|
+
]
|
312
|
+
),
|
313
|
+
"section": "_01_" + _("Plot Planner"),
|
314
|
+
},
|
315
|
+
{
|
316
|
+
"attr": "strict",
|
317
|
+
"object": self,
|
318
|
+
"default": False,
|
319
|
+
"type": bool,
|
320
|
+
"label": _("Strict"),
|
321
|
+
"tip": _(
|
322
|
+
"Forces the device to enter and exit programmed speed mode from the same direction.\nThis may prevent devices like the M2-V4 and earlier from having issues. Not typically needed."
|
323
|
+
),
|
324
|
+
"section": "_00_" + _("General Options"),
|
325
|
+
},
|
326
|
+
{
|
327
|
+
"attr": "twitches",
|
328
|
+
"object": self,
|
329
|
+
"default": False,
|
330
|
+
"type": bool,
|
331
|
+
"label": _("Twitch Vectors"),
|
332
|
+
"tip": _(
|
333
|
+
"Twitching is an unnecessary move in an unneeded direction at the start and end of travel moves between vector burns. "
|
334
|
+
"It is most noticeable when you are doing a number of small burns (e.g. stitch holes in leather). "
|
335
|
+
"A twitchless mode is now default in 0.7.6+ or later which results in a noticeable faster travel time. "
|
336
|
+
"This option allows you to turn on the previous mode if you experience problems."
|
337
|
+
),
|
338
|
+
"section": "_00_" + _("General Options"),
|
339
|
+
},
|
340
|
+
{
|
341
|
+
"attr": "max_vector_speed",
|
342
|
+
"object": self,
|
343
|
+
"default": 140,
|
344
|
+
"type": float,
|
345
|
+
"label": _("Max vector speed"),
|
346
|
+
"trailer": "mm/s",
|
347
|
+
"tip": _(
|
348
|
+
"What is the highest reliable speed your laser is able to perform vector operations, i.e. engraving or cutting.\n"
|
349
|
+
"You can finetune this in the Warning Sections of this configuration dialog."
|
350
|
+
),
|
351
|
+
"section": "_00_" + _("General Options"),
|
352
|
+
"subsection": "_10_",
|
353
|
+
},
|
354
|
+
{
|
355
|
+
"attr": "max_raster_speed",
|
356
|
+
"object": self,
|
357
|
+
"default": 750,
|
358
|
+
"type": float,
|
359
|
+
"label": _("Max raster speed"),
|
360
|
+
"trailer": "mm/s",
|
361
|
+
"tip": _(
|
362
|
+
"What is the highest reliable speed your laser is able to perform raster or image operations.\n"
|
363
|
+
"You can finetune this in the Warning Sections of this configuration dialog."
|
364
|
+
),
|
365
|
+
"section": "_00_" + _("General Options"),
|
366
|
+
"subsection": "_10_",
|
367
|
+
},
|
368
|
+
{
|
369
|
+
"attr": "legacy_raster",
|
370
|
+
"object": self,
|
371
|
+
"default": True,
|
372
|
+
"type": bool,
|
373
|
+
"label": _("Use legacy raster method"),
|
374
|
+
"tip": (
|
375
|
+
_("Active: Use legacy method (seems to work better at higher speeds, but has some artifacts)") + "\n" +
|
376
|
+
_("Inactive: Use regular method (no artifacts but apparently more prone to stuttering at high speeds)")
|
377
|
+
),
|
378
|
+
"section": "_00_" + _("General Options"),
|
379
|
+
"subsection": "_20_",
|
380
|
+
},
|
381
|
+
]
|
382
|
+
self.register_choices("lhy-general", choices)
|
383
|
+
|
384
|
+
self.register_choices("lhy-effects", get_effect_choices(self))
|
385
|
+
|
386
|
+
choices = [
|
387
|
+
{
|
388
|
+
"attr": "opt_rapid_between",
|
389
|
+
"object": self,
|
390
|
+
"default": True,
|
391
|
+
"type": bool,
|
392
|
+
"label": _("Rapid Moves Between Objects"),
|
393
|
+
"tip": _("Perform rapid moves between the objects"),
|
394
|
+
"section": "_00_" + _("Rapid Jog"),
|
395
|
+
},
|
396
|
+
{
|
397
|
+
"attr": "opt_jog_minimum",
|
398
|
+
"object": self,
|
399
|
+
"default": 256,
|
400
|
+
"type": int,
|
401
|
+
"label": _("Minimum Jog Distance"),
|
402
|
+
"tip": _("Minimum travel distance before invoking a rapid jog move."),
|
403
|
+
"conditional": (self, "opt_rapid_between"),
|
404
|
+
"limited": True,
|
405
|
+
"section": "_00_" + _("Rapid Jog"),
|
406
|
+
},
|
407
|
+
{
|
408
|
+
"attr": "opt_jog_mode",
|
409
|
+
"object": self,
|
410
|
+
"default": 0,
|
411
|
+
"type": int,
|
412
|
+
"label": _("Jog Method"),
|
413
|
+
"style": "radio",
|
414
|
+
"choices": [_("Default"), _("Reset"), _("Finish")],
|
415
|
+
"tip": _(
|
416
|
+
"Changes the method of jogging. Default are NSE jogs. Reset are @NSE jogs. Finished are @FNSE jogs followed by a wait."
|
417
|
+
),
|
418
|
+
"section": "_00_" + _("Rapid Jog"),
|
419
|
+
},
|
420
|
+
]
|
421
|
+
self.register_choices("lhy-jog", choices)
|
422
|
+
|
423
|
+
choices = [
|
424
|
+
{
|
425
|
+
"attr": "rapid_override",
|
426
|
+
"object": self,
|
427
|
+
"default": False,
|
428
|
+
"type": bool,
|
429
|
+
"label": _("Override Rapid Movements"),
|
430
|
+
"tip": _("Perform rapid moves between the objects"),
|
431
|
+
"section": "_00_" + _("Rapid Override"),
|
432
|
+
},
|
433
|
+
{
|
434
|
+
"attr": "rapid_override_speed_x",
|
435
|
+
"object": self,
|
436
|
+
"default": 50.0,
|
437
|
+
"type": float,
|
438
|
+
"label": _("X Travel Speed:"),
|
439
|
+
"tip": _("Minimum travel distance before invoking a rapid jog move."),
|
440
|
+
"trailer": "mm/s",
|
441
|
+
"conditional": (self, "rapid_override"),
|
442
|
+
"section": "_00_" + _("Rapid Override"),
|
443
|
+
"subsection": "_10_",
|
444
|
+
},
|
445
|
+
{
|
446
|
+
"attr": "rapid_override_speed_y",
|
447
|
+
"object": self,
|
448
|
+
"default": 50.0,
|
449
|
+
"type": float,
|
450
|
+
"label": _("Y Travel Speed:"),
|
451
|
+
"tip": _("Minimum travel distance before invoking a rapid jog move."),
|
452
|
+
"trailer": "mm/s",
|
453
|
+
"conditional": (self, "rapid_override"),
|
454
|
+
"section": "_00_" + _("Rapid Override"),
|
455
|
+
"subsection": "_10_",
|
456
|
+
},
|
457
|
+
]
|
458
|
+
self.register_choices("lhy-rapid-override", choices)
|
459
|
+
|
460
|
+
choices = [
|
461
|
+
{
|
462
|
+
"attr": "fix_speeds",
|
463
|
+
"object": self,
|
464
|
+
"default": False,
|
465
|
+
"type": bool,
|
466
|
+
"label": _("Fix rated to actual speed"),
|
467
|
+
"tip": _(
|
468
|
+
"Correct for speed invalidity. Lihuiyu Studios speeds are 92% of the correctly rated speed"
|
469
|
+
),
|
470
|
+
"section": "_40_" + _("Speed"),
|
471
|
+
},
|
472
|
+
]
|
473
|
+
self.register_choices("lhy-speed", choices)
|
474
|
+
|
475
|
+
# This device prefers to display power level in ppi
|
476
|
+
self.setting(bool, "use_percent_for_power_display", False)
|
477
|
+
|
478
|
+
# Tuple contains 4 value pairs: Speed Low, Speed High, Power Low, Power High, each with enabled, value
|
479
|
+
self.setting(
|
480
|
+
list, "dangerlevel_op_cut", (False, 0, False, 0, False, 0, False, 0)
|
481
|
+
)
|
482
|
+
self.setting(
|
483
|
+
list, "dangerlevel_op_engrave", (False, 0, False, 0, False, 0, False, 0)
|
484
|
+
)
|
485
|
+
self.setting(
|
486
|
+
list, "dangerlevel_op_hatch", (False, 0, False, 0, False, 0, False, 0)
|
487
|
+
)
|
488
|
+
self.setting(
|
489
|
+
list, "dangerlevel_op_raster", (False, 0, False, 0, False, 0, False, 0)
|
490
|
+
)
|
491
|
+
self.setting(
|
492
|
+
list, "dangerlevel_op_image", (False, 0, False, 0, False, 0, False, 0)
|
493
|
+
)
|
494
|
+
self.setting(
|
495
|
+
list, "dangerlevel_op_dots", (False, 0, False, 0, False, 0, False, 0)
|
496
|
+
)
|
497
|
+
self.view = View(self.bedwidth, self.bedheight, dpi=1000.0)
|
498
|
+
self.realize()
|
499
|
+
self.setting(int, "buffer_max", 900)
|
500
|
+
self.setting(bool, "buffer_limit", True)
|
501
|
+
|
502
|
+
self.setting(bool, "fix_speeds", False)
|
503
|
+
|
504
|
+
self.setting(int, "usb_index", -1)
|
505
|
+
self.setting(int, "usb_bus", -1)
|
506
|
+
self.setting(int, "usb_address", -1)
|
507
|
+
self.setting(int, "usb_version", -1)
|
508
|
+
self.setting(bool, "mock", False)
|
509
|
+
self.setting(bool, "show_usb_log", False)
|
510
|
+
|
511
|
+
self.setting(bool, "networked", False)
|
512
|
+
self.setting(int, "packet_count", 0)
|
513
|
+
self.setting(int, "rejected_count", 0)
|
514
|
+
self.setting(str, "serial", None)
|
515
|
+
self.setting(bool, "serial_enable", False)
|
516
|
+
|
517
|
+
self.setting(int, "port", 1022)
|
518
|
+
self.setting(str, "address", "localhost")
|
519
|
+
|
520
|
+
self.driver = LihuiyuDriver(self)
|
521
|
+
self.spooler = Spooler(self, driver=self.driver)
|
522
|
+
self.add_service_delegate(self.spooler)
|
523
|
+
|
524
|
+
self.tcp = TCPOutput(self)
|
525
|
+
self.add_service_delegate(self.tcp)
|
526
|
+
|
527
|
+
self.controller = LihuiyuController(self)
|
528
|
+
self.add_service_delegate(self.controller)
|
529
|
+
|
530
|
+
self.driver.out_pipe = self.controller if not self.networked else self.tcp
|
531
|
+
|
532
|
+
self.kernel.root.coolant.claim_coolant(self, self.device_coolant)
|
533
|
+
|
534
|
+
_ = self.kernel.translation
|
535
|
+
|
536
|
+
@self.console_option(
|
537
|
+
"idonotlovemyhouse",
|
538
|
+
type=bool,
|
539
|
+
action="store_true",
|
540
|
+
help=_("override one second laser fire pulse duration"),
|
541
|
+
)
|
542
|
+
@self.console_argument("time", type=float, help=_("laser fire pulse duration"))
|
543
|
+
@self.console_command(
|
544
|
+
"pulse",
|
545
|
+
help=_("pulse <time>: Pulse the laser in place."),
|
546
|
+
)
|
547
|
+
def pulse(command, channel, _, time=None, idonotlovemyhouse=False, **kwgs):
|
548
|
+
if time is None:
|
549
|
+
channel(_("Must specify a pulse time in milliseconds."))
|
550
|
+
return
|
551
|
+
if time > 1000.0:
|
552
|
+
channel(
|
553
|
+
_(
|
554
|
+
'"{time}ms" exceeds 1 second limit to fire a standing laser.'
|
555
|
+
).format(time=time)
|
556
|
+
)
|
557
|
+
try:
|
558
|
+
if not idonotlovemyhouse:
|
559
|
+
return
|
560
|
+
except IndexError:
|
561
|
+
return
|
562
|
+
|
563
|
+
def timed_fire():
|
564
|
+
yield "wait_finish"
|
565
|
+
yield "laser_on"
|
566
|
+
yield "wait", time
|
567
|
+
yield "laser_off"
|
568
|
+
|
569
|
+
if self.spooler.is_idle:
|
570
|
+
label = _("Pulse laser for {time}ms").format(time=time)
|
571
|
+
self.spooler.laserjob(
|
572
|
+
list(timed_fire()),
|
573
|
+
label=label,
|
574
|
+
helper=True,
|
575
|
+
outline=[self.native] * 4,
|
576
|
+
)
|
577
|
+
channel(label)
|
578
|
+
else:
|
579
|
+
channel(_("Pulse laser failed: Busy"))
|
580
|
+
return
|
581
|
+
|
582
|
+
@self.console_argument("speed", type=float, help=_("Set the movement speed"))
|
583
|
+
@self.console_argument("dx", type=Length, help=_("change in x"))
|
584
|
+
@self.console_argument("dy", type=Length, help=_("change in y"))
|
585
|
+
@self.console_command(
|
586
|
+
"move_at_speed",
|
587
|
+
help=_("move_at_speed <speed> <dx> <dy>"),
|
588
|
+
all_arguments_required=True,
|
589
|
+
)
|
590
|
+
def move_speed(channel, _, speed, dx, dy, **kwgs):
|
591
|
+
def move_at_speed():
|
592
|
+
yield "set", "speed", speed
|
593
|
+
yield "program_mode"
|
594
|
+
yield "move_rel", dx.length_mil, dy.length_mil
|
595
|
+
yield "rapid_mode"
|
596
|
+
|
597
|
+
if self.spooler.is_idle:
|
598
|
+
self.spooler.laserjob(
|
599
|
+
list(move_at_speed()),
|
600
|
+
label=f"move {dx} {dy} at {speed}",
|
601
|
+
helper=True,
|
602
|
+
outline=self.outline_move_relative(dx.mil, dy.mil),
|
603
|
+
)
|
604
|
+
else:
|
605
|
+
channel(_("Busy"))
|
606
|
+
return
|
607
|
+
|
608
|
+
@self.console_option(
|
609
|
+
"difference",
|
610
|
+
"d",
|
611
|
+
type=bool,
|
612
|
+
action="store_true",
|
613
|
+
help=_("Change speed by this amount."),
|
614
|
+
)
|
615
|
+
@self.console_argument("speed", type=str, help=_("Set the driver speed."))
|
616
|
+
@self.console_command("device_speed", help=_("Set current speed of driver."))
|
617
|
+
def speed(command, channel, _, data=None, speed=None, difference=False, **kwgs):
|
618
|
+
driver = self.device.driver
|
619
|
+
|
620
|
+
if speed is None:
|
621
|
+
current_speed = driver.speed
|
622
|
+
if current_speed is None:
|
623
|
+
channel(_("Speed is unset."))
|
624
|
+
else:
|
625
|
+
channel(_("Speed set at: {speed} mm/s").format(speed=driver.speed))
|
626
|
+
return
|
627
|
+
if speed.endswith("%"):
|
628
|
+
speed = speed[:-1]
|
629
|
+
percent = True
|
630
|
+
else:
|
631
|
+
percent = False
|
632
|
+
|
633
|
+
try:
|
634
|
+
s = float(speed)
|
635
|
+
except ValueError:
|
636
|
+
channel(_("Not a valid speed or percent."))
|
637
|
+
return
|
638
|
+
|
639
|
+
if percent and difference:
|
640
|
+
s = driver.speed + driver.speed * (s / 100.0)
|
641
|
+
elif difference:
|
642
|
+
s += driver.speed
|
643
|
+
elif percent:
|
644
|
+
s = driver.speed * (s / 100.0)
|
645
|
+
driver._set_speed(s)
|
646
|
+
channel(_("Speed set at: {speed} mm/s").format(speed=driver.speed))
|
647
|
+
|
648
|
+
@self.console_argument("ppi", type=int, help=_("pulses per inch [0-1000]"))
|
649
|
+
@self.console_command("power", help=_("Set Driver Power"))
|
650
|
+
def power(command, channel, _, ppi=None, **kwgs):
|
651
|
+
original_power = self.driver.power
|
652
|
+
if ppi is None:
|
653
|
+
if original_power is None:
|
654
|
+
channel(_("Power is not set."))
|
655
|
+
else:
|
656
|
+
channel(
|
657
|
+
_("Power set at: {power} pulses per inch").format(
|
658
|
+
power=original_power
|
659
|
+
)
|
660
|
+
)
|
661
|
+
else:
|
662
|
+
self.driver.set("power", ppi)
|
663
|
+
|
664
|
+
@self.console_argument("accel", type=int, help=_("Acceleration amount [1-4]"))
|
665
|
+
@self.console_command(
|
666
|
+
"acceleration",
|
667
|
+
help=_("Set Driver Acceleration [1-4]"),
|
668
|
+
)
|
669
|
+
def acceleration(channel, _, accel=None, **kwgs):
|
670
|
+
"""
|
671
|
+
Lhymicro-gl speedcodes have a single character of either 1,2,3,4 which indicates
|
672
|
+
the acceleration value of the laser. This is typically 1 below 25.4, 2 below 60,
|
673
|
+
3 below 127, and 4 at any value greater than that. Manually setting this on the
|
674
|
+
fly can be used to check the various properties of that mode.
|
675
|
+
"""
|
676
|
+
if accel is None:
|
677
|
+
if self.driver.acceleration is None:
|
678
|
+
channel(_("Acceleration is set to default."))
|
679
|
+
else:
|
680
|
+
channel(
|
681
|
+
_("Acceleration: {acceleration}").format(
|
682
|
+
acceleration=self.driver.acceleration
|
683
|
+
)
|
684
|
+
)
|
685
|
+
|
686
|
+
else:
|
687
|
+
try:
|
688
|
+
v = accel
|
689
|
+
if v not in (1, 2, 3, 4):
|
690
|
+
self.driver.set("acceleration", None)
|
691
|
+
channel(_("Acceleration is set to default."))
|
692
|
+
return
|
693
|
+
self.driver.set("acceleration", v)
|
694
|
+
channel(
|
695
|
+
_("Acceleration: {acceleration}").format(
|
696
|
+
acceleration=self.driver.acceleration
|
697
|
+
)
|
698
|
+
)
|
699
|
+
except ValueError:
|
700
|
+
channel(_("Invalid Acceleration [1-4]."))
|
701
|
+
return
|
702
|
+
|
703
|
+
@self.console_command(
|
704
|
+
"network_update",
|
705
|
+
hidden=True,
|
706
|
+
help=_("Updates network state for m2nano networked."),
|
707
|
+
)
|
708
|
+
def network_update(**kwgs):
|
709
|
+
self.driver.out_pipe = self.controller if not self.networked else self.tcp
|
710
|
+
|
711
|
+
@self.console_command(
|
712
|
+
"status",
|
713
|
+
help=_("abort waiting process on the controller."),
|
714
|
+
)
|
715
|
+
def realtime_status(channel, _, **kwgs):
|
716
|
+
try:
|
717
|
+
self.controller.update_status()
|
718
|
+
channel(str(self.controller._status))
|
719
|
+
except ConnectionError:
|
720
|
+
channel(_("Could not check status, usb not connected."))
|
721
|
+
|
722
|
+
@self.console_command(
|
723
|
+
"continue",
|
724
|
+
help=_("abort waiting process on the controller."),
|
725
|
+
)
|
726
|
+
def realtime_continue(**kwgs):
|
727
|
+
self.controller.abort_waiting = True
|
728
|
+
|
729
|
+
@self.console_command(
|
730
|
+
"pause",
|
731
|
+
help=_("realtime pause/resume of the machine"),
|
732
|
+
)
|
733
|
+
def realtime_pause(**kwgs):
|
734
|
+
if self.driver.paused:
|
735
|
+
self.driver.resume()
|
736
|
+
else:
|
737
|
+
self.driver.pause()
|
738
|
+
self.signal("pause")
|
739
|
+
|
740
|
+
@self.console_command(("estop", "abort"), help=_("Abort Job"))
|
741
|
+
def pipe_abort(channel, _, **kwgs):
|
742
|
+
self.driver.reset()
|
743
|
+
channel(_("Lihuiyu Channel Aborted."))
|
744
|
+
self.signal("pipe;running", False)
|
745
|
+
|
746
|
+
@self.console_argument(
|
747
|
+
"rapid_x", type=float, help=_("limit x speed for rapid.")
|
748
|
+
)
|
749
|
+
@self.console_argument(
|
750
|
+
"rapid_y", type=float, help=_("limit y speed for rapid.")
|
751
|
+
)
|
752
|
+
@self.console_command(
|
753
|
+
"rapid_override",
|
754
|
+
help=_("limit speed of typical rapid moves."),
|
755
|
+
)
|
756
|
+
def rapid_override(channel, _, rapid_x=None, rapid_y=None, **kwgs):
|
757
|
+
if rapid_x is not None:
|
758
|
+
if rapid_y is None:
|
759
|
+
rapid_y = rapid_x
|
760
|
+
self.rapid_override = True
|
761
|
+
self.rapid_override_speed_x = rapid_x
|
762
|
+
self.rapid_override_speed_y = rapid_y
|
763
|
+
channel(
|
764
|
+
_("Rapid Limit: {max_x}, {max_y}").format(
|
765
|
+
max_x=self.rapid_override_speed_x,
|
766
|
+
max_y=self.rapid_override_speed_y,
|
767
|
+
)
|
768
|
+
)
|
769
|
+
else:
|
770
|
+
self.rapid_override = False
|
771
|
+
channel(_("Rapid Limit Off"))
|
772
|
+
|
773
|
+
@self.console_argument("filename", type=str)
|
774
|
+
@self.console_command("save_job", help=_("save job export"), input_type="plan")
|
775
|
+
def egv_save(channel, _, filename, data=None, **kwgs):
|
776
|
+
if filename is None:
|
777
|
+
raise CommandSyntaxError
|
778
|
+
try:
|
779
|
+
with open(filename, "wb") as f:
|
780
|
+
f.write(b"Document type : LHYMICRO-GL file\n")
|
781
|
+
f.write(b"File version: 1.0.01\n")
|
782
|
+
f.write(b"Copyright: Unknown\n")
|
783
|
+
f.write(
|
784
|
+
bytes(
|
785
|
+
f"Creator-Software: {self.kernel.name} v{self.kernel.version}\n",
|
786
|
+
"utf-8",
|
787
|
+
)
|
788
|
+
)
|
789
|
+
f.write(b"\n")
|
790
|
+
f.write(b"%0%0%0%0%\n")
|
791
|
+
driver = LihuiyuDriver(self)
|
792
|
+
job = LaserJob(filename, list(data.plan), driver=driver)
|
793
|
+
driver.out_pipe = f
|
794
|
+
job.execute()
|
795
|
+
|
796
|
+
except (PermissionError, OSError):
|
797
|
+
channel(_("Could not save: {filename}").format(filename=filename))
|
798
|
+
|
799
|
+
@self.console_argument("filename", type=str)
|
800
|
+
@self.console_command(
|
801
|
+
"egv_import",
|
802
|
+
help=_("Lihuiyu Engrave Buffer Import. egv_import <egv_file>"),
|
803
|
+
)
|
804
|
+
def egv_import(channel, _, filename, **kwgs):
|
805
|
+
if filename is None:
|
806
|
+
raise CommandSyntaxError
|
807
|
+
|
808
|
+
def skip(read, byte, count):
|
809
|
+
"""Skips forward in the file until we find <count> instances of <byte>"""
|
810
|
+
pos = read.tell()
|
811
|
+
while count > 0:
|
812
|
+
char = read.read(1)
|
813
|
+
if char == byte:
|
814
|
+
count -= 1
|
815
|
+
if char is None or len(char) == 0:
|
816
|
+
read.seek(pos, 0)
|
817
|
+
# If we didn't skip the right stuff, reset the position.
|
818
|
+
break
|
819
|
+
|
820
|
+
def skip_header(file):
|
821
|
+
skip(file, "\n", 3)
|
822
|
+
skip(file, "%", 5)
|
823
|
+
|
824
|
+
try:
|
825
|
+
with open(filename) as f:
|
826
|
+
skip_header(f)
|
827
|
+
while True:
|
828
|
+
data = f.read(1024)
|
829
|
+
if not data:
|
830
|
+
break
|
831
|
+
buffer = bytes(data, "utf8")
|
832
|
+
self.output.write(buffer)
|
833
|
+
self.output.write(b"\n")
|
834
|
+
except (PermissionError, OSError, FileNotFoundError):
|
835
|
+
channel(_("Could not load: {filename}").format(filename=filename))
|
836
|
+
|
837
|
+
@self.console_argument("filename", type=str)
|
838
|
+
@self.console_command(
|
839
|
+
"egv_export",
|
840
|
+
help=_("Lihuiyu Engrave Buffer Export. egv_export <egv_file>"),
|
841
|
+
)
|
842
|
+
def egv_export(channel, _, filename, **kwgs):
|
843
|
+
if filename is None:
|
844
|
+
raise CommandSyntaxError
|
845
|
+
try:
|
846
|
+
with open(filename, "w") as f:
|
847
|
+
f.write("Document type : LHYMICRO-GL file\n")
|
848
|
+
f.write("File version: 1.0.01\n")
|
849
|
+
f.write("Copyright: Unknown\n")
|
850
|
+
f.write(
|
851
|
+
f"Creator-Software: {self.kernel.name} v{self.kernel.version}\n"
|
852
|
+
)
|
853
|
+
f.write("\n")
|
854
|
+
f.write("%0%0%0%0%\n")
|
855
|
+
buffer = bytes(self.controller._buffer)
|
856
|
+
buffer += bytes(self.controller._queue)
|
857
|
+
f.write(buffer.decode("utf-8"))
|
858
|
+
except (PermissionError, OSError):
|
859
|
+
channel(_("Could not save: {filename}").format(filename=filename))
|
860
|
+
|
861
|
+
@self.console_command(
|
862
|
+
"egv",
|
863
|
+
help=_("Lihuiyu Engrave Code Sender. egv <lhymicro-gl>"),
|
864
|
+
)
|
865
|
+
def egv(command, channel, _, remainder=None, **kwgs):
|
866
|
+
if not remainder:
|
867
|
+
channel("Lihuiyu Engrave Code Sender. egv <lhymicro-gl>")
|
868
|
+
else:
|
869
|
+
self.output.write(
|
870
|
+
bytes(remainder.replace("$", "\n").replace(" ", "\n"), "utf8")
|
871
|
+
)
|
872
|
+
|
873
|
+
@self.console_command(
|
874
|
+
"challenge",
|
875
|
+
help=_("Challenge code, challenge <serial number>"),
|
876
|
+
)
|
877
|
+
def challenge_egv(command, channel, _, remainder=None, **kwgs):
|
878
|
+
if not remainder:
|
879
|
+
raise CommandSyntaxError
|
880
|
+
else:
|
881
|
+
challenge = bytearray.fromhex(
|
882
|
+
md5(bytes(remainder.upper(), "utf8")).hexdigest()
|
883
|
+
)
|
884
|
+
code = b"A%s\n" % challenge
|
885
|
+
self.output.write(code)
|
886
|
+
|
887
|
+
@self.console_command("start", help=_("Start Pipe to Controller"))
|
888
|
+
def pipe_start(command, channel, _, **kwgs):
|
889
|
+
self.controller.update_state("active")
|
890
|
+
self.controller.start()
|
891
|
+
channel(_("Lihuiyu Channel Started."))
|
892
|
+
|
893
|
+
@self.console_command("hold", help=_("Hold Controller"))
|
894
|
+
def pipe_pause(command, channel, _, **kwgs):
|
895
|
+
self.controller.update_state("pause")
|
896
|
+
self.controller.pause()
|
897
|
+
channel("Lihuiyu Channel Paused.")
|
898
|
+
|
899
|
+
@self.console_command("resume", help=_("Resume Controller"))
|
900
|
+
def pipe_resume(command, channel, _, **kwgs):
|
901
|
+
self.controller.update_state("active")
|
902
|
+
self.controller.start()
|
903
|
+
channel(_("Lihuiyu Channel Resumed."))
|
904
|
+
|
905
|
+
@self.console_command("usb_connect", help=_("Connects USB"))
|
906
|
+
def usb_connect(command, channel, _, **kwgs):
|
907
|
+
try:
|
908
|
+
self.controller.open()
|
909
|
+
channel(_("Usb Connection Opened."))
|
910
|
+
except (ConnectionRefusedError, ConnectionError):
|
911
|
+
# Refused is typical but inability to confirm serial would result in connection error.
|
912
|
+
channel(_("Usb Connection Refused"))
|
913
|
+
|
914
|
+
@self.console_command("usb_disconnect", help=_("Disconnects USB"))
|
915
|
+
def usb_disconnect(command, channel, _, **kwgs):
|
916
|
+
try:
|
917
|
+
self.controller.close()
|
918
|
+
channel(_("CH341 Closed."))
|
919
|
+
except ConnectionError:
|
920
|
+
channel(_("Usb Connection Error"))
|
921
|
+
|
922
|
+
@self.console_command("usb_reset", help=_("Reset USB device"))
|
923
|
+
def usb_reset(command, channel, _, **kwgs):
|
924
|
+
try:
|
925
|
+
self.controller.usb_reset()
|
926
|
+
channel(_("Usb Connection Reset"))
|
927
|
+
except ConnectionError:
|
928
|
+
channel(_("Usb Connection Error"))
|
929
|
+
|
930
|
+
@self.console_command("usb_release", help=_("Release USB device"))
|
931
|
+
def usb_release(command, channel, _, **kwgs):
|
932
|
+
try:
|
933
|
+
self.controller.usb_release()
|
934
|
+
channel(_("Usb Connection Released"))
|
935
|
+
except ConnectionError:
|
936
|
+
channel(_("Usb Connection Error"))
|
937
|
+
|
938
|
+
@self.console_command("usb_abort", help=_("Stops USB retries"))
|
939
|
+
def usb_abort(command, channel, _, **kwgs):
|
940
|
+
self.controller.abort_retry()
|
941
|
+
|
942
|
+
@self.console_command("usb_continue", help=_("Continues USB retries"))
|
943
|
+
def usb_continue(command, channel, _, **kwgs):
|
944
|
+
self.controller.continue_retry()
|
945
|
+
|
946
|
+
@self.console_option(
|
947
|
+
"port", "p", type=int, default=23, help=_("port to listen on.")
|
948
|
+
)
|
949
|
+
@kernel.console_option(
|
950
|
+
"verbose",
|
951
|
+
"v",
|
952
|
+
type=bool,
|
953
|
+
action="store_true",
|
954
|
+
help=_("watch server channels"),
|
955
|
+
)
|
956
|
+
@self.console_option(
|
957
|
+
"watch", "w", type=bool, action="store_true", help=_("watch send/recv data")
|
958
|
+
)
|
959
|
+
@self.console_option(
|
960
|
+
"quit",
|
961
|
+
"q",
|
962
|
+
type=bool,
|
963
|
+
action="store_true",
|
964
|
+
help=_("shutdown current lhyserver"),
|
965
|
+
)
|
966
|
+
@self.console_command("lhyserver", help=_("activate the lhyserver."))
|
967
|
+
def lhyserver(
|
968
|
+
channel, _, port=23, verbose=False, watch=False, quit=False, **kwgs
|
969
|
+
):
|
970
|
+
"""
|
971
|
+
The lhyserver provides for an open TCP on a specific port. Any data sent to this port will be sent directly
|
972
|
+
to the lihuiyu laser. This is how the tcp-connection sends data to the laser if that option is used. This
|
973
|
+
requires an additional computer such a raspberry pi doing the interfacing.
|
974
|
+
"""
|
975
|
+
try:
|
976
|
+
server_name = f"lhyserver{self.path}"
|
977
|
+
output = self.controller
|
978
|
+
server = self.open_as("module/TCPServer", server_name, port=port)
|
979
|
+
if quit:
|
980
|
+
self.close(server_name)
|
981
|
+
return
|
982
|
+
channel(_("TCP Server for lihuiyu on port: {port}").format(port=port))
|
983
|
+
if verbose:
|
984
|
+
console = kernel.channel("console")
|
985
|
+
server.events_channel.watch(console)
|
986
|
+
if watch:
|
987
|
+
server.data_channel.watch(console)
|
988
|
+
channel(_("Watching Channel: {channel}").format(channel="server"))
|
989
|
+
self.channel(f"{server_name}/recv").watch(output.write)
|
990
|
+
channel(_("Attached: {output}").format(output=repr(output)))
|
991
|
+
|
992
|
+
except OSError:
|
993
|
+
channel(_("Server failed on port: {port}").format(port=port))
|
994
|
+
except KeyError:
|
995
|
+
channel(_("Server cannot be attached to any device."))
|
996
|
+
return
|
997
|
+
|
998
|
+
if self.has_feature("interpreter/lihuiyu"):
|
999
|
+
|
1000
|
+
@self.console_command(
|
1001
|
+
"lhyinterpreter", help=_("activate the lhyinterpreter.")
|
1002
|
+
)
|
1003
|
+
def lhyinterpreter(channel, _, **kwgs):
|
1004
|
+
try:
|
1005
|
+
self.open_as("interpreter/lihuiyu", "lhyinterpreter")
|
1006
|
+
channel(
|
1007
|
+
_("Lihuiyu interpreter attached to {device}").format(
|
1008
|
+
device=str(self)
|
1009
|
+
)
|
1010
|
+
)
|
1011
|
+
except KeyError:
|
1012
|
+
channel(_("Interpreter cannot be attached to any device."))
|
1013
|
+
return
|
1014
|
+
|
1015
|
+
def get_raster_instructions(self):
|
1016
|
+
return {
|
1017
|
+
"split_crossover": True,
|
1018
|
+
"unsupported_opt": (
|
1019
|
+
mkconst.RASTER_GREEDY_H, mkconst.RASTER_GREEDY_V, mkconst.RASTER_SPIRAL,
|
1020
|
+
), # Greedy loses registration way too often to be reliable
|
1021
|
+
"gantry" : True,
|
1022
|
+
"legacy" : self.legacy_raster,
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
@property
|
1026
|
+
def safe_label(self):
|
1027
|
+
"""
|
1028
|
+
Provides a safe label without spaces or / which could cause issues when used in timer or other names.
|
1029
|
+
@return:
|
1030
|
+
"""
|
1031
|
+
if not hasattr(self, "label"):
|
1032
|
+
return self.name
|
1033
|
+
name = self.label.replace(" ", "-")
|
1034
|
+
return name.replace("/", "-")
|
1035
|
+
|
1036
|
+
def service_attach(self, *args, **kwargs):
|
1037
|
+
self.realize()
|
1038
|
+
|
1039
|
+
@signal_listener("plot_shift")
|
1040
|
+
@signal_listener("plot_phase_type")
|
1041
|
+
@signal_listener("plot_phase_value")
|
1042
|
+
def plot_attributes_update(self, origin=None, *args):
|
1043
|
+
self.driver.plot_attribute_update()
|
1044
|
+
|
1045
|
+
@signal_listener("user_scale_x")
|
1046
|
+
@signal_listener("user_scale_y")
|
1047
|
+
@signal_listener("bedwidth")
|
1048
|
+
@signal_listener("bedheight")
|
1049
|
+
@signal_listener("flip_x")
|
1050
|
+
@signal_listener("flip_y")
|
1051
|
+
@signal_listener("home_corner")
|
1052
|
+
@signal_listener("swap_xy")
|
1053
|
+
@signal_listener("user_margin_x")
|
1054
|
+
@signal_listener("user_margin_y")
|
1055
|
+
def realize(self, origin=None, *args):
|
1056
|
+
if origin is not None and origin != self.path:
|
1057
|
+
return
|
1058
|
+
corner = self.setting(str, "home_corner")
|
1059
|
+
home_dx = 0
|
1060
|
+
home_dy = 0
|
1061
|
+
if corner == "auto":
|
1062
|
+
pass
|
1063
|
+
elif corner == "top-left":
|
1064
|
+
home_dx = 1 if self.flip_x else 0
|
1065
|
+
home_dy = 1 if self.flip_y else 0
|
1066
|
+
elif corner == "top-right":
|
1067
|
+
home_dx = 0 if self.flip_x else 1
|
1068
|
+
home_dy = 1 if self.flip_y else 0
|
1069
|
+
elif corner == "bottom-left":
|
1070
|
+
home_dx = 1 if self.flip_x else 0
|
1071
|
+
home_dy = 0 if self.flip_y else 1
|
1072
|
+
elif corner == "bottom-right":
|
1073
|
+
home_dx = 0 if self.flip_x else 1
|
1074
|
+
home_dy = 0 if self.flip_y else 1
|
1075
|
+
elif corner == "center":
|
1076
|
+
home_dx = 0.5
|
1077
|
+
home_dy = 0.5
|
1078
|
+
self.view.set_dims(self.bedwidth, self.bedheight)
|
1079
|
+
self.view.transform(
|
1080
|
+
user_scale_x=self.user_scale_x,
|
1081
|
+
user_scale_y=self.user_scale_y,
|
1082
|
+
flip_x=self.flip_x,
|
1083
|
+
flip_y=self.flip_y,
|
1084
|
+
swap_xy=self.swap_xy,
|
1085
|
+
origin_x=home_dx,
|
1086
|
+
origin_y=home_dy,
|
1087
|
+
)
|
1088
|
+
self.view.set_margins(self.user_margin_x, self.user_margin_y)
|
1089
|
+
self.signal("view;realized")
|
1090
|
+
|
1091
|
+
def outline_move_relative(self, dx, dy):
|
1092
|
+
x, y = self.native
|
1093
|
+
new_x = x + dx
|
1094
|
+
new_y = y + dy
|
1095
|
+
min_x = min(x, new_x)
|
1096
|
+
min_y = min(y, new_y)
|
1097
|
+
max_x = max(x, new_x)
|
1098
|
+
max_y = max(y, new_y)
|
1099
|
+
return (min_x, min_y), (max_x, min_y), (max_x, max_y), (min_x, max_y)
|
1100
|
+
|
1101
|
+
@property
|
1102
|
+
def viewbuffer(self):
|
1103
|
+
return self.driver.out_pipe.viewbuffer
|
1104
|
+
|
1105
|
+
@property
|
1106
|
+
def current(self):
|
1107
|
+
"""
|
1108
|
+
@return: the location in units for the current known position.
|
1109
|
+
"""
|
1110
|
+
return self.view.iposition(self.driver.native_x, self.driver.native_y)
|
1111
|
+
|
1112
|
+
@property
|
1113
|
+
def speed(self):
|
1114
|
+
return self.driver.speed
|
1115
|
+
|
1116
|
+
@property
|
1117
|
+
def power(self):
|
1118
|
+
return self.driver.power
|
1119
|
+
|
1120
|
+
@property
|
1121
|
+
def state(self):
|
1122
|
+
return self.driver.state
|
1123
|
+
|
1124
|
+
@property
|
1125
|
+
def native(self):
|
1126
|
+
"""
|
1127
|
+
@return: the location in device native units for the current known position.
|
1128
|
+
"""
|
1129
|
+
return self.driver.native_x, self.driver.native_y
|
1130
|
+
|
1131
|
+
@property
|
1132
|
+
def output(self):
|
1133
|
+
"""
|
1134
|
+
This is the controller in controller mode and the tcp in network mode.
|
1135
|
+
@return:
|
1136
|
+
"""
|
1137
|
+
if self.networked:
|
1138
|
+
return self.tcp
|
1139
|
+
else:
|
1140
|
+
return self.controller
|
1141
|
+
|
1142
|
+
def acceleration_overrun(self, is_raster, op_speed):
|
1143
|
+
"""
|
1144
|
+
https://github.com/meerk40t/meerk40t/wiki/Tech:-Lhymicro-Control-Protocols
|
1145
|
+
Non - Raster:
|
1146
|
+
1: [0 - 25.4]
|
1147
|
+
2: (25.4 - 60]
|
1148
|
+
3: (60 - 127)
|
1149
|
+
4: [127 - max)
|
1150
|
+
Raster:
|
1151
|
+
1: [0 - 25.4]
|
1152
|
+
2: (25.4 - 127]
|
1153
|
+
3: [127 - 320)
|
1154
|
+
4: [320 - max)
|
1155
|
+
Four step ticks will move 1 mil distance.
|
1156
|
+
Acceleration and deceleration (braking) happen
|
1157
|
+
in the same amount of distance, so Accel 1-2 would be
|
1158
|
+
512 steps / 4 = 128 * 2 (for both acceleration and braking)
|
1159
|
+
for a total of 256 mil distance for ramping up to speed and slowing down after.
|
1160
|
+
"""
|
1161
|
+
if is_raster:
|
1162
|
+
limits = (320.0, 127.0, 25.4)
|
1163
|
+
else:
|
1164
|
+
limits = (127.0, 60.0, 25.4)
|
1165
|
+
|
1166
|
+
if op_speed >= limits[0]:
|
1167
|
+
accel = 4
|
1168
|
+
steps = 256
|
1169
|
+
elif op_speed >= limits[1]:
|
1170
|
+
accel = 3
|
1171
|
+
steps = 256
|
1172
|
+
elif op_speed >= limits[2]:
|
1173
|
+
accel = 2
|
1174
|
+
steps = 128
|
1175
|
+
else:
|
1176
|
+
accel = 1
|
1177
|
+
steps = 128
|
1178
|
+
return UNITS_PER_MIL * steps
|
1179
|
+
|
1180
|
+
def cool_helper(self, choice_dict):
|
1181
|
+
self.kernel.root.coolant.coolant_choice_helper(self)(choice_dict)
|