mirror of
https://github.com/RunLit/Bambu-Run.git
synced 2026-06-24 23:00:20 +01:00
Compare commits
5 Commits
feature/mu
...
feature/am
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cc5e85474 | ||
|
|
7dfa98dcc2 | ||
|
|
0a1da46d1f | ||
|
|
4c01b3d909 | ||
|
|
146d5af7aa |
@@ -22,19 +22,20 @@ RUN pip install --no-cache-dir bambu-lab-cloud-api --no-deps && \
|
||||
(d / 'INSTALLER').write_text('pip\n'); \
|
||||
(d / 'RECORD').write_text('')"
|
||||
|
||||
# Install project and remaining dependencies (pip sees opencv-python already satisfied)
|
||||
# Install standalone dependencies first — cached unless pyproject.toml changes
|
||||
COPY pyproject.toml .
|
||||
RUN pip install --no-cache-dir ".[standalone,mcp]"
|
||||
|
||||
# Copy application code
|
||||
# Copy full source and install the local package (no-deps: already installed above)
|
||||
COPY . .
|
||||
RUN pip install --no-cache-dir --no-deps .
|
||||
|
||||
# Create data directory for SQLite
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
# Collect static files
|
||||
# Collect static files from the locally installed package
|
||||
ENV DJANGO_SETTINGS_MODULE=standalone.settings
|
||||
RUN python standalone/manage.py collectstatic --noinput 2>/dev/null || true
|
||||
RUN python standalone/manage.py collectstatic --noinput
|
||||
|
||||
# Supervisor config to run both web and collector
|
||||
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
@@ -8,7 +8,8 @@ from django.utils import timezone
|
||||
AMS_INFO_TO_TYPE = {
|
||||
"1001": "AMS",
|
||||
"1003": "AMS 2 Pro",
|
||||
"2104": "AMS HT",
|
||||
"1104": "AMS HT", # observed on production H2C (last 4 of info code 11001104)
|
||||
"2104": "AMS HT", # observed in dev capture (last 4 of info code 11002104)
|
||||
}
|
||||
|
||||
AMS_TYPE_CHOICES = [
|
||||
|
||||
@@ -113,29 +113,14 @@
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
/* Grouped AMS unit panels — wide (multi-slot) units stack one per row,
|
||||
compact (single-slot, e.g. AMS HT) units flow side-by-side and wrap. */
|
||||
.ams-groups {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* Grouped AMS unit panels — Bootstrap row/col handles sizing;
|
||||
multi-slot units (AMS/AMS 2 Pro) are col-12, single-slot (AMS HT) are col-lg-3. */
|
||||
.ams-group {
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--ams-group-border-color);
|
||||
}
|
||||
|
||||
.ams-group--wide {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.ams-group--compact {
|
||||
flex: 0 1 auto;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.ams-badge-bg-ams {
|
||||
background-color: color-mix(in srgb, var(--ams-badge-ams) 8%, transparent);
|
||||
border-left: 3px solid var(--ams-badge-ams);
|
||||
|
||||
@@ -164,37 +164,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- AMS Status Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>AMS Status</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<strong>Temperature:</strong>
|
||||
{% if stats.ams_temp %}
|
||||
{{ stats.ams_temp|floatformat:1 }}°C
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<strong>Humidity:</strong>
|
||||
{% if stats.ams_humidity %}
|
||||
{{ stats.ams_humidity }}%
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filaments Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@@ -212,9 +181,9 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="ams-groups">
|
||||
<div class="row g-3 ams-groups">
|
||||
{% for group in stats.ams_groups %}
|
||||
<div class="ams-group ams-badge-bg-{{ group.ams_type|slugify }} {% if group.filaments|length > 1 %}ams-group--wide{% else %}ams-group--compact{% endif %}" data-ams-unit-id="{{ group.unit_id }}">
|
||||
<div class="{% if group.filaments|length > 1 %}col-12{% else %}col-12 col-md-6 col-lg-3{% endif %} ams-group ams-badge-bg-{{ group.ams_type|slugify }}" data-ams-unit-id="{{ group.unit_id }}">
|
||||
<div class="ams-group-header d-flex justify-content-between align-items-center mb-2">
|
||||
<strong class="small">{{ group.label }}</strong>
|
||||
{% if group.humidity is not None or group.temp is not None %}
|
||||
|
||||
@@ -159,26 +159,41 @@ class PrinterDashboardView(LoginRequiredMixin, TemplateView):
|
||||
except Exception:
|
||||
filaments_list = []
|
||||
|
||||
# Distinct AMS units represented in this snapshot, for the unit
|
||||
# filter/badges in the template. Sort numeric unit ids first
|
||||
# (AMS / AMS 2 Pro), HT (id 128 / bit 0x80 set) last.
|
||||
# Build a lookup from unit_id → AMS unit metadata (humidity, temp, info code)
|
||||
# first so we can enrich blank ams_type values derived from old snapshots.
|
||||
units_meta = {
|
||||
u.get('unit_id'): u for u in (latest_metric.ams_units or [])
|
||||
}
|
||||
|
||||
# Distinct AMS units in this snapshot. ams_type stored on FilamentSnapshot
|
||||
# may be blank for rows written before the multi-AMS deploy — fall back to
|
||||
# re-deriving from the unit's info code so labels always show correctly.
|
||||
from .models import ams_type_from_info as _ams_type_from_info
|
||||
seen_units = {}
|
||||
for f in filaments_list:
|
||||
uid = f.get('ams_unit_id')
|
||||
if uid is not None and uid not in seen_units:
|
||||
seen_units[uid] = f.get('ams_type') or ''
|
||||
label = f.get('ams_type') or ''
|
||||
if not label:
|
||||
unit_meta = units_meta.get(str(uid), {})
|
||||
label = _ams_type_from_info(unit_meta.get('info', ''))
|
||||
seen_units[uid] = label
|
||||
ams_units_list = [
|
||||
{'ams_unit_id': uid, 'ams_type': label}
|
||||
for uid, label in sorted(seen_units.items())
|
||||
]
|
||||
|
||||
# Group trays by physical AMS unit for the panel-style dashboard layout —
|
||||
# one tinted panel per unit, full-width for multi-slot units (AMS/AMS 2 Pro),
|
||||
# compact for single-slot units (AMS HT) so several can flow side-by-side.
|
||||
units_meta = {
|
||||
u.get('unit_id'): u for u in (latest_metric.ams_units or [])
|
||||
}
|
||||
ams_groups = []
|
||||
ungrouped = [f for f in filaments_list if f.get('ams_unit_id') is None]
|
||||
if ungrouped:
|
||||
ams_groups.append({
|
||||
'unit_id': None,
|
||||
'ams_type': '',
|
||||
'label': 'AMS',
|
||||
'humidity': None,
|
||||
'temp': None,
|
||||
'filaments': ungrouped,
|
||||
})
|
||||
for uid, label in sorted(seen_units.items()):
|
||||
unit_meta = units_meta.get(str(uid), {})
|
||||
ams_groups.append({
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "bambu-run"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
description = "Django reusable app for Bambu Lab 3D printer monitoring and filament inventory management"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
@@ -157,8 +157,8 @@ def test_dashboard_renders_wide_and_compact_panels(logged_in_client):
|
||||
)
|
||||
|
||||
html = resp.content.decode()
|
||||
assert "ams-group--wide" in html
|
||||
assert "ams-group--compact" in html
|
||||
assert "col-12 ams-group" in html # wide group: col-12 only
|
||||
assert "col-lg-3 ams-group" in html # compact group: col-lg-3
|
||||
assert "AMS 2 Pro (Unit 0)" in html
|
||||
assert "AMS HT (Unit 128)" in html
|
||||
|
||||
|
||||
Reference in New Issue
Block a user