Show a printer's camera, from the backend's address not a build-time one
`WebRTCStreamView` has existed since before this commit with no consumer: nothing rendered it, and the URL it would have used came from a `go2rtcStreamBase` in `nuxt.config.ts` defaulting to `http://localhost:1984`. That default was the real problem. A camera stream lives on a gateway box inside one farm's network, each farm has its own, and the gateway now reports its address to the backend when it connects. A compiled-in constant could only ever be correct for a single-farm install, and its localhost default pointed every player at the operator's own laptop. It is gone, replaced by `fetchPrinterStream`, which asks `GET /printers/:id/stream`. Absence is the normal case here, not an error: only Bambu's X1/H2 class publishes a camera URL a gateway can restream, so a P1 or A1 has a camera and nothing to connect to. The backend 404s for those, this resolves to null, and the card renders no player - offering one that can never load would be worse than offering nothing. The lookup also runs only for printers whose `cameraStream` the fleet list already reports, so a twenty-printer farm does not make twenty requests to learn that eighteen of them 404. `PrinterCard` takes the stream as a prop rather than fetching it, like `live` above it: `packages/ui` is plain Vue that knows nothing about the API or about Nuxt, and that is what lets these components render from a test or the desktop shell with no server behind them. Three things in `WebRTCStreamView` that would have bitten whoever first pointed it at a real printer: - The fetch status was never checked. go2rtc answers a request for a stream it does not have with an error page, and handing that to `setRemoteDescription` throws about SDP parsing - which sends you looking at the wrong layer entirely. - `connect()` is async inside a watcher with nothing catching it, so a failure left the badge on "connecting" forever and showed up only as an unhandled rejection in the console. - Two prop changes in quick succession raced: the slower request could finish last and apply its answer to a connection already replaced and closed, leaving a black video with a "connected" badge. No `iceServers`, deliberately and now commented: both ends are on the same LAN, so host candidates are enough. The same fact is the MVP's limitation - there is no relay, so this plays for someone on the printers' network and for nobody else. `nuxt typecheck` and `vue-tsc --noEmit` both clean.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import TemperatureGraph from "./TemperatureGraph.vue";
|
||||
import WebRTCStreamView from "./WebRTCStreamView.vue";
|
||||
|
||||
interface Printer {
|
||||
id: string;
|
||||
@@ -16,9 +17,27 @@ interface LiveTelemetry {
|
||||
progressPct: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where this printer's camera can be watched, from
|
||||
* `GET /printers/:id/stream`.
|
||||
*
|
||||
* Passed in rather than fetched here, matching `live` above: this package is
|
||||
* plain Vue with no knowledge of the API or of Nuxt, and keeping the fetching
|
||||
* in the app is what lets these components be rendered from a test or the
|
||||
* desktop shell without a server behind them.
|
||||
*
|
||||
* Undefined for most printers and that is expected - see
|
||||
* `usePrinterStream`. The player is simply not rendered.
|
||||
*/
|
||||
interface PrinterStream {
|
||||
streamUrl: string;
|
||||
cameraId: string;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
printer: Printer;
|
||||
live?: LiveTelemetry;
|
||||
stream?: PrinterStream | null;
|
||||
}>();
|
||||
|
||||
const state = computed(() => props.live?.state ?? "offline");
|
||||
@@ -33,6 +52,12 @@ const state = computed(() => props.live?.state ?? "offline");
|
||||
|
||||
<p class="printer-card__state">{{ state }}</p>
|
||||
|
||||
<WebRTCStreamView
|
||||
v-if="stream"
|
||||
:stream-base-url="stream.streamUrl"
|
||||
:camera-id="stream.cameraId"
|
||||
/>
|
||||
|
||||
<TemperatureGraph
|
||||
v-if="live"
|
||||
:nozzle-temp-c="live.nozzleTempC"
|
||||
|
||||
Reference in New Issue
Block a user