/** * Copyright (c) 2010-2017 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.cups.internal; import java.io.IOException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; import java.util.Dictionary; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.cups4j.CupsClient; import org.cups4j.CupsPrinter; import org.cups4j.WhichJobsEnum; import org.openhab.binding.cups.CupsBindingProvider; import org.openhab.core.binding.AbstractActiveBinding; import org.openhab.core.library.types.DecimalType; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The RefreshService polls all configured Cups servers with a configurable * interval and posts all values on the internal event bus. The interval is 1 * minute by default. * * @author Tobias Bräutigam * @since 1.1.0 */ public class CupsBinding extends AbstractActiveBinding<CupsBindingProvider>implements ManagedService { private static final Logger logger = LoggerFactory.getLogger(CupsBinding.class); private static final Pattern IP_PATTERN = Pattern.compile("[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"); private CupsClient client; /** the ip address to use for connecting to the Cups server */ private String host = "localhost"; private String ip; /** the port to use for connecting to the Cups server (optional, defaults to 631) */ private int port = 631; /** * the refresh interval which is used to poll values from the Cups server * (optional, defaults to 60000ms) */ private long refreshInterval = 60000; @Override protected String getName() { return "Cups Refresh Service"; } @Override protected long getRefreshInterval() { return refreshInterval; } /** * Create a new {@link CupsClient} with the given <code>host</code> and * <code>port</code> * * @param host * @param port */ private void connect(String host, int port) { if (StringUtils.isNotBlank(host) && port > 0) { try { client = new CupsClient(host, port); logger.debug("Connection to CupsServer {} established", host); } catch (Exception e) { logger.warn("Couldn't connect to CupsServer. [Host '{}' Port '{}']: ", host, port, e.getLocalizedMessage()); } } else { logger.warn( "Couldn't connect to CupsServer because of missing connection parameters. [Host '{}' Port '{}']", host, port); } } /** * @{inheritDoc} */ @Override public void execute() { if (client == null) { logger.warn("CupsClient is null => refresh cycle aborted!"); return; } for (CupsBindingProvider provider : providers) { for (String itemName : provider.getItemNames()) { String printerName = provider.getPrinterName(itemName); WhichJobsEnum whichJobs = provider.getWhichJobs(itemName); if (printerName == null) { logger.warn("printerName isn't defined for itemName '{}'" + " => querying bus for values aborted!", itemName); continue; } State value = UnDefType.UNDEF; try { URL printerUrl = null; CupsPrinter printer = null; try { printerUrl = new URL(printerName); } catch (MalformedURLException e) { try { printerUrl = new URL("http://" + host + ":" + port + "/printers/" + printerName); } catch (MalformedURLException e1) { logger.warn("Failed to construct URL for printer name: {}", printerName); } } if (printerUrl == null) { // try to find printer by name for (CupsPrinter pr : client.getPrinters()) { if (pr.getName().equalsIgnoreCase(printerName)) { printer = pr; break; } } } else { printer = client.getPrinter(printerUrl); } if (printer != null) { value = new DecimalType(client.getJobs(printer, whichJobs, "", false).size()); logger.debug("Found printer {}#{} with value {}", printerUrl, whichJobs, value); } else { logger.info("There is no printer for path {}", printerUrl); } } catch (IOException ioe) { logger.warn("Couldn't establish network connection for printer '{}'", printerName, ioe); } catch (Exception e) { logger.error("Couldn't get printer '{}' from cups server", printerName, e); } finally { eventPublisher.postUpdate(itemName, value); } } } } protected void addBindingProvider(CupsBindingProvider bindingProvider) { super.addBindingProvider(bindingProvider); } protected void removeBindingProvider(CupsBindingProvider bindingProvider) { super.removeBindingProvider(bindingProvider); } @Override @SuppressWarnings("rawtypes") public void updated(Dictionary config) throws ConfigurationException { if (config == null) { return; } host = Objects.toString(config.get("host"), null); Matcher matcher = IP_PATTERN.matcher(host); if (!matcher.matches()) { try { InetAddress address = InetAddress.getByName(host); ip = address.getHostAddress(); } catch (UnknownHostException e) { throw new ConfigurationException("host", "unknown host '" + host + "'!"); } } else { // host should contain an IP address ip = host; } String portString = Objects.toString(config.get("port"), null); if (StringUtils.isNotBlank(portString)) { port = Integer.parseInt(portString); } String refreshIntervalString = Objects.toString(config.get("refresh"), null); if (StringUtils.isNotBlank(refreshIntervalString)) { refreshInterval = Long.parseLong(refreshIntervalString); } // there is a valid Cups configuration, so connect to the Cups // server ... connect(ip, port); setProperlyConfigured(true); } }