mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[epsonprojector] Add retrieval of source list (#18006)
* Add retrieval of source list Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
parent
34d8fec597
commit
05382279a9
@ -25,7 +25,8 @@ 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 |
|
||||
| loadSourceList | Load Source List | Attempt to load source list options from the projector when True; default True. | no |
|
||||
| maxVolume | 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:
|
||||
|
||||
@ -34,12 +35,15 @@ The `projector-tcp` thing has the following configuration parameters:
|
||||
| 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 |
|
||||
| loadSourceList | Load Source List | Attempt to load source list options from the projector when True; default True. | no |
|
||||
| maxVolume | 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.
|
||||
- When the `loadSourceList` configuration option is set to true, the binding attempts to retrieve the available sources list from the projector and loads them into the _source_ channel.
|
||||
- The command to retrieve the sources list is not supported by older projectors and in this case the pre-defined sources list is used instead.
|
||||
- If your projector has a source input that is not in the dropdown, the two character 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 but not every option will be useable on all projectors.
|
||||
@ -159,7 +163,8 @@ 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"]
|
||||
// Uncomment mappings below to override the Source state options
|
||||
Selection item=epsonSource label="Source" // mappings=["30"="HDMI1", "A0"="HDMI2", "14"="Component", "20"="PC DSUB", "41"="Video", "42"="S-Video", "52"="USB", "53"="LAN", "56"="WiFi Direct"]
|
||||
Switch item=epsonFreeze label="Freeze"
|
||||
Switch item=epsonMute label="AV Mute"
|
||||
// Volume can be a Setpoint also
|
||||
|
@ -41,6 +41,7 @@ public class EpsonProjectorBindingConstants {
|
||||
public static final String CHANNEL_TYPE_POWER = "power";
|
||||
public static final String CHANNEL_TYPE_POWERSTATE = "powerstate";
|
||||
public static final String CHANNEL_TYPE_LAMPTIME = "lamptime";
|
||||
public static final String CHANNEL_TYPE_SOURCE = "source";
|
||||
|
||||
// Config properties
|
||||
public static final String THING_PROPERTY_HOST = "host";
|
||||
|
@ -13,9 +13,13 @@
|
||||
package org.openhab.binding.epsonprojector.internal;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -33,6 +37,7 @@ import org.openhab.binding.epsonprojector.internal.enums.PowerStatus;
|
||||
import org.openhab.binding.epsonprojector.internal.enums.Switch;
|
||||
import org.openhab.core.cache.ExpiringCache;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.types.StateOption;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -652,4 +657,28 @@ public class EpsonProjectorDevice {
|
||||
int err = queryHexInt("ERR?");
|
||||
return ErrorMessage.forCode(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Source List
|
||||
*/
|
||||
public List<StateOption> getSourceList() throws EpsonProjectorException {
|
||||
final List<StateOption> sourceListOptions = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// example: 30 HDMI1 A0 HDMI2
|
||||
final String[] sources = queryString("SOURCELIST?").split(" ");
|
||||
|
||||
if (sources.length % 2 != 0) {
|
||||
logger.debug("getSourceList(): {} has odd number of elements!", Arrays.toString(sources));
|
||||
} else if (sources[0].length() != 2) {
|
||||
logger.debug("getSourceList(): {} has invalid first entry", Arrays.toString(sources));
|
||||
} else {
|
||||
IntStream.range(0, sources.length / 2)
|
||||
.forEach(i -> sourceListOptions.add(new StateOption(sources[i * 2], sources[i * 2 + 1])));
|
||||
}
|
||||
} catch (EpsonProjectorCommandException e) {
|
||||
logger.debug("getSourceList(): {}", e.getMessage());
|
||||
}
|
||||
return sourceListOptions;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import org.osgi.service.component.annotations.Reference;
|
||||
@Component(configurationPid = "binding.epsonprojector", service = ThingHandlerFactory.class)
|
||||
public class EpsonProjectorHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final SerialPortManager serialPortManager;
|
||||
private final EpsonStateDescriptionOptionProvider stateDescriptionProvider;
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
@ -45,8 +46,10 @@ public class EpsonProjectorHandlerFactory extends BaseThingHandlerFactory {
|
||||
}
|
||||
|
||||
@Activate
|
||||
public EpsonProjectorHandlerFactory(final @Reference SerialPortManager serialPortManager) {
|
||||
public EpsonProjectorHandlerFactory(final @Reference SerialPortManager serialPortManager,
|
||||
final @Reference EpsonStateDescriptionOptionProvider provider) {
|
||||
this.serialPortManager = serialPortManager;
|
||||
this.stateDescriptionProvider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,7 +57,7 @@ public class EpsonProjectorHandlerFactory extends BaseThingHandlerFactory {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_PROJECTOR_SERIAL.equals(thingTypeUID) || THING_TYPE_PROJECTOR_TCP.equals(thingTypeUID)) {
|
||||
return new EpsonProjectorHandler(thing, serialPortManager);
|
||||
return new EpsonProjectorHandler(thing, serialPortManager, stateDescriptionProvider);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.epsonprojector.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.events.EventPublisher;
|
||||
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
|
||||
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* Dynamic provider of state options while leaving other state description fields as original.
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
@Component(service = { DynamicStateDescriptionProvider.class, EpsonStateDescriptionOptionProvider.class })
|
||||
@NonNullByDefault
|
||||
public class EpsonStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {
|
||||
|
||||
@Activate
|
||||
public EpsonStateDescriptionOptionProvider(final @Reference EventPublisher eventPublisher,
|
||||
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
|
||||
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
|
||||
}
|
||||
}
|
@ -46,4 +46,9 @@ public class EpsonProjectorConfiguration {
|
||||
* Maximum volume setting of this projector, ie 20, 40, etc.
|
||||
*/
|
||||
public int maxVolume = 20;
|
||||
|
||||
/**
|
||||
* Boolean to indicate if source list should be retrieved from projector
|
||||
*/
|
||||
public boolean loadSourceList;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.openhab.binding.epsonprojector.internal.EpsonProjectorCommandExceptio
|
||||
import org.openhab.binding.epsonprojector.internal.EpsonProjectorCommandType;
|
||||
import org.openhab.binding.epsonprojector.internal.EpsonProjectorDevice;
|
||||
import org.openhab.binding.epsonprojector.internal.EpsonProjectorException;
|
||||
import org.openhab.binding.epsonprojector.internal.EpsonStateDescriptionOptionProvider;
|
||||
import org.openhab.binding.epsonprojector.internal.configuration.EpsonProjectorConfiguration;
|
||||
import org.openhab.binding.epsonprojector.internal.enums.AspectRatio;
|
||||
import org.openhab.binding.epsonprojector.internal.enums.Background;
|
||||
@ -49,6 +50,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.StateOption;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -66,18 +68,23 @@ public class EpsonProjectorHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EpsonProjectorHandler.class);
|
||||
private final SerialPortManager serialPortManager;
|
||||
private final EpsonStateDescriptionOptionProvider stateDescriptionProvider;
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
private Optional<EpsonProjectorDevice> device = Optional.empty();
|
||||
|
||||
private boolean loadSourceList = false;
|
||||
private boolean isSourceListLoaded = false;
|
||||
private boolean isPowerOn = false;
|
||||
private int maxVolume = 20;
|
||||
private int curVolumeStep = -1;
|
||||
private int pollingInterval = DEFAULT_POLLING_INTERVAL_SEC;
|
||||
|
||||
public EpsonProjectorHandler(Thing thing, SerialPortManager serialPortManager) {
|
||||
public EpsonProjectorHandler(Thing thing, SerialPortManager serialPortManager,
|
||||
EpsonStateDescriptionOptionProvider stateDescriptionProvider) {
|
||||
super(thing);
|
||||
this.serialPortManager = serialPortManager;
|
||||
this.stateDescriptionProvider = stateDescriptionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -107,6 +114,7 @@ public class EpsonProjectorHandler extends BaseThingHandler {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
|
||||
}
|
||||
|
||||
loadSourceList = config.loadSourceList;
|
||||
maxVolume = config.maxVolume;
|
||||
pollingInterval = config.pollingInterval;
|
||||
device.ifPresent(dev -> dev.setScheduler(scheduler));
|
||||
@ -188,6 +196,18 @@ public class EpsonProjectorHandler extends BaseThingHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
// When polling for PWR status, also try to get SOURCELIST when enabled until successful
|
||||
if (EpsonProjectorCommandType.POWER == commandType && loadSourceList && !isSourceListLoaded) {
|
||||
final List<StateOption> sourceListOptions = remoteController.getSourceList();
|
||||
|
||||
// If a SOURCELIST was retrieved, load it in the source channel state options
|
||||
if (!sourceListOptions.isEmpty()) {
|
||||
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_TYPE_SOURCE),
|
||||
sourceListOptions);
|
||||
isSourceListLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (commandType) {
|
||||
case AKEYSTONE:
|
||||
Switch autoKeystone = remoteController.getAutoKeystone();
|
||||
|
@ -13,6 +13,8 @@ thing-type.epsonprojector.projector-tcp.description = An Epson projector which s
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.epsonprojector.projector-serial.loadSourceList.label = Load Source List
|
||||
thing-type.config.epsonprojector.projector-serial.loadSourceList.description = Attempt to load source list options from the Projector when True
|
||||
thing-type.config.epsonprojector.projector-serial.maxVolume.label = Volume Range
|
||||
thing-type.config.epsonprojector.projector-serial.maxVolume.description = Set to Match the Volume Range Seen in the Projector's OSD
|
||||
thing-type.config.epsonprojector.projector-serial.maxVolume.option.20 = Volume range is 0-20
|
||||
@ -23,6 +25,8 @@ thing-type.config.epsonprojector.projector-serial.serialPort.label = Serial Port
|
||||
thing-type.config.epsonprojector.projector-serial.serialPort.description = Serial Port to Use for Connecting to the Epson Projector
|
||||
thing-type.config.epsonprojector.projector-tcp.host.label = Host
|
||||
thing-type.config.epsonprojector.projector-tcp.host.description = IP address for the projector or serial over IP device
|
||||
thing-type.config.epsonprojector.projector-tcp.loadSourceList.label = Load Source List
|
||||
thing-type.config.epsonprojector.projector-tcp.loadSourceList.description = Attempt to load source list options from the Projector when True
|
||||
thing-type.config.epsonprojector.projector-tcp.maxVolume.label = Volume Range
|
||||
thing-type.config.epsonprojector.projector-tcp.maxVolume.description = Set to Match the Volume Range Seen in the Projector's OSD
|
||||
thing-type.config.epsonprojector.projector-tcp.maxVolume.option.20 = Volume range is 0-20
|
||||
@ -134,6 +138,9 @@ channel-type.epsonprojector.source.state.option.14 = Component
|
||||
channel-type.epsonprojector.source.state.option.20 = PC DSUB
|
||||
channel-type.epsonprojector.source.state.option.41 = Video
|
||||
channel-type.epsonprojector.source.state.option.42 = S-Video
|
||||
channel-type.epsonprojector.source.state.option.52 = USB
|
||||
channel-type.epsonprojector.source.state.option.53 = LAN
|
||||
channel-type.epsonprojector.source.state.option.56 = WiFi Direct
|
||||
channel-type.epsonprojector.tint.label = Tint
|
||||
channel-type.epsonprojector.tint.description = Retrieve or Set the Tint
|
||||
channel-type.epsonprojector.verticalkeystone.label = Vertical Keystone
|
||||
|
@ -51,6 +51,11 @@
|
||||
<description>Configures How Often to Poll the Projector for Updates (5-60; Default 10)</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="loadSourceList" type="boolean">
|
||||
<label>Load Source List</label>
|
||||
<description>Attempt to load source list options from the Projector when True</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="maxVolume" type="integer">
|
||||
<label>Volume Range</label>
|
||||
<description>Set to Match the Volume Range Seen in the Projector's OSD</description>
|
||||
@ -119,6 +124,11 @@
|
||||
<description>Configures How Often to Poll the Projector for Updates (5-60; Default 10)</description>
|
||||
<default>10</default>
|
||||
</parameter>
|
||||
<parameter name="loadSourceList" type="boolean">
|
||||
<label>Load Source List</label>
|
||||
<description>Attempt to load source list options from the Projector when True</description>
|
||||
<default>true</default>
|
||||
</parameter>
|
||||
<parameter name="maxVolume" type="integer">
|
||||
<label>Volume Range</label>
|
||||
<description>Set to Match the Volume Range Seen in the Projector's OSD</description>
|
||||
@ -219,6 +229,9 @@
|
||||
<option value="20">PC DSUB</option>
|
||||
<option value="41">Video</option>
|
||||
<option value="42">S-Video</option>
|
||||
<option value="52">USB</option>
|
||||
<option value="53">LAN</option>
|
||||
<option value="56">WiFi Direct</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
Loading…
Reference in New Issue
Block a user