Skip to content

Commit

Permalink
[epsonprojector] Add configurable volume channel (openhab#10988)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Lobstein <[email protected]>
Signed-off-by: dw-8 <[email protected]>
  • Loading branch information
mlobstein authored and dw-8 committed Jul 25, 2021
1 parent afe9142 commit 543317b
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 68 deletions.
86 changes: 45 additions & 41 deletions bundles/org.openhab.binding.epsonprojector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,26 @@ The `projector-serial` thing has the following configuration parameters:
|-----------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| serialPort | Serial Port | Serial port device name that is connected to the Epson 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 |
| maxVolume | Max Volume Range | Set to the maximum volume level available in the projector's OSD to select the correct range for the volume control. e.g. 20 or 40; default 20 | 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 3629 for projectors with built-in ethernet connector or Wi-Fi. | yes |
| pollingInterval | Polling Interval | Polling interval in seconds to update channel states, range 5-60 seconds; default 10 seconds. | no |
| 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 3629 for projectors with built-in ethernet connector or Wi-Fi. | yes |
| pollingInterval | Polling Interval | Polling interval in seconds to update channel states, range 5-60 seconds; default 10 seconds. | no |
| maxVolume | Max Volume Range | Set to the maximum volume level available in the projector's OSD to select the correct range for the volume control. e.g. 20 or 40; default 20 | no |

Some notes:

* The binding should work on all Epson projectors that support the ESC/VP21 protocol, however not all binding channels will be useable on all projectors.
* The _source_ channel includes a dropdown with the most common source inputs.
* If your projector has a source input that is not in the dropdown, the two digit hex code to access that input will be displayed by the _source_ channel when that input is selected by the remote control.
* By using the sitemap mapping or a rule to send the input's code back to the _source_ channel, any source on the projector can be accessed by the binding.
* The following channels _aspectratio_, _colormode_, _luminance_, _gamma_ and _background_ are pre-populated with a full set of options and not every option will be useable on all projectors.
* The following channels _aspectratio_, _colormode_, _luminance_, _gamma_ and _background_ are pre-populated with a full set of options but not every option will be useable on all projectors.
* If your projector has an option in one of the above mentioned channels that is not recognized by the binding, the channel will display 'UNKNOWN' if that un-recognized option is selected by the remote control.
* The volume channel is a dimmer (0-100%) that is scaled to the range on the projector, either 0-20 or 0-40 per the maxVolume configuration setting. If your projector uses a different range, then the volume channel will not work.
* If the projector power is switched to off in the middle of a polling operation, some of the channel values may become undefined until the projector is switched on again.
* If the binding fails to connect to the projector using the direct IP connection, ensure that no password is configured on the projctor.

Expand All @@ -56,47 +59,47 @@ Some notes:

## Channels

| Channel | Item Type | Purpose | Values |
| ------------------ | --------- | ----------------------------------------------------------------- | --------- |
| power | Switch | Powers the projector on or off. | |
| powerstate | String | Retrieves the textual power state of the projector. | Read only |
| source | String | Retrieve or set the input source. | See above |
| aspectratio | String | Retrieve or set the aspect ratio. | See above |
| colormode | String | Retrieve or set the color mode. | See above |
| freeze | Switch | Turn the freeze screen mode on or off. | |
| mute | Switch | Turn the AV mute on or off. | |
| volume | Number | Retrieve or set the volume. | 0 - +20 |
| luminance | String | Retrieve or set the lamp mode. | See above |
| brightness | Number | Retrieve or set the brightness. | -24 - +24 |
| contrast | Number | Retrieve or set the contrast. | -24 - +24 |
| density | Number | Retrieve or set the density (color saturation). | -32 - +32 |
| tint | Number | Retrieve or set the tint. | -32 - +32 |
| colortemperature | Number | Retrieve or set the color temperature. | 0 - +9 |
| fleshtemperature | Number | Retrieve or set the flesh temperature. | 0 - +6 |
| gamma | String | Retrieve or set the gamma setting. | See above |
| autokeystone | Switch | Turn the auto keystone mode on or off. | |
| verticalkeystone | Number | Retrieve or set the vertical keystone. | -30 - +30 |
| horizontalkeystone | Number | Retrieve or set the horizontal keystone. | -30 - +30 |
| verticalposition | Number | Retrieve or set the vertical position. | -8 - +10 |
| horizontalposition | Number | Retrieve or set the horizontal position. | -23 - +26 |
| verticalreverse | Switch | Turn the vertical reverse mode on or off. | |
| horizontalreverse | Switch | Turn the horizontal reverse mode on or off. | |
| background | String | Retrieve or set the background color/logo. | See above |
| keycode | String | Send a key operation command to the projector. (2 character code) | Send only |
| lamptime | Number | Retrieves the lamp hours. | Read only |
| errcode | Number | Retrieves the last error code. | Read only |
| errmessage | String | Retrieves the description of the last error. | Read only |
| Channel | Item Type | Purpose | Values |
| ------------------ | --------- | ------------------------------------------------------------------------------------------ | --------- |
| power | Switch | Powers the projector on or off. | |
| powerstate | String | Retrieves the textual power state of the projector. | Read only |
| source | String | Retrieve or set the input source. | See above |
| aspectratio | String | Retrieve or set the aspect ratio. | See above |
| colormode | String | Retrieve or set the color mode. | See above |
| freeze | Switch | Turn the freeze screen mode on or off. | |
| mute | Switch | Turn the AV mute on or off. | |
| volume | Dimmer | Retrieve or set the volume. Scaled to 0-20 or 0-40 on the projector per maxVolume setting. | 0% - 100% |
| luminance | String | Retrieve or set the lamp mode. | See above |
| brightness | Number | Retrieve or set the brightness. | -24 - +24 |
| contrast | Number | Retrieve or set the contrast. | -24 - +24 |
| density | Number | Retrieve or set the density (color saturation). | -32 - +32 |
| tint | Number | Retrieve or set the tint. | -32 - +32 |
| colortemperature | Number | Retrieve or set the color temperature. | 0 - +9 |
| fleshtemperature | Number | Retrieve or set the flesh temperature. | 0 - +6 |
| gamma | String | Retrieve or set the gamma setting. | See above |
| autokeystone | Switch | Turn the auto keystone mode on or off. | |
| verticalkeystone | Number | Retrieve or set the vertical keystone. | -30 - +30 |
| horizontalkeystone | Number | Retrieve or set the horizontal keystone. | -30 - +30 |
| verticalposition | Number | Retrieve or set the vertical position. | -8 - +10 |
| horizontalposition | Number | Retrieve or set the horizontal position. | -23 - +26 |
| verticalreverse | Switch | Turn the vertical reverse mode on or off. | |
| horizontalreverse | Switch | Turn the horizontal reverse mode on or off. | |
| background | String | Retrieve or set the background color/logo. | See above |
| keycode | String | Send a key operation command to the projector. (2 character code) | Send only |
| lamptime | Number | Retrieves the lamp hours. | Read only |
| errcode | Number | Retrieves the last error code. | Read only |
| errmessage | String | Retrieves the description of the last error. | Read only |

## Full Example

things/epson.things:

```
// serial port connection
epsonprojector:projector-serial:hometheater "Projector" [ serialPort="COM5", pollingInterval=10 ]
epsonprojector:projector-serial:hometheater "Projector" [ serialPort="COM5", pollingInterval=10, maxVolume=20 ]
// direct IP or serial over IP connection
epsonprojector:projector-tcp:hometheater "Projector" [ host="192.168.0.10", port=3629, pollingInterval=10 ]
epsonprojector:projector-tcp:hometheater "Projector" [ host="192.168.0.10", port=3629, pollingInterval=10, maxVolume=20 ]
```

Expand All @@ -109,7 +112,7 @@ String epsonAspectRatio "Aspect Ratio [%s]" { channel="epsonprojector
String epsonColorMode "Color Mode [%s]" { channel="epsonprojector:projector-serial:hometheater:colormode" }
Switch epsonFreeze { channel="epsonprojector:projector-serial:hometheater:freeze" }
Switch epsonMute { channel="epsonprojector:projector-serial:hometheater:mute" }
Number epsonVolume { channel="epsonprojector:projector-serial:hometheater:volume" }
Dimmer epsonVolume { channel="epsonprojector:projector-serial:hometheater:volume" }
String epsonLuminance "Lamp Mode [%s]" { channel="epsonprojector:projector-serial:hometheater:luminance" }
Number epsonBrightness { channel="epsonprojector:projector-serial:hometheater:brightness" }
Expand Down Expand Up @@ -139,14 +142,15 @@ String epsonErrMessage "Error Message [%s]" <"siren-off"> { channel="epsonproj
sitemaps/epson.sitemap

```
sitemap epson label="Epson Projector Demo"
sitemap epson label="Epson Projector"
{
Frame label="Controls" {
Switch item=epsonPower label="Power"
Selection item=epsonSource label="Source" mappings=["30"="HDMI1", "A0"="HDMI2", "14"="Component", "20"="PC DSUB", "41"="Video", "42"="S-Video"]
Switch item=epsonFreeze label="Freeze"
Switch item=epsonMute label="AV Mute"
Setpoint item=epsonVolume label="Volume"
// Volume can be a Setpoint also
Slider item=epsonVolume label="Volume" minValue=0 maxValue=100 step=1 icon="soundvolume"
Switch item=epsonKeyCode label="Navigation" icon="screen" mappings=["03"="Menu", "35"="˄", "36"="˅", "37"="<", "38"=">", "16"="Enter"]
}
Frame label="Adjust Image" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.DimmerItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
Expand Down Expand Up @@ -49,7 +50,7 @@ public enum EpsonProjectorCommandType {
HPOSITION("HorizontalPosition", NumberItem.class),
VPOSITION("VerticalPosition", NumberItem.class),
GAMMA("Gamma", StringItem.class),
VOLUME("Volume", NumberItem.class),
VOLUME("Volume", DimmerItem.class),
MUTE("Mute", SwitchItem.class),
HREVERSE("HorizontalReverse", SwitchItem.class),
VREVERSE("VerticalReverse", SwitchItem.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ public class EpsonProjectorDevice {
94, 99, 104, 109, 114, 120, 125, 130, 135, 141, 146, 151, 156, 161, 167, 172, 177, 182, 188, 193, 198, 203,
208, 214, 219, 224, 229, 235, 240, 245, 250 };

private static final int[] MAP40 = new int[] { 0, 6, 12, 18, 24, 31, 37, 43, 49, 56, 62, 68, 74, 81, 87, 93, 99,
106, 112, 118, 124, 131, 137, 143, 149, 156, 162, 168, 174, 181, 187, 193, 199, 206, 212, 218, 224, 231,
237, 243, 249 };

private static final int[] MAP20 = new int[] { 0, 12, 24, 36, 48, 60, 73, 85, 97, 109, 121, 134, 146, 158, 170, 182,
195, 207, 219, 231, 243 };

Expand All @@ -78,6 +82,7 @@ public class EpsonProjectorDevice {

private static final String ON = "ON";
private static final String ERR = "ERR";
private static final String IMEVENT = "IMEVENT";

private final Logger logger = LoggerFactory.getLogger(EpsonProjectorDevice.class);

Expand Down Expand Up @@ -118,7 +123,7 @@ public void setScheduler(ScheduledExecutorService scheduler) {
response = response.replace("\r:", "");
logger.debug("Response: '{}'", response);

if (ERR.equals(response)) {
if (ERR.equals(response) || response.startsWith(IMEVENT)) {
throw new EpsonProjectorCommandException("Error response received for command: " + query);
}

Expand Down Expand Up @@ -522,19 +527,36 @@ public void setGamma(Gamma value) throws EpsonProjectorCommandException, EpsonPr
/*
* Volume
*/
public int getVolume() throws EpsonProjectorCommandException, EpsonProjectorException {
int vol = queryInt("VOL?");
for (int i = 0; i < MAP20.length; i++) {
if (vol == MAP20[i]) {
public int getVolume(int maxVolume) throws EpsonProjectorCommandException, EpsonProjectorException {
int vol = this.queryInt("VOL?");
switch (maxVolume) {
case 20:
return this.getMappingValue(MAP20, vol);
case 40:
return this.getMappingValue(MAP40, vol);
}
return 0;
}

private int getMappingValue(int[] map, int value) {
for (int i = 0; i < map.length; i++) {
if (value == map[i]) {
return i;
}
}
return 0;
}

public void setVolume(int value) throws EpsonProjectorCommandException, EpsonProjectorException {
if (value >= 0 && value <= 20) {
sendCommand(String.format("VOL %d", MAP20[value]));
public void setVolume(int value, int maxVolume) throws EpsonProjectorCommandException, EpsonProjectorException {
if (value >= 0 && value <= maxVolume) {
switch (maxVolume) {
case 20:
this.sendCommand(String.format("VOL %d", MAP20[value]));
return;
case 40:
this.sendCommand(String.format("VOL %d", MAP40[value]));
return;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@ public class EpsonProjectorConfiguration {
* Polling interval to refresh states.
*/
public int pollingInterval;

/**
* Maximum volume setting of this projector, ie 20, 40, etc.
*/
public int maxVolume = 20;
}
Loading

0 comments on commit 543317b

Please sign in to comment.