added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.hpprinter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-addons

View File

@@ -0,0 +1,138 @@
# HP Printer Binding
This binding supports [HP Printers](https://store.hp.com/us/en/cv/printers), which are reachable through IP on the local network.
## Supported Things
There is only one thing type named `printer`.
All channels are added dynamically depending on the type of printer and its capabilities.
## Discovery
This binding uses mDNS for discovering HP Printers on the local network.
## Thing Configuration
The configuration parameters are:
| Parameter | Name | Type | Required | Default |
| --------------------------------- | --------------- | ------- | -------- | ------- |
| IP Address | ipAddress | String | yes | |
| Usage Refresh Interval (seconds) | usageInterval | Integer | | 30 |
| Status Refresh Interval (seconds) | statusInterval | Integer | | 4 |
## Channels
| Channel | Group | Name | Data Type |
| ------------------------------------------ | ----------- | --------------------- | -------------------- |
| Printer Status | status | status | String |
| Tray Empty/Open | status | trayEmptyOrOpen | Switch |
| Scanner Status | status | scannerStatus | String |
| ADF Loaded | status | scannerAdfLoaded | Switch |
| Black Colour Level | usage | blackLevel | Number:Dimensionless |
| Colour Level | usage | colorLevel | Number:Dimensionless |
| Cyan Colour Level | usage | cyanLevel | Number:Dimensionless |
| Magenta Colour Level | usage | magentaLevel | Number:Dimensionless |
| Yellow Colour Level | usage | yellowLevel | Number:Dimensionless |
| Black Marking Used | usage | blackMarker | Number:Volume |
| Colour Marking Used | usage | colorMarker | Number:Volume |
| Cyan Marking Used | usage | cyanMarker | Number:Volume |
| Magenta Marking Used | usage | magentaMarker | Number:Volume |
| Yellow Marking Used | usage | yellowMarker | Number:Volume |
| Black Pages Remaining | usage | blackPagesRemaining | Number |
| Colour Pages Remaining | usage | colorPagesRemaining | Number |
| Cyan Pages Remaining | usage | cyanPagesRemaining | Number |
| Magenta Pages Remaining | usage | magentaPagesRemaining | Number |
| Yellow Pages Remaining | usage | yellowPagesRemaining | Number |
| Total Number of Pages Printed Lifetime | usage | totalCount | Number |
| Total Number of Colour Pages Printed | usage | totalColorCount | Number |
| Total Number of Monochrome Pages Printed | usage | totalMonochromeCount | Number |
| Paper Jams | usage | jamEvents | Number |
| Missed Pick Events | usage | mispickEvents | Number |
| Front Panel Cancel Count | usage | fpCancelCount | Number |
| Subscription Count | usage | subscriptionCount | Number |
| Scanner Document Feeder Count | scanner | totalAdf | Number |
| Scanner Flatbed Count | scanner | totalFlatbed | Number |
| Scanner Paper Jams | scanner | jamEvents | Number |
| Scanner Missed Picks | scanner | mispickEvents | Number |
| Scan Document Feeder Count | scan | totalAdf | Number |
| Scan Flatbed Count | scan | totalFlatbed | Number |
| Scan to Email Count | scan | totalToEmail | Number |
| Scan to Folder Count | scan | totalToFolder | Number |
| Scan to Host Count | scan | totalToHost | Number |
| Copy Document Feeder Count | copy | totalAdf | Number |
| Copy Flatbed Count | copy | totalFlatbed | Number |
| Copy Total Pages Count | copy | totalCount | Number |
| Copy Total Colour Pages Count | copy | totalColorCount | Number |
| Copy Total Monochrome Pages Count | copy | totalMonochromeCount | Number |
| Windows Page Count | app | totalWin | Number |
| Android Page Count | app | totalAndroid | Number |
| iOS Page Count | app | totalIos | Number |
| OSX Page Count | app | totalOsx | Number |
| Samsung Page Count | app | totalSamsung | Number |
| Chrome Page Count | app | totalChrome | Number |
| Google Cloud Print Count | other | cloudPrint | Number |
Notes:
* All channels are dynamically added at runtime.
* The word color in channel names follows American spelling ("color").
* The `colorLevel`, `colorMarkingUsed` and `colorPagesRemaining` channels are used on printers that have only a single color cartridge instead of separate Ccyan, magenta and yellow cartridges.
* The `scanner` group is for the scanning engine which consists of scan, copy and other operations; the `scan` group is for scanner operations only.
* If no `status` group channels are selected, then those relevant data endpoints on the *Embedded Web Server* are not polled for status information.
## Full Textual Example
### Thing File
```
Thing hpprinter:printer:djprinter "Printer" @ "Office" [ ipAddress="192.168.1.1", usageInterval="30", statusInterval="4" ]
```
### Item File
```
String PrinterStatus "Status" { channel="pprinter:printer:djprinter:status#status" }
Number:Dimensionless PrinterBlackLevel "Black Level" { channel="hpprinter:printer:djprinter:ink#blackLevel" }
Number:Dimensionless PrinterCyanLevel "Cyan Level" { channel="hpprinter:printer:djprinter:ink#cyanLevel" }
Number:Dimensionless PrinterMagentaLevel "Magenta Level" { channel="hpprinter:printer:djprinter:ink#magentaLevel" }
Number:Dimensionless PrinterYellowLevel "Yellow Level" { channel="hpprinter:printer:djprinter:ink#yellowLevel" }
Number PrinterTotalPages "Total Pages" { channel="hpprinter:printer:djprinter:usage#totalCount" }
Number PrinterTotalColourPages "Total Colour Pages" { channel="hpprinter:printer:djprinter:usage#totalColorCount" }
Number PrinterTotalMonochromePages "Total Monochrome Pages" { channel="hpprinter:printer:djprinter:usage#totalMonochromeCount" }
```
### Sitemap File
Black Ink displayed as a whole percentage - `60 %`
```
Text item=hpprinter_printer_djprinter_ink_blackLevel label="Black [%.0f %unit%]"
```
Black Marker displayed in millilitres - `21 ml`
*Default*
```
Text item=hpprinter_printer_djprinter_usage_blackMarker label="Black Marker [%.0f %unit%]"
```
Black Marker displayed in litres - `0.021 l`
```
Text item=hpprinter_printer_djprinter_usage_blackMarker label="Black Marker [%.3f l]"
```
Black Marker displayed in microlitres - `21000 µl`
```
Text item=hpprinter_printer_djprinter_usage_blackMarker label="Black Marker [%.0f µl]"
```
Scanner Document Feeder loaded with text status display - `ON` or `OFF`
```
Text item=hpprinter_printer_djprinter_status_scannerAdfLoaded label="ADF Loaded [%s]"
```

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.hpprinter</artifactId>
<name>openHAB Add-ons :: Bundles :: HP Printer Binding</name>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.hpprinter-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-hpprinter" description="HP Printer Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-mdns</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.hpprinter/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,785 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import static org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.hpprinter.internal.api.HPFeatures;
import org.openhab.binding.hpprinter.internal.api.HPProductUsageFeatures;
import org.openhab.binding.hpprinter.internal.api.HPProductUsageFeatures.PrinterType;
import org.openhab.binding.hpprinter.internal.api.HPProperties;
import org.openhab.binding.hpprinter.internal.api.HPScannerStatus;
import org.openhab.binding.hpprinter.internal.api.HPScannerStatusFeatures;
import org.openhab.binding.hpprinter.internal.api.HPServerResult;
import org.openhab.binding.hpprinter.internal.api.HPServerResult.RequestStatus;
import org.openhab.binding.hpprinter.internal.api.HPStatus;
import org.openhab.binding.hpprinter.internal.api.HPUsage;
import org.openhab.binding.hpprinter.internal.api.HPWebServerClient;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.MetricPrefix;
import org.openhab.core.library.unit.SmartHomeUnits;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link HPPrinterBinder} connects the binding to the Web Server Client
* classes.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPPrinterBinder {
private final Logger logger = LoggerFactory.getLogger(HPPrinterBinder.class);
private static final int OFFLINE_CHECK_INTERVAL = 15;
private HPPrinterHandler handler;
private ScheduledExecutorService scheduler;
private final int statusCheckInterval;
private final int usageCheckInterval;
private final HPWebServerClient printerClient;
private @Nullable ScheduledFuture<?> statusScheduler;
private @Nullable ScheduledFuture<?> scannerStatusScheduler;
private @Nullable ScheduledFuture<?> usageScheduler;
private @Nullable ScheduledFuture<?> offlineScheduler;
/**
* Creates a new HP Printer Binder object
*
* @param handler {HPPrinterBinderEvent} The Event handler for the binder.
* @param httpClient {HttpClient} The HttpClient object to use to perform HTTP
* requests.
* @param scheduler {ScheduledExecutorService} The scheduler service object.
* @param config {HPPrinterConfiguration} The configuration object.
*/
public HPPrinterBinder(HPPrinterHandler handler, HttpClient httpClient, ScheduledExecutorService scheduler,
HPPrinterConfiguration config) {
this.handler = handler;
this.scheduler = scheduler;
usageCheckInterval = config.usageInterval;
statusCheckInterval = config.statusInterval;
String ipAddress = config.ipAddress;
if (ipAddress == null) {
throw new IllegalStateException("ip-address should have been validated already and may not be empty.");
}
printerClient = new HPWebServerClient(httpClient, ipAddress);
}
public void retrieveProperties() {
HPServerResult<HPProperties> result = printerClient.getProperties();
if (result.getStatus() == RequestStatus.SUCCESS) {
handler.updateProperties(result.getData().getProperties());
}
}
public synchronized void channelsChanged() {
logger.trace("Channels have been changed");
close();
open();
}
/**
* Dynamically add channels to the Thing based on the Embedded Web Server Usage
* Feed
*/
public void dynamicallyAddChannels(ThingUID thingUid) {
logger.debug("Building dynamic channels based on printer");
HPServerResult<HPFeatures> featureResult = printerClient.getProductUsageFeatures();
if (featureResult.getStatus() == RequestStatus.SUCCESS) {
final List<Channel> channels = new ArrayList<>();
HPFeatures features = featureResult.getData();
if (features.getProductStatusSupported()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_STATUS), CoreItemFactory.STRING)
.withLabel("Status").withDescription("Printer status").withType(chanTypeStatus).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_TRAYEMPTYOROPEN),
CoreItemFactory.SWITCH)
.withLabel("Tray Empty/Open").withDescription("The tray is empty or open")
.withType(chanTypeReadSwitch).build());
}
if (features.getScannerStatusSupported()) {
HPServerResult<HPScannerStatusFeatures> result = printerClient.getScannerFeatures();
if (result.getStatus() == RequestStatus.SUCCESS) {
HPScannerStatusFeatures feature = result.getData();
if (feature.hasStatus()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_SCANNER_STATUS),
CoreItemFactory.STRING)
.withLabel("Scanner").withDescription("Scanner status").withType(chanTypeStatus)
.build());
}
if (feature.hasAdf()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_STATUS, CHANNEL_SCANNER_ADFLOADED),
CoreItemFactory.SWITCH)
.withLabel("ADF Loaded").withDescription("The automatic document feeder is loaded")
.withType(chanTypeReadSwitch).build());
}
}
}
if (features.getProductUsageSupported()) {
HPServerResult<HPProductUsageFeatures> result = printerClient.getProductFeatures();
if (result.getStatus() == RequestStatus.SUCCESS) {
HPProductUsageFeatures feature = result.getData();
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_BLACK_LEVEL),
HPPrinterBindingConstants.ITEM_TYPE_INK)
.withLabel("Black Level").withDescription("Shows the amount of Black Ink/Toner remaining")
.withType(chanTypeInkLevel).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_PAGES), CoreItemFactory.NUMBER)
.withLabel("Total Lifetime Pages")
.withDescription("The amount of pages printed over the printer lifetime")
.withType(chanTypeTotals).build());
if (feature.hasCumulativeMarking()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_MARKING),
HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
.withLabel("Black Marking Used").withDescription("The amount of Black Marking used")
.withType(chanTypeMarking).build());
}
switch (feature.getType()) {
case SINGLECOLOR:
if (feature.hasCumulativeMarking()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_COLOR_MARKING),
HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
.withLabel("Colour Marking Used")
.withDescription("The amount of Colour Marking used").withType(chanTypeMarking)
.build());
}
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_COLOR_LEVEL),
HPPrinterBindingConstants.ITEM_TYPE_INK)
.withLabel("Color Level")
.withDescription("Shows the amount of Colour Ink/Toner remaining")
.withType(chanTypeInkLevel).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Colour Pages")
.withDescription("The amount of colour pages printed").withType(chanTypeTotals)
.build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Monochrome Pages")
.withDescription("The amount of monochrome pages printed").withType(chanTypeTotals)
.build());
if (feature.hasPagesRemaining()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Black Pages Remaining")
.withDescription("Estimated Black pages remaining")
.withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_COLOR_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Colour Pages Remaining")
.withDescription("Estimated Colour pages remaining")
.withType(chanTypeTotalsAdvanced).build());
}
break;
case MULTICOLOR:
if (feature.hasCumulativeMarking()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_CYAN_MARKING),
HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
.withLabel("Cyan Marking Used")
.withDescription("The amount of Cyan Marking used").withType(chanTypeMarking)
.build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MAGENTA_MARKING),
HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
.withLabel("Magenta Marking Used")
.withDescription("The amount of Magenta Marking used").withType(chanTypeMarking)
.build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_YELLOW_MARKING),
HPPrinterBindingConstants.ITEM_TYPE_CUMLMARK)
.withLabel("Yellow Marking Used")
.withDescription("The amount of Yellow Marking used").withType(chanTypeMarking)
.build());
}
if (feature.hasPagesRemaining()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Black Pages Remaining")
.withDescription("Estimated Black pages remaining")
.withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_CYAN_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Cyan Pages Remaining")
.withDescription("Estimated Cyan pages remaining")
.withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MAGENTA_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Magenta Pages Remaining")
.withDescription("Estimated Magenta pages remaining")
.withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_YELLOW_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Yellow Pages Remaining")
.withDescription("Estimated Yellow pages remaining")
.withType(chanTypeTotalsAdvanced).build());
}
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_CYAN_LEVEL),
HPPrinterBindingConstants.ITEM_TYPE_INK)
.withLabel("Cyan Level")
.withDescription("Shows the amount of Cyan Ink/Toner remaining")
.withType(chanTypeInkLevel).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_MAGENTA_LEVEL),
HPPrinterBindingConstants.ITEM_TYPE_INK)
.withLabel("Magenta Level")
.withDescription("Shows the amount of Magenta Ink/Toner remaining")
.withType(chanTypeInkLevel).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_YELLOW_LEVEL),
HPPrinterBindingConstants.ITEM_TYPE_INK)
.withLabel("Yellow Level")
.withDescription("Shows the amount of Yellow Ink/Toner remaining")
.withType(chanTypeInkLevel).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Colour Pages")
.withDescription("The amount of colour pages printed").withType(chanTypeTotals)
.build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Monochrome Pages")
.withDescription("The amount of monochrome pages printed").withType(chanTypeTotals)
.build());
break;
default:
if (feature.hasPagesRemaining()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING),
CoreItemFactory.NUMBER)
.withLabel("Black Pages Remaining")
.withDescription("Estimated Black pages remaining")
.withType(chanTypeTotalsAdvanced).build());
}
}
if (feature.hasJamEvents()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_JAM_EVENTS),
CoreItemFactory.NUMBER)
.withLabel("Jams").withDescription("The amount of times the paper has jammed")
.withType(chanTypeTotalsAdvanced).build());
}
if (feature.hasMispickEvents()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MISPICK_EVENTS),
CoreItemFactory.NUMBER)
.withLabel("Missed Picks")
.withDescription("The amount of times the paper failed to feed into the printer")
.withType(chanTypeTotalsAdvanced).build());
}
if (feature.hasSubscriptionCount()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_SUBSCRIPTION),
CoreItemFactory.NUMBER)
.withLabel("Subscription Count")
.withDescription("The amount of times an item has been printed in subscription")
.withType(chanTypeTotalsAdvanced).build());
}
if (feature.hasTotalFrontPanelCancelPresses()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_FRONT_PANEL_CANCEL),
CoreItemFactory.NUMBER)
.withLabel("Front Panel Cancel Count")
.withDescription("The amount of times a print has been cancelled from the Front Panel")
.withType(chanTypeTotalsAdvanced).build());
}
// Other
if (feature.hasCloudPrint()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_OTHER, CHANNEL_CLOUD_PRINT),
CoreItemFactory.NUMBER)
.withLabel("Cloud Print Count")
.withDescription(
"The amount of times a document has been printed via Google Cloud Print")
.withType(chanTypeTotalsAdvanced).build());
}
// Scan
if (feature.hasScanADF()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_ADF),
CoreItemFactory.NUMBER)
.withLabel("Document Feeder Count")
.withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
.build());
}
if (feature.hasScanFlatbed()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_FLATBED),
CoreItemFactory.NUMBER)
.withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
.withType(chanTypeTotals).build());
}
if (feature.hasScanToEmail()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOEMAIL),
CoreItemFactory.NUMBER)
.withLabel("Scan to Email Count").withDescription("Times scanned using Scan to Email")
.withType(chanTypeTotalsAdvanced).build());
}
if (feature.hasScanToFolder()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOFOLDER),
CoreItemFactory.NUMBER)
.withLabel("Scan to Folder Count").withDescription("Times scanned using Scan to Folder")
.withType(chanTypeTotalsAdvanced).build());
}
if (feature.hasScanToHost()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCAN, CHANNEL_TOTAL_TOHOST),
CoreItemFactory.NUMBER)
.withLabel("Scan to Host Count")
.withDescription("Times scanned using Scan to Host Device")
.withType(chanTypeTotalsAdvanced).build());
}
// Scanner Engine
if (feature.hasScannerEngine()) {
if (feature.hasScanADF()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_TOTAL_ADF),
CoreItemFactory.NUMBER)
.withLabel("Document Feeder Count")
.withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
.build());
}
if (feature.hasScanFlatbed()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_TOTAL_FLATBED),
CoreItemFactory.NUMBER)
.withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
.withType(chanTypeTotals).build());
}
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_JAM_EVENTS),
CoreItemFactory.NUMBER)
.withLabel("Jams").withDescription("The amount of times the paper has jammed")
.withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_SCANNER, CHANNEL_MISPICK_EVENTS),
CoreItemFactory.NUMBER)
.withLabel("Missed Picks")
.withDescription("The amount of times the paper failed to feed into the printer")
.withType(chanTypeTotalsAdvanced).build());
}
// Copy Engine
if (feature.hasCopyApplication()) {
if (feature.hasScanADF()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_ADF),
CoreItemFactory.NUMBER)
.withLabel("Document Feeder Count")
.withDescription("Times scanned via the Document Feeder").withType(chanTypeTotals)
.build());
}
if (feature.hasScanFlatbed()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_FLATBED),
CoreItemFactory.NUMBER)
.withLabel("Flatbed Count").withDescription("Times scanned via the Flatbed/Glass")
.withType(chanTypeTotals).build());
}
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_PAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Pages").withDescription("The amount of pages copied")
.withType(chanTypeTotals).build());
if (feature.getType() == PrinterType.MULTICOLOR
|| feature.getType() == PrinterType.SINGLECOLOR) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_COLORPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Colour Pages")
.withDescription("The amount of colour pages copied").withType(chanTypeTotals)
.build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_COPY, CHANNEL_TOTAL_MONOPAGES),
CoreItemFactory.NUMBER)
.withLabel("Total Monochrome Pages")
.withDescription("The amount of monochrome pages copied").withType(chanTypeTotals)
.build());
}
}
// App Usage
if (feature.hasPrintApplication()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_WIN), CoreItemFactory.NUMBER)
.withLabel("Windows").withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_ANDROID),
CoreItemFactory.NUMBER)
.withLabel("Android").withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_IOS), CoreItemFactory.NUMBER)
.withLabel("iOS").withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_OSX), CoreItemFactory.NUMBER)
.withLabel("OSX").withType(chanTypeTotalsAdvanced).build());
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_SAMSUNG),
CoreItemFactory.NUMBER)
.withLabel("Samsung").withType(chanTypeTotalsAdvanced).build());
if (feature.hasPrintApplicationChrome()) {
channels.add(ChannelBuilder
.create(new ChannelUID(thingUid, CGROUP_APP, CHANNEL_TOTAL_CHROME),
CoreItemFactory.NUMBER)
.withLabel("Chrome").withType(chanTypeTotalsAdvanced).build());
}
}
}
}
handler.binderAddChannels(channels);
}
}
/**
* Opens the connection to the Embedded Web Server
*/
public void open() {
runOfflineScheduler();
}
/**
* Close the connection to the Embedded Web Server
*/
public void close() {
stopBackgroundSchedules();
final ScheduledFuture<?> localOfflineScheduler = offlineScheduler;
if (localOfflineScheduler != null) {
localOfflineScheduler.cancel(true);
offlineScheduler = null;
}
}
/**
* The device has gone offline
*/
public void goneOffline() {
handler.updateStatus(ThingStatus.OFFLINE);
close();
runOfflineScheduler();
}
private void runOfflineScheduler() {
offlineScheduler = scheduler.scheduleWithFixedDelay(this::checkOnline, 0, OFFLINE_CHECK_INTERVAL,
TimeUnit.SECONDS);
}
private synchronized void stopBackgroundSchedules() {
logger.debug("Stopping Interval Refreshes");
ScheduledFuture<?> localUsageScheduler = usageScheduler;
if (localUsageScheduler != null) {
localUsageScheduler.cancel(true);
}
ScheduledFuture<?> localStatusScheduler = statusScheduler;
if (localStatusScheduler != null) {
localStatusScheduler.cancel(true);
}
ScheduledFuture<?> localScannerStatusScheduler = scannerStatusScheduler;
if (localScannerStatusScheduler != null) {
localScannerStatusScheduler.cancel(true);
}
}
private synchronized void startBackgroundSchedules() {
stopBackgroundSchedules();
logger.debug("Starting Interval Refreshes");
usageScheduler = scheduler.scheduleWithFixedDelay(this::checkUsage, 0, usageCheckInterval, TimeUnit.SECONDS);
// Only schedule below items when there channels are linked
if (handler.areStatusChannelsLinked(new String[] { CHANNEL_STATUS, CHANNEL_TRAYEMPTYOROPEN })) {
statusScheduler = scheduler.scheduleWithFixedDelay(this::checkStatus, 0, statusCheckInterval,
TimeUnit.SECONDS);
}
if (handler.areStatusChannelsLinked(new String[] { CHANNEL_SCANNER_STATUS, CHANNEL_SCANNER_ADFLOADED })) {
scannerStatusScheduler = scheduler.scheduleWithFixedDelay(this::checkScannerStatus, 0, statusCheckInterval,
TimeUnit.SECONDS);
}
}
private void checkScannerStatus() {
HPServerResult<HPScannerStatus> result = printerClient.getScannerStatus();
if (result.getStatus() == RequestStatus.SUCCESS) {
handler.updateState(CGROUP_STATUS, CHANNEL_SCANNER_STATUS,
new StringType(result.getData().getScannerStatus()));
handler.updateState(CGROUP_STATUS, CHANNEL_SCANNER_ADFLOADED,
convertToOnOffType(result.getData().getAdfLoaded()));
} else {
goneOffline();
}
}
private void checkStatus() {
HPServerResult<HPStatus> result = printerClient.getStatus();
if (result.getStatus() == RequestStatus.SUCCESS) {
handler.updateState(CGROUP_STATUS, CHANNEL_STATUS, new StringType(result.getData().getPrinterStatus()));
handler.updateState(CGROUP_STATUS, CHANNEL_TRAYEMPTYOROPEN,
convertToOnOffType(result.getData().getTrayEmptyOrOpen()));
} else {
goneOffline();
}
}
private static State convertToOnOffType(Boolean bool) {
if (bool) {
return OnOffType.ON;
} else {
return OnOffType.OFF;
}
}
private void checkUsage() {
HPServerResult<HPUsage> result = printerClient.getUsage();
if (result.getStatus() == RequestStatus.SUCCESS) {
// Inks
handler.updateState(CGROUP_INK, CHANNEL_BLACK_LEVEL,
new QuantityType<>(result.getData().getInkBlack(), SmartHomeUnits.PERCENT));
handler.updateState(CGROUP_INK, CHANNEL_COLOR_LEVEL,
new QuantityType<>(result.getData().getInkColor(), SmartHomeUnits.PERCENT));
handler.updateState(CGROUP_INK, CHANNEL_CYAN_LEVEL,
new QuantityType<>(result.getData().getInkCyan(), SmartHomeUnits.PERCENT));
handler.updateState(CGROUP_INK, CHANNEL_MAGENTA_LEVEL,
new QuantityType<>(result.getData().getInkMagenta(), SmartHomeUnits.PERCENT));
handler.updateState(CGROUP_INK, CHANNEL_YELLOW_LEVEL,
new QuantityType<>(result.getData().getInkYellow(), SmartHomeUnits.PERCENT));
handler.updateState(CGROUP_USAGE, CHANNEL_JAM_EVENTS, new DecimalType(result.getData().getJamEvents()));
handler.updateState(CGROUP_USAGE, CHANNEL_SUBSCRIPTION,
new DecimalType(result.getData().getTotalSubscriptionImpressions()));
handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_COLORPAGES,
new DecimalType(result.getData().getTotalColorImpressions()));
handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_MONOPAGES,
new DecimalType(result.getData().getTotalMonochromeImpressions()));
handler.updateState(CGROUP_USAGE, CHANNEL_TOTAL_PAGES,
new DecimalType(result.getData().getTotalImpressions()));
handler.updateState(CGROUP_USAGE, CHANNEL_MISPICK_EVENTS,
new DecimalType(result.getData().getMispickEvents()));
handler.updateState(CGROUP_USAGE, CHANNEL_FRONT_PANEL_CANCEL,
new DecimalType(result.getData().getFrontPanelCancelCount()));
handler.updateState(CGROUP_USAGE, CHANNEL_BLACK_MARKING, new QuantityType<>(
result.getData().getInkBlackMarking(), MetricPrefix.MILLI(SmartHomeUnits.LITRE)));
handler.updateState(CGROUP_USAGE, CHANNEL_COLOR_MARKING, new QuantityType<>(
result.getData().getInkColorMarking(), MetricPrefix.MILLI(SmartHomeUnits.LITRE)));
handler.updateState(CGROUP_USAGE, CHANNEL_CYAN_MARKING,
new QuantityType<>(result.getData().getInkCyanMarking(), MetricPrefix.MILLI(SmartHomeUnits.LITRE)));
handler.updateState(CGROUP_USAGE, CHANNEL_MAGENTA_MARKING, new QuantityType<>(
result.getData().getInkMagentaMarking(), MetricPrefix.MILLI(SmartHomeUnits.LITRE)));
handler.updateState(CGROUP_USAGE, CHANNEL_YELLOW_MARKING, new QuantityType<>(
result.getData().getInkYellowMarking(), MetricPrefix.MILLI(SmartHomeUnits.LITRE)));
handler.updateState(CGROUP_USAGE, CHANNEL_BLACK_PAGES_REMAINING,
new DecimalType(result.getData().getInkBlackPagesRemaining()));
handler.updateState(CGROUP_USAGE, CHANNEL_COLOR_PAGES_REMAINING,
new DecimalType(result.getData().getInkColorPagesRemaining()));
handler.updateState(CGROUP_USAGE, CHANNEL_CYAN_PAGES_REMAINING,
new DecimalType(result.getData().getInkCyanPagesRemaining()));
handler.updateState(CGROUP_USAGE, CHANNEL_MAGENTA_PAGES_REMAINING,
new DecimalType(result.getData().getInkMagentaPagesRemaining()));
handler.updateState(CGROUP_USAGE, CHANNEL_YELLOW_PAGES_REMAINING,
new DecimalType(result.getData().getInkYellowPagesRemaining()));
// Scan
handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_ADF, new DecimalType(result.getData().getScanAdfCount()));
handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_FLATBED,
new DecimalType(result.getData().getScanFlatbedCount()));
handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOEMAIL,
new DecimalType(result.getData().getScanToEmailCount()));
handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOFOLDER,
new DecimalType(result.getData().getScanToFolderCount()));
handler.updateState(CGROUP_SCAN, CHANNEL_TOTAL_TOHOST,
new DecimalType(result.getData().getScanToHostCount()));
// Scanner
handler.updateState(CGROUP_SCANNER, CHANNEL_TOTAL_ADF,
new DecimalType(result.getData().getScannerAdfCount()));
handler.updateState(CGROUP_SCANNER, CHANNEL_TOTAL_FLATBED,
new DecimalType(result.getData().getScannerFlatbedCount()));
handler.updateState(CGROUP_SCANNER, CHANNEL_JAM_EVENTS,
new DecimalType(result.getData().getScannerJamEvents()));
handler.updateState(CGROUP_SCANNER, CHANNEL_MISPICK_EVENTS,
new DecimalType(result.getData().getScannerMispickEvents()));
// Copy
handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_ADF, new DecimalType(result.getData().getCopyAdfCount()));
handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_FLATBED,
new DecimalType(result.getData().getCopyFlatbedCount()));
handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_PAGES,
new DecimalType(result.getData().getCopyTotalImpressions()));
handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_COLORPAGES,
new DecimalType(result.getData().getCopyTotalColorImpressions()));
handler.updateState(CGROUP_COPY, CHANNEL_TOTAL_MONOPAGES,
new DecimalType(result.getData().getCopyTotalMonochromeImpressions()));
// App Usage
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_WIN, new DecimalType(result.getData().getAppWindowsCount()));
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_OSX, new DecimalType(result.getData().getAppOSXCount()));
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_IOS, new DecimalType(result.getData().getAppIosCount()));
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_ANDROID,
new DecimalType(result.getData().getAppAndroidCount()));
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_SAMSUNG,
new DecimalType(result.getData().getAppSamsungCount()));
handler.updateState(CGROUP_APP, CHANNEL_TOTAL_CHROME,
new DecimalType(result.getData().getAppChromeCount()));
// Other
handler.updateState(CGROUP_OTHER, CHANNEL_CLOUD_PRINT,
new DecimalType(result.getData().getCloudPrintImpressions()));
} else {
goneOffline();
}
}
private void goneOnline() {
handler.updateStatus(ThingStatus.ONLINE);
final ScheduledFuture<?> localOfflineScheduler = offlineScheduler;
if (localOfflineScheduler != null) {
localOfflineScheduler.cancel(true);
offlineScheduler = null;
}
retrieveProperties();
startBackgroundSchedules();
}
private void checkOnline() {
HPServerResult<HPStatus> result = printerClient.getStatus();
if (result.getStatus() == RequestStatus.SUCCESS) {
goneOnline();
} else if (result.getStatus() == RequestStatus.TIMEOUT) {
handler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, result.getErrorMessage());
} else {
handler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, result.getErrorMessage());
}
}
}

View File

@@ -0,0 +1,114 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.type.ChannelTypeUID;
/**
* The {@link HPPrinterBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPPrinterBindingConstants {
private static final String BINDING_ID = "hpprinter";
// ********** List of all Thing Type UIDs **********
public static final ThingTypeUID THING_PRINTER = new ThingTypeUID(BINDING_ID, "printer");
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream.of(THING_PRINTER)
.collect(Collectors.toSet());
// ********** Channel Types **********
public static ChannelTypeUID chanTypeStatus = new ChannelTypeUID("hpprinter:status");
public static ChannelTypeUID chanTypeReadSwitch = new ChannelTypeUID("hpprinter:readonlyswitch");
public static ChannelTypeUID chanTypeTotals = new ChannelTypeUID("hpprinter:totals");
public static ChannelTypeUID chanTypeTotalsAdvanced = new ChannelTypeUID("hpprinter:totalsAdv");
public static ChannelTypeUID chanTypeMarking = new ChannelTypeUID("hpprinter:cumlMarkingUsed");
public static ChannelTypeUID chanTypeInkLevel = new ChannelTypeUID("hpprinter:inkLevel");
// ********** Item Types **********
public static final String ITEM_TYPE_CUMLMARK = "Number:Volume";
public static final String ITEM_TYPE_INK = "Number:Dimensionless";
// ********** List of all Channel ids **********
// Status
public static final String CHANNEL_STATUS = "status";
public static final String CHANNEL_TRAYEMPTYOROPEN = "trayEmptyOrOpen";
public static final String CHANNEL_SCANNER_STATUS = "scannerStatus";
public static final String CHANNEL_SCANNER_ADFLOADED = "scannerAdfLoaded";
// Colours
public static final String CHANNEL_COLOR_LEVEL = "colorLevel";
public static final String CHANNEL_CYAN_LEVEL = "cyanLevel";
public static final String CHANNEL_MAGENTA_LEVEL = "magentaLevel";
public static final String CHANNEL_YELLOW_LEVEL = "yellowLevel";
public static final String CHANNEL_BLACK_LEVEL = "blackLevel";
public static final String CHANNEL_COLOR_MARKING = "colorMarker";
public static final String CHANNEL_CYAN_MARKING = "cyanMarker";
public static final String CHANNEL_MAGENTA_MARKING = "magentaMarker";
public static final String CHANNEL_YELLOW_MARKING = "yellowMarker";
public static final String CHANNEL_BLACK_MARKING = "blackMarker";
// Estimated Pages Remaining
public static final String CHANNEL_COLOR_PAGES_REMAINING = "colorPagesRemaining";
public static final String CHANNEL_CYAN_PAGES_REMAINING = "cyanPagesRemaining";
public static final String CHANNEL_MAGENTA_PAGES_REMAINING = "magentaPagesRemaining";
public static final String CHANNEL_YELLOW_PAGES_REMAINING = "yellowPagesRemaining";
public static final String CHANNEL_BLACK_PAGES_REMAINING = "blackPagesRemaining";
// Page Counts
public static final String CHANNEL_TOTAL_PAGES = "totalCount";
public static final String CHANNEL_SUBSCRIPTION = "subsciptionCount";
public static final String CHANNEL_TOTAL_COLORPAGES = "totalColorCount";
public static final String CHANNEL_TOTAL_MONOPAGES = "totalMonochromeCount";
public static final String CHANNEL_JAM_EVENTS = "jamEvents";
public static final String CHANNEL_MISPICK_EVENTS = "mispickEvents";
public static final String CHANNEL_FRONT_PANEL_CANCEL = "fpCancelCount";
public static final String CHANNEL_CLOUD_PRINT = "cloudPrint";
// Scanner
public static final String CHANNEL_TOTAL_ADF = "totalAdf";
public static final String CHANNEL_TOTAL_FLATBED = "totalFlatbed";
public static final String CHANNEL_TOTAL_TOEMAIL = "totalToEmail";
public static final String CHANNEL_TOTAL_TOFOLDER = "totalToFolder";
public static final String CHANNEL_TOTAL_TOHOST = "totalToHost";
// App Usage
public static final String CHANNEL_TOTAL_WIN = "totalWin";
public static final String CHANNEL_TOTAL_ANDROID = "totalAndroid";
public static final String CHANNEL_TOTAL_IOS = "totalIos";
public static final String CHANNEL_TOTAL_OSX = "totalOsx";
public static final String CHANNEL_TOTAL_SAMSUNG = "totalSamsung";
public static final String CHANNEL_TOTAL_CHROME = "totalChrome";
// ********** List of all Channel Groups **********
public static final String CGROUP_INK = "ink";
public static final String CGROUP_STATUS = "status";
public static final String CGROUP_USAGE = "usage";
public static final String CGROUP_SCANNER = "scanner"; // Scanner Engine
public static final String CGROUP_SCAN = "scan"; // Scan Application
public static final String CGROUP_COPY = "copy";
public static final String CGROUP_APP = "app";
public static final String CGROUP_OTHER = "other";
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link HPPrinterConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPPrinterConfiguration {
public static final String IP_ADDRESS = "ipAddress";
public static final String USAGE_INTERVAL = "usageInterval";
public static final String STATUS_INTERVAL = "statusInterval";
public @Nullable String ipAddress;
public int usageInterval;
public int statusInterval;
}

View File

@@ -0,0 +1,135 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import static org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants.THING_PRINTER;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.jmdns.ServiceInfo;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link HPPrinterDiscoveryParticipant} class discovers HP Printers over
* mDNS.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
@Component(immediate = true)
public class HPPrinterDiscoveryParticipant implements MDNSDiscoveryParticipant {
private final Logger logger = LoggerFactory.getLogger(HPPrinterDiscoveryParticipant.class);
@Override
public @Nullable DiscoveryResult createResult(ServiceInfo service) {
if (!service.hasData()) {
logger.trace("Service has no data.");
return null;
}
// We only care about HP Printers
String ty = service.getPropertyString("ty");
if (ty != null && ty.toLowerCase().startsWith("hp")) {
String rp = service.getPropertyString("rp");
if (rp == null) {
return null;
}
logger.debug("Found HP Printer ID: {}", ty);
ThingUID uid = getThingUID(service);
if (uid != null) {
Map<String, Object> properties = new HashMap<>(2);
InetAddress ip = getIpAddress(service);
if (ip == null) {
return null;
}
String inetAddress = ip.toString().substring(1); // trim leading slash
String label = service.getName();
properties.put(HPPrinterConfiguration.IP_ADDRESS, inetAddress);
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label)
.build();
logger.trace("Created a DiscoveryResult {} for printer on host '{}' name '{}'", result, inetAddress,
label);
return result;
} else {
logger.debug("Found unsupported HP Printer ID: {}", ty);
}
} else {
logger.trace("Ignore non HP device {}", ty);
}
return null;
}
private String getUIDName(ServiceInfo service) {
return service.getName().replaceAll("[^A-Za-z0-9_]", "_");
}
@Override
public String getServiceType() {
return "_printer._tcp.local.";
}
@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
return HPPrinterBindingConstants.SUPPORTED_THING_TYPES_UIDS;
}
@Override
public @Nullable ThingUID getThingUID(ServiceInfo service) {
if (service.getType() != null) {
logger.trace("ServiceInfo: {}", service);
if (service.getType().equals(getServiceType())) {
String uidName = getUIDName(service);
ThingTypeUID mdl = findThingType();
return new ThingUID(mdl, uidName);
}
}
return null;
}
@Nullable
private InetAddress getIpAddress(ServiceInfo service) {
InetAddress address = null;
for (InetAddress addr : service.getInet4Addresses()) {
logger.debug("Get IP address for device {}", addr);
return addr;
}
// Fallback for Inet6addresses
for (InetAddress addr : service.getInet6Addresses()) {
logger.debug("Get IP address for device {}", addr);
return addr;
}
return address;
}
private ThingTypeUID findThingType() {
return THING_PRINTER;
}
}

View File

@@ -0,0 +1,159 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import static org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* The {@link HPPrinterHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPPrinterHandler extends BaseThingHandler {
private final HttpClient httpClient;
private @Nullable HPPrinterBinder binder;
public HPPrinterHandler(final Thing thing, final HttpClient httpClient) {
super(thing);
this.httpClient = httpClient;
}
@Override
public void thingUpdated(final Thing thing) {
super.thingUpdated(thing);
final HPPrinterBinder printerBinder = this.binder;
if (printerBinder != null) {
printerBinder.dynamicallyAddChannels(thing.getUID());
}
}
@Override
public void handleCommand(final ChannelUID channelUID, final Command command) {
}
@Override
public void initialize() {
final HPPrinterConfiguration config = getConfigAs(HPPrinterConfiguration.class);
if (!"".equals(config.ipAddress)) {
final HPPrinterBinder localBinder = binder = new HPPrinterBinder(this, httpClient, scheduler, config);
localBinder.dynamicallyAddChannels(thing.getUID());
localBinder.retrieveProperties();
localBinder.open();
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "You must set an IP Address");
}
}
@Override
public void dispose() {
final HPPrinterBinder localBinder = binder;
if (localBinder != null) {
localBinder.close();
binder = null;
}
}
protected Boolean areStatusChannelsLinked(final String[] channels) {
for (int i = 0; i < channels.length; i++) {
if (isLinked(new ChannelUID(thing.getUID(), CGROUP_STATUS, channels[i]))) {
return true;
}
}
return false;
}
protected void updateStatus(final ThingStatus status) {
super.updateStatus(status);
}
@Override
public void channelLinked(ChannelUID channelUID) {
final HPPrinterBinder localBinder = binder;
if (localBinder != null) {
localBinder.channelsChanged();
}
}
@Override
public void channelUnlinked(ChannelUID channelUID) {
final HPPrinterBinder localBinder = binder;
if (localBinder != null) {
localBinder.channelsChanged();
}
}
protected void updateStatus(final ThingStatus status, final ThingStatusDetail thingStatusDetail,
@Nullable final String message) {
super.updateStatus(status, thingStatusDetail, message);
}
public void updateState(final String group, final String channel, final State state) {
super.updateState(new ChannelUID(thing.getUID(), group, channel), state);
}
public void binderAddChannels(final List<Channel> channels) {
final List<Channel> thingChannels = new ArrayList<>(getThing().getChannels());
for (final Channel channel : channels) {
addOrUpdateChannel(channel, thingChannels);
}
updateThing(editThing().withChannels(thingChannels).build());
}
protected ThingBuilder editThing() {
return super.editThing();
}
protected @Nullable ThingHandlerCallback getCallback() {
return super.getCallback();
}
protected void updateProperties(final Map<String, String> properties) {
super.updateProperties(properties);
}
private static void addOrUpdateChannel(final Channel newChannel, final List<Channel> thingChannels) {
removeChannelByUID(thingChannels, newChannel.getUID());
thingChannels.add(newChannel);
}
private static void removeChannelByUID(final List<Channel> thingChannels, final ChannelUID channelUIDtoRemove) {
final Predicate<Channel> channelPredicate = c -> c.getUID().getId().equals(channelUIDtoRemove.getId());
thingChannels.removeIf(channelPredicate);
}
}

View File

@@ -0,0 +1,62 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal;
import static org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants.SUPPORTED_THING_TYPES_UIDS;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* The {@link HPPrinterHandlerFactory} is responsible for creating things and
* thing handlers.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.hpprinter", service = ThingHandlerFactory.class)
public class HPPrinterHandlerFactory extends BaseThingHandlerFactory {
private final HttpClient httpClient;
@Activate
public HPPrinterHandlerFactory(@Reference final HttpClientFactory httpClientFactory) {
this.httpClient = httpClientFactory.getCommonHttpClient();
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new HPPrinterHandler(thing, httpClient);
}
return null;
}
}

View File

@@ -0,0 +1,81 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The {@link HPScannerStatus} is responsible for handling reading of scanner status data.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPFeatures {
public static final String ENDPOINT = "/DevMgmt/DiscoveryTree.xml";
private final boolean productStatus;
private final boolean productUsage;
private final boolean scannerStatus;
public HPFeatures(Document document) {
Element root = (Element) document.getDocumentElement();
boolean localProductStatus = false;
boolean localProductUsage = false;
boolean localScannerStatus = false;
for (Node n = root.getFirstChild(); n != null; n = n.getNextSibling()) {
if (n instanceof Element) {
Element feature = (Element) n;
NodeList resourceType = feature.getElementsByTagName("dd:ResourceType");
if (resourceType.getLength() > 0) {
switch (resourceType.item(0).getTextContent()) {
case "ledm:hpLedmProductStatusDyn":
localProductStatus = true;
break;
case "ledm:hpLedmProductUsageDyn":
localProductUsage = true;
break;
case "eSCL:eSclManifest":
localScannerStatus = true;
break;
}
}
}
}
productStatus = localProductStatus;
productUsage = localProductUsage;
scannerStatus = localScannerStatus;
}
public boolean getProductStatusSupported() {
return productStatus;
}
public boolean getProductUsageSupported() {
return productUsage;
}
public boolean getScannerStatusSupported() {
return scannerStatus;
}
}

View File

@@ -0,0 +1,328 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* The {@link HPProductUsageFeatures} is responsible for determining what type of printer usage
* data the Web Interface supports including any features.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPProductUsageFeatures {
public static final String ENDPOINT = "/DevMgmt/ProductUsageDyn.xml";
private PrinterType printerType = PrinterType.UNKNOWN;
private boolean jamEvents;
private boolean mispickEvents;
private boolean subscriptionImpressions;
private boolean frontPanelCancel;
private boolean cumuMarking;
private boolean pagesRemaining;
private boolean scanAdf;
private boolean scanFlatbed;
private boolean scanToHost;
private boolean scanToEmail;
private boolean scanToFolder;
private boolean printApplication;
private boolean printApplicationChrome;
private boolean scannerEngine;
private boolean copyApplication;
private boolean cloudPrint;
public enum PrinterType {
UNKNOWN,
MONOCHROME,
SINGLECOLOR,
MULTICOLOR
}
public HPProductUsageFeatures(final Document document) {
// Check what Ink/Toner colours are present
final NodeList consumableInk = document.getDocumentElement().getElementsByTagName("pudyn:Consumable");
for (int i = 0; i < consumableInk.getLength(); i++) {
final Element currInk = (Element) consumableInk.item(i);
final String inkName = currInk.getElementsByTagName("dd:MarkerColor").item(0).getTextContent();
final String consumeType = currInk.getElementsByTagName("dd:ConsumableTypeEnum").item(0).getTextContent();
if (consumeType.equalsIgnoreCase("printhead")) {
continue;
}
cumuMarking = (currInk.getElementsByTagName("dd2:CumulativeMarkingAgentUsed").getLength() > 0);
switch (inkName.toLowerCase()) {
case "cyan":
case "magenta":
case "yellow":
printerType = PrinterType.MULTICOLOR; // Is multicolor if it has this ink
break;
case "cyanmagentayellow":
printerType = PrinterType.SINGLECOLOR; // Is singlecolor if it has this ink
break;
case "black":
if (printerType == PrinterType.UNKNOWN) {
printerType = PrinterType.MONOCHROME; // Is Monochrome
}
break;
}
}
pagesRemaining = (((Element) consumableInk.item(0)).getElementsByTagName("dd:EstimatedPagesRemaining")
.getLength() > 0);
final NodeList printerSubUnit = document.getDocumentElement().getElementsByTagName("pudyn:PrinterSubunit");
if (printerSubUnit.getLength() > 0) {
final Element currPrinterSubUnit = (Element) printerSubUnit.item(0);
jamEvents = (currPrinterSubUnit.getElementsByTagName("dd:JamEvents").getLength() > 0);
mispickEvents = (currPrinterSubUnit.getElementsByTagName("dd:MispickEvents").getLength() > 0);
subscriptionImpressions = (currPrinterSubUnit.getElementsByTagName("pudyn:SubscriptionImpressions")
.getLength() > 0);
frontPanelCancel = (currPrinterSubUnit.getElementsByTagName("dd:TotalFrontPanelCancelPresses")
.getLength() > 0);
}
final NodeList scannerSubUnit = document.getDocumentElement()
.getElementsByTagName("pudyn:ScanApplicationSubunit");
if (scannerSubUnit.getLength() > 0) {
final Element currScannerSubUnit = (Element) scannerSubUnit.item(0);
scanAdf = (currScannerSubUnit.getElementsByTagName("dd:AdfImages").getLength() > 0);
scanFlatbed = (currScannerSubUnit.getElementsByTagName("dd:FlatbedImages").getLength() > 0);
scanToEmail = (currScannerSubUnit.getElementsByTagName("dd:ImagesSentToEmail").getLength() > 0);
scanToFolder = (currScannerSubUnit.getElementsByTagName("dd:ImagesSentToFolder").getLength() > 0);
scanToHost = (currScannerSubUnit.getElementsByTagName("dd:ScanToHostImages").getLength() > 0);
}
final NodeList scanAppSubUnit = document.getDocumentElement()
.getElementsByTagName("pudyn:ScanApplicationSubunit");
if (scanAppSubUnit.getLength() > 0) {
printApplication = true;
final Element currAppSubUnit = (Element) scanAppSubUnit.item(0);
printApplicationChrome = (currAppSubUnit.getElementsByTagName("pudyn:RemoteDeviceType").getLength() > 0);
}
final NodeList printAppSubUnit = document.getDocumentElement()
.getElementsByTagName("pudyn:PrintApplicationSubunit");
if (printAppSubUnit.getLength() > 0) {
final Element currPrintAppSubUnit = (Element) printAppSubUnit.item(0);
cloudPrint = (currPrintAppSubUnit.getElementsByTagName("dd:CloudPrintImpressions").getLength() > 0);
}
final NodeList scannerEngineSubUnit = document.getDocumentElement()
.getElementsByTagName("pudyn:ScannerEngineSubunit");
scannerEngine = (scannerEngineSubUnit.getLength() > 0);
final NodeList copyAppSubUnit = document.getDocumentElement()
.getElementsByTagName("pudyn:CopyApplicationSubunit");
copyApplication = (copyAppSubUnit.getLength() > 0);
}
public PrinterType getType() {
return printerType;
}
/**
* Printer data contains Scanner Engine.
*
* pudyn:ProductUsageDyn -> pudyn:ScannerEngineSubunit
*
* return {boolean} True is supported.
*/
public boolean hasScannerEngine() {
return scannerEngine;
}
/**
* Printer data contains Copy Application.
*
* pudyn:ProductUsageDyn -> pudyn:ScannerEngineSubunit
*
* return {boolean} True is supported.
*/
public boolean hasCopyApplication() {
return copyApplication;
}
/**
* Printer data contains Estimated Pages Remaining.
*
* pudyn:ProductUsageDyn -> pudyn:ConsumableSubunit -> pudyn:Consumable -> dd:EstimatedPagesRemaining
*
* return {boolean} True is supported.
*/
public boolean hasPagesRemaining() {
return pagesRemaining;
}
/**
* Printer data contains Scan to Email.
*
* pudyn:ProductUsageDyn -> pudyn:ScanApplicationSubunit -> dd:ImagesSentToEmail
*
* @return {boolean} True if supported.
*/
public boolean hasScanToEmail() {
return scanToEmail;
}
/**
* Printer data contains Scan to Folder.
*
* pudyn:ProductUsageDyn -> pudyn:ScanApplicationSubunit -> dd:ImagesSentToFolder
*
* @return {boolean} True if supported.
*/
public boolean hasScanToFolder() {
return scanToFolder;
}
/**
* Printer data contains Scan to Host.
*
* pudyn:ProductUsageDyn -> pudyn:ScanApplicationSubunit -> dd:ScanToHostImages
*
* @return {boolean} True if supported.
*/
public boolean hasScanToHost() {
return scanToHost;
}
/**
* Printer data contains Scanner Automatic Document Feeder.
*
* pudyn:ProductUsageDyn -> pudyn:ScanApplicationSubunit -> dd:AdfImages
*
* @return {boolean} True if supported.
*/
public boolean hasScanADF() {
return scanAdf;
}
/**
* Printer data contains Scanner Flatbed.
*
* pudyn:ProductUsageDyn -> pudyn:ScanApplicationSubunit -> dd:FlatbedImages
*
* @return {boolean} True if supported.
*/
public boolean hasScanFlatbed() {
return scanFlatbed;
}
/**
* Printer data has Google Cloud Print impressions.
*
* pudyn:ProductUsageDyn -> pudyn:PrintApplicationSubunit -> dd:CloudPrintImpressions
*
* @return {boolean} True if supported.
*/
public boolean hasCloudPrint() {
return cloudPrint;
}
/**
* Printer data contains Print Application Usage Information.
*
* pudyn:ProductUsageDyn -> pudyn:MobileApplicationSubunit
*
* @return {boolean} True if supported.
*/
public boolean hasPrintApplication() {
return printApplication;
}
/**
* Printer data contains Chrome Print Application Usage Information.
*
* pudyn:ProductUsageDyn -> pudyn:MobileApplicationSubunit
*
* @return {boolean} True if supported.
*/
public boolean hasPrintApplicationChrome() {
return printApplicationChrome;
}
/**
* Printer data contains Cumulative Marking Agent Used.
*
* pudyn:ProductUsageDyn -> pudyn:ConsumableSubunit -> pudyn:Consumable -> dd2:CumulativeMarkingAgentUsed
*
* @return {boolean} True if supported.
*/
public boolean hasCumulativeMarking() {
return cumuMarking;
}
/**
* Printer data contains Jam Events.
*
* pudyn:ProductUsageDyn -> pudyn:PrinterSubunit -> dd:JamEvents
*
* @return {boolean} True if supported.
*/
public boolean hasJamEvents() {
return jamEvents;
}
/**
* Printer data contains Mispick Events.
*
* pudyn:ProductUsageDyn -> pudyn:PrinterSubunit -> dd:MispickEvents
*
* @return {boolean} True if supported.
*/
public boolean hasMispickEvents() {
return mispickEvents;
}
/**
* Printer data contains Subscription Impressions count.
*
* pudyn:ProductUsageDyn -> pudyn:PrinterSubunit ->
* pudyn:SubscriptionImpressions
*
* @return {boolean} True if supported.
*/
public boolean hasSubscriptionCount() {
return subscriptionImpressions;
}
/**
* Printer data contains Front panel cancel presses count.
*
* pudyn:ProductUsageDyn -> pudyn:PrinterSubunit ->
* dd:TotalFrontPanelCancelPresses
*
* @return {boolean} True if supported.
*/
public boolean hasTotalFrontPanelCancelPresses() {
return frontPanelCancel;
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.Thing;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The {@link HPProperties} is responsible for returning the
* reading of data from the HP Embedded Web Server.
*
* @author Martin van Wingerden - Initial contribution
*/
@NonNullByDefault
public class HPProperties {
public static final String ENDPOINT = "/DevMgmt/ProductConfigDyn.xml";
private final Map<String, String> properties = new HashMap<>();
public HPProperties(Document document) {
NodeList nodes = document.getDocumentElement().getElementsByTagName("prdcfgdyn:ProductInformation");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
properties.put(Thing.PROPERTY_SERIAL_NUMBER,
element.getElementsByTagName("dd:SerialNumber").item(0).getTextContent());
properties.put(Thing.PROPERTY_MODEL_ID,
element.getElementsByTagName("dd:ProductNumber").item(0).getTextContent());
Node firmwareDate = element.getElementsByTagName("dd:Version").item(0);
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, firmwareDate.getChildNodes().item(0).getTextContent());
}
}
public Map<String, String> getProperties() {
return properties;
}
}

View File

@@ -0,0 +1,65 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* The {@link HPScannerStatus} is responsible for handling reading of scanner status data.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPScannerStatus {
public static final String ENDPOINT = "/eSCL/ScannerStatus";
private final String status;
private final Boolean adfLoaded;
public HPScannerStatus(Document document) {
String localScannerStatus = "Unknown";
Boolean localAdfLoaded = false;
Element nodes = (Element) document.getDocumentElement();
NodeList state = nodes.getElementsByTagName("pwg:State");
if (state.getLength() > 0) {
localScannerStatus = state.item(0).getTextContent();
}
NodeList adfState = nodes.getElementsByTagName("scan:AdfState");
if (adfState.getLength() > 0) {
String adfStatus = adfState.item(0).getTextContent();
localAdfLoaded = convertAdfStatus(adfStatus);
}
adfLoaded = localAdfLoaded;
status = localScannerStatus;
}
private static Boolean convertAdfStatus(String status) {
return "ScannerAdfLoaded".equals(status);
}
public Boolean getAdfLoaded() {
return adfLoaded;
}
public @Nullable String getScannerStatus() {
return status;
}
}

View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* The {@link HPScannerStatusFeatures} is responsible for determining what type of printer scanner
* status features the Web Interface supports.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPScannerStatusFeatures {
public static final String ENDPOINT = "/eSCL/ScannerStatus";
private final boolean hasStatus;
private final boolean hasAdf;
public HPScannerStatusFeatures(Document document) {
boolean localHasStatus = false;
boolean localHasAdf = false;
Element nodes = (Element) document.getDocumentElement();
localHasStatus = (nodes.getElementsByTagName("pwg:State").getLength() > 0);
localHasAdf = (nodes.getElementsByTagName("scan:AdfState").getLength() > 0);
hasStatus = localHasStatus;
hasAdf = localHasAdf;
}
public boolean hasStatus() {
return hasStatus;
}
public boolean hasAdf() {
return hasAdf;
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link HPServerResult} is responsible for returning the
* reading of data from the HP Embedded Web Server.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPServerResult<result> {
private final RequestStatus status;
private final @Nullable result data;
private final String errorMessage;
public HPServerResult(RequestStatus status, String errorMessage) {
this.status = status;
this.data = null;
this.errorMessage = errorMessage;
}
public HPServerResult(result data) {
this.status = RequestStatus.SUCCESS;
this.data = data;
this.errorMessage = "";
}
@SuppressWarnings("null")
public result getData() {
final result localData = data;
if (status != RequestStatus.SUCCESS || localData == null) {
throw new IllegalStateException("No data available for result");
}
return localData;
}
public RequestStatus getStatus() {
return status;
}
public String getErrorMessage() {
return errorMessage;
}
public enum RequestStatus {
SUCCESS,
TIMEOUT,
ERROR
}
}

View File

@@ -0,0 +1,78 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* The {@link HPStatus} is responsible for handling reading of status data.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPStatus {
public static final String ENDPOINT = "/DevMgmt/ProductStatusDyn.xml";
private static final Map<String, String> STATUS_MESSAGES = initializeStatus();
private final String printerStatus;
private final boolean trayEmptyOrOpen;
public HPStatus(Document document) {
NodeList nodes = document.getDocumentElement().getElementsByTagName("psdyn:Status");
String localPrinterStatus = "Unknown";
boolean localTrayEmptyOrOpen = false;
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
String statusCategory = element.getElementsByTagName("pscat:StatusCategory").item(0).getTextContent();
if (!"genuineHP".equals(statusCategory) && !"trayEmpty".equals(statusCategory)) {
localPrinterStatus = STATUS_MESSAGES.getOrDefault(statusCategory, statusCategory);
}
if ("trayEmpty".equals(statusCategory)) {
localTrayEmptyOrOpen = true;
}
}
trayEmptyOrOpen = localTrayEmptyOrOpen;
printerStatus = localPrinterStatus;
}
private static Map<String, String> initializeStatus() {
Map<String, String> statusMap = new HashMap<>();
statusMap.put("processing", "Printing...");
statusMap.put("scanProcessing", "Scanning...");
statusMap.put("inPowerSave", "Power Save");
statusMap.put("ready", "Idle");
statusMap.put("initializing", "Initializing...");
statusMap.put("closeDoorOrCover", "Door/Cover Open");
statusMap.put("inkSystemInitializing", "Loading Ink...");
statusMap.put("shuttingDown", "Shutting Down...");
return statusMap;
}
public boolean getTrayEmptyOrOpen() {
return trayEmptyOrOpen;
}
public @Nullable String getPrinterStatus() {
return printerStatus;
}
}

View File

@@ -0,0 +1,476 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The {@link HPUsage} is responsible for handling reading of usage data.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPUsage {
public static final String ENDPOINT = "/DevMgmt/ProductUsageDyn.xml";
private int totalSubscriptionImpressions;
private int mispickEvents;
private int totalMonochromeImpressions;
private int totalColorImpressions;
private int frontpanelCancelCount;
private int totalImpressions;
private int jamEvents;
private int inkBlack;
private int inkCyan;
private int inkMagenta;
private int inkYellow;
private int inkColor;
private float inkBlackMarking;
private float inkCyanMarking;
private float inkMagentaMarking;
private float inkYellowMarking;
private float inkColorMarking;
private int inkBlackPagesRemaining;
private int inkColorPagesRemaining;
private int inkCyanPagesRemaining;
private int inkMagentaPagesRemaining;
private int inkYellowPagesRemaining;
// Scan
private int scanAdfCount;
private int scanFlatbedCount;
private int scanToEmailCount;
private int scanToFolderCount;
private int scanToHostCount;
// Scanner
private int scannerAdfCount;
private int scannerFlatbedCount;
private int scannerJamEvents;
private int scannerMispickEvents;
// Copy
private int copyAdfCount;
private int copyFlatbedCount;
private int copyTotalImpressions;
private int copyTotalMonochromeImpressions;
private int copyTotalColorImpressions;
// App
private int appWindowsCount;
private int appOsxCount;
private int appIosCount;
private int appAndroidCount;
private int appSamsungCount;
private int appChromeCount;
// Other
private int cloudPrintImpressions;
public HPUsage() {
}
public HPUsage(Document document) {
// Get Ink Levels
NodeList consumableInk = document.getDocumentElement().getElementsByTagName("pudyn:Consumable");
for (int i = 0; i < consumableInk.getLength(); i++) {
Element currInk = (Element) consumableInk.item(i);
String inkName = currInk.getElementsByTagName("dd:MarkerColor").item(0).getTextContent();
String consumeType = currInk.getElementsByTagName("dd:ConsumableTypeEnum").item(0).getTextContent();
if ("printhead".equalsIgnoreCase(consumeType)) {
continue;
}
String inkRemaining = currInk.getElementsByTagName("dd:ConsumableRawPercentageLevelRemaining").item(0)
.getTextContent();
int markAgentLength = currInk.getElementsByTagName("dd2:CumulativeMarkingAgentUsed").getLength();
Boolean hasPagesRemaining = currInk.getElementsByTagName("dd:EstimatedPagesRemaining").getLength() > 0;
float totalMarking = 0;
int pagesRemaining = 0;
if (markAgentLength > 0) { // Check to make sure Cumulative Marking Agent exists
for (int ai = 0; ai < markAgentLength; ai++) {
Element currMarking = (Element) currInk.getElementsByTagName("dd2:CumulativeMarkingAgentUsed")
.item(ai);
float marking = Integer
.parseInt(currMarking.getElementsByTagName("dd:ValueFloat").item(0).getTextContent());
switch (currMarking.getElementsByTagName("dd:Unit").item(0).getTextContent().toLowerCase()) {
case "microliters":
marking = marking / 1000; // Convert from microlitres to millilitres
break;
case "liters":
marking = marking * 1000; // Convert to litres to millilitres
}
totalMarking = totalMarking + marking; // Sum the marking counts together
}
}
if (hasPagesRemaining) {
pagesRemaining = Integer.parseInt(((Element) currInk).getElementsByTagName("dd:EstimatedPagesRemaining")
.item(0).getTextContent());
}
switch (inkName.toLowerCase()) {
case "black":
inkBlack = Integer.parseInt(inkRemaining);
inkBlackMarking = totalMarking;
inkBlackPagesRemaining = pagesRemaining;
break;
case "yellow":
inkYellow = Integer.parseInt(inkRemaining);
inkYellowMarking = totalMarking;
inkYellowPagesRemaining = pagesRemaining;
break;
case "magenta":
inkMagenta = Integer.parseInt(inkRemaining);
inkMagentaMarking = totalMarking;
inkMagentaPagesRemaining = pagesRemaining;
break;
case "cyan":
inkCyan = Integer.parseInt(inkRemaining);
inkCyanMarking = totalMarking;
inkCyanPagesRemaining = pagesRemaining;
break;
case "cyanmagentayellow":
inkColor = Integer.parseInt(inkRemaining);
inkColorMarking = totalMarking;
inkColorPagesRemaining = pagesRemaining;
break;
}
}
// Get other usage info
NodeList jamEvents = document.getDocumentElement().getElementsByTagName("dd:JamEvents");
if (jamEvents.getLength() > 0) {
this.jamEvents = Integer.parseInt(jamEvents.item(0).getTextContent());
}
NodeList totalImpressions = document.getDocumentElement().getElementsByTagName("dd:TotalImpressions");
if (totalImpressions.getLength() > 0) {
this.totalImpressions = Integer.parseInt(totalImpressions.item(0).getTextContent());
}
NodeList totalColorImpressions = document.getDocumentElement().getElementsByTagName("dd:ColorImpressions");
if (totalColorImpressions.getLength() > 0) {
this.totalColorImpressions = Integer.parseInt(totalColorImpressions.item(0).getTextContent());
}
NodeList totalMonochromeImpressions = document.getDocumentElement()
.getElementsByTagName("dd:MonochromeImpressions");
if (totalMonochromeImpressions.getLength() > 0) {
this.totalMonochromeImpressions = Integer.parseInt(totalMonochromeImpressions.item(0).getTextContent());
}
NodeList totalSubscriptionImpressions = document.getDocumentElement()
.getElementsByTagName("pudyn:SubscriptionImpressions");
if (totalSubscriptionImpressions.getLength() > 0) {
this.totalSubscriptionImpressions = Integer.parseInt(totalSubscriptionImpressions.item(0).getTextContent());
}
NodeList mispickEvents = document.getDocumentElement().getElementsByTagName("dd:MispickEvents");
if (mispickEvents.getLength() > 0) {
this.mispickEvents = Integer.parseInt(mispickEvents.item(0).getTextContent());
}
NodeList frontpanelCancelCount = document.getDocumentElement()
.getElementsByTagName("dd:TotalFrontPanelCancelPresses");
if (frontpanelCancelCount.getLength() > 0) {
this.frontpanelCancelCount = Integer.parseInt(frontpanelCancelCount.item(0).getTextContent());
}
// Print Apps
NodeList printAppsSubUnit = document.getDocumentElement().getElementsByTagName("pudyn:PrintApplicationSubunit");
if (printAppsSubUnit.getLength() > 0) {
Element currPrintAppsSubUnit = (Element) printAppsSubUnit.item(0);
NodeList cloudPrintImpressions = currPrintAppsSubUnit.getElementsByTagName("dd:CloudPrintImpressions");
if (cloudPrintImpressions.getLength() > 0) {
this.cloudPrintImpressions = Integer.parseInt(cloudPrintImpressions.item(0).getTextContent());
}
}
// Scan
NodeList scanSubUnit = document.getDocumentElement().getElementsByTagName("pudyn:ScanApplicationSubunit");
if (scanSubUnit.getLength() > 0) {
Element currScanSubUnit = (Element) scanSubUnit.item(0);
this.scanAdfCount = setInt("dd:AdfImages", currScanSubUnit);
this.scanFlatbedCount = setInt("dd:FlatbedImages", currScanSubUnit);
this.scanToEmailCount = setInt("dd:ImagesSentToEmail", currScanSubUnit);
this.scanToFolderCount = setInt("dd:ImagesSentToFolder", currScanSubUnit);
this.scanToHostCount = setInt("dd:ScanToHostImages", currScanSubUnit);
}
// Scanner
NodeList scannerSubUnit = document.getDocumentElement().getElementsByTagName("pudyn:ScannerEngineSubunit");
if (scannerSubUnit.getLength() > 0) {
Element currScannerSubUnit = (Element) scannerSubUnit.item(0);
this.scannerAdfCount = setInt("dd:AdfImages", currScannerSubUnit);
this.scannerFlatbedCount = setInt("dd:FlatbedImages", currScannerSubUnit);
this.scannerJamEvents = setInt("dd:JamEvents", currScannerSubUnit);
this.scannerMispickEvents = setInt("dd:MispickEvents", currScannerSubUnit);
}
// Copy
NodeList copySubUnit = document.getDocumentElement().getElementsByTagName("pudyn:CopyApplicationSubunit");
if (copySubUnit.getLength() > 0) {
Element currCopySubUnit = (Element) copySubUnit.item(0);
this.copyAdfCount = setInt("dd:AdfImages", currCopySubUnit);
this.copyFlatbedCount = setInt("dd:FlatbedImages", currCopySubUnit);
this.copyTotalColorImpressions = setInt("dd:ColorImpressions", currCopySubUnit);
this.copyTotalMonochromeImpressions = setInt("dd:MonochromeImpressions", currCopySubUnit);
this.copyTotalImpressions = setInt("dd:TotalImpressions", currCopySubUnit);
}
// App Usage
NodeList appSubUnit = document.getDocumentElement().getElementsByTagName("pudyn:MobileApplicationSubunit");
if (appSubUnit.getLength() > 0) {
Element currAppSubUnit = (Element) appSubUnit.item(0);
this.appWindowsCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "Windows",
"pudyn:TotalImpressions");
this.appOsxCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "OSX",
"pudyn:TotalImpressions");
this.appIosCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "iOS",
"pudyn:TotalImpressions");
this.appAndroidCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "Android",
"pudyn:TotalImpressions");
this.appSamsungCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "samsung",
"pudyn:TotalImpressions");
this.appChromeCount = setIntCollateDirectChildren(currAppSubUnit, "pudyn:RemoteDeviceType", "Chrome",
"pudyn:TotalImpressions");
}
}
private static int setIntCollateDirectChildren(Element parentNode, String collateTagName,
String collateTagNameValue, String valueTagName) {
int value = 0;
for (Node n = parentNode.getFirstChild(); n != null; n = n.getNextSibling()) {
if (n instanceof Element) {
Element nodeItem = (Element) n;
if (nodeItem.getElementsByTagName(collateTagName).item(0).getTextContent()
.equalsIgnoreCase(collateTagNameValue)) {
int nodeValue = Integer
.parseInt(nodeItem.getElementsByTagName(valueTagName).item(0).getTextContent());
value += nodeValue;
}
}
}
return value;
}
private int setInt(String tagName, Element parentNode) {
NodeList nodeList = parentNode.getElementsByTagName(tagName);
if (nodeList.getLength() > 0) {
return Integer.parseInt(nodeList.item(0).getTextContent());
}
return 0;
}
public int getFrontPanelCancelCount() {
return frontpanelCancelCount;
}
public int getTotalSubscriptionImpressions() {
return totalSubscriptionImpressions;
}
public int getMispickEvents() {
return mispickEvents;
}
public int getTotalMonochromeImpressions() {
return totalMonochromeImpressions;
}
public int getTotalColorImpressions() {
return totalColorImpressions;
}
public int getTotalImpressions() {
return totalImpressions;
}
public int getCloudPrintImpressions() {
return cloudPrintImpressions;
}
public int getJamEvents() {
return jamEvents;
}
public int getInkBlack() {
return inkBlack;
}
public float getInkBlackMarking() {
return inkBlackMarking;
}
public int getInkCyan() {
return inkCyan;
}
public float getInkCyanMarking() {
return inkCyanMarking;
}
public int getInkMagenta() {
return inkMagenta;
}
public float getInkMagentaMarking() {
return inkMagentaMarking;
}
public int getInkYellow() {
return inkYellow;
}
public float getInkYellowMarking() {
return inkYellowMarking;
}
public int getInkBlackPagesRemaining() {
return inkBlackPagesRemaining;
}
public int getInkColorPagesRemaining() {
return inkColorPagesRemaining;
}
public int getInkMagentaPagesRemaining() {
return inkMagentaPagesRemaining;
}
public int getInkCyanPagesRemaining() {
return inkCyanPagesRemaining;
}
public int getInkYellowPagesRemaining() {
return inkYellowPagesRemaining;
}
public int getInkColor() {
return inkColor;
}
public float getInkColorMarking() {
return inkColorMarking;
}
public int getScanAdfCount() {
return scanAdfCount;
}
public int getScanFlatbedCount() {
return scanFlatbedCount;
}
public int getScanToEmailCount() {
return scanToEmailCount;
}
public int getScanToFolderCount() {
return scanToFolderCount;
}
public int getScanToHostCount() {
return scanToHostCount;
}
public int getAppWindowsCount() {
return appWindowsCount;
}
public int getAppOSXCount() {
return appOsxCount;
}
public int getAppIosCount() {
return appIosCount;
}
public int getAppAndroidCount() {
return appAndroidCount;
}
public int getAppSamsungCount() {
return appSamsungCount;
}
public int getAppChromeCount() {
return appChromeCount;
}
public int getScannerAdfCount() {
return scannerAdfCount;
}
public int getScannerFlatbedCount() {
return scannerFlatbedCount;
}
public int getScannerJamEvents() {
return scannerJamEvents;
}
public int getScannerMispickEvents() {
return scannerMispickEvents;
}
public int getCopyAdfCount() {
return copyAdfCount;
}
public int getCopyFlatbedCount() {
return copyFlatbedCount;
}
public int getCopyTotalImpressions() {
return copyTotalImpressions;
}
public int getCopyTotalColorImpressions() {
return copyTotalColorImpressions;
}
public int getCopyTotalMonochromeImpressions() {
return copyTotalMonochromeImpressions;
}
}

View File

@@ -0,0 +1,127 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hpprinter.internal.api;
import java.io.IOException;
import java.io.StringReader;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.hpprinter.internal.api.HPServerResult.RequestStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* The {@link HPWebServerClient} is responsible for handling reading of data from the HP Embedded Web Server.
*
* @author Stewart Cossey - Initial contribution
*/
@NonNullByDefault
public class HPWebServerClient {
public static final int REQUEST_TIMEOUT_SEC = 10;
private final Logger logger = LoggerFactory.getLogger(HPWebServerClient.class);
private final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
private final HttpClient httpClient;
private final String serverAddress;
/**
* Creates a new HP Web Server Client object.
*
* @param httpClient {HttpClient} The HttpClient to use for HTTP requests.
* @param address The address for the Embedded Web Server.
*/
public HPWebServerClient(HttpClient httpClient, String address) {
this.httpClient = httpClient;
serverAddress = "http://" + address;
logger.debug("Create printer connection {}", serverAddress);
}
/**
* Gets the Status information from the Embedded Web Server.
*
* @return The status information.
*/
public HPServerResult<HPStatus> getStatus() {
return fetchData(serverAddress + HPStatus.ENDPOINT, (HPStatus::new));
}
public HPServerResult<HPProductUsageFeatures> getProductFeatures() {
return fetchData(serverAddress + HPProductUsageFeatures.ENDPOINT, (HPProductUsageFeatures::new));
}
public HPServerResult<HPFeatures> getProductUsageFeatures() {
return fetchData(serverAddress + HPFeatures.ENDPOINT, (HPFeatures::new));
}
public HPServerResult<HPScannerStatusFeatures> getScannerFeatures() {
return fetchData(serverAddress + HPScannerStatusFeatures.ENDPOINT, (HPScannerStatusFeatures::new));
}
/**
* Gets the Usage information from the Embedded Web Server.
*
* @return The usage information.
*/
public HPServerResult<HPUsage> getUsage() {
return fetchData(serverAddress + HPUsage.ENDPOINT, (HPUsage::new));
}
public HPServerResult<HPScannerStatus> getScannerStatus() {
return fetchData(serverAddress + HPScannerStatus.ENDPOINT, (HPScannerStatus::new));
}
public HPServerResult<HPProperties> getProperties() {
return fetchData(serverAddress + HPProperties.ENDPOINT, (HPProperties::new));
}
private <T> HPServerResult<T> fetchData(String endpoint, Function<Document, T> function) {
try {
logger.trace("HTTP Client Load {}", endpoint);
ContentResponse cr = httpClient.newRequest(endpoint).method(HttpMethod.GET)
.timeout(REQUEST_TIMEOUT_SEC, TimeUnit.SECONDS).send();
String contentAsString = cr.getContentAsString();
logger.trace("HTTP Client Result {} Size {}", cr.getStatus(), contentAsString.length());
return new HPServerResult<>(function.apply(getDocument(contentAsString)));
} catch (TimeoutException ex) {
logger.trace("HTTP Client Timeout Exception {}", ex.getMessage());
return new HPServerResult<>(RequestStatus.TIMEOUT, ex.getMessage());
} catch (InterruptedException | ExecutionException | ParserConfigurationException | SAXException
| IOException ex) {
logger.trace("HTTP Client Exception {}", ex.getMessage());
return new HPServerResult<>(RequestStatus.ERROR, ex.getMessage());
}
}
private synchronized Document getDocument(String contentAsString)
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource source = new InputSource(new StringReader(contentAsString));
return builder.parse(source);
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="hpprinter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>HP Printer Binding</name>
<description>Binding for HP Printers with Embedded Web Servers</description>
<author>Stewart Cossey</author>
</binding:binding>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="thing-type:hpprinter:config">
<parameter name="ipAddress" type="text" required="true">
<label>Network Address</label>
<description>The IP or host name of the HP Printer</description>
<context>network-address</context>
</parameter>
<parameter name="usageInterval" type="integer" min="4">
<label>Usage Interval</label>
<description>The refresh interval in seconds for polling the printer usage information</description>
<default>30</default>
<advanced>true</advanced>
</parameter>
<parameter name="statusInterval" type="integer" min="4">
<label>Status Interval</label>
<description>The refresh interval in seconds for polling status information</description>
<default>4</default>
<advanced>true</advanced>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="hpprinter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- Channel Groups -->
<channel-group-type id="ink">
<label>Ink/Toner Levels</label>
<description>Ink/Toner amounts for each cartridge.</description>
</channel-group-type>
<channel-group-type id="usageInfo">
<label>Printer</label>
<description>Print Engine Usage Information</description>
</channel-group-type>
<channel-group-type id="printerStatus">
<label>Status</label>
<description>Printer Statuses</description>
</channel-group-type>
<channel-group-type id="scanner">
<label>Scanner</label>
<description>Scanner Engine Usage Information</description>
</channel-group-type>
<channel-group-type id="scan">
<label>Scan</label>
<description>Scan Application Usage Information</description>
</channel-group-type>
<channel-group-type id="copy">
<label>Copy</label>
<description>Copy Application Usage Information</description>
</channel-group-type>
<channel-group-type id="app">
<label>Application</label>
<description>Application Usage by Device or Operating System</description>
</channel-group-type>
<channel-group-type id="other">
<label>Other</label>
<description>Other Usage or Details</description>
</channel-group-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<thing:thing-descriptions bindingId="hpprinter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-type id="inkLevel">
<item-type>Number:Dimensionless</item-type>
<label>Ink Level</label>
<description>Shows the amount of Ink/Toner remaining</description>
<state readOnly="true" pattern="%f %%"/>
</channel-type>
<channel-type id="totals">
<item-type>Number</item-type>
<label>Totals</label>
<description>Amount of pages.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="totalsAdv" advanced="true">
<item-type>Number</item-type>
<label>Totals</label>
<description>Amount of pages.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="cumlMarkingUsed" advanced="true">
<item-type>Number:Volume</item-type>
<label>Cumulative Marking Used</label>
<description>Shows the amount of Ink/Toner used</description>
<state readOnly="true" pattern="%f mL"/>
</channel-type>
<channel-type id="status">
<item-type>String</item-type>
<label>Status</label>
<description>Printer Status</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="readonlyswitch" advanced="true">
<item-type>Switch</item-type>
<label>Read Only Switch Item</label>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="hpprinter"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="printer">
<label>HP Printer</label>
<description>An HP Printer.</description>
<channel-groups>
<channel-group typeId="printerStatus" id="status"/>
<channel-group typeId="ink" id="ink"/>
<channel-group typeId="usageInfo" id="usage"/>
<channel-group typeId="scanner" id="scanner"/>
<channel-group typeId="scan" id="scan"/>
<channel-group typeId="copy" id="copy"/>
<channel-group typeId="app" id="app"/>
<channel-group typeId="other" id="other"/>
</channel-groups>
<properties>
<property name="vendor">HP</property>
</properties>
<representation-property>serialNumber</representation-property>
<config-description-ref uri="thing-type:hpprinter:config"/>
</thing-type>
</thing:thing-descriptions>