]> git.basschouten.com Git - openhab-addons.git/blob
e4f429cfebe0973d9ba68e0c24e31511aaffa364
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.ipp.internal.handler;
14
15 import static org.openhab.binding.ipp.internal.IppBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.util.Collection;
21 import java.util.Set;
22 import java.util.concurrent.ScheduledFuture;
23 import java.util.concurrent.TimeUnit;
24
25 import org.cups4j.CupsPrinter;
26 import org.cups4j.WhichJobsEnum;
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.openhab.core.config.core.Configuration;
30 import org.openhab.core.config.discovery.DiscoveryListener;
31 import org.openhab.core.config.discovery.DiscoveryResult;
32 import org.openhab.core.config.discovery.DiscoveryService;
33 import org.openhab.core.config.discovery.DiscoveryServiceRegistry;
34 import org.openhab.core.library.types.DecimalType;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingTypeUID;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.thing.binding.BaseThingHandler;
41 import org.openhab.core.types.Command;
42 import org.openhab.core.types.RefreshType;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * The {@link IppPrinterHandler} is responsible for handling commands, which are sent
48  * to one of the channels.
49  *
50  * @author Tobias Braeutigam - Initial contribution
51  */
52 @NonNullByDefault
53 public class IppPrinterHandler extends BaseThingHandler implements DiscoveryListener {
54
55     /**
56      * Refresh interval defaults to every minute (60s)
57      */
58     private static final int DEFAULT_REFRESH_INTERVAL_IN_SECONDS = 60;
59
60     private final Logger logger = LoggerFactory.getLogger(IppPrinterHandler.class);
61
62     private @Nullable URL url;
63     private @Nullable CupsPrinter printer;
64
65     private @Nullable ScheduledFuture<?> refreshJob;
66
67     private final DiscoveryServiceRegistry discoveryServiceRegistry;
68
69     public IppPrinterHandler(Thing thing, DiscoveryServiceRegistry discoveryServiceRegistry) {
70         super(thing);
71         this.discoveryServiceRegistry = discoveryServiceRegistry;
72     }
73
74     @Override
75     public void initialize() {
76         Configuration config = getThing().getConfiguration();
77         String name = (String) config.get(PRINTER_PARAMETER_NAME);
78         try {
79             Object obj = config.get(PRINTER_PARAMETER_URL);
80             if (obj instanceof URL) {
81                 url = (URL) obj;
82             } else if (obj instanceof String) {
83                 url = new URL((String) obj);
84             }
85             printer = new CupsPrinter(null, url, name);
86         } catch (MalformedURLException e) {
87             logger.error("malformed url {}, printer thing creation failed", config.get(PRINTER_PARAMETER_URL));
88         }
89
90         int refresh = DEFAULT_REFRESH_INTERVAL_IN_SECONDS;
91         Object obj = config.get(PRINTER_PARAMETER_REFRESH_INTERVAL);
92         if (obj != null) {
93             BigDecimal ref = (BigDecimal) obj;
94             refresh = ref.intValue();
95         }
96
97         updateStatus(ThingStatus.UNKNOWN);
98         deviceOnlineWatchdog(refresh);
99         discoveryServiceRegistry.addDiscoveryListener(this);
100     }
101
102     @Override
103     public void dispose() {
104         stopRefreshJob();
105         logger.debug("IppPrinterHandler {} disposed.", url);
106         super.dispose();
107     }
108
109     private void deviceOnlineWatchdog(int refresh) {
110         stopRefreshJob();
111         refreshJob = scheduler.scheduleWithFixedDelay(() -> {
112             try {
113                 onDeviceStateChanged(printer);
114             } catch (Exception e) {
115                 logger.debug("Exception occurred during execution: {}", e.getMessage(), e);
116             }
117         }, 0, refresh, TimeUnit.SECONDS);
118     }
119
120     private void stopRefreshJob() {
121         ScheduledFuture<?> localRefreshJob = refreshJob;
122         if (localRefreshJob != null && !localRefreshJob.isCancelled()) {
123             localRefreshJob.cancel(true);
124             refreshJob = null;
125         }
126     }
127
128     @Override
129     public void handleCommand(ChannelUID channelUID, Command command) {
130         if (command instanceof RefreshType) {
131             onDeviceStateChanged(printer);
132             return;
133         }
134     }
135
136     public void onDeviceStateChanged(@Nullable CupsPrinter device) {
137         if (device != null && device.getPrinterURL().equals(url)) {
138             boolean online = false;
139             try {
140                 updateState(JOBS_CHANNEL, new DecimalType(device.getJobs(WhichJobsEnum.ALL, "", false).size()));
141                 online = true;
142             } catch (Exception e) {
143                 logger.debug("error updating jobs channel, reason: {}", e.getMessage());
144             }
145             try {
146                 updateState(WAITING_JOBS_CHANNEL,
147                         new DecimalType(device.getJobs(WhichJobsEnum.NOT_COMPLETED, "", false).size()));
148                 online = true;
149             } catch (Exception e) {
150                 logger.debug("error updating waiting-jobs channel, reason: {}", e.getMessage());
151             }
152             try {
153                 updateState(DONE_JOBS_CHANNEL,
154                         new DecimalType(device.getJobs(WhichJobsEnum.COMPLETED, "", false).size()));
155                 online = true;
156             } catch (Exception e) {
157                 logger.debug("error updating done-jobs channel, reason: {}", e.getMessage());
158             }
159             if (online) {
160                 updateStatus(ThingStatus.ONLINE);
161             }
162         }
163     }
164
165     @Override
166     public void thingDiscovered(DiscoveryService source, DiscoveryResult result) {
167         if (result.getThingUID().equals(getThing().getUID())) {
168             updateStatus(ThingStatus.ONLINE);
169         }
170     }
171
172     @Override
173     public void thingRemoved(DiscoveryService source, ThingUID thingUID) {
174         if (thingUID.equals(getThing().getUID())) {
175             updateStatus(ThingStatus.OFFLINE);
176         }
177     }
178
179     @Override
180     public @Nullable Collection<ThingUID> removeOlderResults(DiscoveryService source, long timestamp,
181             @Nullable Collection<ThingTypeUID> thingTypeUIDs, @Nullable ThingUID bridgeUID) {
182         return Set.of();
183     }
184 }