2 * Copyright (c) 2010-2021 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.ipp.internal.handler;
15 import java.math.BigDecimal;
16 import java.net.MalformedURLException;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import org.cups4j.CupsPrinter;
24 import org.cups4j.WhichJobsEnum;
25 import org.openhab.binding.ipp.internal.IppBindingConstants;
26 import org.openhab.core.config.core.Configuration;
27 import org.openhab.core.config.discovery.DiscoveryListener;
28 import org.openhab.core.config.discovery.DiscoveryResult;
29 import org.openhab.core.config.discovery.DiscoveryService;
30 import org.openhab.core.config.discovery.DiscoveryServiceRegistry;
31 import org.openhab.core.library.types.DecimalType;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.ThingUID;
37 import org.openhab.core.thing.binding.BaseThingHandler;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.RefreshType;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * The {@link IppPrinterHandler} is responsible for handling commands, which are sent
45 * to one of the channels.
47 * @author Tobias Braeutigam - Initial contribution
49 public class IppPrinterHandler extends BaseThingHandler implements DiscoveryListener {
51 private final Logger logger = LoggerFactory.getLogger(IppPrinterHandler.class);
55 private CupsPrinter printer;
57 private int refresh = 60; // refresh every minute as default
58 ScheduledFuture<?> refreshJob;
60 private DiscoveryServiceRegistry discoveryServiceRegistry;
62 public IppPrinterHandler(Thing thing, DiscoveryServiceRegistry discoveryServiceRegistry) {
64 if (discoveryServiceRegistry != null) {
65 this.discoveryServiceRegistry = discoveryServiceRegistry;
70 public void initialize() {
71 Configuration config = getThing().getConfiguration();
73 Object obj = config.get(IppBindingConstants.PRINTER_PARAMETER_URL);
74 name = (String) config.get(IppBindingConstants.PRINTER_PARAMETER_NAME);
75 if (config.get(IppBindingConstants.PRINTER_PARAMETER_REFRESH_INTERVAL) != null) {
76 BigDecimal ref = (BigDecimal) config.get(IppBindingConstants.PRINTER_PARAMETER_REFRESH_INTERVAL);
77 refresh = ref.intValue();
79 if (obj instanceof URL) {
81 } else if (obj instanceof String) {
82 url = new URL((String) obj);
84 printer = new CupsPrinter(url, name, false);
85 } catch (MalformedURLException e) {
86 logger.error("malformed url {}, printer thing creation failed",
87 config.get(IppBindingConstants.PRINTER_PARAMETER_URL));
89 // until we get an update put the Thing offline
90 updateStatus(ThingStatus.OFFLINE);
91 deviceOnlineWatchdog();
92 if (this.discoveryServiceRegistry != null) {
93 this.discoveryServiceRegistry.addDiscoveryListener(this);
98 public void dispose() {
99 if (refreshJob != null && !refreshJob.isCancelled()) {
100 refreshJob.cancel(true);
103 logger.debug("IppPrinterHandler {} disposed.", url);
107 private void deviceOnlineWatchdog() {
108 Runnable runnable = () -> {
110 onDeviceStateChanged(printer);
111 } catch (Exception e) {
112 logger.debug("Exception occurred during execution: {}", e.getMessage(), e);
115 refreshJob = scheduler.scheduleWithFixedDelay(runnable, 0, refresh, TimeUnit.SECONDS);
119 public void handleCommand(ChannelUID channelUID, Command command) {
120 if (command instanceof RefreshType) {
121 onDeviceStateChanged(printer);
126 public void onDeviceStateChanged(CupsPrinter device) {
127 if (device.getPrinterURL().equals(url)) {
128 boolean online = false;
130 updateState(new ChannelUID(getThing().getUID(), IppBindingConstants.JOBS_CHANNEL),
131 new DecimalType(device.getJobs(WhichJobsEnum.ALL, "", false).size()));
133 } catch (Exception e) {
134 logger.debug("error updating jobs channel, reason: {}", e.getMessage());
137 updateState(new ChannelUID(getThing().getUID(), IppBindingConstants.WAITING_JOBS_CHANNEL),
138 new DecimalType(device.getJobs(WhichJobsEnum.NOT_COMPLETED, "", false).size()));
140 } catch (Exception e) {
141 logger.debug("error updating waiting-jobs channel, reason: {}", e.getMessage());
144 updateState(new ChannelUID(getThing().getUID(), IppBindingConstants.DONE_JOBS_CHANNEL),
145 new DecimalType(device.getJobs(WhichJobsEnum.COMPLETED, "", false).size()));
147 } catch (Exception e) {
148 logger.debug("error updating done-jobs channel, reason: {}", e.getMessage());
151 updateStatus(ThingStatus.ONLINE);
157 public void thingDiscovered(DiscoveryService source, DiscoveryResult result) {
158 if (result.getThingUID().equals(this.getThing().getUID())) {
159 updateStatus(ThingStatus.ONLINE);
164 public void thingRemoved(DiscoveryService source, ThingUID thingUID) {
165 if (thingUID.equals(this.getThing().getUID())) {
166 updateStatus(ThingStatus.OFFLINE);
171 public Collection<ThingUID> removeOlderResults(DiscoveryService source, long timestamp,
172 Collection<ThingTypeUID> thingTypeUIDs, ThingUID bridgeUID) {
173 return Collections.emptyList();