## Discovery
-If the projector has a built-in Ethernet port connected to the same network as the openHAB server and supports AMX Device Discovery, the thing will be discovered automatically.
+If the projector has a built-in Ethernet port connected to the same network as the openHAB server and either the 'AMX Device Discovery' or 'Control4' options are present and enabled in the projector's network menu, the thing will be discovered automatically.
Serial port or serial over IP connections must be configured manually.
## Binding Configuration
## 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 |
+| 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. | Write only |
+| lamptime | Number | Retrieves the number of hours the lamp has been used. | Read only |
## Full Example
<feature name="openhab-binding-benqprojector" description="BenQ Projector Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-serial</feature>
+ <feature>openhab-core-config-discovery-sddp</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.benqprojector/${project.version}</bundle>
</feature>
</features>
--- /dev/null
+/**
+ * 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.benqprojector.internal.discovery;
+
+import static org.openhab.binding.benqprojector.internal.BenqProjectorBindingConstants.*;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+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.sddp.SddpDevice;
+import org.openhab.core.config.discovery.sddp.SddpDiscoveryParticipant;
+import org.openhab.core.thing.Thing;
+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;
+
+/**
+ *
+ * Discovery Service for BenQ Projectors that support SDDP.
+ *
+ * @author Michael Lobstein - Initial contribution
+ *
+ */
+@NonNullByDefault
+@Component(immediate = true)
+public class BenqProjectorDiscoveryParticipant implements SddpDiscoveryParticipant {
+ private final Logger logger = LoggerFactory.getLogger(BenqProjectorDiscoveryParticipant.class);
+
+ private static final String BENQ = "BENQ";
+ private static final String TYPE_PROJECTOR = "PROJECTOR";
+
+ @Override
+ public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
+ return Set.of(THING_TYPE_PROJECTOR_TCP);
+ }
+
+ @Override
+ public @Nullable DiscoveryResult createResult(SddpDevice device) {
+ final ThingUID uid = getThingUID(device);
+ if (uid != null) {
+ final Map<String, Object> properties = new HashMap<>(3);
+ final String label = device.manufacturer + " " + device.model;
+
+ properties.put(Thing.PROPERTY_MAC_ADDRESS, uid.getId());
+ properties.put(THING_PROPERTY_HOST, device.ipAddress);
+ properties.put(THING_PROPERTY_PORT, DEFAULT_PORT);
+
+ final DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
+ .withRepresentationProperty(Thing.PROPERTY_MAC_ADDRESS).withLabel(label).build();
+
+ logger.debug("Created a DiscoveryResult for device '{}' with UID '{}'", label, uid.getId());
+ return result;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public @Nullable ThingUID getThingUID(SddpDevice device) {
+ if (device.manufacturer.toUpperCase(Locale.ENGLISH).contains(BENQ)
+ && device.type.toUpperCase(Locale.ENGLISH).contains(TYPE_PROJECTOR) && !device.macAddress.isBlank()
+ && !device.ipAddress.isBlank()) {
+ logger.debug("BenQ projector with mac {} found at {}", device.macAddress, device.ipAddress);
+
+ return new ThingUID(THING_TYPE_PROJECTOR_TCP,
+ device.macAddress.replaceAll("-", "").toUpperCase(Locale.ENGLISH));
+ }
+ return null;
+ }
+}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
- return SUPPORTED_THING_TYPES_UIDS;
+ return Set.of(THING_TYPE_PROJECTOR_TCP);
}
@Override
<description>This binding is compatible with BenQ projectors</description>
<connection>local</connection>
+ <discovery-methods>
+ <discovery-method>
+ <service-type>sddp</service-type>
+ <match-properties>
+ <match-property>
+ <name>manufacturer</name>
+ <regex>(?i).*benq.*</regex>
+ </match-property>
+ <match-property>
+ <name>type</name>
+ <regex>(?i).*projector.*</regex>
+ </match-property>
+ </match-properties>
+ </discovery-method>
+ </discovery-methods>
+
</addon:addon>
channel-type.benqprojector.aspectratio.state.option.auto = Auto
channel-type.benqprojector.aspectratio.state.option.lbox = Letterbox
channel-type.benqprojector.aspectratio.state.option.wide = Wide
+channel-type.benqprojector.aspectratio.state.option.2.35 = 2.35:1
channel-type.benqprojector.blank.label = Screen Blank
channel-type.benqprojector.blank.description = Turn the Screen Blank On or Off
channel-type.benqprojector.directcmd.label = Direct Command
channel-type.benqprojector.freeze.label = Freeze Image
channel-type.benqprojector.freeze.description = Turn the Freeze Image Mode On or Off
channel-type.benqprojector.lamptime.label = Lamp Time
-channel-type.benqprojector.lamptime.description = Retrieves the Lamp Hours
+channel-type.benqprojector.lamptime.description = Retrieves the number of hours the lamp has been used
channel-type.benqprojector.picturemode.label = Picture Mode
channel-type.benqprojector.picturemode.description = Retrieve or Set the Picture Mode
channel-type.benqprojector.picturemode.state.option.dynamic = Dynamic
channel-type.benqprojector.picturemode.state.option.preset = Presentation
channel-type.benqprojector.picturemode.state.option.srgb = sRGB
channel-type.benqprojector.picturemode.state.option.bright = Bright
+channel-type.benqprojector.picturemode.state.option.brightcine = Bright Cinema
+channel-type.benqprojector.picturemode.state.option.filmmaker = Filmmaker Mode
channel-type.benqprojector.picturemode.state.option.livingroom = Living Room
channel-type.benqprojector.picturemode.state.option.game = Game
channel-type.benqprojector.picturemode.state.option.cine = Cinema
channel-type.benqprojector.picturemode.state.option.isfday = ISF Day
channel-type.benqprojector.picturemode.state.option.isfnight = ISF Night
channel-type.benqprojector.picturemode.state.option.threed = 3-D
+channel-type.benqprojector.picturemode.state.option.hdr = HDR10
+channel-type.benqprojector.picturemode.state.option.hdr+ = HDR10+
+channel-type.benqprojector.picturemode.state.option.hlg = HLG
channel-type.benqprojector.source.label = Source
channel-type.benqprojector.source.description = Retrieve or Set the Input Source
channel-type.benqprojector.source.state.option.hdmi = HDMI
channel-type.benqprojector.source.state.option.hdmi2 = HDMI2
+channel-type.benqprojector.source.state.option.usbreader = USB Reader
channel-type.benqprojector.source.state.option.ypbr = Component
channel-type.benqprojector.source.state.option.rgb = Computer/YPbPr
channel-type.benqprojector.source.state.option.rgb2 = Computer/YPbPr2
<options>
<option value="hdmi">HDMI</option>
<option value="hdmi2">HDMI2</option>
+ <option value="usbreader">USB Reader</option>
<option value="ypbr">Component</option>
<option value="rgb">Computer/YPbPr</option>
<option value="rgb2">Computer/YPbPr2</option>
<option value="preset">Presentation</option>
<option value="srgb">sRGB</option>
<option value="bright">Bright</option>
+ <option value="brightcine">Bright Cinema</option>
+ <option value="filmmaker">Filmmaker Mode</option>
<option value="livingroom">Living Room</option>
<option value="game">Game</option>
<option value="cine">Cinema</option>
<option value="isfday">ISF Day</option>
<option value="isfnight">ISF Night</option>
<option value="threed">3-D</option>
+ <option value="hdr">HDR10</option>
+ <option value="hdr+">HDR10+</option>
+ <option value="hlg">HLG</option>
</options>
</state>
</channel-type>
<option value="auto">Auto</option>
<option value="lbox">Letterbox</option>
<option value="wide">Wide</option>
+ <option value="2.35">2.35:1</option>
</options>
</state>
</channel-type>
<channel-type id="lamptime">
<item-type>Number</item-type>
<label>Lamp Time</label>
- <description>Retrieves the Lamp Hours</description>
+ <description>Retrieves the number of hours the lamp has been used</description>
<state readOnly="true" pattern="%d h"/>
</channel-type>