pytrain-ogr-deck 2.9.10__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.
- pytrain/__init__.py +230 -0
- pytrain/_version.py +24 -0
- pytrain/atc/__init__.py +9 -0
- pytrain/atc/block.py +494 -0
- pytrain/cli/__init__.py +334 -0
- pytrain/cli/acc.py +135 -0
- pytrain/cli/amc2.py +188 -0
- pytrain/cli/asc2.py +116 -0
- pytrain/cli/bpc2.py +84 -0
- pytrain/cli/cache.py +260 -0
- pytrain/cli/clear.py +158 -0
- pytrain/cli/configure.py +1130 -0
- pytrain/cli/csv_export.py +209 -0
- pytrain/cli/dialogs.py +512 -0
- pytrain/cli/echo.py +39 -0
- pytrain/cli/effects.py +297 -0
- pytrain/cli/engine.py +881 -0
- pytrain/cli/halt.py +43 -0
- pytrain/cli/lcs.py +188 -0
- pytrain/cli/lighting.py +299 -0
- pytrain/cli/make_base.py +371 -0
- pytrain/cli/make_gui.py +827 -0
- pytrain/cli/make_service.py +194 -0
- pytrain/cli/piconfig.py +480 -0
- pytrain/cli/pytrain.py +1833 -0
- pytrain/cli/reindex.py +462 -0
- pytrain/cli/route.py +44 -0
- pytrain/cli/sounds.py +244 -0
- pytrain/cli/switch.py +67 -0
- pytrain/comm/__init__.py +8 -0
- pytrain/comm/comm_buffer.py +962 -0
- pytrain/comm/command_listener.py +963 -0
- pytrain/comm/enqueue_proxy_requests.py +359 -0
- pytrain/comm/serial_reader.py +93 -0
- pytrain/db/__init__.py +0 -0
- pytrain/db/accessory_state.py +315 -0
- pytrain/db/base_state.py +163 -0
- pytrain/db/block_state.py +168 -0
- pytrain/db/cache_sync.py +722 -0
- pytrain/db/client_state_listener.py +226 -0
- pytrain/db/comp_data.py +1254 -0
- pytrain/db/component_state.py +1120 -0
- pytrain/db/component_state_store.py +602 -0
- pytrain/db/components.py +239 -0
- pytrain/db/engine_state.py +1341 -0
- pytrain/db/irda_state.py +207 -0
- pytrain/db/prod_info.py +245 -0
- pytrain/db/startup_state.py +203 -0
- pytrain/db/state_watcher.py +87 -0
- pytrain/db/sync_state.py +92 -0
- pytrain/db/watchable.py +37 -0
- pytrain/gpio/__init__.py +0 -0
- pytrain/gpio/base_watcher.py +101 -0
- pytrain/gpio/controller.py +629 -0
- pytrain/gpio/crane_car.py +283 -0
- pytrain/gpio/culvert_loader.py +39 -0
- pytrain/gpio/engine_controller.py +639 -0
- pytrain/gpio/engine_status.py +248 -0
- pytrain/gpio/gantry_crane.py +251 -0
- pytrain/gpio/gpio_device.py +174 -0
- pytrain/gpio/gpio_handler.py +843 -0
- pytrain/gpio/i2c/__init__.py +0 -0
- pytrain/gpio/i2c/ads_1x15.py +579 -0
- pytrain/gpio/i2c/analog_handler_i2c.py +161 -0
- pytrain/gpio/i2c/button_i2c.py +132 -0
- pytrain/gpio/i2c/i2c.py +40 -0
- pytrain/gpio/i2c/i2c_device.py +18 -0
- pytrain/gpio/i2c/lcd.py +150 -0
- pytrain/gpio/i2c/led_i2c.py +203 -0
- pytrain/gpio/i2c/mcp23017.py +631 -0
- pytrain/gpio/i2c/oled.py +450 -0
- pytrain/gpio/keypad.py +494 -0
- pytrain/gpio/launch_pad.py +193 -0
- pytrain/gpio/launch_status.py +331 -0
- pytrain/gpio/power_district.py +63 -0
- pytrain/gpio/power_watcher.py +45 -0
- pytrain/gpio/py_rotary_encoder.py +163 -0
- pytrain/gpio/route.py +72 -0
- pytrain/gpio/smoke_fluid_loader.py +104 -0
- pytrain/gpio/state_source.py +170 -0
- pytrain/gpio/switch.py +67 -0
- pytrain/gpio/sys_admin.py +92 -0
- pytrain/gpio/utils/__init__.py +0 -0
- pytrain/gpio/utils/sh1122.py +115 -0
- pytrain/gpio/utils/text_buffer.py +248 -0
- pytrain/gui/__init__.py +0 -0
- pytrain/gui/accessories/__init__.py +8 -0
- pytrain/gui/accessories/accessory_base.py +723 -0
- pytrain/gui/accessories/accessory_gui.py +144 -0
- pytrain/gui/accessories/accessory_gui_catalog.py +114 -0
- pytrain/gui/accessories/accessory_registry.py +507 -0
- pytrain/gui/accessories/accessory_type.py +59 -0
- pytrain/gui/accessories/bootstrap_accessories.py +70 -0
- pytrain/gui/accessories/config.py +246 -0
- pytrain/gui/accessories/configured_accessory.py +892 -0
- pytrain/gui/accessories/construction_gui.py +113 -0
- pytrain/gui/accessories/control_tower_gui.py +138 -0
- pytrain/gui/accessories/culvert_gui.py +91 -0
- pytrain/gui/accessories/defs/__init__.py +8 -0
- pytrain/gui/accessories/defs/base_defs.py +223 -0
- pytrain/gui/accessories/defs/construction_defs.py +108 -0
- pytrain/gui/accessories/defs/control_tower_defs.py +142 -0
- pytrain/gui/accessories/defs/culvert_handler_defs.py +161 -0
- pytrain/gui/accessories/defs/fire_station_defs.py +128 -0
- pytrain/gui/accessories/defs/freight_depot_defs.py +107 -0
- pytrain/gui/accessories/defs/gas_station_defs.py +154 -0
- pytrain/gui/accessories/defs/hobby_shop_defs.py +135 -0
- pytrain/gui/accessories/defs/milk_loader_defs.py +143 -0
- pytrain/gui/accessories/defs/playground_defs.py +142 -0
- pytrain/gui/accessories/defs/single_latch_defs.py +126 -0
- pytrain/gui/accessories/defs/smoke_fluid_loader_defs.py +130 -0
- pytrain/gui/accessories/defs/station_defs.py +228 -0
- pytrain/gui/accessories/defs/uncoupler_defs.py +106 -0
- pytrain/gui/accessories/fire_station_gui.py +133 -0
- pytrain/gui/accessories/freight_depot_gui.py +120 -0
- pytrain/gui/accessories/gas_station_gui.py +112 -0
- pytrain/gui/accessories/hobby_shop_gui.py +99 -0
- pytrain/gui/accessories/milk_loader_gui.py +128 -0
- pytrain/gui/accessories/playground_gui.py +127 -0
- pytrain/gui/accessories/single_latch_gui.py +134 -0
- pytrain/gui/accessories/smoke_fluid_loader_gui.py +191 -0
- pytrain/gui/accessories/station_gui.py +164 -0
- pytrain/gui/accessories/uncoupler_gui.py +89 -0
- pytrain/gui/accessories_gui.py +123 -0
- pytrain/gui/component_state_gui.py +176 -0
- pytrain/gui/components/__init__.py +8 -0
- pytrain/gui/components/analog_gauge.py +420 -0
- pytrain/gui/components/checkbox_group.py +694 -0
- pytrain/gui/components/editable_text.py +1142 -0
- pytrain/gui/components/hold_button.py +1159 -0
- pytrain/gui/components/scroll_box.py +620 -0
- pytrain/gui/components/scrolling_text.py +333 -0
- pytrain/gui/components/spinner.py +533 -0
- pytrain/gui/components/swipe_detector.py +232 -0
- pytrain/gui/components/touch_contact.py +217 -0
- pytrain/gui/components/touch_list.py +155 -0
- pytrain/gui/components/touch_list_box.py +426 -0
- pytrain/gui/controller/__init__.py +8 -0
- pytrain/gui/controller/accessory_bindings.py +800 -0
- pytrain/gui/controller/admin_panel.py +1062 -0
- pytrain/gui/controller/amc2_ops_panel.py +705 -0
- pytrain/gui/controller/bell_horn_panel.py +129 -0
- pytrain/gui/controller/catalog_panel.py +346 -0
- pytrain/gui/controller/configured_accessory_adapter.py +234 -0
- pytrain/gui/controller/configured_accessory_adapter_provider.py +227 -0
- pytrain/gui/controller/control_labels.py +651 -0
- pytrain/gui/controller/controller_view.py +1494 -0
- pytrain/gui/controller/controls_panel.py +1304 -0
- pytrain/gui/controller/engine_gui.py +2978 -0
- pytrain/gui/controller/engine_gui_conf.py +594 -0
- pytrain/gui/controller/image_presenter.py +440 -0
- pytrain/gui/controller/keypad_view.py +1518 -0
- pytrain/gui/controller/lcs_config_panel.py +5536 -0
- pytrain/gui/controller/lcs_device_registry.py +992 -0
- pytrain/gui/controller/lcs_gui.py +223 -0
- pytrain/gui/controller/lcs_id_map.py +557 -0
- pytrain/gui/controller/lcs_sequence_builder.py +111 -0
- pytrain/gui/controller/lighting_panel.py +119 -0
- pytrain/gui/controller/overlay_panel.py +106 -0
- pytrain/gui/controller/popup_manager.py +918 -0
- pytrain/gui/controller/rr_speed_panel.py +75 -0
- pytrain/gui/controller/speed_limit_panel.py +127 -0
- pytrain/gui/controller/state_info_overlay.py +444 -0
- pytrain/gui/controller/steam_deck_default.json +183 -0
- pytrain/gui/controller/steam_deck_gui.py +562 -0
- pytrain/gui/controller/steam_deck_input.py +2553 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAM.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMFAT.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMFATNARROW.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMFATSKEW.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMFATSKEWNARROW.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMNARROW.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMSKEW.ttf +0 -0
- pytrain/gui/fonts/digital-dream/DIGITALDREAMSKEWNARROW.ttf +0 -0
- pytrain/gui/guizero_base.py +1039 -0
- pytrain/gui/images/192-Control-Tower-6-37996.jpg +0 -0
- pytrain/gui/images/192-Control-Tower-6-82014.jpg +0 -0
- pytrain/gui/images/192R-Railroad-Control-Tower-6-32988.jpg +0 -0
- pytrain/gui/images/Adolph-Coors-Brewing-Co-30-9161.jpg +0 -0
- pytrain/gui/images/Advanced-Smoke-Fluid-Loader-6-37821.jpg +0 -0
- pytrain/gui/images/Altoona-Brewing-CO-30-90191.jpg +0 -0
- pytrain/gui/images/Atlantic-Gas-Station-30-91003.jpg +0 -0
- pytrain/gui/images/BP-Gas-Station-30-9181.jpg +0 -0
- pytrain/gui/images/Backhoe-Construction-Scene-K-42416.gif +0 -0
- pytrain/gui/images/Breaking-News-Emoji.gif +0 -0
- pytrain/gui/images/Budweiser-30-9171.jpg +0 -0
- pytrain/gui/images/Citgo-Gas-Station-30-9113.jpg +0 -0
- pytrain/gui/images/Dairymens-League-6-14291.jpg +0 -0
- pytrain/gui/images/Engine-Company-1-MTH-30-9136.jpg +0 -0
- pytrain/gui/images/Engine-Company-219-MTH-30-9159.jpg +0 -0
- pytrain/gui/images/Engine-Company-234-MTH-30-9102.jpg +0 -0
- pytrain/gui/images/Engine-Company-54-MTH-30-9196.jpg +0 -0
- pytrain/gui/images/Esso-Gas-Station-30-9106.jpg +0 -0
- pytrain/gui/images/Fastrack-Uncoupling-6-12020.jpg +0 -0
- pytrain/gui/images/Fire-Station-MTH-30-9157.jpg +0 -0
- pytrain/gui/images/Freight-Depot-Platform-30-9199.jpg +0 -0
- pytrain/gui/images/Gray-Fire-Station-MTH-30-9112.jpg +0 -0
- pytrain/gui/images/Gulf-Gas-Station-30-9168.jpg +0 -0
- pytrain/gui/images/Hobo-Depot-6-34191.jpg +0 -0
- pytrain/gui/images/K-Line-Operating-Freight-Platform-6-21449.jpg +0 -0
- pytrain/gui/images/K-Lineville-Freight-Depot-K-42418.jpg +0 -0
- pytrain/gui/images/Keystone-Smoke-Fluid-Loader-6-83634.jpg +0 -0
- pytrain/gui/images/LCS-AMC2-6-81641.jpg +0 -0
- pytrain/gui/images/LCS-ASC2-6-81639.jpg +0 -0
- pytrain/gui/images/LCS-BPC2-6-81640.jpg +0 -0
- pytrain/gui/images/LCS-Sensor-Track-6-81294.jpg +0 -0
- pytrain/gui/images/Lionelville-Culvert-Loader-6-82029.jpg +0 -0
- pytrain/gui/images/Lionelville-Culvert-Unloader-6-82030.jpg +0 -0
- pytrain/gui/images/Lionelville-Hobby-Shop-6-85294.jpg +0 -0
- pytrain/gui/images/Madison-Hobby-Shop-6-14133.jpg +0 -0
- pytrain/gui/images/Man-With-Handcart.png +0 -0
- pytrain/gui/images/Middletown-Freight-Station-30-9184.jpg +0 -0
- pytrain/gui/images/Middletown-Military-Station-30-9183.jpg +0 -0
- pytrain/gui/images/Middletown-Passenger-Station-30-9125.jpg +0 -0
- pytrain/gui/images/Midtown-Models-Hobby-Shop-6-32998.jpg +0 -0
- pytrain/gui/images/Mobile-Gas-Station-30-9124.jpg +0 -0
- pytrain/gui/images/Moose-Pond-Creamery-6-22660.jpg +0 -0
- pytrain/gui/images/Mountain-View-Creamery-6-21675.jpg +0 -0
- pytrain/gui/images/NASA-Mission-Control-Tower-2229040.jpg +0 -0
- pytrain/gui/images/New-York-Central-Freight-Station-30-9151.jpg +0 -0
- pytrain/gui/images/New-York-Central-Passenger-Station-30-9164.jpg +0 -0
- pytrain/gui/images/Numbers-1-Black-icon.png +0 -0
- pytrain/gui/images/Old-Reading-Brewing-Co-30-90190.jpg +0 -0
- pytrain/gui/images/Pennsylvania-Railroad-PRR-30-9152.jpg +0 -0
- pytrain/gui/images/Pittsburgh-Brewing-Co-30-90189.jpg +0 -0
- pytrain/gui/images/Playground-6-82104.jpg +0 -0
- pytrain/gui/images/Radio-Control-Tower-6-24153.jpg +0 -0
- pytrain/gui/images/Route-66-Gas-Station-30-91002.jpg +0 -0
- pytrain/gui/images/Safety-Attention-Sticker.gif +0 -0
- pytrain/gui/images/Shell-Gas-Station-30-9182.jpg +0 -0
- pytrain/gui/images/Sinclair-Gas-Station-30-9101.jpg +0 -0
- pytrain/gui/images/Sunoco-Gas-Station-30-9154.jpg +0 -0
- pytrain/gui/images/Swing-6-14199.jpg +0 -0
- pytrain/gui/images/Texaco-Gas-Station-30-91001.jpg +0 -0
- pytrain/gui/images/Tidewater-Oil-Gas-Station-30-9181.jpg +0 -0
- pytrain/gui/images/Tire-Swing-6-82105.jpg +0 -0
- pytrain/gui/images/Tug-of-War-6-82107.jpg +0 -0
- pytrain/gui/images/Union-76-Gas-Station-30-9109.jpg +0 -0
- pytrain/gui/images/__init__.py +0 -0
- pytrain/gui/images/abort.jpg +0 -0
- pytrain/gui/images/animated_backhoe.gif +0 -0
- pytrain/gui/images/brews-waiting.png +0 -0
- pytrain/gui/images/bulb-power-off.png +0 -0
- pytrain/gui/images/bulb-power-on.png +0 -0
- pytrain/gui/images/control_tower_animation.gif +0 -0
- pytrain/gui/images/delete-key.jpg +0 -0
- pytrain/gui/images/depot-milk-can-eject.jpeg +0 -0
- pytrain/gui/images/engine_gui/RR-Speeds.jpg +0 -0
- pytrain/gui/images/engine_gui/acela.jpg +0 -0
- pytrain/gui/images/engine_gui/aux-hook.jpg +0 -0
- pytrain/gui/images/engine_gui/bell.jpg +0 -0
- pytrain/gui/images/engine_gui/blend-down.jpg +0 -0
- pytrain/gui/images/engine_gui/blend-up.jpg +0 -0
- pytrain/gui/images/engine_gui/boom.jpg +0 -0
- pytrain/gui/images/engine_gui/boost.jpg +0 -0
- pytrain/gui/images/engine_gui/brake.jpg +0 -0
- pytrain/gui/images/engine_gui/car-lights-off.jpg +0 -0
- pytrain/gui/images/engine_gui/car-lights-on.jpg +0 -0
- pytrain/gui/images/engine_gui/conductor.jpg +0 -0
- pytrain/gui/images/engine_gui/effect-down.jpg +0 -0
- pytrain/gui/images/engine_gui/effect-up.jpg +0 -0
- pytrain/gui/images/engine_gui/flat-wheel-off.jpg +0 -0
- pytrain/gui/images/engine_gui/flat-wheel-on.jpg +0 -0
- pytrain/gui/images/engine_gui/front-coupler.jpg +0 -0
- pytrain/gui/images/engine_gui/front-lamp.jpg +0 -0
- pytrain/gui/images/engine_gui/fuel-level.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_crane_car.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_diesel.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_diesel_switcher.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_electric.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_freight.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_passenger_car.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_steam.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_steam_santa.jpg +0 -0
- pytrain/gui/images/engine_gui/generic_steam_switcher.jpg +0 -0
- pytrain/gui/images/engine_gui/horn.jpg +0 -0
- pytrain/gui/images/engine_gui/lights-off.jpg +0 -0
- pytrain/gui/images/engine_gui/lights-on.jpg +0 -0
- pytrain/gui/images/engine_gui/load.jpg +0 -0
- pytrain/gui/images/engine_gui/loading_image.png +0 -0
- pytrain/gui/images/engine_gui/main-hook.jpg +0 -0
- pytrain/gui/images/engine_gui/master-down.jpg +0 -0
- pytrain/gui/images/engine_gui/master-up.jpg +0 -0
- pytrain/gui/images/engine_gui/next-stop.jpg +0 -0
- pytrain/gui/images/engine_gui/outriggers.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-down-a.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-down-f.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-down-r.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-up-a.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-up-f.jpg +0 -0
- pytrain/gui/images/engine_gui/panto-up-r.jpg +0 -0
- pytrain/gui/images/engine_gui/panto_down.jpg +0 -0
- pytrain/gui/images/engine_gui/panto_up.jpg +0 -0
- pytrain/gui/images/engine_gui/power_master.jpg +0 -0
- pytrain/gui/images/engine_gui/rail_crossing.jpg +0 -0
- pytrain/gui/images/engine_gui/rear-coupler.jpg +0 -0
- pytrain/gui/images/engine_gui/rear-lamp.jpg +0 -0
- pytrain/gui/images/engine_gui/roll-speed.jpg +0 -0
- pytrain/gui/images/engine_gui/rpm-down.jpg +0 -0
- pytrain/gui/images/engine_gui/rpm-up.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-down.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-high.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-low.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-med.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-off.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-on.jpg +0 -0
- pytrain/gui/images/engine_gui/smoke-up.jpg +0 -0
- pytrain/gui/images/engine_gui/sound-off.jpg +0 -0
- pytrain/gui/images/engine_gui/sound-on.jpg +0 -0
- pytrain/gui/images/engine_gui/station.jpg +0 -0
- pytrain/gui/images/engine_gui/steward.jpg +0 -0
- pytrain/gui/images/engine_gui/stock-a-off.jpg +0 -0
- pytrain/gui/images/engine_gui/stock-a-on.jpg +0 -0
- pytrain/gui/images/engine_gui/stock-b-off.jpg +0 -0
- pytrain/gui/images/engine_gui/stock-b-on.jpg +0 -0
- pytrain/gui/images/engine_gui/toggle.jpg +0 -0
- pytrain/gui/images/engine_gui/unload.jpg +0 -0
- pytrain/gui/images/engine_gui/vol-down.jpg +0 -0
- pytrain/gui/images/engine_gui/vol-up.jpg +0 -0
- pytrain/gui/images/engine_gui/water-level.jpg +0 -0
- pytrain/gui/images/engine_gui/whistle.jpg +0 -0
- pytrain/gui/images/engines/2127380.jpg +0 -0
- pytrain/gui/images/engines/2127390.jpg +0 -0
- pytrain/gui/images/engines/2133640.jpg +0 -0
- pytrain/gui/images/engines/2133760.jpg +0 -0
- pytrain/gui/images/engines/2135110.jpg +0 -0
- pytrain/gui/images/engines/2229300.jpg +0 -0
- pytrain/gui/images/engines/2234040.jpg +0 -0
- pytrain/gui/images/engines/2333080.jpg +0 -0
- pytrain/gui/images/engines/2333088.jpg +0 -0
- pytrain/gui/images/engines/2333331-B.jpg +0 -0
- pytrain/gui/images/engines/2335090.jpg +0 -0
- pytrain/gui/images/engines/2427170.jpg +0 -0
- pytrain/gui/images/engines/2526430.jpg +0 -0
- pytrain/gui/images/engines/2527180.jpg +0 -0
- pytrain/gui/images/engines/2535130.jpg +0 -0
- pytrain/gui/images/engines/2633240.jpg +0 -0
- pytrain/gui/images/engines/6-11224.jpg +0 -0
- pytrain/gui/images/engines/6-18353.jpg +0 -0
- pytrain/gui/images/engines/6-28338.jpg +0 -0
- pytrain/gui/images/engines/6-28411.jpg +0 -0
- pytrain/gui/images/engines/6-31747.jpg +0 -0
- pytrain/gui/images/engines/6-37064.jpg +0 -0
- pytrain/gui/images/engines/6-38466.jpg +0 -0
- pytrain/gui/images/engines/6-38527.jpg +0 -0
- pytrain/gui/images/engines/6-38528.jpg +0 -0
- pytrain/gui/images/engines/6-38805.jpg +0 -0
- pytrain/gui/images/engines/6-51007.jpg +0 -0
- pytrain/gui/images/engines/6-81142.jpg +0 -0
- pytrain/gui/images/engines/6-81212.jpg +0 -0
- pytrain/gui/images/engines/6-81443.jpg +0 -0
- pytrain/gui/images/engines/6-81883.jpg +0 -0
- pytrain/gui/images/engines/6-81888.jpg +0 -0
- pytrain/gui/images/engines/6-85183.jpg +0 -0
- pytrain/gui/images/freight-waiting.jpg +0 -0
- pytrain/gui/images/gas-station-car.png +0 -0
- pytrain/gui/images/green_light.jpg +0 -0
- pytrain/gui/images/green_light_off.jpg +0 -0
- pytrain/gui/images/launch.jpg +0 -0
- pytrain/gui/images/launch_btn.jpg +0 -0
- pytrain/gui/images/left_arrow.jpg +0 -0
- pytrain/gui/images/let-off.jpg +0 -0
- pytrain/gui/images/load_culvert.png +0 -0
- pytrain/gui/images/loaded.png +0 -0
- pytrain/gui/images/off_button.jpg +0 -0
- pytrain/gui/images/on_button.jpg +0 -0
- pytrain/gui/images/op-acc.jpg +0 -0
- pytrain/gui/images/op-asc2.jpg +0 -0
- pytrain/gui/images/op-bpc2.jpg +0 -0
- pytrain/gui/images/op-control-tower.jpg +0 -0
- pytrain/gui/images/op-fire-station.jpg +0 -0
- pytrain/gui/images/op-gas-station.jpg +0 -0
- pytrain/gui/images/op-hobby-shop.jpg +0 -0
- pytrain/gui/images/op-hobo-depot.jpg +0 -0
- pytrain/gui/images/op-log-loader.jpg +0 -0
- pytrain/gui/images/op-milk-loader.jpg +0 -0
- pytrain/gui/images/op-playground.jpg +0 -0
- pytrain/gui/images/op-screen.jpg +0 -0
- pytrain/gui/images/op-smoke-fluid.jpg +0 -0
- pytrain/gui/images/op-station.jpg +0 -0
- pytrain/gui/images/op-uncoupler.jpg +0 -0
- pytrain/gui/images/passengers-waiting.png +0 -0
- pytrain/gui/images/raw-acc.jpg +0 -0
- pytrain/gui/images/raw-acs2.jpg +0 -0
- pytrain/gui/images/raw-keypad.jpg +0 -0
- pytrain/gui/images/red_light.jpg +0 -0
- pytrain/gui/images/red_light_off.jpg +0 -0
- pytrain/gui/images/right_arrow.jpg +0 -0
- pytrain/gui/images/smoke-fluid.png +0 -0
- pytrain/gui/images/swinging-child.jpg +0 -0
- pytrain/gui/images/tire-swing-child.jpg +0 -0
- pytrain/gui/images/tower.jpg +0 -0
- pytrain/gui/images/tower.png +0 -0
- pytrain/gui/images/tug-of-war.jpg +0 -0
- pytrain/gui/images/uncouple-motion.jpg +0 -0
- pytrain/gui/images/unload_culvert.png +0 -0
- pytrain/gui/images/walkie_talkie.jpg +0 -0
- pytrain/gui/images/walkie_talkie.png +0 -0
- pytrain/gui/images/water-inject.jpg +0 -0
- pytrain/gui/launch_gui.py +650 -0
- pytrain/gui/motors_gui.py +657 -0
- pytrain/gui/power_district_gui.py +84 -0
- pytrain/gui/routes_gui.py +71 -0
- pytrain/gui/state_based_gui.py +524 -0
- pytrain/gui/switches_gui.py +71 -0
- pytrain/gui/systems_gui.py +171 -0
- pytrain/gui/wide_component_state_gui.py +649 -0
- pytrain/installation/__init__.py +9 -0
- pytrain/installation/buttons_gui.py.template +14 -0
- pytrain/installation/launch_pytrain.bash.template +80 -0
- pytrain/installation/pytrain.bash.template +45 -0
- pytrain/installation/pytrain.service.template +14 -0
- pytrain/installation/pytrain_desktop.template +6 -0
- pytrain/pdi/__init__.py +0 -0
- pytrain/pdi/amc2_req.py +383 -0
- pytrain/pdi/asc2_req.py +222 -0
- pytrain/pdi/base3_buffer.py +292 -0
- pytrain/pdi/base3_db_refresh_manager.py +222 -0
- pytrain/pdi/base_req.py +934 -0
- pytrain/pdi/block_req.py +146 -0
- pytrain/pdi/bpc2_req.py +181 -0
- pytrain/pdi/constants.py +561 -0
- pytrain/pdi/d4_req.py +251 -0
- pytrain/pdi/irda_req.py +310 -0
- pytrain/pdi/lcs_req.py +268 -0
- pytrain/pdi/pdi_device.py +518 -0
- pytrain/pdi/pdi_listener.py +472 -0
- pytrain/pdi/pdi_req.py +460 -0
- pytrain/pdi/pdi_state_store.py +106 -0
- pytrain/pdi/stm2_req.py +122 -0
- pytrain/pdi/wifi_req.py +78 -0
- pytrain/protocol/__init__.py +0 -0
- pytrain/protocol/command_base.py +234 -0
- pytrain/protocol/command_def.py +344 -0
- pytrain/protocol/command_req.py +762 -0
- pytrain/protocol/constants.py +395 -0
- pytrain/protocol/multibyte/__init__.py +0 -0
- pytrain/protocol/multibyte/dcds_command_req.py +179 -0
- pytrain/protocol/multibyte/dialog_cmd.py +17 -0
- pytrain/protocol/multibyte/effects_cmd.py +17 -0
- pytrain/protocol/multibyte/lighting_cmd.py +17 -0
- pytrain/protocol/multibyte/masking_cmd.py +17 -0
- pytrain/protocol/multibyte/multibyte_command_req.py +228 -0
- pytrain/protocol/multibyte/multibyte_constants.py +908 -0
- pytrain/protocol/multibyte/param_command_req.py +113 -0
- pytrain/protocol/multibyte/r4lc_command_req.py +86 -0
- pytrain/protocol/multibyte/sound_effects_cmd.py +17 -0
- pytrain/protocol/sequence/__init__.py +0 -0
- pytrain/protocol/sequence/abs_speed_rpm.py +49 -0
- pytrain/protocol/sequence/cycle_tone_req.py +82 -0
- pytrain/protocol/sequence/grade_crossing_req.py +48 -0
- pytrain/protocol/sequence/labor_effect.py +90 -0
- pytrain/protocol/sequence/ramped_speed_req.py +191 -0
- pytrain/protocol/sequence/sequence_constants.py +75 -0
- pytrain/protocol/sequence/sequence_req.py +368 -0
- pytrain/protocol/sequence/set_speed_req.py +66 -0
- pytrain/protocol/sequence/speed_req.py +27 -0
- pytrain/protocol/sequence/steward_chatter_req.py +44 -0
- pytrain/protocol/tmcc1/__init__.py +0 -0
- pytrain/protocol/tmcc1/acc_cmd.py +21 -0
- pytrain/protocol/tmcc1/engine_cmd.py +26 -0
- pytrain/protocol/tmcc1/halt_cmd.py +16 -0
- pytrain/protocol/tmcc1/route_cmd.py +16 -0
- pytrain/protocol/tmcc1/switch_cmd.py +21 -0
- pytrain/protocol/tmcc1/tmcc1_command.py +41 -0
- pytrain/protocol/tmcc1/tmcc1_constants.py +658 -0
- pytrain/protocol/tmcc2/__init__.py +0 -0
- pytrain/protocol/tmcc2/engine_cmd.py +24 -0
- pytrain/protocol/tmcc2/halt_cmd.py +15 -0
- pytrain/protocol/tmcc2/route_cmd.py +18 -0
- pytrain/protocol/tmcc2/tmcc2_command.py +62 -0
- pytrain/protocol/tmcc2/tmcc2_constants.py +459 -0
- pytrain/utils/__init__.py +10 -0
- pytrain/utils/argument_parser.py +202 -0
- pytrain/utils/dual_logging.py +159 -0
- pytrain/utils/expiring_set.py +65 -0
- pytrain/utils/host_info.py +139 -0
- pytrain/utils/image_utils.py +106 -0
- pytrain/utils/ip_tools.py +144 -0
- pytrain/utils/path_utils.py +168 -0
- pytrain/utils/perf_utils.py +37 -0
- pytrain/utils/pollable_queue.py +49 -0
- pytrain/utils/singleton.py +82 -0
- pytrain/utils/text_utils.py +67 -0
- pytrain/utils/unique_deque.py +147 -0
- pytrain/utils/validations.py +68 -0
- pytrain/utils/wifi_info.py +264 -0
- pytrain_ogr_deck-2.9.10.dist-info/METADATA +823 -0
- pytrain_ogr_deck-2.9.10.dist-info/RECORD +494 -0
- pytrain_ogr_deck-2.9.10.dist-info/WHEEL +5 -0
- pytrain_ogr_deck-2.9.10.dist-info/entry_points.txt +11 -0
- pytrain_ogr_deck-2.9.10.dist-info/licenses/AUTHORS +1 -0
- pytrain_ogr_deck-2.9.10.dist-info/licenses/LICENSE +165 -0
- pytrain_ogr_deck-2.9.10.dist-info/top_level.txt +1 -0
pytrain/__init__.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#
|
|
2
|
+
#
|
|
3
|
+
# PyTrain: a library for controlling Lionel Legacy engines, trains, switches, and accessories
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) 2024-2025 Dave Swindell <pytraininfo.gmail.com>
|
|
6
|
+
#
|
|
7
|
+
# SPDX-License-Identifier: LPGL
|
|
8
|
+
|
|
9
|
+
import importlib.metadata
|
|
10
|
+
import sys
|
|
11
|
+
from importlib.metadata import PackageNotFoundError
|
|
12
|
+
|
|
13
|
+
from .atc.block import Block # noqa: F401
|
|
14
|
+
from .cli.pytrain import (
|
|
15
|
+
PyTrain,
|
|
16
|
+
PyTrainExitException, # noqa: F401
|
|
17
|
+
PyTrainExitStatus, # noqa: F401
|
|
18
|
+
)
|
|
19
|
+
from .db.accessory_state import AccessoryState # noqa: F401
|
|
20
|
+
from .db.component_state import (
|
|
21
|
+
ComponentState, # noqa: F401
|
|
22
|
+
RouteState, # noqa: F401
|
|
23
|
+
SwitchState, # noqa: F401
|
|
24
|
+
)
|
|
25
|
+
from .db.component_state_store import ComponentStateStore # noqa: F401
|
|
26
|
+
from .db.engine_state import EngineState, TrainState # noqa: F401
|
|
27
|
+
from .db.irda_state import IrdaState # noqa: F401
|
|
28
|
+
from .db.sync_state import SyncState # noqa: F401
|
|
29
|
+
from .gpio.base_watcher import BaseWatcher # noqa: F401
|
|
30
|
+
from .gpio.controller import Controller # noqa: F401
|
|
31
|
+
from .gpio.crane_car import CraneCar # noqa: F401
|
|
32
|
+
from .gpio.culvert_loader import CulvertLoader, CulvertUnloader # noqa: F401
|
|
33
|
+
from .gpio.engine_controller import EngineController # noqa: F401
|
|
34
|
+
from .gpio.engine_status import EngineStatus # noqa: F401
|
|
35
|
+
from .gpio.gantry_crane import GantryCrane # noqa: F401
|
|
36
|
+
from .gpio.gpio_handler import (
|
|
37
|
+
GpioHandler, # noqa: F401
|
|
38
|
+
JoyStickHandler, # noqa: F401
|
|
39
|
+
PotHandler, # noqa: F401
|
|
40
|
+
)
|
|
41
|
+
from .gpio.launch_pad import LaunchPad # noqa: F401
|
|
42
|
+
from .gpio.launch_status import LaunchStatus # noqa: F401
|
|
43
|
+
from .gpio.power_district import PowerDistrict # noqa: F401
|
|
44
|
+
from .gpio.power_watcher import PowerWatcher # noqa: F401
|
|
45
|
+
from .gpio.route import Route # noqa: F401
|
|
46
|
+
from .gpio.smoke_fluid_loader import SmokeFluidLoader # noqa: F401
|
|
47
|
+
from .gpio.switch import Switch # noqa: F401
|
|
48
|
+
from .gpio.sys_admin import SystemAdmin # noqa: F401
|
|
49
|
+
from .gui.accessories.accessory_gui import AccessoryGui # noqa: F401
|
|
50
|
+
from .gui.accessories.construction_gui import ConstructionGui # noqa: F401
|
|
51
|
+
from .gui.accessories.control_tower_gui import ControlTowerGui # noqa: F401
|
|
52
|
+
from .gui.accessories.culvert_gui import CulvertGui # noqa: F401
|
|
53
|
+
from .gui.accessories.fire_station_gui import FireStationGui # noqa: F401
|
|
54
|
+
from .gui.accessories.gas_station_gui import GasStationGui # noqa: F401
|
|
55
|
+
from .gui.accessories.hobby_shop_gui import HobbyShopGui # noqa: F401
|
|
56
|
+
from .gui.accessories.milk_loader_gui import MilkLoaderGui # noqa: F401
|
|
57
|
+
from .gui.accessories.playground_gui import PlaygroundGui # noqa: F401
|
|
58
|
+
from .gui.accessories.smoke_fluid_loader_gui import SmokeFluidLoaderGui # noqa: F401
|
|
59
|
+
from .gui.accessories.station_gui import StationGui # noqa: F401
|
|
60
|
+
from .gui.accessories_gui import AccessoriesGui # noqa: F401
|
|
61
|
+
from .gui.component_state_gui import ComponentStateGui # noqa: F401
|
|
62
|
+
from .gui.controller.engine_gui import EngineGui # noqa: F401
|
|
63
|
+
from .gui.controller.steam_deck_gui import SteamDeckGui # noqa: F401
|
|
64
|
+
from .gui.launch_gui import LaunchGui # noqa: F401
|
|
65
|
+
from .gui.motors_gui import MotorsGui # noqa: F401
|
|
66
|
+
from .gui.power_district_gui import PowerDistrictsGui # noqa: F401
|
|
67
|
+
from .gui.routes_gui import RoutesGui # noqa: F401
|
|
68
|
+
from .gui.switches_gui import SwitchesGui # noqa: F401
|
|
69
|
+
from .gui.systems_gui import SystemsGui # noqa: F401
|
|
70
|
+
from .gui.wide_component_state_gui import WideComponentStateGui # noqa: F401
|
|
71
|
+
from .protocol.command_def import CommandDefEnum # noqa: F401
|
|
72
|
+
from .protocol.command_req import CommandReq # noqa: F401
|
|
73
|
+
from .protocol.constants import (
|
|
74
|
+
CommandScope, # noqa: F401
|
|
75
|
+
CommandSyntax, # noqa: F401
|
|
76
|
+
ControlType, # noqa: F401
|
|
77
|
+
PROGRAM_BASE, # noqa: F401
|
|
78
|
+
PROGRAM_NAME,
|
|
79
|
+
)
|
|
80
|
+
from .protocol.multibyte.multibyte_constants import (
|
|
81
|
+
TMCC2EffectsControl, # noqa: F401
|
|
82
|
+
TMCC2LightingControl, # noqa: F401
|
|
83
|
+
TMCC2MaskingControl, # noqa: F401
|
|
84
|
+
TMCC2R4LCEnum, # noqa: F401
|
|
85
|
+
TMCC2RailSoundsDialogControl, # noqa: F401
|
|
86
|
+
TMCC2RailSoundsEffectsControl, # noqa: F401
|
|
87
|
+
TMCC2EngineCommandEnumEx, # noqa: F401
|
|
88
|
+
TMCC2VariableEnum, # noqa: F401
|
|
89
|
+
UnitAssignment, # noqa: F401
|
|
90
|
+
)
|
|
91
|
+
from .protocol.sequence.cycle_tone_req import (
|
|
92
|
+
CycleBellToneReq, # noqa: F401
|
|
93
|
+
CycleHornToneReq, # noqa: F401
|
|
94
|
+
)
|
|
95
|
+
from .protocol.sequence.grade_crossing_req import (
|
|
96
|
+
GradeCrossingReq, # noqa: F401
|
|
97
|
+
)
|
|
98
|
+
from .protocol.sequence.labor_effect import (
|
|
99
|
+
LaborEffectDownReq, # noqa: F401
|
|
100
|
+
LaborEffectUpReq, # noqa: F401
|
|
101
|
+
)
|
|
102
|
+
from .protocol.sequence.ramped_speed_req import (
|
|
103
|
+
RampedSpeedDialogReq, # noqa: F401
|
|
104
|
+
RampedSpeedReq, # noqa: F401
|
|
105
|
+
)
|
|
106
|
+
from .protocol.sequence.sequence_constants import (
|
|
107
|
+
SequenceCommandEnum, # noqa: F401 # noqa: F401
|
|
108
|
+
)
|
|
109
|
+
from .protocol.sequence.sequence_req import (
|
|
110
|
+
SequenceReq, # noqa: F401
|
|
111
|
+
SequencedReq, # noqa: F401
|
|
112
|
+
)
|
|
113
|
+
from .protocol.sequence.set_speed_req import (
|
|
114
|
+
SetSpeedReq, # noqa: F401
|
|
115
|
+
)
|
|
116
|
+
from .protocol.sequence.steward_chatter_req import (
|
|
117
|
+
StewardChatterReq, # noqa: F401
|
|
118
|
+
)
|
|
119
|
+
from .protocol.tmcc1.tmcc1_constants import (
|
|
120
|
+
TMCC1AuxCommandEnum, # noqa: F401
|
|
121
|
+
TMCC1EngineCommandEnum, # noqa: F401
|
|
122
|
+
TMCC1HaltCommandEnum, # noqa: F401
|
|
123
|
+
TMCC1RRSpeedsEnum, # noqa: F401
|
|
124
|
+
TMCC1RouteCommandEnum, # noqa: F401
|
|
125
|
+
TMCC1SwitchCommandEnum, # noqa: F401
|
|
126
|
+
)
|
|
127
|
+
from .protocol.tmcc2.tmcc2_constants import (
|
|
128
|
+
TMCC2EngineCommandEnum, # noqa: F401
|
|
129
|
+
TMCC2EngineOpsEnum, # noqa: F401
|
|
130
|
+
TMCC2HaltCommandEnum, # noqa: F401
|
|
131
|
+
TMCC2RRSpeedsEnum, # noqa: F401
|
|
132
|
+
TMCC2RouteCommandEnum, # noqa: F401
|
|
133
|
+
)
|
|
134
|
+
from .utils.host_info import is_linux # noqa: F401
|
|
135
|
+
from .utils.path_utils import (
|
|
136
|
+
find_dir, # noqa: F401
|
|
137
|
+
find_file, # noqa: F401
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
PROGRAM_PACKAGE = "pytrain-ogr"
|
|
141
|
+
PROGRAM_PACKAGE_DECK = "pytrain-ogr-deck"
|
|
142
|
+
|
|
143
|
+
# The distributions that install this package, most specific first. pytrain-ogr targets
|
|
144
|
+
# the Raspberry Pi and requires rpi-lgpio and spidev; pytrain-ogr-deck is the same
|
|
145
|
+
# release built without them, because neither is installable on the Steam Deck. Both
|
|
146
|
+
# provide the identical code and console scripts, so only one is ever installed.
|
|
147
|
+
PROGRAM_PACKAGES = (PROGRAM_PACKAGE, PROGRAM_PACKAGE_DECK)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def main(args: list[str] | None = None) -> int:
|
|
151
|
+
if args is None:
|
|
152
|
+
args = sys.argv[1:]
|
|
153
|
+
try:
|
|
154
|
+
PyTrain(args)
|
|
155
|
+
return 0
|
|
156
|
+
except Exception as e:
|
|
157
|
+
# Output anything else nicely formatted on stderr and exit code 1
|
|
158
|
+
sys.exit(f"{PROGRAM_NAME}: error: {e}\n")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def installed_package() -> str | None:
|
|
162
|
+
#
|
|
163
|
+
# which of the PyTrain distributions are we running from, if any? this is what
|
|
164
|
+
# tells a Steam Deck install to update itself rather than the Pi package...
|
|
165
|
+
#
|
|
166
|
+
for package in PROGRAM_PACKAGES:
|
|
167
|
+
try:
|
|
168
|
+
importlib.metadata.version(package)
|
|
169
|
+
return package
|
|
170
|
+
except PackageNotFoundError:
|
|
171
|
+
continue
|
|
172
|
+
return None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def is_package() -> bool:
|
|
176
|
+
# production version
|
|
177
|
+
return installed_package() is not None
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def get_version() -> str:
|
|
181
|
+
#
|
|
182
|
+
# this should be easier, but it is what it is.
|
|
183
|
+
# we handle the two major cases; we're running from
|
|
184
|
+
# the PyTrain pypi package, or we're running from
|
|
185
|
+
# source retrieved from git...
|
|
186
|
+
#
|
|
187
|
+
# we try the package path first...
|
|
188
|
+
version = None
|
|
189
|
+
package = installed_package()
|
|
190
|
+
if package is not None:
|
|
191
|
+
# production version
|
|
192
|
+
version = importlib.metadata.version(package)
|
|
193
|
+
|
|
194
|
+
# finally, call the method to read it from git
|
|
195
|
+
if version is None:
|
|
196
|
+
from setuptools_scm import get_version as get_git_version
|
|
197
|
+
|
|
198
|
+
version = get_git_version(root="../..", relative_to=__file__, version_scheme="only-version")
|
|
199
|
+
|
|
200
|
+
v_parts = version.split("+", 1)
|
|
201
|
+
version = v_parts[0] + ("" if len(v_parts) == 1 else "+")
|
|
202
|
+
version = version if version.startswith("v") else f"v{version}"
|
|
203
|
+
version = version.replace(".post0", "")
|
|
204
|
+
return version
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def get_version_tuple() -> tuple[int, int, int]:
|
|
208
|
+
version = get_version()
|
|
209
|
+
version = version.replace("v", "")
|
|
210
|
+
if "+" in version:
|
|
211
|
+
plus_pos = version.find("+")
|
|
212
|
+
version = version[0:plus_pos]
|
|
213
|
+
version = version.split(".")
|
|
214
|
+
return int(version[0]), int(version[1]), int(version[2])
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def get_version_bytes() -> bytes:
|
|
218
|
+
version = get_version_tuple()
|
|
219
|
+
ver_bytes = bytes()
|
|
220
|
+
for v in version:
|
|
221
|
+
ver_bytes += v.to_bytes(1, "big")
|
|
222
|
+
return ver_bytes
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
SMOKE_LEVEL_MAP = {
|
|
226
|
+
0: TMCC2EffectsControl.SMOKE_OFF,
|
|
227
|
+
1: TMCC2EffectsControl.SMOKE_LOW,
|
|
228
|
+
2: TMCC2EffectsControl.SMOKE_MEDIUM,
|
|
229
|
+
3: TMCC2EffectsControl.SMOKE_HIGH,
|
|
230
|
+
}
|
pytrain/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '2.9.10'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 9, 10)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
pytrain/atc/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#
|
|
2
|
+
# PyTrain: a library for controlling Lionel Legacy engines, trains, switches, and accessories.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2024-2026 Dave Swindell <pytraininfo.gmail.com>
|
|
5
|
+
#
|
|
6
|
+
# SPDX-FileCopyrightText: 2024-2026 Dave Swindell <pytraininfo.gmail.com>
|
|
7
|
+
# SPDX-License-Identifier: LGPL-3.0-only
|
|
8
|
+
#
|
|
9
|
+
|