Skip to content

Commit c08ea0a

Browse files
Fix Klipper preview not showing when item linked after fetch
The job-preview channel was only pushed a state the moment the print filename changed, so an item linked to that channel afterward (while the same file was still active) never received a value. Cache the last fetched thumbnail and re-push it every refresh cycle, and add debug logging to the previously-silent failure paths. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Scott Hanson <scooter_seh@yahoo.com>
1 parent 0054e69 commit c08ea0a

1 file changed

Lines changed: 29 additions & 4 deletions

File tree

  • bundles/org.openhab.binding.threedprinter/src/main/java/org/openhab/binding/threedprinter/internal/handler

bundles/org.openhab.binding.threedprinter/src/main/java/org/openhab/binding/threedprinter/internal/handler/KlipperHandler.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public class KlipperHandler extends AbstractPrinterHandler {
6767

6868
private @Nullable KlipperConfiguration config;
6969
private String lastPreviewFilename = "";
70+
private @Nullable RawType lastPreviewState;
7071

7172
public KlipperHandler(Thing thing, HttpClient httpClient) {
7273
super(thing, httpClient);
@@ -146,10 +147,19 @@ protected void refresh() {
146147

147148
if (!stats.filename.isBlank()) {
148149
if (!stats.filename.equals(lastPreviewFilename)) {
150+
logger.debug("Fetching preview for {} (last was '{}')", stats.filename, lastPreviewFilename);
149151
fetchAndUpdatePreview(baseUrl, cfg.apiKey, stats.filename);
152+
} else {
153+
// Re-push the cached image every cycle rather than only on filename change, so a channel
154+
// linked to an item after the initial fetch (or a UI reconnecting) still gets the preview.
155+
RawType cached = lastPreviewState;
156+
if (cached != null) {
157+
updateState(CHANNEL_JOB_PREVIEW, cached);
158+
}
150159
}
151160
} else {
152161
lastPreviewFilename = "";
162+
lastPreviewState = null;
153163
}
154164
}
155165

@@ -180,23 +190,28 @@ private void fetchAndUpdatePreview(String baseUrl, String apiKey, String filenam
180190
String encodedFilename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
181191
String metaJson = httpGet(baseUrl + "/server/files/metadata?filename=" + encodedFilename, apiKey);
182192
if (metaJson == null) {
193+
logger.debug("Preview for {}: metadata request failed (see prior GET log)", filename);
183194
return;
184195
}
185196
KlipperMetadataResponse meta = fromJson(metaJson, KlipperMetadataResponse.class);
186197
if (meta == null) {
198+
logger.debug("Preview for {}: metadata response was not valid JSON", filename);
187199
return;
188200
}
189201
KlipperMetadataResult metaResult = meta.result;
190202
if (metaResult == null) {
203+
logger.debug("Preview for {}: metadata response had no 'result' field", filename);
191204
return;
192205
}
193206
List<KlipperThumbnail> thumbnails = metaResult.thumbnails;
194207
if (thumbnails == null || thumbnails.isEmpty()) {
208+
logger.debug("Preview for {}: metadata has no thumbnails", filename);
195209
return;
196210
}
197211
@Nullable
198212
KlipperThumbnail best = thumbnails.stream().max(Comparator.comparingInt(t -> t.size)).orElse(null);
199213
if (best == null || best.relativePath.isBlank()) {
214+
logger.debug("Preview for {}: no usable thumbnail entry (relative_path blank)", filename);
200215
return;
201216
}
202217
// relative_path is relative to the gcode file's own directory, not the gcodes root
@@ -207,11 +222,21 @@ private void fetchAndUpdatePreview(String baseUrl, String apiKey, String filenam
207222
String encodedPath = Arrays.stream(fullPath.split("/"))
208223
.map(s -> URLEncoder.encode(s, StandardCharsets.UTF_8).replace("+", "%20"))
209224
.collect(Collectors.joining("/"));
210-
byte @Nullable [] bytes = httpGetBytes(baseUrl + "/server/files/gcodes/" + encodedPath, apiKey);
211-
if (bytes != null && bytes.length > 0) {
212-
updateState(CHANNEL_JOB_PREVIEW, new RawType(bytes, "image/png"));
213-
lastPreviewFilename = filename;
225+
String previewUrl = baseUrl + "/server/files/gcodes/" + encodedPath;
226+
byte @Nullable [] bytes = httpGetBytes(previewUrl, apiKey);
227+
if (bytes == null) {
228+
logger.debug("Preview for {}: image GET {} failed (see prior GET log)", filename, previewUrl);
229+
return;
230+
}
231+
if (bytes.length == 0) {
232+
logger.debug("Preview for {}: image GET {} returned an empty body", filename, previewUrl);
233+
return;
214234
}
235+
logger.debug("Preview for {}: fetched {} bytes from {}", filename, bytes.length, previewUrl);
236+
RawType state = new RawType(bytes, "image/png");
237+
updateState(CHANNEL_JOB_PREVIEW, state);
238+
lastPreviewFilename = filename;
239+
lastPreviewState = state;
215240
}
216241

217242
@Override

0 commit comments

Comments
 (0)