Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[benqprojector] Migrate benqprojector binding to OH3 #10341

Merged
merged 13 commits into from
Jun 12, 2021
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
/bundles/org.openhab.binding.autelis/ @digitaldan
/bundles/org.openhab.binding.automower/ @maxpg
/bundles/org.openhab.binding.avmfritz/ @cweitkamp
/bundles/org.openhab.binding.benqprojector/ @mlobstein
/bundles/org.openhab.binding.bigassfan/ @mhilbush
/bundles/org.openhab.binding.bluetooth/ @cdjackson @cpmeister
/bundles/org.openhab.binding.bluetooth.airthings/ @paulianttila
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@
<artifactId>org.openhab.binding.avmfritz</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.benqprojector</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.bigassfan</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.benqprojector/NOTICE
Original file line number Diff line number Diff line change
@@ -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
115 changes: 115 additions & 0 deletions bundles/org.openhab.binding.benqprojector/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# BenQ Projector Binding

This binding is compatible with BenQ projectors that support the control protocol via the built-in ethernet port, serial port or USB to serial adapter.
If your projector does not have built-in networking, you can connect to your projector's serial port via a TCP connection using a serial over IP device or by using`ser2net`.

The control protocol can be found here: https://business-display.benq.com/content/dam/bb/en/product/projector/corporate/lx770/quick-start-guide/lx770-rs232-control-guide-0-windows7-windows8-winxp.pdf

## Supported Things

This binding supports two thing types based on the connection used: `projector-serial` and `projector-tcp`.

## Discovery

The projector thing cannot be auto-discovered, it has to be configured manually.

## Binding Configuration

There are no overall binding configuration settings that need to be set.
All settings are through thing configuration parameters.

## Thing Configuration

The `projector-serial` thing has the following configuration parameters:
mlobstein marked this conversation as resolved.
Show resolved Hide resolved

| Parameter | Name | Description | Required |
|-----------------|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| serialPort | Serial Port | Serial port device name that is connected to the BenQ projector to control, e.g. COM1 on Windows, /dev/ttyS0 on Linux or /dev/tty.PL2303-0000103D on Mac. | yes |
| pollingInterval | Polling Interval | Polling interval in seconds to update channel states, range 5-60 seconds; default 10 seconds. | no |

The `projector-tcp` thing has the following configuration parameters:

| Parameter | Name | Description | Required |
|-----------------|------------------|-------------------------------------------------------------------------------------------------------------|----------|
| host | Host Name | Host Name or IP address for the projector or serial over IP device. | yes |
| port | Port | Port for the projector or serial over IP device, Default 8000 for BenQ projectors with built in networking. | yes |
| pollingInterval | Polling Interval | Polling interval in seconds to update channel states, range 5-60 seconds; default 10 seconds. | no |

Some notes:

* If using a serial port connection, the baud rate in the projector OSD menu must be set to 9600 bps.
* The _source_, _picturemode_ and _aspectratio_ channels include a dropdown with the most commonly used settings.
* Not all pre-defined dropdown options will be usable if your particular projector does support a given option.
* If your projector has an option that is not in the dropdown, the string code to access that option will be displayed by the channel when that option is selected by the remote control.
* By using the sitemap mapping or a rule to send that code back to the channel, any options that are missing in the binding can be accessed.

* On Linux, you may get an error stating the serial port cannot be opened when the benqprojector binding tries to load.
* You can get around this by adding the `openhab` user to the `dialout` group like this: `usermod -a -G dialout openhab`.
* Also on Linux you may have issues with the USB if using two serial USB devices e.g. benqprojector and RFXcom. See the [general documentation about serial port configuration](/docs/administration/serial.html) for more on symlinking the USB ports.
* Here is an example of ser2net.conf you can use to share your serial port /dev/ttyUSB0 on IP port 4444 using [ser2net Linux tool](https://sourceforge.net/projects/ser2net/) (take care, the baud rate is specific to the BenQ projector):

```
4444:raw:0:/dev/ttyUSB0:9600 8DATABITS NONE 1STOPBIT LOCAL
```

## Channels

| Channel | Item Type | Purpose | Values |
| ------------------ | --------- | --------------------------------------------------- | --------- |
| power | Switch | Powers the projector on or off. | |
| source | String | Retrieve or set the input source. | See above |
| picturemode | String | Retrieve or set the picture mode. | See above |
| aspectratio | String | Retrieve or set the aspect ratio. | See above |
| freeze | Switch | Turn the freeze image mode on or off. | |
| blank | Switch | Turn the screen blank mode on or off. | |
| directcmd | String | Send a command directly to the projector. | Send only |
| lamptime | Number | Retrieves the lamp hours. | Read only |

## Full Example

things/benq.things:

```
//serial port connection
benqprojector:projector-serial:hometheater "Projector" [ serialPort="COM5", pollingInterval=10 ]
// serial over IP connection
benqprojector:projector-tcp:hometheater "Projector" [ host="192.168.0.10", port=8000, pollingInterval=10 ]
```

items/benq.items

```
Switch benqPower { channel="benqprojector:projector-serial:hometheater:power" }
String benqSource "Source [%s]" { channel="benqprojector:projector-serial:hometheater:source" }
String benqPictureMode "Picture Mode [%s]" { channel="benqprojector:projector-serial:hometheater:picturemode" }
String benqAspectRatio "Aspect Ratio [%s]" { channel="benqprojector:projector-serial:hometheater:aspectratio" }
Switch benqFreeze { channel="benqprojector:projector-serial:hometheater:freeze" }
Switch benqBlank { channel="benqprojector:projector-serial:hometheater:blank" }
String benqDirect { channel="benqprojector:projector-serial:hometheater:directcmd", autoupdate="false" }
Number benqLampTime "Lamp Time [%d h]" <switch> { channel="benqprojector:projector-serial:hometheater:lamptime" }
```

sitemaps/benq.sitemap

```
sitemap benq label="BenQ Projector Demo" {
Frame label="Controls" {
Switch item=benqPower label="Power"
Selection item=benqSource label="Source" mappings=["hdmi"="HDMI", "hdmi2"="HDMI2", "ypbr"="Component", "RGB"="Computer", "vid"="Video", "svid"="S-Video"]
Selection item=benqPictureMode label="Picture Mode"
Selection item=benqAspectRatio label="Aspect Ratio"
Switch item=benqFreeze label="Freeze"
Switch item=benqBlank label="Blank Screen"
Selection item=benqDirect label="Direct Command"
Text item=benqLampTime
}
Frame label="Advanced Controls" {
Switch item=benqDirect label="Image Flip" mappings=["pp=FT"="Front","pp=RE"="Rear","pp=FC"="Front Ceiling","pp=RC"="Rear Ceiling"]
Switch item=benqDirect label="Load Lens Memory" mappings=["lensload=m1"="1","lensload=m2"="2","lensload=m3"="3","lensload=m4"="4"]
Switch item=benqDirect label="Lamp Mode" mappings=["lampm=lnor"="Normal","lampm=eco"="Eco","lampm=seco"="SmartEco"]
Switch item=benqDirect label="Lamp Mode" mappings=["lampm=seco2"="SmartEco2","lampm=seco3"="SmartEco3","lampm=dimming"="Dimming","lampm=custom"="Custom"]
}
}
```
17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.benqprojector/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.1.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.binding.benqprojector</artifactId>

<name>openHAB Add-ons :: Bundles :: BenQ Projector Binding</name>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.benqprojector-${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-benqprojector" description="BenQ Projector Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-serial</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.benqprojector/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2021 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.benqprojector.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;

/**
* The {@link BenqProjectorBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Michael Lobstein - Initial contribution
*/
@NonNullByDefault
public class BenqProjectorBindingConstants {

private static final String BINDING_ID = "benqprojector";

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_PROJECTOR_SERIAL = new ThingTypeUID(BINDING_ID, "projector-serial");
public static final ThingTypeUID THING_TYPE_PROJECTOR_TCP = new ThingTypeUID(BINDING_ID, "projector-tcp");

// Some Channel types
public static final String CHANNEL_TYPE_POWER = "power";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2010-2021 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.benqprojector.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* Exception for BenQ projector command errors.
*
* @author Michael Lobstein - Initial contribution
*/
@NonNullByDefault
public class BenqProjectorCommandException extends Exception {

private static final long serialVersionUID = -8048415193494625295L;

public BenqProjectorCommandException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* Copyright (c) 2010-2021 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.benqprojector.internal;

import java.io.InvalidClassException;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;

/**
* Represents all valid command types which could be processed by this
* binding.
*
* @author Michael Lobstein - Initial contribution
*/
@NonNullByDefault
public enum BenqProjectorCommandType {
POWER("Power", SwitchItem.class),
SOURCE("Source", StringItem.class),
PICTURE_MODE("PictureMode", StringItem.class),
ASPECT_RATIO("AspectRatio", StringItem.class),
FREEZE("Freeze", SwitchItem.class),
BLANK("Blank", SwitchItem.class),
DIRECTCMD("DirectCmd", StringItem.class),
LAMP_TIME("LampTime", NumberItem.class);

private final String text;
private Class<? extends Item> itemClass;

private BenqProjectorCommandType(final String text, Class<? extends Item> itemClass) {
this.text = text;
this.itemClass = itemClass;
}

@Override
public String toString() {
return text;
}

public Class<? extends Item> getItemClass() {
return itemClass;
}

/**
* Procedure to validate command type string.
*
* @param commandTypeText
* command string e.g. RawData, Command, Brightness
* @return true if item is valid.
* @throws IllegalArgumentException
* Not valid command type.
* @throws InvalidClassException
* Not valid class for command type.
*/
public static boolean validateBinding(String commandTypeText, Class<? extends Item> itemClass)
throws IllegalArgumentException, InvalidClassException {
for (BenqProjectorCommandType c : BenqProjectorCommandType.values()) {
if (c.text.equalsIgnoreCase(commandTypeText)) {
if (c.getItemClass().equals(itemClass)) {
return true;
} else {
throw new InvalidClassException("Not valid class for command type");
}
}
}

throw new IllegalArgumentException("Not valid command type");
}

/**
* Procedure to convert command type string to command type class.
*
* @param commandTypeText
* command string e.g. RawData, Command, Brightness
* @return corresponding command type.
* @throws InvalidClassException
* Not valid class for command type.
*/
public static BenqProjectorCommandType getCommandType(String commandTypeText) throws IllegalArgumentException {
for (BenqProjectorCommandType c : BenqProjectorCommandType.values()) {
if (c.text.equalsIgnoreCase(commandTypeText)) {
return c;
}
}

throw new IllegalArgumentException("Not valid command type");
}
}
Loading