Create distinct separate boxes for NAIL 1 and NAIL 2

- Changed from single box with divider to two completely separate boxes
- Nail 1 box in red header, Nail 2 box in blue header
- Two space gap between boxes for clear visual separation
- Condensed panel content to fit 24-character box width
- Essential metrics only: status, temp, error, output, mode, phase, safety
- Better visual distinction between the two nail controllers
- Deployed and verified on Pi
This commit is contained in:
2026-03-12 04:25:07 +00:00
parent 8f72402009
commit b22702bc9d
+34 -29
View File
@@ -156,51 +156,46 @@ class StatusDisplay:
lines = [] lines = []
# Header # Header
nail_name = "Nail 1" if nail_id == "nail1" else "Nail 2"
enabled = status.get("enabled", False) enabled = status.get("enabled", False)
has_error = status.get("error", False) has_error = status.get("error", False)
icon = self.format_status_icon(enabled, has_error) icon = self.format_status_icon(enabled, has_error)
status_text = "ONLINE" if enabled else "OFFLINE" status_text = "ONLINE" if enabled else "OFFLINE"
lines.append("{}{} {} {}{}".format( lines.append("{} {}{}".format(icon, status_text, Colors.RESET))
Colors.BOLD, nail_name, icon,
status_text,
Colors.RESET
))
# Temperature display # Temperature display
current = float(status.get("current_temp", 0)) current = float(status.get("current_temp", 0))
setpoint = float(status.get("setpoint", 0)) setpoint = float(status.get("setpoint", 0))
temp_str = "{:6.1f}F".format(current) if current else "ERROR" temp_str = "{:5.0f}F".format(current) if current else "ERROR"
setpt_str = "{:6.1f}F".format(setpoint) setpt_str = "{:5.0f}F".format(setpoint)
lines.append("Temp: {} / {}".format(temp_str, setpt_str)) lines.append("T: {} S: {}".format(temp_str, setpt_str))
# Error display # Error display
error = float(status.get("error", 0)) error = float(status.get("error", 0))
error_color = Colors.RED if abs(error) > 20 else Colors.YELLOW if abs(error) > 5 else Colors.GREEN error_color = Colors.RED if abs(error) > 20 else Colors.YELLOW if abs(error) > 5 else Colors.GREEN
lines.append("{}Error: {:+7.1f}F{}".format(error_color, error, Colors.RESET)) lines.append("{}Err: {:+5.1f}F{}".format(error_color, error, Colors.RESET))
# PID Output bar # PID Output bar
output = float(status.get("output", 0)) output = float(status.get("output", 0))
output_pct = min(100.0, max(0.0, output * 100)) output_pct = min(100.0, max(0.0, output * 100))
bar_filled = int(output_pct / 10) bar_filled = int(output_pct / 5)
bar = "{}[{}{}]{}".format( bar = "{}[{}{}]{}".format(
Colors.BRIGHT_GREEN, Colors.BRIGHT_GREEN,
"=" * bar_filled, "=" * bar_filled,
" " * (10 - bar_filled), " " * (5 - bar_filled),
Colors.RESET Colors.RESET
) )
lines.append("Output: {} {:5.1f}%".format(bar, output_pct)) lines.append("Out: {} {:3.0f}%".format(bar, output_pct))
# Flight mode and phase # Flight mode
mode = status.get("flight_mode", "grounded") mode = status.get("flight_mode", "grounded")
mode_short = mode[:7]
lines.append("Mode: {}".format(mode_short))
# Phase
phase = status.get("phase", "idle") phase = status.get("phase", "idle")
lines.append("{}Mode: {:<10} Phase: {}{}".format( phase_short = phase[:7]
Colors.CYAN, lines.append("Phase: {}".format(phase_short))
mode[:10],
phase[:8],
Colors.RESET
))
# Safety status # Safety status
safety = status.get("safety", {}) safety = status.get("safety", {})
@@ -208,8 +203,8 @@ class StatusDisplay:
tc_ok = safety.get("tc_ok", True) tc_ok = safety.get("tc_ok", True)
watchdog_ok = safety.get("watchdog_ok", True) watchdog_ok = safety.get("watchdog_ok", True)
safety_status = "{}Safety: OK{}".format(Colors.GREEN, Colors.RESET) if (temp_ok and tc_ok and watchdog_ok) else "{}Safety: WARN{}".format(Colors.RED, Colors.RESET) safety_status = "{}OK{}".format(Colors.GREEN, Colors.RESET) if (temp_ok and tc_ok and watchdog_ok) else "{}WARN{}".format(Colors.RED, Colors.RESET)
lines.append(safety_status) lines.append("Safety: {}".format(safety_status))
return lines return lines
@@ -271,18 +266,28 @@ class StatusDisplay:
while len(nail2_lines) < max_lines: while len(nail2_lines) < max_lines:
nail2_lines.append("") nail2_lines.append("")
# Draw side-by-side panels with better spacing # Draw separate boxes for each nail side-by-side
lines.append("{}┌─ NAIL 1 ─────────────────────┬─ NAIL 2 ─────────────────────┐{}".format( lines.append("{}┌──────────────────────────┐ ┌──────────────────────────┐{}".format(
Colors.CYAN, Colors.RESET))
lines.append("{}{}NAIL 1{} │ │ {}NAIL 2{}{}".format(
Colors.CYAN,
Colors.BRIGHT_RED + Colors.BOLD,
Colors.CYAN,
Colors.BRIGHT_BLUE + Colors.BOLD,
Colors.CYAN,
Colors.RESET
))
lines.append("{}├──────────────────────────┤ ├──────────────────────────┤{}".format(
Colors.CYAN, Colors.RESET)) Colors.CYAN, Colors.RESET))
for n1_line, n2_line in zip(nail1_lines, nail2_lines): for n1_line, n2_line in zip(nail1_lines, nail2_lines):
# Pad lines to 29 chars with good spacing # Pad lines to 24 chars for each box
left = "{:<27} ".format(n1_line[:27]) left = "{:<22} ".format(n1_line[:22])
right = "{:<27}".format(n2_line[:27]) right = "{:<22}".format(n2_line[:22])
lines.append("{}{}{}".format(left, right, Colors.RESET)) lines.append("{}{} {}{}".format(left, Colors.CYAN, right, Colors.RESET))
# Footer # Footer
lines.append("{}└───────────────────────────────┴───────────────────────────────┘{}".format( lines.append("{}└──────────────────────────┘ └──────────────────────────┘{}".format(
Colors.CYAN, Colors.RESET)) Colors.CYAN, Colors.RESET))
return "\n".join(lines) return "\n".join(lines)