]> git.basschouten.com Git - openhab-addons.git/blob
090de76178e7fe9ee05bdf6232f9062408f842a1
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.benqprojector.internal;
14
15 import java.time.Duration;
16
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;
28
29 /**
30  * Provide high level interface to BenQ projector.
31  *
32  * @author Michael Lobstein - Initial contribution
33  */
34 @NonNullByDefault
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";
39
40     private static final int LAMP_REFRESH_WAIT_MINUTES = 5;
41
42     private ExpiringCache<Integer> cachedLampHours = new ExpiringCache<>(Duration.ofMinutes(LAMP_REFRESH_WAIT_MINUTES),
43             this::queryLamp);
44
45     private final Logger logger = LoggerFactory.getLogger(BenqProjectorDevice.class);
46
47     private BenqProjectorConnector connection;
48     private boolean connected = false;
49
50     public BenqProjectorDevice(SerialPortManager serialPortManager, BenqProjectorConfiguration config) {
51         connection = new BenqProjectorSerialConnector(serialPortManager, config.serialPort);
52     }
53
54     public BenqProjectorDevice(BenqProjectorConfiguration config) {
55         connection = new BenqProjectorTcpConnector(config.host, config.port);
56     }
57
58     private synchronized String sendQuery(String query) throws BenqProjectorCommandException, BenqProjectorException {
59         logger.debug("Query: '{}'", query);
60         String response = connection.sendMessage(query);
61
62         if (response.length() == 0) {
63             throw new BenqProjectorException("No response received");
64         }
65
66         if (response.contains(UNSUPPORTED_ITM)) {
67             return "UNSUPPORTED";
68         }
69
70         if (response.contains(BLOCK_ITM)) {
71             throw new BenqProjectorCommandException("Block Item received for command: " + query);
72         }
73
74         if (response.contains(ILLEGAL_FMT)) {
75             throw new BenqProjectorCommandException("Illegal Format response received for command: " + query);
76         }
77
78         logger.debug("Response: '{}'", response);
79
80         // example: SOUR=HDMI2
81         String[] responseParts = response.split("=");
82         if (responseParts.length != 2) {
83             throw new BenqProjectorCommandException("Invalid respose for command: " + query);
84         }
85
86         return responseParts[1].toLowerCase();
87     }
88
89     protected void sendCommand(String command) throws BenqProjectorCommandException, BenqProjectorException {
90         sendQuery(command);
91     }
92
93     protected int queryInt(String query) throws BenqProjectorCommandException, BenqProjectorException {
94         String response = sendQuery(query);
95         return Integer.parseInt(response);
96     }
97
98     protected String queryString(String query) throws BenqProjectorCommandException, BenqProjectorException {
99         return sendQuery(query);
100     }
101
102     public void connect() throws BenqProjectorException {
103         connection.connect();
104         connected = true;
105     }
106
107     public void disconnect() throws BenqProjectorException {
108         connection.disconnect();
109         connected = false;
110     }
111
112     public boolean isConnected() {
113         return connected;
114     }
115
116     /*
117      * Power
118      */
119     public Switch getPowerStatus() throws BenqProjectorCommandException, BenqProjectorException {
120         return (queryString("pow=?").contains("on") ? Switch.ON : Switch.OFF);
121     }
122
123     public void setPower(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
124         sendCommand(value == Switch.ON ? "pow=on" : "pow=off");
125     }
126
127     /*
128      * Source
129      */
130     public @Nullable String getSource() throws BenqProjectorCommandException, BenqProjectorException {
131         return queryString("sour=?");
132     }
133
134     public void setSource(String value) throws BenqProjectorCommandException, BenqProjectorException {
135         sendCommand(String.format("sour=%s", value));
136     }
137
138     /*
139      * Picture Mode
140      */
141     public @Nullable String getPictureMode() throws BenqProjectorCommandException, BenqProjectorException {
142         return queryString("appmod=?");
143     }
144
145     public void setPictureMode(String value) throws BenqProjectorCommandException, BenqProjectorException {
146         sendCommand(String.format("appmod=%s", value));
147     }
148
149     /*
150      * Aspect Ratio
151      */
152     public @Nullable String getAspectRatio() throws BenqProjectorCommandException, BenqProjectorException {
153         return queryString("asp=?");
154     }
155
156     public void setAspectRatio(String value) throws BenqProjectorCommandException, BenqProjectorException {
157         sendCommand(String.format("asp=%s", value));
158     }
159
160     /*
161      * Blank Screen
162      */
163     public Switch getBlank() throws BenqProjectorCommandException, BenqProjectorException {
164         return (queryString("blank=?").contains("on") ? Switch.ON : Switch.OFF);
165     }
166
167     public void setBlank(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
168         sendCommand(String.format("blank=%s", (value == Switch.ON ? "on" : "off")));
169     }
170
171     /*
172      * Freeze
173      */
174     public Switch getFreeze() throws BenqProjectorCommandException, BenqProjectorException {
175         return (queryString("freeze=?").contains("on") ? Switch.ON : Switch.OFF);
176     }
177
178     public void setFreeze(Switch value) throws BenqProjectorCommandException, BenqProjectorException {
179         sendCommand(String.format("freeze=%s", (value == Switch.ON ? "on" : "off")));
180     }
181
182     /*
183      * Direct Command
184      */
185     public void sendDirectCommand(String value) throws BenqProjectorCommandException, BenqProjectorException {
186         sendCommand(value);
187     }
188
189     /*
190      * Lamp Time (hours) - get from cache
191      */
192     public int getLampTime() throws BenqProjectorCommandException, BenqProjectorException {
193         Integer lampHours = cachedLampHours.getValue();
194
195         if (lampHours != null) {
196             return lampHours.intValue();
197         } else {
198             throw new BenqProjectorCommandException("cachedLampHours returned null");
199         }
200     }
201
202     /*
203      * Get Lamp Time
204      */
205     private @Nullable Integer queryLamp() {
206         try {
207             return Integer.valueOf(queryInt("ltim=?"));
208         } catch (BenqProjectorCommandException | BenqProjectorException e) {
209             logger.debug("Error executing command ltim=?", e);
210             return null;
211         }
212     }
213 }