2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.benqprojector.internal;
15 import java.time.Duration;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.benqprojector.internal.configuration.BenqProjectorConfiguration;
20 import org.openhab.binding.benqprojector.internal.connector.BenqProjectorConnector;
21 import org.openhab.binding.benqprojector.internal.connector.BenqProjectorSerialConnector;
22 import org.openhab.binding.benqprojector.internal.connector.BenqProjectorTcpConnector;
23 import org.openhab.binding.benqprojector.internal.enums.Switch;
24 import org.openhab.core.cache.ExpiringCache;
25 import org.openhab.core.io.transport.serial.SerialPortManager;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Provide high level interface to BenQ projector.
32 * @author Michael Lobstein - Initial contribution
35 public class BenqProjectorDevice {
36 private static final String UNSUPPORTED_ITM = "Unsupported item";
37 private static final String BLOCK_ITM = "Block item";
38 private static final String ILLEGAL_FMT = "Illegal format";
40 private static final int LAMP_REFRESH_WAIT_MINUTES = 5;
42 private ExpiringCache<Integer> cachedLampHours = new ExpiringCache<>(Duration.ofMinutes(LAMP_REFRESH_WAIT_MINUTES),
45 private final Logger logger = LoggerFactory.getLogger(BenqProjectorDevice.class);
47 private BenqProjectorConnector connection;
48 private boolean connected = false;
50 public BenqProjectorDevice(SerialPortManager serialPortManager, BenqProjectorConfiguration config) {
51 connection = new BenqProjectorSerialConnector(serialPortManager, config.serialPort);
54 public BenqProjectorDevice(BenqProjectorConfiguration config) {
55 connection = new BenqProjectorTcpConnector(config.host, config.port);
58 private synchronized String sendQuery(String query) throws BenqProjectorCommandException, BenqProjectorException {
59 logger.debug("Query: '{}'", query);
60 String response = connection.sendMessage(query);
62 if (response.length() == 0) {
63 throw new BenqProjectorException("No response received");
66 if (response.contains(UNSUPPORTED_ITM)) {
70 if (response.contains(BLOCK_ITM)) {
71 throw new BenqProjectorCommandException("Block Item received for command: " + query);
74 if (response.contains(ILLEGAL_FMT)) {
75 throw new BenqProjectorCommandException("Illegal Format response received for command: " + query);
78 logger.debug("Response: '{}'", response);
80 // example: SOUR=HDMI2
81 String[] responseParts = response.split("=");
82 if (responseParts.length != 2) {
83 throw new BenqProjectorCommandException("Invalid respose for command: " + query);
86 return responseParts[1].toLowerCase();
89 protected void sendCommand(String command) throws BenqProjectorCommandException, BenqProjectorException {
93 protected int queryInt(String query) throws BenqProjectorCommandException, BenqProjectorException {
94 String response = sendQuery(query);
95 return Integer.parseInt(response);
98 protected String queryString(String query) throws BenqProjectorCommandException, BenqProjectorException {
99 return sendQuery(query);
102 public void connect() throws BenqProjectorException {
103 connection.connect();
107 public void disconnect() throws BenqProjectorException {
108 connection.disconnect();
112 public boolean isConnected() {
119 public Switch getPowerStatus() throws BenqProjectorCommandException, BenqProjectorException {
120 return (queryString("pow=?").contains("on") ? Switch.ON : Switch.OFF);
123 public void setPower(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
124 sendCommand(value == Switch.ON ? "pow=on" : "pow=off");
130 public @Nullable String getSource() throws BenqProjectorCommandException, BenqProjectorException {
131 return queryString("sour=?");
134 public void setSource(String value) throws BenqProjectorCommandException, BenqProjectorException {
135 sendCommand(String.format("sour=%s", value));
141 public @Nullable String getPictureMode() throws BenqProjectorCommandException, BenqProjectorException {
142 return queryString("appmod=?");
145 public void setPictureMode(String value) throws BenqProjectorCommandException, BenqProjectorException {
146 sendCommand(String.format("appmod=%s", value));
152 public @Nullable String getAspectRatio() throws BenqProjectorCommandException, BenqProjectorException {
153 return queryString("asp=?");
156 public void setAspectRatio(String value) throws BenqProjectorCommandException, BenqProjectorException {
157 sendCommand(String.format("asp=%s", value));
163 public Switch getBlank() throws BenqProjectorCommandException, BenqProjectorException {
164 return (queryString("blank=?").contains("on") ? Switch.ON : Switch.OFF);
167 public void setBlank(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
168 sendCommand(String.format("blank=%s", (value == Switch.ON ? "on" : "off")));
174 public Switch getFreeze() throws BenqProjectorCommandException, BenqProjectorException {
175 return (queryString("freeze=?").contains("on") ? Switch.ON : Switch.OFF);
178 public void setFreeze(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
179 sendCommand(String.format("freeze=%s", (value == Switch.ON ? "on" : "off")));
185 public void sendDirectCommand(String value) throws BenqProjectorCommandException, BenqProjectorException {
190 * Lamp Time (hours) - get from cache
192 public int getLampTime() throws BenqProjectorCommandException, BenqProjectorException {
193 Integer lampHours = cachedLampHours.getValue();
195 if (lampHours != null) {
196 return lampHours.intValue();
198 throw new BenqProjectorCommandException("cachedLampHours returned null");
205 private @Nullable Integer queryLamp() {
207 return Integer.valueOf(queryInt("ltim=?"));
208 } catch (BenqProjectorCommandException | BenqProjectorException e) {
209 logger.debug("Error executing command ltim=?", e);