2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.hpprinter.internal;
15 import static org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants.*;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.eclipse.jetty.client.HttpClient;
26 import org.openhab.binding.hpprinter.internal.api.HPFeatures;
27 import org.openhab.binding.hpprinter.internal.api.HPProductUsageFeatures;
28 import org.openhab.binding.hpprinter.internal.api.HPProductUsageFeatures.PrinterType;
29 import org.openhab.binding.hpprinter.internal.api.HPProperties;
30 import org.openhab.binding.hpprinter.internal.api.HPScannerStatus;
31 import org.openhab.binding.hpprinter.internal.api.HPScannerStatusFeatures;
32 import org.openhab.binding.hpprinter.internal.api.HPServerResult;
33 import org.openhab.binding.hpprinter.internal.api.HPServerResult.RequestStatus;
34 import org.openhab.binding.hpprinter.internal.api.HPStatus;
35 import org.openhab.binding.hpprinter.internal.api.HPUsage;
36 import org.openhab.binding.hpprinter.internal.api.HPWebServerClient;
37 import org.openhab.core.library.CoreItemFactory;
38 import org.openhab.core.library.types.DecimalType;
39 import org.openhab.core.library.types.OnOffType;
40 import org.openhab.core.library.types.QuantityType;
41 import org.openhab.core.library.types.StringType;
42 import org.openhab.core.library.unit.MetricPrefix;
43 import org.openhab.core.library.unit.Units;
44 import org.openhab.core.thing.Channel;
45 import org.openhab.core.thing.ChannelUID;
46 import org.openhab.core.thing.ThingStatus;
47 import org.openhab.core.thing.ThingStatusDetail;
48 import org.openhab.core.thing.ThingUID;
49 import org.openhab.core.thing.binding.builder.ChannelBuilder;
50 import org.openhab.core.types.State;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
55 * The {@link HPPrinterBinder} connects the binding to the Web Server Client
58 * @author Stewart Cossey - Initial contribution
61 public class HPPrinterBinder {
62 private final Logger logger = LoggerFactory.getLogger(HPPrinterBinder.class);
64 private static final int OFFLINE_CHECK_INTERVAL = 15;
66 private HPPrinterHandler handler;
67 private ScheduledExecutorService scheduler;
69 private final int statusCheckInterval;
70 private final int usageCheckInterval;
71 private final HPWebServerClient printerClient;
73 private @Nullable ScheduledFuture<?> statusScheduler;
74 private @Nullable ScheduledFuture<?> scannerStatusScheduler;
75 private @Nullable ScheduledFuture<?> usageScheduler;
76 private @Nullable ScheduledFuture<?> offlineScheduler;
78 private boolean handlerDisposed;
81 * Creates a new HP Printer Binder object
83 * @param handler {HPPrinterBinderEvent} The Event handler for the binder.
84 * @param httpClient {HttpClient} The HttpClient object to use to perform HTTP
86 * @param scheduler {ScheduledExecutorService} The scheduler service object.
87 * @param config {HPPrinterConfiguration} The configuration object.
89 public HPPrinterBinder(HPPrinterHandler handler, HttpClient httpClient, ScheduledExecutorService scheduler,
90 HPPrinterConfiguration config) {
91 this.handler = handler;
92 this.scheduler = scheduler;
93 usageCheckInterval = config.usageInterval;
94 statusCheckInterval = config.statusInterval;
95 String ipAddress = config.ipAddress;
96 if (ipAddress == null) {
97 throw new IllegalStateException("ip-address should have been validated already and may not be empty.");
99 printerClient = new HPWebServerClient(httpClient, ipAddress);
100 handlerDisposed = false;
103 public void retrieveProperties() {
104 HPServerResult<HPProperties> result = printerClient.getProperties();
106 if (result.getStatus() == RequestStatus.SUCCESS) {
107 handler.updateProperties(result.getData().getProperties());
111 public synchronized void channelsChanged() {
112 logger.trace("Channels have been changed");
118 * Dynamically add channels to the Thing based on the Embedded Web Server Usage
121 public void dynamicallyAddChannels(ThingUID thingUid) {
122 logger.debug("Building dynamic channels based on printer");
124 HPServerResult<HPFeatures> featureResult = printerClient.getProductUsageFeatures();
125 if (featureResult.getStatus() == RequestStatus.SUCCESS) {
126 final List<Channel> channels = new ArrayList<>();
128 HPFeatures features = featureResult.getData();
130 if (features.getProductStatusSupported()) {
131 channels.add(ChannelBuilder
132 .create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_STATUS), CoreItemFactory.STRING)
133 .withLabel("Status").withDescription("Printer status").withType(chanTypeStatus).build());
135 channels.add(ChannelBuilder
136 .create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_TRAYEMPTYOROPEN),
137 CoreItemFactory.SWITCH)
138 .withLabel("Tray Empty/Open").withDescription("The tray is empty or open")
139 .withType(chanTypeReadSwitch).build());
142 if (features.getScannerStatusSupported()) {
143 HPServerResult<HPScannerStatusFeatures> result = printerClient.getScannerFeatures();
144 if (result.getStatus() == RequestStatus.SUCCESS) {
145 HPScannerStatusFeatures feature = result.getData();
147 if (feature.hasStatus()) {
148 channels.add(ChannelBuilder
149 .create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_SCANNER_STATUS),
150 CoreItemFactory.STRING)
151 .withLabel("Scanner").withDescription("Scanner status").withType(chanTypeStatus)
155 if (feature.hasAdf()) {
156 channels.add(ChannelBuilder
157 .create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_SCANNER_ADFLOADED),
158 CoreItemFactory.SWITCH)
159 .withLabel("ADF Loaded").withDescription("The automatic document feeder is loaded")
160 .withType(chanTypeReadSwitch).build());
165 if (features.getProductUsageSupported()) {
166 HPServerResult<HPProductUsageFeatures> result = printerClient.getProductFeatures();
167 if (result.getStatus() == RequestStatus.SUCCESS) {
168 HPProductUsageFeatures feature = result.getData();
170 channels.add(ChannelBuilder
171 .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_BLACK_LEVEL),
172 HPPrinterBindingConstants.ITEM_TYPE_INK)
173 .withLabel("Black Level").withDescription("Shows the amount of Black Ink/Toner remaining")
174 .withType(chanTypeInkLevel).build());
176 channels.add(ChannelBuilder
177 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_PAGES), CoreItemFactory.NUMBER)
178 .withLabel("Total Lifetime Pages")
179 .withDescription("The amount of pages printed over the printer lifetime")
180 .withType(chanTypeTotals).build());
182 if (feature.hasCumulativeMarking()) {
183 channels.add(ChannelBuilder
184 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_MARKING),
185 HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
186 .withLabel("Black Marking Used").withDescription("The amount of Black Marking used")
187 .withType(chanTypeMarking).build());
190 switch (feature.getType()) {
192 if (feature.hasCumulativeMarking()) {
193 channels.add(ChannelBuilder
194 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_COLOR_MARKING),
195 HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
196 .withLabel("Colour Marking Used")
197 .withDescription("The amount of Colour Marking used").withType(chanTypeMarking)
201 channels.add(ChannelBuilder
202 .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_COLOR_LEVEL),
203 HPPrinterBindingConstants.ITEM_TYPE_INK)
204 .withLabel("Color Level")
205 .withDescription("Shows the amount of Colour Ink/Toner remaining")
206 .withType(chanTypeInkLevel).build());
208 channels.add(ChannelBuilder
209 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES),
210 CoreItemFactory.NUMBER)
211 .withLabel("Total Colour Pages")
212 .withDescription("The amount of colour pages printed").withType(chanTypeTotals)
215 channels.add(ChannelBuilder
216 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES),
217 CoreItemFactory.NUMBER)
218 .withLabel("Total Monochrome Pages")
219 .withDescription("The amount of monochrome pages printed").withType(chanTypeTotals)
222 if (feature.hasPagesRemaining()) {
223 channels.add(ChannelBuilder
224 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
225 CoreItemFactory.NUMBER)
226 .withLabel("Black Pages Remaining")
227 .withDescription("Estimated Black pages remaining")
228 .withType(chanTypeTotalsAdvanced).build());
230 channels.add(ChannelBuilder
231 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_COLOR_PAGES_REMAINING),
232 CoreItemFactory.NUMBER)
233 .withLabel("Colour Pages Remaining")
234 .withDescription("Estimated Colour pages remaining")
235 .withType(chanTypeTotalsAdvanced).build());
241 if (feature.hasCumulativeMarking()) {
242 channels.add(ChannelBuilder
243 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_CYAN_MARKING),
244 HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
245 .withLabel("Cyan Marking Used")
246 .withDescription("The amount of Cyan Marking used").withType(chanTypeMarking)
249 channels.add(ChannelBuilder
250 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MAGENTA_MARKING),
251 HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
252 .withLabel("Magenta Marking Used")
253 .withDescription("The amount of Magenta Marking used").withType(chanTypeMarking)
256 channels.add(ChannelBuilder
257 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_YELLOW_MARKING),
258 HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
259 .withLabel("Yellow Marking Used")
260 .withDescription("The amount of Yellow Marking used").withType(chanTypeMarking)
264 if (feature.hasPagesRemaining()) {
265 channels.add(ChannelBuilder
266 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
267 CoreItemFactory.NUMBER)
268 .withLabel("Black Pages Remaining")
269 .withDescription("Estimated Black pages remaining")
270 .withType(chanTypeTotalsAdvanced).build());
272 channels.add(ChannelBuilder
273 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_CYAN_PAGES_REMAINING),
274 CoreItemFactory.NUMBER)
275 .withLabel("Cyan Pages Remaining")
276 .withDescription("Estimated Cyan pages remaining")
277 .withType(chanTypeTotalsAdvanced).build());
279 channels.add(ChannelBuilder
280 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MAGENTA_PAGES_REMAINING),
281 CoreItemFactory.NUMBER)
282 .withLabel("Magenta Pages Remaining")
283 .withDescription("Estimated Magenta pages remaining")
284 .withType(chanTypeTotalsAdvanced).build());
286 channels.add(ChannelBuilder
287 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_YELLOW_PAGES_REMAINING),
288 CoreItemFactory.NUMBER)
289 .withLabel("Yellow Pages Remaining")
290 .withDescription("Estimated Yellow pages remaining")
291 .withType(chanTypeTotalsAdvanced).build());
294 channels.add(ChannelBuilder
295 .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_CYAN_LEVEL),
296 HPPrinterBindingConstants.ITEM_TYPE_INK)
297 .withLabel("Cyan Level")
298 .withDescription("Shows the amount of Cyan Ink/Toner remaining")
299 .withType(chanTypeInkLevel).build());
301 channels.add(ChannelBuilder
302 .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_MAGENTA_LEVEL),
303 HPPrinterBindingConstants.ITEM_TYPE_INK)
304 .withLabel("Magenta Level")
305 .withDescription("Shows the amount of Magenta Ink/Toner remaining")
306 .withType(chanTypeInkLevel).build());
308 channels.add(ChannelBuilder
309 .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_YELLOW_LEVEL),
310 HPPrinterBindingConstants.ITEM_TYPE_INK)
311 .withLabel("Yellow Level")
312 .withDescription("Shows the amount of Yellow Ink/Toner remaining")
313 .withType(chanTypeInkLevel).build());
315 channels.add(ChannelBuilder
316 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES),
317 CoreItemFactory.NUMBER)
318 .withLabel("Total Colour Pages")
319 .withDescription("The amount of colour pages printed").withType(chanTypeTotals)
322 channels.add(ChannelBuilder
323 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES),
324 CoreItemFactory.NUMBER)
325 .withLabel("Total Monochrome Pages")
326 .withDescription("The amount of monochrome pages printed").withType(chanTypeTotals)
332 if (feature.hasPagesRemaining()) {
333 channels.add(ChannelBuilder
334 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
335 CoreItemFactory.NUMBER)
336 .withLabel("Black Pages Remaining")
337 .withDescription("Estimated Black pages remaining")
338 .withType(chanTypeTotalsAdvanced).build());
342 if (feature.hasJamEvents()) {
343 channels.add(ChannelBuilder
344 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_JAM_EVENTS),
345 CoreItemFactory.NUMBER)
346 .withLabel("Jams").withDescription("The amount of times the paper has jammed")
347 .withType(chanTypeTotalsAdvanced).build());
350 if (feature.hasMispickEvents()) {
351 channels.add(ChannelBuilder
352 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MISPICK_EVENTS),
353 CoreItemFactory.NUMBER)
354 .withLabel("Missed Picks")
355 .withDescription("The amount of times the paper failed to feed into the printer")
356 .withType(chanTypeTotalsAdvanced).build());
359 if (feature.hasSubscriptionCount()) {
360 channels.add(ChannelBuilder
361 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_SUBSCRIPTION),
362 CoreItemFactory.NUMBER)
363 .withLabel("Subscription Count")
364 .withDescription("The amount of times an item has been printed in subscription")
365 .withType(chanTypeTotalsAdvanced).build());
368 if (feature.hasTotalFrontPanelCancelPresses()) {
369 channels.add(ChannelBuilder
370 .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_FRONT_PANEL_CANCEL),
371 CoreItemFactory.NUMBER)
372 .withLabel("Front Panel Cancel Count")
373 .withDescription("The amount of times a print has been cancelled from the Front Panel")
374 .withType(chanTypeTotalsAdvanced).build());
378 if (feature.hasCloudPrint()) {
379 channels.add(ChannelBuilder
380 .create(new ChannelUID(thingUid, CGROUP_OTHER, CHANNEL_CLOUD_PRINT),
381 CoreItemFactory.NUMBER)
382 .withLabel("Cloud Print Count")
384 "The amount of times a document has been printed via Google Cloud Print")
385 .withType(chanTypeTotalsAdvanced).build());
389 if (feature.hasScanADF()) {
390 channels.add(ChannelBuilder
391 .create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_ADF),
392 CoreItemFactory.NUMBER)
393 .withLabel("Document Feeder Count")
394 .withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
398 if (feature.hasScanFlatbed()) {
399 channels.add(ChannelBuilder
400 .create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_FLATBED),
401 CoreItemFactory.NUMBER)
402 .withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
403 .withType(chanTypeTotals).build());
406 if (feature.hasScanToEmail()) {
407 channels.add(ChannelBuilder
408 .create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOEMAIL),
409 CoreItemFactory.NUMBER)
410 .withLabel("Scan to Email Count").withDescription("Times scanned using Scan to Email")
411 .withType(chanTypeTotalsAdvanced).build());
414 if (feature.hasScanToFolder()) {
415 channels.add(ChannelBuilder
416 .create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOFOLDER),
417 CoreItemFactory.NUMBER)
418 .withLabel("Scan to Folder Count").withDescription("Times scanned using Scan to Folder")
419 .withType(chanTypeTotalsAdvanced).build());
422 if (feature.hasScanToHost()) {
423 channels.add(ChannelBuilder
424 .create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOHOST),
425 CoreItemFactory.NUMBER)
426 .withLabel("Scan to Host Count")
427 .withDescription("Times scanned using Scan to Host Device")
428 .withType(chanTypeTotalsAdvanced).build());
432 if (feature.hasScannerEngine()) {
433 if (feature.hasScanADF()) {
434 channels.add(ChannelBuilder
435 .create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_TOTAL_ADF),
436 CoreItemFactory.NUMBER)
437 .withLabel("Document Feeder Count")
438 .withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
442 if (feature.hasScanFlatbed()) {
443 channels.add(ChannelBuilder
444 .create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_TOTAL_FLATBED),
445 CoreItemFactory.NUMBER)
446 .withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
447 .withType(chanTypeTotals).build());
450 channels.add(ChannelBuilder
451 .create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_JAM_EVENTS),
452 CoreItemFactory.NUMBER)
453 .withLabel("Jams").withDescription("The amount of times the paper has jammed")
454 .withType(chanTypeTotalsAdvanced).build());
456 channels.add(ChannelBuilder
457 .create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_MISPICK_EVENTS),
458 CoreItemFactory.NUMBER)
459 .withLabel("Missed Picks")
460 .withDescription("The amount of times the paper failed to feed into the printer")
461 .withType(chanTypeTotalsAdvanced).build());
466 if (feature.hasCopyApplication()) {
467 if (feature.hasScanADF()) {
468 channels.add(ChannelBuilder
469 .create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_ADF),
470 CoreItemFactory.NUMBER)
471 .withLabel("Document Feeder Count")
472 .withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
476 if (feature.hasScanFlatbed()) {
477 channels.add(ChannelBuilder
478 .create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_FLATBED),
479 CoreItemFactory.NUMBER)
480 .withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
481 .withType(chanTypeTotals).build());
484 channels.add(ChannelBuilder
485 .create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_PAGES),
486 CoreItemFactory.NUMBER)
487 .withLabel("Total Pages").withDescription("The amount of pages copied")
488 .withType(chanTypeTotals).build());
490 if (feature.getType() == PrinterType.MULTICOLOR
491 || feature.getType() == PrinterType.SINGLECOLOR) {
492 channels.add(ChannelBuilder
493 .create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_COLORPAGES),
494 CoreItemFactory.NUMBER)
495 .withLabel("Total Colour Pages")
496 .withDescription("The amount of colour pages copied").withType(chanTypeTotals)
499 channels.add(ChannelBuilder
500 .create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_MONOPAGES),
501 CoreItemFactory.NUMBER)
502 .withLabel("Total Monochrome Pages")
503 .withDescription("The amount of monochrome pages copied").withType(chanTypeTotals)
509 if (feature.hasPrintApplication()) {
510 channels.add(ChannelBuilder
511 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_WIN), CoreItemFactory.NUMBER)
512 .withLabel("Windows").withType(chanTypeTotalsAdvanced).build());
514 channels.add(ChannelBuilder
515 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_ANDROID),
516 CoreItemFactory.NUMBER)
517 .withLabel("Android").withType(chanTypeTotalsAdvanced).build());
519 channels.add(ChannelBuilder
520 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_IOS), CoreItemFactory.NUMBER)
521 .withLabel("iOS").withType(chanTypeTotalsAdvanced).build());
523 channels.add(ChannelBuilder
524 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_OSX), CoreItemFactory.NUMBER)
525 .withLabel("OSX").withType(chanTypeTotalsAdvanced).build());
527 channels.add(ChannelBuilder
528 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_SAMSUNG),
529 CoreItemFactory.NUMBER)
530 .withLabel("Samsung").withType(chanTypeTotalsAdvanced).build());
532 if (feature.hasPrintApplicationChrome()) {
533 channels.add(ChannelBuilder
534 .create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_CHROME),
535 CoreItemFactory.NUMBER)
536 .withLabel("Chrome").withType(chanTypeTotalsAdvanced).build());
542 handler.binderAddChannels(channels);
547 * Opens the connection to the Embedded Web Server
550 runOfflineScheduler();
554 * Public method to close the connection to the Embedded Web Server
556 * Set handlerDisposed to prevent call-backs to the handler after it has been disposed
557 * Then call the closeinternal() method
559 public void close() {
560 handlerDisposed = true;
565 * Private (internal) method to close the connection to the Embedded Web Server
567 private void closeInternal() {
568 stopBackgroundSchedules();
570 final ScheduledFuture<?> localOfflineScheduler = offlineScheduler;
572 if (localOfflineScheduler != null) {
573 localOfflineScheduler.cancel(true);
574 offlineScheduler = null;
579 * The device has gone offline
581 private void goneOffline() {
582 handler.updateStatus(ThingStatus.OFFLINE);
585 runOfflineScheduler();
588 private void runOfflineScheduler() {
589 offlineScheduler = scheduler.scheduleWithFixedDelay(this::checkOnline, 0, OFFLINE_CHECK_INTERVAL,
593 private synchronized void stopBackgroundSchedules() {
594 logger.debug("Stopping Interval Refreshes");
595 ScheduledFuture<?> localUsageScheduler = usageScheduler;
596 if (localUsageScheduler != null) {
597 localUsageScheduler.cancel(true);
600 ScheduledFuture<?> localStatusScheduler = statusScheduler;
601 if (localStatusScheduler != null) {
602 localStatusScheduler.cancel(true);
605 ScheduledFuture<?> localScannerStatusScheduler = scannerStatusScheduler;
606 if (localScannerStatusScheduler != null) {
607 localScannerStatusScheduler.cancel(true);
611 private synchronized void startBackgroundSchedules() {
612 stopBackgroundSchedules();
613 logger.debug("Starting Interval Refreshes");
615 usageScheduler = scheduler.scheduleWithFixedDelay(this::checkUsage, 0, usageCheckInterval, TimeUnit.SECONDS);
617 // Only schedule below items when there channels are linked
618 if (handler.areStatusChannelsLinked(new String[] { CHANNEL_STATUS, CHANNEL_TRAYEMPTYOROPEN })) {
619 statusScheduler = scheduler.scheduleWithFixedDelay(this::checkStatus, 0, statusCheckInterval,
623 if (handler.areStatusChannelsLinked(new String[] { CHANNEL_SCANNER_STATUS, CHANNEL_SCANNER_ADFLOADED })) {
624 scannerStatusScheduler = scheduler.scheduleWithFixedDelay(this::checkScannerStatus, 0, statusCheckInterval,
629 private void checkScannerStatus() {
630 HPServerResult<HPScannerStatus> result = printerClient.getScannerStatus();
632 if (handlerDisposed) {
635 if (result.getStatus() == RequestStatus.SUCCESS) {
636 handler.updateState(CGROUP_STATUS, CHANNEL_SCANNER_STATUS,
637 new StringType(result.getData().getScannerStatus()));
638 handler.updateState(CGROUP_STATUS, CHANNEL_SCANNER_ADFLOADED,
639 convertToOnOffType(result.getData().getAdfLoaded()));
645 private void checkStatus() {
646 HPServerResult<HPStatus> result = printerClient.getStatus();
648 if (handlerDisposed) {
651 if (result.getStatus() == RequestStatus.SUCCESS) {
652 handler.updateState(CGROUP_STATUS, CHANNEL_STATUS, new StringType(result.getData().getPrinterStatus()));
653 handler.updateState(CGROUP_STATUS, CHANNEL_TRAYEMPTYOROPEN,
654 convertToOnOffType(result.getData().getTrayEmptyOrOpen()));
660 private static State convertToOnOffType(Boolean bool) {
664 return OnOffType.OFF;
668 private void checkUsage() {
669 HPServerResult<HPUsage> result = printerClient.getUsage();
671 if (handlerDisposed) {
674 if (result.getStatus() == RequestStatus.SUCCESS) {
676 handler.updateState(CGROUP_INK, CHANNEL_BLACK_LEVEL,
677 new QuantityType<>(result.getData().getInkBlack(), Units.PERCENT));
678 handler.updateState(CGROUP_INK, CHANNEL_COLOR_LEVEL,
679 new QuantityType<>(result.getData().getInkColor(), Units.PERCENT));
680 handler.updateState(CGROUP_INK, CHANNEL_CYAN_LEVEL,
681 new QuantityType<>(result.getData().getInkCyan(), Units.PERCENT));
682 handler.updateState(CGROUP_INK, CHANNEL_MAGENTA_LEVEL,
683 new QuantityType<>(result.getData().getInkMagenta(), Units.PERCENT));
684 handler.updateState(CGROUP_INK, CHANNEL_YELLOW_LEVEL,
685 new QuantityType<>(result.getData().getInkYellow(), Units.PERCENT));
687 handler.updateState(CGROUP_USAGE, CHANNEL_JAM_EVENTS, new DecimalType(result.getData().getJamEvents()));
688 handler.updateState(CGROUP_USAGE, CHANNEL_SUBSCRIPTION,
689 new DecimalType(result.getData().getTotalSubscriptionImpressions()));
690 handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES,
691 new DecimalType(result.getData().getTotalColorImpressions()));
692 handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES,
693 new DecimalType(result.getData().getTotalMonochromeImpressions()));
694 handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_PAGES,
695 new DecimalType(result.getData().getTotalImpressions()));
696 handler.updateState(CGROUP_USAGE, CHANNEL_MISPICK_EVENTS,
697 new DecimalType(result.getData().getMispickEvents()));
698 handler.updateState(CGROUP_USAGE, CHANNEL_FRONT_PANEL_CANCEL,
699 new DecimalType(result.getData().getFrontPanelCancelCount()));
701 handler.updateState(CGROUP_USAGE, CHANNEL_BLACK_MARKING,
702 new QuantityType<>(result.getData().getInkBlackMarking(), MetricPrefix.MILLI(Units.LITRE)));
703 handler.updateState(CGROUP_USAGE, CHANNEL_COLOR_MARKING,
704 new QuantityType<>(result.getData().getInkColorMarking(), MetricPrefix.MILLI(Units.LITRE)));
705 handler.updateState(CGROUP_USAGE, CHANNEL_CYAN_MARKING,
706 new QuantityType<>(result.getData().getInkCyanMarking(), MetricPrefix.MILLI(Units.LITRE)));
707 handler.updateState(CGROUP_USAGE, CHANNEL_MAGENTA_MARKING,
708 new QuantityType<>(result.getData().getInkMagentaMarking(), MetricPrefix.MILLI(Units.LITRE)));
709 handler.updateState(CGROUP_USAGE, CHANNEL_YELLOW_MARKING,
710 new QuantityType<>(result.getData().getInkYellowMarking(), MetricPrefix.MILLI(Units.LITRE)));
712 handler.updateState(CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING,
713 new DecimalType(result.getData().getInkBlackPagesRemaining()));
715 handler.updateState(CGROUP_USAGE, CHANNEL_COLOR_PAGES_REMAINING,
716 new DecimalType(result.getData().getInkColorPagesRemaining()));
718 handler.updateState(CGROUP_USAGE, CHANNEL_CYAN_PAGES_REMAINING,
719 new DecimalType(result.getData().getInkCyanPagesRemaining()));
721 handler.updateState(CGROUP_USAGE, CHANNEL_MAGENTA_PAGES_REMAINING,
722 new DecimalType(result.getData().getInkMagentaPagesRemaining()));
724 handler.updateState(CGROUP_USAGE, CHANNEL_YELLOW_PAGES_REMAINING,
725 new DecimalType(result.getData().getInkYellowPagesRemaining()));
728 handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_ADF, new DecimalType(result.getData().getScanAdfCount()));
730 handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_FLATBED,
731 new DecimalType(result.getData().getScanFlatbedCount()));
733 handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOEMAIL,
734 new DecimalType(result.getData().getScanToEmailCount()));
736 handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOFOLDER,
737 new DecimalType(result.getData().getScanToFolderCount()));
739 handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOHOST,
740 new DecimalType(result.getData().getScanToHostCount()));
743 handler.updateState(CGROUP_SCANNER, CHANNEL_TOTAL_ADF,
744 new DecimalType(result.getData().getScannerAdfCount()));
745 handler.updateState(CGROUP_SCANNER, CHANNEL_TOTAL_FLATBED,
746 new DecimalType(result.getData().getScannerFlatbedCount()));
747 handler.updateState(CGROUP_SCANNER, CHANNEL_JAM_EVENTS,
748 new DecimalType(result.getData().getScannerJamEvents()));
749 handler.updateState(CGROUP_SCANNER, CHANNEL_MISPICK_EVENTS,
750 new DecimalType(result.getData().getScannerMispickEvents()));
753 handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_ADF, new DecimalType(result.getData().getCopyAdfCount()));
754 handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_FLATBED,
755 new DecimalType(result.getData().getCopyFlatbedCount()));
756 handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_PAGES,
757 new DecimalType(result.getData().getCopyTotalImpressions()));
758 handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_COLORPAGES,
759 new DecimalType(result.getData().getCopyTotalColorImpressions()));
760 handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_MONOPAGES,
761 new DecimalType(result.getData().getCopyTotalMonochromeImpressions()));
764 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_WIN, new DecimalType(result.getData().getAppWindowsCount()));
765 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_OSX, new DecimalType(result.getData().getAppOSXCount()));
766 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_IOS, new DecimalType(result.getData().getAppIosCount()));
767 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_ANDROID,
768 new DecimalType(result.getData().getAppAndroidCount()));
769 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_SAMSUNG,
770 new DecimalType(result.getData().getAppSamsungCount()));
771 handler.updateState(CGROUP_APP, CHANNEL_TOTAL_CHROME,
772 new DecimalType(result.getData().getAppChromeCount()));
775 handler.updateState(CGROUP_OTHER, CHANNEL_CLOUD_PRINT,
776 new DecimalType(result.getData().getCloudPrintImpressions()));
783 private void goneOnline() {
784 handler.updateStatus(ThingStatus.ONLINE);
786 final ScheduledFuture<?> localOfflineScheduler = offlineScheduler;
788 if (localOfflineScheduler != null) {
789 localOfflineScheduler.cancel(true);
790 offlineScheduler = null;
792 retrieveProperties();
794 startBackgroundSchedules();
797 private void checkOnline() {
798 HPServerResult<HPStatus> result = printerClient.getStatus();
800 if (handlerDisposed) {
803 if (result.getStatus() == RequestStatus.SUCCESS) {
805 } else if (result.getStatus() == RequestStatus.TIMEOUT) {
806 handler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, result.getErrorMessage());
808 handler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, result.getErrorMessage());