Python API¶
Automatically generated from the source docstrings with
mkdocstrings. Run mkdocs serve to render
this page locally.
Plugin¶
The OctoPrint plugin implementation: mixins, settings, SimpleAPI and the rule application loop.
PandaBranchPlusPlugin ¶
PandaBranchPlusPlugin()
Bases: SettingsPlugin, AssetPlugin, TemplatePlugin, StartupPlugin, EventHandlerPlugin, SimpleApiPlugin, PrinterCallback
Source code in octoprint_pandabranchplus/__init__.py
78 79 80 81 82 83 84 85 86 87 88 | |
apply_channel_rules ¶
apply_channel_rules(reason='')
Resolve every channel's target on/off and switch where needed.
Manual channels follow manual_on; auto channels follow the state matrix combined with their temp rule (see rules.py). Only channels whose target differs from the live state get a WS command, rate limited per channel by min_switch_interval.
Source code in octoprint_pandabranchplus/__init__.py
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 474 475 476 477 478 479 480 481 482 | |
options: show_root_heading: true members_order: source
WebSocket client¶
The long-lived connection to the Panda: reconnect with backoff, TCP keepalive, state parsing, error classification.
PandaWsClient ¶
PandaWsClient(logger, host, port=80, path='/ws', on_state=None, on_connection=None, reconnect_min=1, reconnect_max=30, frame_log=False)
Long-lived WebSocket client for the Panda's channel control.
Parameters¶
logger:
A logger instance.
host, port, path:
Panda address and WebSocket endpoint (default port 80, path /ws).
on_state:
Callback on_state(channels: dict) invoked with the parsed channel
state of every push ({"usb": {id: 0|1}, "mx24v": {id: 0|1}}).
on_connection:
Callback on_connection(connected: bool) invoked on every
connect/disconnect of the socket.
reconnect_min, reconnect_max:
Backoff window (seconds) between reconnect attempts; the delay doubles
from min up to max after each failed attempt and resets on success.
frame_log:
When true, log every raw frame at DEBUG level (diagnostics).
Source code in octoprint_pandabranchplus/panda_ws.py
123 124 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 | |
current_state ¶
current_state()
Return the last known channel state snapshot.
Source code in octoprint_pandabranchplus/panda_ws.py
161 162 163 164 | |
set_channel ¶
set_channel(kind, channel_id, on)
Switch a channel on/off.
Sends {"<kind>": {"id": id, "on": 0|1}}. kind is "usb" or
"mx24v". Raises :class:PandaWsError on send failure. The Panda
confirms by broadcasting the new state, which arrives via on_state.
Source code in octoprint_pandabranchplus/panda_ws.py
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |
start ¶
start()
Open the connection and start the background receive/reconnect loop.
Source code in octoprint_pandabranchplus/panda_ws.py
168 169 170 171 172 173 174 175 176 177 | |
stop ¶
stop()
Close the connection and stop the loop. Idempotent.
Source code in octoprint_pandabranchplus/panda_ws.py
179 180 181 182 183 184 185 186 187 188 189 | |
options: show_root_heading: true members_order: source
PandaWsError ¶
PandaWsError(reason, message='')
Bases: Exception
A Panda WebSocket operation failed, carrying a classified reason.
reason is one of unreachable / timeout / send_failed so the
UI can translate it without parsing raw socket errors.
Source code in octoprint_pandabranchplus/panda_ws.py
30 31 32 | |
options: show_root_heading: true
test_connection ¶
test_connection(host, port=80, path='/ws', timeout=5)
One-shot connect: open the socket, read the snapshot, close.
Returns {"channels": {...}, "raw_keys": [...]} on success. Raises
:class:PandaWsError with a classified reason on failure. Used by the
settings dialog's "Test connection" button — runs against the entered
values, independent of the long-lived client.
Source code in octoprint_pandabranchplus/panda_ws.py
59 60 61 62 63 64 65 66 67 68 69 70 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 | |
options: show_root_heading: true
Rule engine¶
Pure functions — no OctoPrint imports, fully unit-tested.
rules ¶
Pure rule engine for the channel automation.
Kept free of OctoPrint imports so the decision logic is unit-testable in
isolation. The plugin resolves the current printer state and temperatures,
then asks :func:resolve_target what each channel should do.
Semantics (see .ideas/channel-automation-plan.md):
mode: "manual"always wins: the channel followsmanual_on, automation never touches it.mode: "auto": the state matrixrules[state]decides —"on","off"or"ignore"(= leave the channel exactly as it is).- An enabled
temp_rulefires when the sensor crossesthreshold(with hysteresis on the falling edge) and contributesabove("on"/"off") while active; while inactive it has no opinion. combine_logicmerges the two verdicts:temp_override: an active temp rule replaces the state verdict.and: on only if both say on, otherwise off.or: on if either says on, otherwise off.
evaluate_temp_rule ¶
evaluate_temp_rule(rule, temps, was_active, hysteresis)
Evaluate a channel's temperature rule.
Parameters¶
rule:
The channel's temp_rule dict (enabled, sensor,
threshold, above).
temps:
Last known temperatures, e.g. {"bed": 62.1, "tool": 210.4}.
Missing sensors simply keep the previous verdict (no flapping on
gaps in the data).
was_active:
Whether the rule was active after the previous evaluation (needed
for the hysteresis dead band).
hysteresis:
Dead band in degrees applied on the falling edge.
Returns (active, target) where target is rule["above"] while
active and None (no opinion) while inactive.
Source code in octoprint_pandabranchplus/rules.py
23 24 25 26 27 28 29 30 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 | |
map_octoprint_state ¶
map_octoprint_state(state_id)
Map an OctoPrint state id to the plugin's five canonical states.
STARTING is what BambuConnector reports for Bambu's PREPARE phase.
Anything unknown (offline, detecting, ...) counts as idle — no
printer means no print is running (see the plan's state resolution).
Source code in octoprint_pandabranchplus/rules.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
resolve_target ¶
resolve_target(channel, state, temps, was_active, combine_logic='temp_override', hysteresis=2)
Resolve what a channel should do right now.
Parameters¶
channel:
The channel's stored config (mode, manual_on, rules,
temp_rule).
state:
Canonical printer state: idle/prepare/printing/
paused/error.
temps / was_active / hysteresis:
See :func:evaluate_temp_rule.
combine_logic:
temp_override | and | or.
Returns (target, temp_active) where target is "on", "off"
or None (= leave the channel untouched).
Source code in octoprint_pandabranchplus/rules.py
61 62 63 64 65 66 67 68 69 70 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 | |
options: show_root_heading: true members_order: source
Hardware layout¶
hardware ¶
Fixed hardware layout of the Panda Branch Plus.
The Panda has 10 switchable outputs the firmware exposes under two WebSocket
roots: usb (5x Type-C) and mx24v (5x MX3.0 24V). The channel type is
fixed by the hardware and is shown as a badge in the UI; only the label is
user-editable. Verified layout: see .ideas/panda-branch-plus-recon.md.
channel_type ¶
channel_type(kind, channel_id)
Return the fixed type string for a channel, or None if unknown.
Source code in octoprint_pandabranchplus/hardware.py
33 34 35 | |
options: show_root_heading: true members_order: source