meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7020__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 +1194 -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 +1858 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4595 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4315 -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 +934 -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/testcases.py +105 -0
- 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 +463 -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 +204 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +834 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +628 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +283 -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 +1084 -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 +232 -133
- meerk40t/gui/choicepropertypanel.py +1662 -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 +1440 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +897 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2944 -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 +500 -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 +2471 -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 +592 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2958 -2756
- meerk40t/gui/simpleui.py +362 -333
- meerk40t/gui/simulation.py +2451 -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 +590 -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 +163 -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 +1447 -1169
- meerk40t/gui/wxmmain.py +5644 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1631 -1453
- meerk40t/gui/wxmtree.py +2416 -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 +2793 -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 +3828 -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 +140 -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 +404 -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 +676 -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 +941 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +1047 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/METADATA +150 -139
- meerk40t-0.9.7020.dist-info/RECORD +446 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.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.7020.dist-info}/entry_points.txt +0 -0
meerk40t/moshi/controller.py
CHANGED
@@ -1,499 +1,505 @@
|
|
1
|
-
"""
|
2
|
-
Moshiboard Controller
|
3
|
-
|
4
|
-
Tasked with sending data to usb connection.
|
5
|
-
"""
|
6
|
-
|
7
|
-
import threading
|
8
|
-
import time
|
9
|
-
|
10
|
-
from ..ch341 import get_ch341_interface
|
11
|
-
from .builder import MoshiBuilder
|
12
|
-
|
13
|
-
STATUS_OK = 205 # Seen before file send. And after file send.
|
14
|
-
STATUS_PROCESSING = 207 # PROCESSING
|
15
|
-
STATUS_ERROR = 237 # ERROR
|
16
|
-
STATUS_RESET = 239 # Seen during reset
|
17
|
-
|
18
|
-
|
19
|
-
def get_code_string_from_moshicode(code):
|
20
|
-
"""
|
21
|
-
Moshiboard CH341 codes into code strings.
|
22
|
-
"""
|
23
|
-
if code == STATUS_OK:
|
24
|
-
return "OK"
|
25
|
-
elif code == STATUS_PROCESSING:
|
26
|
-
return "Processing"
|
27
|
-
elif code == STATUS_ERROR:
|
28
|
-
return "Error"
|
29
|
-
elif code == STATUS_RESET:
|
30
|
-
return "Resetting"
|
31
|
-
elif code == 0:
|
32
|
-
return "USB Failed"
|
33
|
-
else:
|
34
|
-
return f"UNK {code:02x}"
|
35
|
-
|
36
|
-
|
37
|
-
class MoshiController:
|
38
|
-
"""
|
39
|
-
The Moshiboard Controller takes data programs built by the MoshiDriver and sends to the Moshiboard
|
40
|
-
according to established moshi protocols.
|
41
|
-
|
42
|
-
The output device is concerned with sending the moshibuilder.data to the control board and control events and
|
43
|
-
to the CH341 chip on the Moshiboard. We use the same ch341 driver as the Lihuiyu boards. Giving us
|
44
|
-
access to both libusb drivers and windll drivers.
|
45
|
-
|
46
|
-
The protocol for sending rasters is as follows:
|
47
|
-
Check processing-state of board, seeking 205
|
48
|
-
Send Preamble.
|
49
|
-
Check processing-state of board, seeking 205
|
50
|
-
Send bulk data of moshibuilder. No checks between packets.
|
51
|
-
Send Epilogue.
|
52
|
-
While Check processing-state is 207:
|
53
|
-
wait 0.2 seconds
|
54
|
-
Send Preamble
|
55
|
-
Send 0,0 offset 0,0 move.
|
56
|
-
Send Epilogue
|
57
|
-
|
58
|
-
Checks done before the Epilogue will have 205 state.
|
59
|
-
"""
|
60
|
-
|
61
|
-
def __init__(self,
|
62
|
-
self.context =
|
63
|
-
self.state = "unknown"
|
64
|
-
|
65
|
-
self._programs = [] # Programs to execute.
|
66
|
-
self._buffer = (
|
67
|
-
bytearray()
|
68
|
-
) # Threadsafe buffered commands to be sent to controller.
|
69
|
-
|
70
|
-
self._thread = None
|
71
|
-
self.is_shutdown = False
|
72
|
-
self._program_lock = threading.Lock()
|
73
|
-
|
74
|
-
self._status = [0] * 6
|
75
|
-
self._usb_state = -1
|
76
|
-
|
77
|
-
self.connection = None
|
78
|
-
self.force_mock = force_mock
|
79
|
-
|
80
|
-
self.max_attempts = 5
|
81
|
-
self.refuse_counts = 0
|
82
|
-
self.connection_errors = 0
|
83
|
-
self.count = 0
|
84
|
-
self.abort_waiting = False
|
85
|
-
|
86
|
-
name =
|
87
|
-
self.pipe_channel =
|
88
|
-
self.usb_log =
|
89
|
-
self.usb_send_channel =
|
90
|
-
self.recv_channel =
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
self.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
self.
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
self.
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
self.
|
213
|
-
self.
|
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
|
-
def
|
280
|
-
"""
|
281
|
-
Notify listening processes that the
|
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
|
-
if self.
|
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
|
-
if len(self._buffer) == 0:
|
344
|
-
self.
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
self.
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
self.
|
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
|
-
|
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
|
-
if
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
if
|
486
|
-
self.
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
if
|
492
|
-
self.
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
if
|
498
|
-
|
499
|
-
|
1
|
+
"""
|
2
|
+
Moshiboard Controller
|
3
|
+
|
4
|
+
Tasked with sending data to usb connection.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import threading
|
8
|
+
import time
|
9
|
+
|
10
|
+
from ..ch341 import get_ch341_interface
|
11
|
+
from .builder import MoshiBuilder
|
12
|
+
|
13
|
+
STATUS_OK = 205 # Seen before file send. And after file send.
|
14
|
+
STATUS_PROCESSING = 207 # PROCESSING
|
15
|
+
STATUS_ERROR = 237 # ERROR
|
16
|
+
STATUS_RESET = 239 # Seen during reset
|
17
|
+
|
18
|
+
|
19
|
+
def get_code_string_from_moshicode(code):
|
20
|
+
"""
|
21
|
+
Moshiboard CH341 codes into code strings.
|
22
|
+
"""
|
23
|
+
if code == STATUS_OK:
|
24
|
+
return "OK"
|
25
|
+
elif code == STATUS_PROCESSING:
|
26
|
+
return "Processing"
|
27
|
+
elif code == STATUS_ERROR:
|
28
|
+
return "Error"
|
29
|
+
elif code == STATUS_RESET:
|
30
|
+
return "Resetting"
|
31
|
+
elif code == 0:
|
32
|
+
return "USB Failed"
|
33
|
+
else:
|
34
|
+
return f"UNK {code:02x}"
|
35
|
+
|
36
|
+
|
37
|
+
class MoshiController:
|
38
|
+
"""
|
39
|
+
The Moshiboard Controller takes data programs built by the MoshiDriver and sends to the Moshiboard
|
40
|
+
according to established moshi protocols.
|
41
|
+
|
42
|
+
The output device is concerned with sending the moshibuilder.data to the control board and control events and
|
43
|
+
to the CH341 chip on the Moshiboard. We use the same ch341 driver as the Lihuiyu boards. Giving us
|
44
|
+
access to both libusb drivers and windll drivers.
|
45
|
+
|
46
|
+
The protocol for sending rasters is as follows:
|
47
|
+
Check processing-state of board, seeking 205
|
48
|
+
Send Preamble.
|
49
|
+
Check processing-state of board, seeking 205
|
50
|
+
Send bulk data of moshibuilder. No checks between packets.
|
51
|
+
Send Epilogue.
|
52
|
+
While Check processing-state is 207:
|
53
|
+
wait 0.2 seconds
|
54
|
+
Send Preamble
|
55
|
+
Send 0,0 offset 0,0 move.
|
56
|
+
Send Epilogue
|
57
|
+
|
58
|
+
Checks done before the Epilogue will have 205 state.
|
59
|
+
"""
|
60
|
+
|
61
|
+
def __init__(self, service, channel=None, force_mock=False, *args, **kwargs):
|
62
|
+
self.context = service
|
63
|
+
self.state = "unknown"
|
64
|
+
|
65
|
+
self._programs = [] # Programs to execute.
|
66
|
+
self._buffer = (
|
67
|
+
bytearray()
|
68
|
+
) # Threadsafe buffered commands to be sent to controller.
|
69
|
+
|
70
|
+
self._thread = None
|
71
|
+
self.is_shutdown = False
|
72
|
+
self._program_lock = threading.Lock()
|
73
|
+
|
74
|
+
self._status = [0] * 6
|
75
|
+
self._usb_state = -1
|
76
|
+
|
77
|
+
self.connection = None
|
78
|
+
self.force_mock = force_mock
|
79
|
+
|
80
|
+
self.max_attempts = 5
|
81
|
+
self.refuse_counts = 0
|
82
|
+
self.connection_errors = 0
|
83
|
+
self.count = 0
|
84
|
+
self.abort_waiting = False
|
85
|
+
|
86
|
+
name = service.safe_label
|
87
|
+
self.pipe_channel = service.channel(f"{name}/events")
|
88
|
+
self.usb_log = service.channel(f"{name}/usb", buffer_size=500)
|
89
|
+
self.usb_send_channel = service.channel(f"{name}/usb_send")
|
90
|
+
self.recv_channel = service.channel(f"{name}/recv")
|
91
|
+
|
92
|
+
def usb_signal_update(self, e):
|
93
|
+
self.context.signal("pipe;usb_status", e)
|
94
|
+
|
95
|
+
def viewbuffer(self):
|
96
|
+
"""
|
97
|
+
Viewbuffer is used by the BufferView class if such a value exists it provides a view of the
|
98
|
+
buffered data. Without this class the BufferView displays nothing. This is optional for any output
|
99
|
+
device.
|
100
|
+
"""
|
101
|
+
buffer = f"Current Working Buffer: {str(self._buffer)}\n"
|
102
|
+
for p in self._programs:
|
103
|
+
if hasattr(p, "data"):
|
104
|
+
buffer += f"{str(p.data)}\n"
|
105
|
+
else:
|
106
|
+
buffer += f"{str(p)} [dataless]\n"
|
107
|
+
return buffer
|
108
|
+
|
109
|
+
def added(self, *args, **kwargs):
|
110
|
+
self.start()
|
111
|
+
self.usb_log.watch(self.usb_signal_update)
|
112
|
+
|
113
|
+
def shutdown(self, *args, **kwargs):
|
114
|
+
self.usb_log.unwatch(self.usb_signal_update)
|
115
|
+
self.update_state("terminate")
|
116
|
+
if self._thread is not None:
|
117
|
+
self.is_shutdown = True
|
118
|
+
|
119
|
+
def __repr__(self):
|
120
|
+
return "MoshiController()"
|
121
|
+
|
122
|
+
def __len__(self):
|
123
|
+
"""Provides the length of the buffer of this device."""
|
124
|
+
return len(self._buffer) + sum(map(len, self._programs))
|
125
|
+
|
126
|
+
def open(self):
|
127
|
+
_ = self.usb_log._
|
128
|
+
if self.connection is not None and self.connection.is_connected():
|
129
|
+
return # Already connected.
|
130
|
+
self.pipe_channel("open()")
|
131
|
+
|
132
|
+
try:
|
133
|
+
interfaces = list(
|
134
|
+
get_ch341_interface(
|
135
|
+
self.context,
|
136
|
+
self.usb_log,
|
137
|
+
mock=self.force_mock or self.context.mock,
|
138
|
+
mock_status=STATUS_OK,
|
139
|
+
bulk=False,
|
140
|
+
)
|
141
|
+
)
|
142
|
+
if self.context.usb_index != -1:
|
143
|
+
# Instructed to check one specific device.
|
144
|
+
devices = [self.context.usb_index]
|
145
|
+
else:
|
146
|
+
devices = range(16)
|
147
|
+
|
148
|
+
for interface in interfaces:
|
149
|
+
self.connection = interface
|
150
|
+
for i in devices:
|
151
|
+
try:
|
152
|
+
self._open_at_index(i)
|
153
|
+
return # Opened successfully.
|
154
|
+
except ConnectionRefusedError as e:
|
155
|
+
self.usb_log(str(e))
|
156
|
+
if self.connection is not None:
|
157
|
+
self.connection.close()
|
158
|
+
except IndexError:
|
159
|
+
self.usb_log(_("Connection failed."))
|
160
|
+
self.connection = None
|
161
|
+
break
|
162
|
+
except PermissionError as e:
|
163
|
+
self.usb_log(str(e))
|
164
|
+
return # OS denied permissions, no point checking anything else.
|
165
|
+
if self.connection:
|
166
|
+
self.close()
|
167
|
+
raise ConnectionRefusedError(
|
168
|
+
_("No valid connection matched any given criteria.")
|
169
|
+
)
|
170
|
+
|
171
|
+
def _open_at_index(self, usb_index):
|
172
|
+
_ = self.context.kernel.translation
|
173
|
+
self.connection.open(usb_index=usb_index)
|
174
|
+
if not self.connection.is_connected():
|
175
|
+
raise ConnectionRefusedError("ch341 connect did not return a connection.")
|
176
|
+
if self.context.usb_bus != -1 and self.connection.bus != -1:
|
177
|
+
if self.connection.bus != self.context.usb_bus:
|
178
|
+
raise ConnectionRefusedError(
|
179
|
+
_("K40 devices were found but they were rejected due to usb bus.")
|
180
|
+
)
|
181
|
+
if self.context.usb_address != -1 and self.connection.address != -1:
|
182
|
+
if self.connection.address != self.context.usb_address:
|
183
|
+
raise ConnectionRefusedError(
|
184
|
+
_(
|
185
|
+
"K40 devices were found but they were rejected due to usb address."
|
186
|
+
)
|
187
|
+
)
|
188
|
+
if self.context.usb_version != -1:
|
189
|
+
version = self.connection.get_chip_version()
|
190
|
+
if version != self.context.usb_version:
|
191
|
+
raise ConnectionRefusedError(
|
192
|
+
_(
|
193
|
+
"K40 devices were found but they were rejected due to chip version."
|
194
|
+
)
|
195
|
+
)
|
196
|
+
|
197
|
+
def close(self):
|
198
|
+
self.pipe_channel("close()")
|
199
|
+
if self.connection is not None:
|
200
|
+
self.connection.close()
|
201
|
+
self.connection = None
|
202
|
+
else:
|
203
|
+
raise ConnectionError
|
204
|
+
|
205
|
+
def write(self, data):
|
206
|
+
with self._program_lock:
|
207
|
+
self._programs.append(data)
|
208
|
+
self.start()
|
209
|
+
|
210
|
+
def realtime(self, data):
|
211
|
+
if MoshiBuilder.is_estop(data):
|
212
|
+
self.context.signal("pipe;buffer", 0)
|
213
|
+
self.update_state("terminate")
|
214
|
+
with self._program_lock:
|
215
|
+
self._programs.clear()
|
216
|
+
self._buffer.clear()
|
217
|
+
try:
|
218
|
+
self.open()
|
219
|
+
self.connection.write_addr(data)
|
220
|
+
except ConnectionRefusedError:
|
221
|
+
pass # could not open connection.
|
222
|
+
except ConnectionError:
|
223
|
+
pass # Connection did not return success.
|
224
|
+
|
225
|
+
def start(self):
|
226
|
+
"""
|
227
|
+
Controller state change to `Started`.
|
228
|
+
@return:
|
229
|
+
"""
|
230
|
+
if self._thread is None or not self._thread.is_alive():
|
231
|
+
self._thread = self.context.threaded(
|
232
|
+
self._thread_data_send,
|
233
|
+
thread_name=f"MoshiPipe({self.context.path})",
|
234
|
+
result=self.stop,
|
235
|
+
)
|
236
|
+
self.update_state("init")
|
237
|
+
|
238
|
+
def pause(self):
|
239
|
+
"""
|
240
|
+
Pause simply holds the controller from sending any additional packets.
|
241
|
+
|
242
|
+
If this state change is done from INITIALIZE it will start the processing.
|
243
|
+
Otherwise, it must be done from ACTIVE or IDLE.
|
244
|
+
"""
|
245
|
+
if self.state == "init":
|
246
|
+
self.start()
|
247
|
+
self.update_state("pause")
|
248
|
+
if self.state in ("active", "idle"):
|
249
|
+
self.update_state("pause")
|
250
|
+
|
251
|
+
def resume(self):
|
252
|
+
"""
|
253
|
+
Resume can only be called from PAUSE.
|
254
|
+
"""
|
255
|
+
if self.state == "pause":
|
256
|
+
self.update_state("active")
|
257
|
+
|
258
|
+
def stop(self, *args):
|
259
|
+
"""
|
260
|
+
Start the shutdown of the local send thread.
|
261
|
+
"""
|
262
|
+
if self._thread is not None:
|
263
|
+
try:
|
264
|
+
self._thread.join() # Wait until stop completes before continuing.
|
265
|
+
except RuntimeError:
|
266
|
+
pass # Thread is current thread.
|
267
|
+
self._thread = None
|
268
|
+
|
269
|
+
def update_state(self, state):
|
270
|
+
"""
|
271
|
+
Update the local state for the output device
|
272
|
+
"""
|
273
|
+
if state == self.state:
|
274
|
+
return
|
275
|
+
self.state = state
|
276
|
+
if self.context is not None:
|
277
|
+
self.context.signal("pipe;thread", self.state)
|
278
|
+
|
279
|
+
def update_buffer(self):
|
280
|
+
"""
|
281
|
+
Notify listening processes that the buffer size of this output has changed.
|
282
|
+
"""
|
283
|
+
self.context.signal("pipe;buffer", len(self._buffer))
|
284
|
+
|
285
|
+
def update_packet(self, packet):
|
286
|
+
"""
|
287
|
+
Notify listening processes that the last sent packet has changed.
|
288
|
+
"""
|
289
|
+
if self.context is not None:
|
290
|
+
self.context.signal("pipe;packet_text", packet)
|
291
|
+
self.usb_send_channel(packet)
|
292
|
+
|
293
|
+
def _send_buffer(self):
|
294
|
+
"""
|
295
|
+
Send the current Moshiboard buffer
|
296
|
+
"""
|
297
|
+
self.pipe_channel("Sending Buffer...")
|
298
|
+
while len(self._buffer) != 0:
|
299
|
+
queue_processed = self.process_buffer()
|
300
|
+
self.refuse_counts = 0
|
301
|
+
|
302
|
+
if queue_processed:
|
303
|
+
# Packet was sent.
|
304
|
+
if self.state not in (
|
305
|
+
"pause",
|
306
|
+
"busy",
|
307
|
+
"active",
|
308
|
+
"terminate",
|
309
|
+
):
|
310
|
+
self.update_state("active")
|
311
|
+
self.count = 0
|
312
|
+
else:
|
313
|
+
# No packet could be sent.
|
314
|
+
if self.state not in (
|
315
|
+
"pause",
|
316
|
+
"busy",
|
317
|
+
"terminate",
|
318
|
+
):
|
319
|
+
self.update_state("idle")
|
320
|
+
if self.count > 50:
|
321
|
+
self.count = 50
|
322
|
+
time.sleep(0.02 * self.count)
|
323
|
+
# will tick up to 1 second waits if there's never a queue.
|
324
|
+
self.count += 1
|
325
|
+
|
326
|
+
def _thread_data_send(self):
|
327
|
+
"""
|
328
|
+
Main threaded function to send data. While the controller is working the thread
|
329
|
+
will be doing work in this function.
|
330
|
+
"""
|
331
|
+
self.pipe_channel(f"Send Thread Start... {len(self._programs)}")
|
332
|
+
self.count = 0
|
333
|
+
self.is_shutdown = False
|
334
|
+
|
335
|
+
while True:
|
336
|
+
self.pipe_channel("While Loop")
|
337
|
+
try:
|
338
|
+
if self.state == "init":
|
339
|
+
# If we are initialized. Change that to active since we're running.
|
340
|
+
self.update_state("active")
|
341
|
+
if self.is_shutdown:
|
342
|
+
break
|
343
|
+
if len(self._buffer) == 0 and len(self._programs) == 0:
|
344
|
+
self.pipe_channel("Nothing to process")
|
345
|
+
break # There is nothing to run.
|
346
|
+
if self.connection is None:
|
347
|
+
self.open()
|
348
|
+
# Stage 0: New Program send.
|
349
|
+
if len(self._buffer) == 0:
|
350
|
+
self.context.laser_status = "active"
|
351
|
+
self.pipe_channel("New Program")
|
352
|
+
self.wait_until_accepting_packets()
|
353
|
+
MoshiBuilder.prologue(self.connection.write_addr, self.pipe_channel)
|
354
|
+
with self._program_lock:
|
355
|
+
self._buffer += self._programs.pop(0)
|
356
|
+
if len(self._buffer) == 0:
|
357
|
+
continue
|
358
|
+
|
359
|
+
# Stage 1: Send Program.
|
360
|
+
self.context.laser_status = "active"
|
361
|
+
self.pipe_channel(f"Sending Data... {len(self._buffer)} bytes")
|
362
|
+
self._send_buffer()
|
363
|
+
self.update_status()
|
364
|
+
MoshiBuilder.epilogue(self.connection.write_addr, self.pipe_channel)
|
365
|
+
if self.is_shutdown:
|
366
|
+
break
|
367
|
+
|
368
|
+
# Stage 2: Wait for Program to Finish.
|
369
|
+
self.pipe_channel("Waiting for finish processing.")
|
370
|
+
if len(self._buffer) == 0:
|
371
|
+
self.wait_finished()
|
372
|
+
self.context.laser_status = "idle"
|
373
|
+
|
374
|
+
except ConnectionRefusedError:
|
375
|
+
if self.is_shutdown:
|
376
|
+
break
|
377
|
+
# The attempt refused the connection.
|
378
|
+
self.refuse_counts += 1
|
379
|
+
|
380
|
+
if self.refuse_counts >= 5:
|
381
|
+
self.context.signal("pipe;state", "STATE_FAILED_RETRYING")
|
382
|
+
self.context.signal("pipe;failing", self.refuse_counts)
|
383
|
+
self.context.laser_status = "idle"
|
384
|
+
time.sleep(3) # 3-second sleep on failed connection attempt.
|
385
|
+
continue
|
386
|
+
except ConnectionError:
|
387
|
+
# There was an error with the connection, close it and try again.
|
388
|
+
if self.is_shutdown:
|
389
|
+
break
|
390
|
+
self.connection_errors += 1
|
391
|
+
time.sleep(0.5)
|
392
|
+
try:
|
393
|
+
self.close()
|
394
|
+
except ConnectionError:
|
395
|
+
pass
|
396
|
+
continue
|
397
|
+
self.context.laser_status = "idle"
|
398
|
+
self._thread = None
|
399
|
+
self.is_shutdown = False
|
400
|
+
self.update_state("end")
|
401
|
+
self.pipe_channel("Send Thread Finished...")
|
402
|
+
|
403
|
+
def process_buffer(self):
|
404
|
+
"""
|
405
|
+
Attempts to process the program send from the buffer.
|
406
|
+
|
407
|
+
@return: queue process success.
|
408
|
+
"""
|
409
|
+
if len(self._buffer) > 0:
|
410
|
+
buffer = self._buffer
|
411
|
+
else:
|
412
|
+
return False
|
413
|
+
|
414
|
+
length = min(32, len(buffer))
|
415
|
+
packet = buffer[:length]
|
416
|
+
|
417
|
+
# Packet is prepared and ready to send. Open Channel.
|
418
|
+
|
419
|
+
self.send_packet(packet)
|
420
|
+
self.context.packet_count += 1
|
421
|
+
|
422
|
+
# Packet was processed. Remove that data.
|
423
|
+
self._buffer = self._buffer[length:]
|
424
|
+
self.update_buffer()
|
425
|
+
return True # A packet was prepped and sent correctly.
|
426
|
+
|
427
|
+
def send_packet(self, packet):
|
428
|
+
"""
|
429
|
+
Send packet to the CH341 connection.
|
430
|
+
"""
|
431
|
+
if self.connection is None:
|
432
|
+
raise ConnectionError
|
433
|
+
self.connection.write(packet)
|
434
|
+
self.update_packet(packet)
|
435
|
+
|
436
|
+
def update_status(self):
|
437
|
+
"""
|
438
|
+
Request a status update from the CH341 connection.
|
439
|
+
"""
|
440
|
+
if self.connection is None:
|
441
|
+
raise ConnectionError
|
442
|
+
self._status = self.connection.get_status()
|
443
|
+
if self.context is not None:
|
444
|
+
try:
|
445
|
+
self.context.signal(
|
446
|
+
"pipe;status",
|
447
|
+
self._status,
|
448
|
+
get_code_string_from_moshicode(self._status[1]),
|
449
|
+
)
|
450
|
+
except IndexError:
|
451
|
+
pass
|
452
|
+
self.recv_channel(str(self._status))
|
453
|
+
|
454
|
+
def wait_until_accepting_packets(self):
|
455
|
+
"""
|
456
|
+
Wait until the device can accept packets.
|
457
|
+
"""
|
458
|
+
i = 0
|
459
|
+
while self.state != "terminate":
|
460
|
+
self.update_status()
|
461
|
+
status = self._status[1]
|
462
|
+
if status == 0:
|
463
|
+
raise ConnectionError
|
464
|
+
if status == STATUS_ERROR:
|
465
|
+
raise ConnectionRefusedError
|
466
|
+
if status == STATUS_OK:
|
467
|
+
return
|
468
|
+
time.sleep(0.05)
|
469
|
+
i += 1
|
470
|
+
if self.abort_waiting:
|
471
|
+
self.abort_waiting = False
|
472
|
+
return # Wait abort was requested.
|
473
|
+
|
474
|
+
def wait_finished(self):
|
475
|
+
"""
|
476
|
+
Wait until the device has finished the current sending buffer.
|
477
|
+
"""
|
478
|
+
self.pipe_channel("Wait Finished")
|
479
|
+
i = 0
|
480
|
+
original_state = self.state
|
481
|
+
if self.state != "pause":
|
482
|
+
self.pause()
|
483
|
+
|
484
|
+
while True:
|
485
|
+
if self.state != "wait":
|
486
|
+
if self.state == "terminate":
|
487
|
+
return # Abort all the processes was requested. This state change would be after clearing.
|
488
|
+
self.update_state("wait")
|
489
|
+
self.update_status()
|
490
|
+
status = self._status[1]
|
491
|
+
if status == 0:
|
492
|
+
self.close()
|
493
|
+
self.open()
|
494
|
+
continue
|
495
|
+
if status == STATUS_OK:
|
496
|
+
break
|
497
|
+
if self.context is not None:
|
498
|
+
self.context.signal("pipe;wait", status, i)
|
499
|
+
i += 1
|
500
|
+
if self.abort_waiting:
|
501
|
+
self.abort_waiting = False
|
502
|
+
return # Wait abort was requested.
|
503
|
+
if status == STATUS_PROCESSING:
|
504
|
+
time.sleep(0.5) # Half a second between requests.
|
505
|
+
self.update_state(original_state)
|