REST API in Go for controlling a 3D printer power relay through MQTT, with a safe power-off flow coordinated with Moonraker and SSH.
- HTTP server listens on
:8000 - Endpoints:
GET /api/3d-printerPOST /api/3d-printer
- MQTT topics are currently hardcoded:
- read state from
zigbee2mqtt/R - publish commands to
zigbee2mqtt/R/set
- read state from
POST OFFis a blocking flow (waits until print is done and hotend cools down)
- Go
1.25+(module is set togo 1.25.0) - Reachable MQTT broker on port
1883 - SSH access to printer host (password auth)
- Moonraker API reachable by this service
The app loads variables from:
.envin project root/root/power-api/.env(useful for deployments)- process environment
Use lowercase keys exactly as below:
mqtt_host=
mqtt_user=
mqtt_pass=
ssh_host=
ssh_user=
ssh_pass=
ssh_host_public_key=
moonraker_url=
threshold_temp=Notes:
threshold_tempdefaults to49when missing/invalidssh_host_public_keyshould contain the full OpenSSH public key line for the printer host (for exampleecdsa-sha2-nistp256 AAAA...)- no strict startup validation is done for empty values, so wrong/missing config will usually fail at runtime (MQTT/HTTP/SSH operations)
- Prepare env file:
cp template.env .env-
Fill
.envwith your values. -
Run:
go run .The service starts on http://localhost:8000.
go build -o power-api .Tests are organized in the dedicated tests/ folder and split by source responsibility:
tests/config_test.gotests/moonraker_test.gotests/mqtt_test.gotests/handlers_test.gotests/shutdown_test.gotests/helpers_test.go
Run all tests:
go test ./...Generate and print coverage summary:
make coverageThis runs tests from ./tests and measures coverage for ./src/....
Generate HTML coverage report:
make coverage-htmlThis creates:
coverage.out(profile)coverage.html(visual report)
Returns current relay state from MQTT.
Example response:
{
"state": "ON"
}Request body:
{
"state": "ON"
}Allowed values:
ON– immediately publishes MQTTONOFF– starts safe shutdown flow:- poll Moonraker print state (
standbyorcompleterequired) - poll Moonraker temperature store and compute average of recent extruder readings
- wait until average temp is below
threshold_temp - execute SSH command
/sbin/shutdown 0 - wait until host no longer responds to ping
- publish MQTT
OFF
- poll Moonraker print state (
{moonraker_url}/printer/objects/query?print_stats{moonraker_url}/server/temperature_store
- multi-stage build
- final image is
scratch - binary entrypoint is
/power-api
If you run in a container, pass env vars explicitly (or mount a file at /root/power-api/.env if your runtime allows it).
- MQTT client uses auto-reconnect
- API request for
POST OFFcan be long-running due to cooldown and host shutdown waiting - app runs Gin in
releasemode