Google Workspace × Bambu Lab in School. Why Not?
We have two Bambu Lab A1 printers sitting in the robotics lab. We have Google Workspace running everything — Classroom, Drive, Forms, Sheets, Apps Script. For a long time, those two ecosystems lived completely separate lives.
Then came a simple question: what if the print queue was just a Google Sheet?
No third-party platform. No new login for teachers. No new tool to learn. Just the infrastructure we already have — extended by about 250 lines of code.
The result: students submit a design, Gemini reviews the project description, the job joins the queue, and a Python daemon on a Mac Mini handles the rest — automatically, without anyone touching a keyboard.
Why Build This on Google Workspace?
The answer isn’t obvious until you think about what a school IT environment actually looks like. Every teacher already has Forms, Sheets, Drive, Gmail, and Apps Script. Every student already has a school Google account. The infrastructure is there — it just hasn’t been connected to the printers yet.
The best school infrastructure is the kind students don’t notice — because it feels like a natural extension of the work itself.
Zero new tools. Every component is already deployed and used daily. Teachers don’t need a new login. Students don’t need a new app.
Audit trail built-in. Sheets logs every submission, colour override, Gemini score, printer assignment, and status change. Perfect for demonstrating responsible AI use to parents and school inspectors.
AI that teaches, not replaces. Gemini doesn’t grade the project — it asks whether the description is complete enough to start printing. Students learn to articulate their work before the machine moves.
250 lines of code. The entire system — Apps Script trigger, Gemini integration, Sheets queue, Python MQTT bridge, email templates — fits under 250 lines. Maintainable by any tech-savvy teacher.
The Pipeline: What Happens After Submit
The student sees a form and then sees their model on the print bed. Between those two moments, three separate systems work together — invisible, automatic, and fault-tolerant.
Google Form
↓ trigger: onFormSubmit
Apps Script
↓
┌─────────────────────────────────┐
│ applyPaintingLogic() │
│ reviewWithGemini() │
│ addToQueue() │
│ sendConfirmationEmail() │
└─────────────────────────────────┘
↓ Google Sheets (queue)
Mac Mini daemon — polls every 60s
↓ MQTT over TLS
Bambu Cloud → A1 / A1 + AMS Lite
The student does one thing. The system does six.
The Form: What Students Actually Fill In
The form has a deliberate structure. Every field serves a purpose — either as content for the queue, or as input for the routing logic.
| Field | Type | Purpose |
|---|---|---|
| Name + email | Short answer | Identity + notification |
| Class + subject | Dropdown | Filtering + Gemini context |
| Project name | Short answer | Queue display name |
| Description & educational purpose | Paragraph | Gemini review input |
| STL/3MF link in Drive | Short answer | File for printer |
| Filament colour | Dropdown | Printer routing |
| Will the model be painted with acrylics? | Yes/No | Colour override logic |
| Accept white fallback if AMS is busy? | Yes/No | Queue fallback control |
| Estimated print time (hours) | Number | Gemini validation |
The last two questions are where the interesting logic lives. If a student says the model will be painted with acrylics, the system automatically overrides their colour choice to grey — the best primer base for acrylic paint, no priming required. The student gets a notification explaining why.
The Colour Logic: One Insight That Changes Everything
In our school we often paint prints with acrylics. This one operational detail — something most 3D printing tutorials never mention — completely changes the optimal colour choice.
Grey filament is the best base for acrylic painting. It doesn’t bleed through the paint, doesn’t require priming, and makes errors in the paint layer less visible. When a student says they’ll paint the model, the system silently overrides their colour selection and explains the reasoning in the confirmation email.
// Apps Script — the painting override
function applyPaintingLogic(job) {
if (job.willBePainted === 'Tak') {
if (job.color !== 'szary') {
job.originalColor = job.color; // remember original choice
job.color = 'szary'; // override to grey
job.colorOverridden = true;
}
// Never fall back to white on a painted model
job.allowWhiteFallback = false;
} else {
job.allowWhiteFallback = (job.acceptsWhiteFallback === 'Tak');
}
job.targetPrinter = AMS_COLORS.includes(job.color)
? 'A1 + AMS Lite'
: 'A1 (white)';
}
The AI Review Layer
Gemini 2.0 Flash Lite scores each submission 1–5 across four criteria before any filament moves:
- Does the description clearly explain what is being printed?
- Does it explain why (educational purpose)?
- Is the project realistic for a school 3D printer?
- Is the estimated print time under the 8-hour school limit?
The model responds in JSON and generates Polish-language feedback addressed directly to the student. Submissions scoring below 3 are returned for revision. The feedback tone is deliberately encouraging — students are aged 11–15.
// The prompt structure (simplified)
const prompt = `
You are an educational assistant reviewing a student 3D print request.
Student: ${job.studentName}, class ${job.className}
Project: "${job.projectName}"
Description: "${job.description}"
Score 1-5 and respond ONLY with JSON:
{"score": <1-5>, "feedback": "<one sentence in Polish>", "approved": <true|false>}
`;
If Gemini is unavailable, the pipeline doesn’t block — the fallback sets score to 3 and marks the job as accepted. The print queue never stalls because of an AI timeout.
The Mac Mini Bridge
The connection between Google Sheets and the physical printer runs through a 250-line Python daemon on a Mac Mini in the server room. It runs as a launchd service, starts at login, and polls Sheets every 60 seconds.
When it finds a row with status Zaakceptowane (Accepted), it:
- Checks printer availability via Bambu MQTT (
gcode_state == IDLE) - Verifies daily print limit (6 jobs per printer per day)
- Checks the 5-minute cooldown between jobs
- Routes to the correct printer based on colour
- Falls back to white A1 only if: student consented and model won’t be painted
- Sends the
.3MFfile URL and starts the print - Updates Sheets with the task ID and new status
The MQTT connection uses TLS to Bambu’s European cloud broker at eu.mqtt.bambulab.com:8883. Authentication is via a user token obtained through the Bambu Cloud login API. Note: Bambu does not publish an official public API — this uses community-documented endpoints that may change.
Printer Protection: Three Guardrails
Running two printers in a school environment without guardrails is a recipe for equipment damage. Three mechanisms protect the hardware:
Daily limit. Each printer accepts a maximum of 6 jobs per day. This translates to roughly 48 hours of continuous printing per day at average job lengths — enough for a busy class week, impossible to accidentally exceed.
Cooldown period. After each print completes, the bridge waits 5 minutes before starting the next job. This allows the bed to cool, the student to collect the print, and any manual intervention if needed.
Idle check. Every job is gated on gcode_state == IDLE. The bridge never sends a print command to a busy printer. If both printers are occupied, the job waits in the Sheets queue and retries on the next 60-second cycle.
The Pedagogical Loop
The physical print is not the endpoint — it’s the middle of a documented learning sequence:
- Design in TinkerCAD on iPad or Chromebook
- Submit via Google Form — describe what you’re making and why
- Receive Gemini feedback on the description quality
- Wait for the automated print
- Collect the physical model from the TechLab
- Document back in Google Classroom: photo + reflection + self-assessment
What used to require a teacher to manually queue jobs, track filament, and chase students for documentation now happens as a structured workflow. The teacher sets up the system once. It runs itself.
The Interactive Explainer
The component below walks through the full pipeline, lets you simulate a print request, and shows the colour→printer decision logic in action.
Interactive explainer
Animated pipeline — click any step
TinkerCAD — Student design
Students design their 3D model in TinkerCAD on school iPads or Chromebooks, then export as a .3MF file and upload to the class Google Drive folder. No special software — just a browser tab.
The Same Pattern, Different Problems
This architecture — form → Apps Script → structured output → physical trigger — is reusable across school workflows that involve real-world equipment.
Lab equipment booking. Students submit a reservation form for microscopes, oscilloscopes, or chemistry lab stations. Apps Script checks a Sheets availability calendar, confirms or waitlists, sends a confirmation, and creates a calendar event.
Laser cutter queue. Same pipeline as the 3D printer, different MQTT endpoint. Add a material safety check: Gemini validates that the described material is safe to cut before the job is queued.
School radio scheduling. A weekly form collects episode pitches from student teams. Apps Script schedules the accepted pitches, assigns recording slots in Google Calendar, and sends reminders.
Equipment maintenance log. After each print job, the system logs filament used, print time, and any errors to a maintenance spreadsheet. When cumulative print hours approach the nozzle replacement threshold, the admin gets an automated email.
The pattern is always the same: structured input → automatic routing → physical or digital output → documented record. The teacher or student does one thing. The institution remembers everything.
A note on the Bambu API
The MQTT endpoints used in this project are community-documented, not officially published by Bambu Lab. They work reliably as of firmware versions 01.08.x and 01.09.x, but Bambu may change them without notice. The bridge is architected so that all Bambu-specific code lives in a single Python module — if the API changes, only that module needs updating. The Google Workspace layer is completely stable and unaffected by any changes on the Bambu side.
A note on AI and data
The prompt sent to Gemini contains a project name, a description, and a class name — never student ID numbers, photos, or personal data. The Gemini API key is stored in Apps Script Script Properties, never in code. Keep the description field focused on the project, not the student, and the system is GDPR-compliant by design.