2 * Copyright (c) 2010-2023 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.sonyprojector.internal.communication;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.util.Arrays;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.sonyprojector.internal.SonyProjectorException;
23 import org.openhab.binding.sonyprojector.internal.SonyProjectorModel;
24 import org.openhab.core.i18n.CommunicationException;
25 import org.openhab.core.i18n.ConnectionException;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.util.HexUtils;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * Class for communicating with Sony Projectors
34 * @author Markus Wehrle - Initial contribution
35 * @author Laurent Garnier - Refactoring to include new channels, consider serial connection and protocol depending on
39 public abstract class SonyProjectorConnector {
41 private final Logger logger = LoggerFactory.getLogger(SonyProjectorConnector.class);
43 private static final byte[] DUMMY_DATA = new byte[] { 0x00, 0x00 };
44 private static final byte[] POWER_ON = new byte[] { 0x00, 0x01 };
45 private static final byte[] POWER_OFF = new byte[] { 0x00, 0x00 };
46 private static final byte[] OVERSCAN_ON = new byte[] { 0x00, 0x01 };
47 private static final byte[] OVERSCAN_OFF = new byte[] { 0x00, 0x00 };
48 private static final byte[] PICTURE_ON = new byte[] { 0x00, 0x01 };
49 private static final byte[] PICTURE_OFF = new byte[] { 0x00, 0x00 };
50 private static final byte[] XVCOLOR_ON = new byte[] { 0x00, 0x01 };
51 private static final byte[] XVCOLOR_OFF = new byte[] { 0x00, 0x00 };
53 private SonyProjectorModel model;
55 /** The output stream */
56 protected @Nullable OutputStream dataOut;
58 /** The input stream */
59 protected @Nullable InputStream dataIn;
61 /** true if the connection is established, false if not */
62 protected boolean connected;
69 * @param model the projector model in use
70 * @param simu whether the communication is simulated or real
72 public SonyProjectorConnector(SonyProjectorModel model, boolean simu) {
78 * Set the projector model in use
80 * @param model the projector model in use
82 public void setModel(SonyProjectorModel model) {
87 * Request the projector to get the current power status
89 * @return the current power status
91 * @throws SonyProjectorException in case of any problem
93 public SonyProjectorStatusPower getStatusPower() throws SonyProjectorException {
94 return SonyProjectorStatusPower.getFromDataCode(getSetting(SonyProjectorItem.STATUS_POWER));
98 * Power ON the projector
100 * @throws SonyProjectorException in case the projector is not ready for a power ON command or any other problem
102 public void powerOn() throws SonyProjectorException {
103 SonyProjectorStatusPower status = null;
105 status = getStatusPower();
106 } catch (SonyProjectorException e) {
108 logger.debug("Current Power Status: {}", status == null ? "undefined" : status.toString());
109 if (status != null && status != SonyProjectorStatusPower.STANDBY) {
110 throw new SonyProjectorException("Projector not ready for command ON");
111 } else if (model.isPowerCmdAvailable()) {
112 logger.debug("Set Power ON using Power command");
113 setSetting(SonyProjectorItem.POWER, POWER_ON);
115 logger.debug("Set Power ON using IR Power command");
116 sendIR(SonyProjectorItem.IR_POWER_ON);
117 if (status == null) {
118 sendIR(SonyProjectorItem.IR_POWER_ON);
124 * Power OFF the projector
126 * @throws SonyProjectorException in case the projector is not ready for a power OFF command or any other problem
128 public void powerOff() throws SonyProjectorException {
129 SonyProjectorStatusPower status = null;
131 status = getStatusPower();
132 } catch (SonyProjectorException e) {
134 logger.debug("Current Power Status: {}", status == null ? "undefined" : status.toString());
135 if (status == null || status != SonyProjectorStatusPower.POWER_ON) {
136 throw new SonyProjectorException("Projector not ready for command OFF");
137 } else if (model.isPowerCmdAvailable()) {
138 logger.debug("Set Power OFF using Power command");
139 setSetting(SonyProjectorItem.POWER, POWER_OFF);
141 logger.debug("Set Power OFF using IR Power command");
142 sendIR(SonyProjectorItem.IR_POWER_OFF);
147 * Request the projector to get the current calibration preset
149 * @return the current calibration preset
151 * @throws SonyProjectorException in case of any problem
153 public String getCalibrationPreset() throws SonyProjectorException {
154 return model.getCalibrPresetNameFromDataCode(getSetting(SonyProjectorItem.CALIBRATION_PRESET));
158 * Request the projector to change the calibration preset
160 * @param value the calibration preset to set
162 * @throws SonyProjectorException in case of any problem
164 public void setCalibrationPreset(String value) throws SonyProjectorException {
165 setSetting(SonyProjectorItem.CALIBRATION_PRESET, model.getCalibrPresetDataCodeFromName(value));
169 * Request the projector to get the current video input
171 * @return the current video input
173 * @throws SonyProjectorException in case of any problem
175 public String getInput() throws SonyProjectorException {
176 return model.getInputNameFromDataCode(getSetting(SonyProjectorItem.INPUT));
180 * Request the projector to change the video input
182 * @param value the video input to set
184 * @throws SonyProjectorException in case of any problem
186 public void setInput(String value) throws SonyProjectorException {
187 setSetting(SonyProjectorItem.INPUT, model.getInputDataCodeFromName(value));
191 * Request the projector to get the current contrast setting
193 * @return the current contrast value
195 * @throws SonyProjectorException in case of any problem
197 public int getContrast() throws SonyProjectorException {
198 return convertDataToInt(getSetting(SonyProjectorItem.CONTRAST));
202 * Request the projector to change the contrast setting
204 * @param value the contrast value to set
206 * @throws SonyProjectorException in case of any problem
208 public void setContrast(int value) throws SonyProjectorException {
209 setSetting(SonyProjectorItem.CONTRAST, convertIntToData(value));
213 * Request the projector to get the current brightness setting
215 * @return the current brightness value
217 * @throws SonyProjectorException in case of any problem
219 public int getBrightness() throws SonyProjectorException {
220 return convertDataToInt(getSetting(SonyProjectorItem.BRIGHTNESS));
224 * Request the projector to change the brightness setting
226 * @param value the brightness value to set
228 * @throws SonyProjectorException in case of any problem
230 public void setBrightness(int value) throws SonyProjectorException {
231 setSetting(SonyProjectorItem.BRIGHTNESS, convertIntToData(value));
235 * Request the projector to get the current color setting
237 * @return the current color value
239 * @throws SonyProjectorException in case of any problem
241 public int getColor() throws SonyProjectorException {
242 return convertDataToInt(getSetting(SonyProjectorItem.COLOR));
246 * Request the projector to change the color setting
248 * @param value the color value to set
250 * @throws SonyProjectorException in case of any problem
252 public void setColor(int value) throws SonyProjectorException {
253 setSetting(SonyProjectorItem.COLOR, convertIntToData(value));
257 * Request the projector to get the current hue setting
259 * @return the current hue value
261 * @throws SonyProjectorException in case of any problem
263 public int getHue() throws SonyProjectorException {
264 return convertDataToInt(getSetting(SonyProjectorItem.HUE));
268 * Request the projector to change the hue setting
270 * @param value the hue value to set
272 * @throws SonyProjectorException in case of any problem
274 public void setHue(int value) throws SonyProjectorException {
275 setSetting(SonyProjectorItem.HUE, convertIntToData(value));
279 * Request the projector to get the current sharpness setting
281 * @return the current sharpness value
283 * @throws SonyProjectorException in case of any problem
285 public int getSharpness() throws SonyProjectorException {
286 return convertDataToInt(getSetting(SonyProjectorItem.SHARPNESS));
290 * Request the projector to change the sharpness setting
292 * @param value the sharpness value to set
294 * @throws SonyProjectorException in case of any problem
296 public void setSharpness(int value) throws SonyProjectorException {
297 setSetting(SonyProjectorItem.SHARPNESS, convertIntToData(value));
301 * Request the projector to get the current contrast enhancer mode
303 * @return the current contrast enhancer mode
305 * @throws SonyProjectorException in case of any problem
307 public String getContrastEnhancer() throws SonyProjectorException {
308 return model.getContrastEnhancerNameFromDataCode(getSetting(SonyProjectorItem.CONTRAST_ENHANCER));
312 * Request the projector to change the contrast enhancer mode
314 * @param value the contrast enhancer mode to set
316 * @throws SonyProjectorException in case of any problem
318 public void setContrastEnhancer(String value) throws SonyProjectorException {
319 setSetting(SonyProjectorItem.CONTRAST_ENHANCER, model.getContrastEnhancerDataCodeFromName(value));
323 * Request the projector to get the current film mode
325 * @return the current film mode
327 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
329 public String getFilmMode() throws SonyProjectorException {
330 if (!model.isFilmModeAvailable()) {
331 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.FILM_MODE.getName()
332 + " for projector model " + model.getName());
334 return model.getFilmModeNameFromDataCode(getSetting(SonyProjectorItem.FILM_MODE));
338 * Request the projector to change the film mode
340 * @param value the film mode to set
342 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
344 public void setFilmMode(String value) throws SonyProjectorException {
345 if (!model.isFilmModeAvailable()) {
346 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.FILM_MODE.getName()
347 + " for projector model " + model.getName());
349 setSetting(SonyProjectorItem.FILM_MODE, model.getFilmModeDataCodeFromName(value));
353 * Request the projector to get the lamp use time
355 * @return the lamp use time
357 * @throws SonyProjectorException in case of any problem
359 public int getLampUseTime() throws SonyProjectorException {
360 return convertDataToInt(getSetting(SonyProjectorItem.LAMP_USE_TIME));
364 * Request the projector to get the current mode for the lamp control setting
366 * @return the current mode for the lamp control setting
368 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
370 public String getLampControl() throws SonyProjectorException {
371 if (!model.isLampControlAvailable()) {
372 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.LAMP_CONTROL.getName()
373 + " for projector model " + model.getName());
375 return SonyProjectorLampControl.getFromDataCode(getSetting(SonyProjectorItem.LAMP_CONTROL)).getName();
379 * Request the projector to change the mode for the lamp control setting
381 * @param value the mode to set for the lamp control setting
383 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
385 public void setLampControl(String value) throws SonyProjectorException {
386 if (!model.isLampControlAvailable()) {
387 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.LAMP_CONTROL.getName()
388 + " for projector model " + model.getName());
390 setSetting(SonyProjectorItem.LAMP_CONTROL, SonyProjectorLampControl.getFromName(value).getDataCode());
394 * Request the projector if the picture is muted or not
396 * @return OnOffType.ON if the picture is muted, OnOffType.OFF if not
398 * @throws SonyProjectorException in case of any problem
400 public OnOffType getPictureMuting() throws SonyProjectorException {
401 return Arrays.equals(getSetting(SonyProjectorItem.PICTURE_MUTING), PICTURE_ON) ? OnOffType.ON : OnOffType.OFF;
405 * Request the projector to mute the picture
407 * @throws SonyProjectorException in case of any problem
409 public void mutePicture() throws SonyProjectorException {
410 setSetting(SonyProjectorItem.PICTURE_MUTING, PICTURE_ON);
414 * Request the projector to unmute the picture
416 * @throws SonyProjectorException in case of any problem
418 public void unmutePicture() throws SonyProjectorException {
419 setSetting(SonyProjectorItem.PICTURE_MUTING, PICTURE_OFF);
423 * Request the projector to get the current mode for the picture position setting
425 * @return the current mode for the picture position setting
427 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
429 public String getPicturePosition() throws SonyProjectorException {
430 if (!model.isPicturePositionAvailable()) {
431 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.PICTURE_POSITION.getName()
432 + " for projector model " + model.getName());
434 return model.getPicturePositionNameFromDataCode(getSetting(SonyProjectorItem.PICTURE_POSITION));
438 * Request the projector to change the mode for the picture position setting
440 * @param value the mode to set for the picture position setting
442 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
444 public void setPicturePosition(String value) throws SonyProjectorException {
445 if (!model.isPicturePositionAvailable()) {
446 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.PICTURE_POSITION.getName()
447 + " for projector model " + model.getName());
449 setSetting(SonyProjectorItem.PICTURE_POSITION, model.getPicturePositionCodeFromName(value));
453 * Request the projector if the overscan is enabled or not
455 * @return OnOffType.ON if the overscan is enabled, OnOffType.OFF if not
457 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
459 public OnOffType getOverscan() throws SonyProjectorException {
460 if (!model.isOverscanAvailable()) {
461 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.OVERSCAN.getName()
462 + " for projector model " + model.getName());
464 return Arrays.equals(getSetting(SonyProjectorItem.OVERSCAN), OVERSCAN_ON) ? OnOffType.ON : OnOffType.OFF;
468 * Request the projector to enable the overscan
470 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
472 public void enableOverscan() throws SonyProjectorException {
473 if (!model.isOverscanAvailable()) {
474 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.OVERSCAN.getName()
475 + " for projector model " + model.getName());
477 setSetting(SonyProjectorItem.OVERSCAN, OVERSCAN_ON);
481 * Request the projector to disable the overscan
483 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
485 public void disableOverscan() throws SonyProjectorException {
486 if (!model.isOverscanAvailable()) {
487 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.OVERSCAN.getName()
488 + " for projector model " + model.getName());
490 setSetting(SonyProjectorItem.OVERSCAN, OVERSCAN_OFF);
494 * Request the projector to get the current aspect ratio mode
496 * @return the current current aspect ratio mode
498 * @throws SonyProjectorException in case of any problem
500 public String getAspect() throws SonyProjectorException {
501 return model.getAspectNameFromDataCode(getSetting(SonyProjectorItem.ASPECT));
505 * Request the projector to change the aspect ratio mode
507 * @param value the aspect ratio mode to set
509 * @throws SonyProjectorException in case of any problem
511 public void setAspect(String value) throws SonyProjectorException {
512 setSetting(SonyProjectorItem.ASPECT, model.getAspectCodeFromName(value));
516 * Request the projector to get the current color temperature setting
518 * @return the current color temperature value
520 * @throws SonyProjectorException in case of any problem
522 public String getColorTemperature() throws SonyProjectorException {
523 return model.getColorTempNameFromDataCode(getSetting(SonyProjectorItem.COLOR_TEMP));
527 * Request the projector to change the color temperature setting
529 * @param value the color temperature value to set
531 * @throws SonyProjectorException in case of any problem
533 public void setColorTemperature(String value) throws SonyProjectorException {
534 setSetting(SonyProjectorItem.COLOR_TEMP, model.getColorTempCodeFromName(value));
538 * Request the projector to get the current iris mode
540 * @return the current iris mode
542 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
544 public String getIrisMode() throws SonyProjectorException {
545 if (!model.isIrisModeAvailable()) {
546 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_MODE.getName()
547 + " for projector model " + model.getName());
549 return model.getIrisModeNameFromDataCode(getSetting(SonyProjectorItem.IRIS_MODE));
553 * Request the projector to change the iris mode
555 * @param value the iris mode to set
557 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
559 public void setIrisMode(String value) throws SonyProjectorException {
560 if (!model.isIrisModeAvailable()) {
561 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_MODE.getName()
562 + " for projector model " + model.getName());
564 setSetting(SonyProjectorItem.IRIS_MODE, model.getIrisModeCodeFromName(value));
568 * Request the projector to get the current iris manual setting
570 * @return the current value for the iris manual setting
572 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
574 public int getIrisManual() throws SonyProjectorException {
575 if (!model.isIrisManualAvailable()) {
576 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_MANUAL.getName()
577 + " for projector model " + model.getName());
579 return convertDataToInt(getSetting(SonyProjectorItem.IRIS_MANUAL));
583 * Request the projector to change the iris manual setting
585 * @param value the iris manual value to set
587 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
589 public void setIrisManual(int value) throws SonyProjectorException {
590 if (!model.isIrisManualAvailable()) {
591 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_MANUAL.getName()
592 + " for projector model " + model.getName());
594 setSetting(SonyProjectorItem.IRIS_MANUAL, convertIntToData(value));
598 * Request the projector to get the current iris sensitivity
600 * @return the current iris sensitivity
602 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
604 public String getIrisSensitivity() throws SonyProjectorException {
605 if (!model.isIrisSensitivityAvailable()) {
606 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_SENSITIVITY.getName()
607 + " for projector model " + model.getName());
609 return SonyProjectorIrisSensitivity.getFromDataCode(getSetting(SonyProjectorItem.IRIS_SENSITIVITY)).getName();
613 * Request the projector to change the iris sensitivity
615 * @param value the iris sensitivity to set
617 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
619 public void setIrisSensitivity(String value) throws SonyProjectorException {
620 if (!model.isIrisSensitivityAvailable()) {
621 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.IRIS_SENSITIVITY.getName()
622 + " for projector model " + model.getName());
624 setSetting(SonyProjectorItem.IRIS_SENSITIVITY, SonyProjectorIrisSensitivity.getFromName(value).getDataCode());
628 * Request the projector to get the current film projection mode
630 * @return the current film projection mode
632 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
634 public String getFilmProjection() throws SonyProjectorException {
635 if (!model.isFilmProjectionAvailable()) {
636 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.FILM_PROJECTION.getName()
637 + " for projector model " + model.getName());
639 return model.getFilmProjectionNameFromDataCode(getSetting(SonyProjectorItem.FILM_PROJECTION));
643 * Request the projector to change the film projection mode
645 * @param value the film projection mode to set
647 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
649 public void setFilmProjection(String value) throws SonyProjectorException {
650 if (!model.isFilmProjectionAvailable()) {
651 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.FILM_PROJECTION.getName()
652 + " for projector model " + model.getName());
654 setSetting(SonyProjectorItem.FILM_PROJECTION, model.getFilmProjectionCodeFromName(value));
658 * Request the projector to get the current motion enhancer mode
660 * @return the current motion enhancer mode
662 * @throws SonyProjectorException in case of any problem
664 public String getMotionEnhancer() throws SonyProjectorException {
665 if (!model.isMotionEnhancerAvailable()) {
666 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MOTION_ENHANCER.getName()
667 + " for projector model " + model.getName());
669 return model.getMotionEnhancerNameFromDataCode(getSetting(SonyProjectorItem.MOTION_ENHANCER));
673 * Request the projector to change the motion enhancer mode
675 * @param value the motion enhancer mode to set
677 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
679 public void setMotionEnhancer(String value) throws SonyProjectorException {
680 if (!model.isMotionEnhancerAvailable()) {
681 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MOTION_ENHANCER.getName()
682 + " for projector model " + model.getName());
684 setSetting(SonyProjectorItem.MOTION_ENHANCER, model.getMotionEnhancerCodeFromName(value));
688 * Request the projector to get the current gamma correction
690 * @return the current gamma correction
692 * @throws SonyProjectorException in case of any problem
694 public String getGammaCorrection() throws SonyProjectorException {
695 return model.getGammaCorrectionNameFromDataCode(getSetting(SonyProjectorItem.GAMMA_CORRECTION));
699 * Request the projector to change the gamma correction
701 * @param value the gamma correction to set
703 * @throws SonyProjectorException in case of any problem
705 public void setGammaCorrection(String value) throws SonyProjectorException {
706 setSetting(SonyProjectorItem.GAMMA_CORRECTION, model.getGammaCorrectionCodeFromName(value));
710 * Request the projector to get the current color space
712 * @return the current color space
714 * @throws SonyProjectorException in case of any problem
716 public String getColorSpace() throws SonyProjectorException {
717 return model.getColorSpaceNameFromDataCode(getSetting(SonyProjectorItem.COLOR_SPACE));
721 * Request the projector to change the color space
723 * @param value the color space to set
725 * @throws SonyProjectorException in case of any problem
727 public void setColorSpace(String value) throws SonyProjectorException {
728 setSetting(SonyProjectorItem.COLOR_SPACE, model.getColorSpaceCodeFromName(value));
732 * Request the projector to get the current noise reduction mode
734 * @return the current noise reduction mode
736 * @throws SonyProjectorException in case of any problem
738 public String getNr() throws SonyProjectorException {
739 return model.getNrNameFromDataCode(getSetting(SonyProjectorItem.NR));
743 * Request the projector to change the noise reduction mode
745 * @param value the noise reduction mode to set
747 * @throws SonyProjectorException in case of any problem
749 public void setNr(String value) throws SonyProjectorException {
750 setSetting(SonyProjectorItem.NR, model.getNrCodeFromName(value));
754 * Request the projector to get the current block noise reduction mode
756 * @return the current block noise reduction mode
758 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
760 public String getBlockNr() throws SonyProjectorException {
761 if (!model.isBlockNrAvailable()) {
762 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.BLOCK_NR.getName()
763 + " for projector model " + model.getName());
765 return SonyProjectorBlockNr.getFromDataCode(getSetting(SonyProjectorItem.BLOCK_NR)).getName();
769 * Request the projector to change the block noise reduction mode
771 * @param value the block noise reduction mode to set
773 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
775 public void setBlockNr(String value) throws SonyProjectorException {
776 if (!model.isBlockNrAvailable()) {
777 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.BLOCK_NR.getName()
778 + " for projector model " + model.getName());
780 setSetting(SonyProjectorItem.BLOCK_NR, SonyProjectorBlockNr.getFromName(value).getDataCode());
784 * Request the projector to get the current mosquito noise reduction mode
786 * @return the current mosquito noise reduction mode
788 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
790 public String getMosquitoNr() throws SonyProjectorException {
791 if (!model.isMosquitoNrAvailable()) {
792 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MOSQUITO_NR.getName()
793 + " for projector model " + model.getName());
795 return SonyProjectorMosquitoNr.getFromDataCode(getSetting(SonyProjectorItem.MOSQUITO_NR)).getName();
799 * Request the projector to change the mosquito noise reduction mode
801 * @param value the mosquito noise reduction mode to set
803 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
805 public void setMosquitoNr(String value) throws SonyProjectorException {
806 if (!model.isMosquitoNrAvailable()) {
807 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MOSQUITO_NR.getName()
808 + " for projector model " + model.getName());
810 setSetting(SonyProjectorItem.MOSQUITO_NR, SonyProjectorMosquitoNr.getFromName(value).getDataCode());
814 * Request the projector to get the current MPEG noise reduction mode
816 * @return the current MPEG noise reduction mode
818 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
820 public String getMpegNr() throws SonyProjectorException {
821 if (!model.isMpegNrAvailable()) {
822 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MPEG_NR.getName()
823 + " for projector model " + model.getName());
825 return model.getMpegNrNameFromDataCode(getSetting(SonyProjectorItem.MPEG_NR));
829 * Request the projector to change the MPEG noise reduction mode
831 * @param value the MPEG noise reduction mode to set
833 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
835 public void setMpegNr(String value) throws SonyProjectorException {
836 if (!model.isMpegNrAvailable()) {
837 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.MPEG_NR.getName()
838 + " for projector model " + model.getName());
840 setSetting(SonyProjectorItem.MPEG_NR, model.getMpegNrCodeFromName(value));
844 * Request the projector to get the current value for xvColor
846 * @return the current value for xvColor
848 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
850 public OnOffType getXvColor() throws SonyProjectorException {
851 if (!model.isXvColorAvailable()) {
852 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.XVCOLOR.getName()
853 + " for projector model " + model.getName());
855 return Arrays.equals(getSetting(SonyProjectorItem.XVCOLOR), XVCOLOR_ON) ? OnOffType.ON : OnOffType.OFF;
859 * Request the projector to set xvColor to ON
861 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
863 public void enableXvColor() throws SonyProjectorException {
864 if (!model.isXvColorAvailable()) {
865 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.XVCOLOR.getName()
866 + " for projector model " + model.getName());
868 setSetting(SonyProjectorItem.XVCOLOR, XVCOLOR_ON);
872 * Request the projector to set xvColor to OFF
874 * @throws SonyProjectorException in case this setting is not available for the projector or any other problem
876 public void disableXvColor() throws SonyProjectorException {
877 if (!model.isXvColorAvailable()) {
878 throw new SonyProjectorException("Unavailable item " + SonyProjectorItem.XVCOLOR.getName()
879 + " for projector model " + model.getName());
881 setSetting(SonyProjectorItem.XVCOLOR, XVCOLOR_OFF);
885 * Request the projector to get the current value for a setting
887 * @param item the projector setting to get
889 * @return the current value for the setting
891 * @throws SonyProjectorException in case of any problem
893 protected byte[] getSetting(SonyProjectorItem item) throws SonyProjectorException {
894 logger.debug("Get setting {}", item.getName());
897 byte[] result = getResponseData(executeCommand(item, true, DUMMY_DATA));
899 logger.debug("Get setting {} succeeded: result data: {}", item.getName(), HexUtils.bytesToHex(result));
902 } catch (CommunicationException e) {
903 throw new SonyProjectorException("Get setting " + item.getName() + " failed", e);
908 * Request the projector to set a new value for a setting
910 * @param item the projector setting to set
911 * @param data the value to set for the setting
913 * @throws SonyProjectorException in case of any problem
915 private void setSetting(SonyProjectorItem item, byte[] data) throws SonyProjectorException {
916 logger.debug("Set setting {} data {}", item.getName(), HexUtils.bytesToHex(data));
919 executeCommand(item, false, data);
920 } catch (CommunicationException e) {
921 throw new SonyProjectorException("Set setting " + item.getName() + " failed", e);
924 logger.debug("Set setting {} succeeded", item.getName());
928 * Send an IR command to the projector
930 * @param item the IR information to send
932 * @throws SonyProjectorException in case of any problem
934 private synchronized void sendIR(SonyProjectorItem item) throws SonyProjectorException {
935 logger.debug("Send IR {}", item.getName());
938 boolean runningSession = connected;
942 // Build the message and send it
943 writeCommand(buildMessage(item, false, DUMMY_DATA));
945 // Wait at least 45 ms
948 // No response expected for SIRCS commands
950 if (!runningSession) {
953 } catch (CommunicationException e) {
954 throw new SonyProjectorException("Send IR " + item.getName() + " failed", e);
955 } catch (InterruptedException e) {
956 Thread.currentThread().interrupt();
957 throw new SonyProjectorException("Send IR " + item.getName() + " interrupted", e);
960 logger.debug("Send IR {} succeeded", item.getName());
964 * Connect to the projector, write a command, read the response and disconnect
966 * @param item the projector setting to get or set
967 * @param getCommand true for a GET command or false for a SET command
968 * @param data the value to be considered in case of a SET command
970 * @return the buffer containing the returned message
972 * @throws ConnectionException in case of any connection problem
973 * @throws CommunicationException in case of any communication problem
975 private synchronized byte[] executeCommand(SonyProjectorItem item, boolean getCommand, byte[] data)
976 throws ConnectionException, CommunicationException {
977 boolean runningSession = connected;
981 // Build the message and send it
982 writeCommand(buildMessage(item, getCommand, data));
985 byte[] responseMessage = readResponse();
987 if (!runningSession) {
991 // Validate the content of the response
992 validateResponse(responseMessage, item);
994 return responseMessage;
998 * Open the connection with the projector if not yet opened
1000 * @throws ConnectionException in case of any problem
1002 public abstract void open() throws ConnectionException;
1005 * Close the connection with the projector
1007 public void close() {
1009 OutputStream dataOut = this.dataOut;
1010 if (dataOut != null) {
1013 } catch (IOException e) {
1015 this.dataOut = null;
1017 InputStream dataIn = this.dataIn;
1018 if (dataIn != null) {
1021 } catch (IOException e) {
1030 * Build the message buffer corresponding to the request of a particular information
1032 * @param item the projector setting to get or set
1033 * @param getCommand true for a GET command or false for a SET command
1034 * @param data the value to be considered in case of a SET command
1036 * @return the message buffer
1038 protected abstract byte[] buildMessage(SonyProjectorItem item, boolean getCommand, byte[] data);
1041 * Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes
1042 * actually read is returned as an integer.
1044 * @param dataBuffer the buffer into which the data is read.
1045 * @return the total number of bytes read into the buffer, or -1 if there is no more data because the end of the
1046 * stream has been reached.
1047 * @throws CommunicationException if the input stream is null, if the first byte cannot be read for any reason
1048 * other than the end of the file, if the input stream has been closed, or if some other I/O error
1051 protected int readInput(byte[] dataBuffer) throws CommunicationException {
1053 throw new CommunicationException("readInput failed: should not be called in simu mode");
1055 InputStream dataIn = this.dataIn;
1056 if (dataIn == null) {
1057 throw new CommunicationException("readInput failed: input stream is null");
1060 return dataIn.read(dataBuffer);
1061 } catch (IOException e) {
1062 logger.debug("readInput failed: {}", e.getMessage());
1063 throw new CommunicationException("readInput failed", e);
1068 * Write a command to the output stream
1070 * @param message the buffer containing the message to be sent
1072 * @throws CommunicationException in case of any communication problem
1074 protected void writeCommand(byte[] message) throws CommunicationException {
1075 logger.debug("writeCommand: {}", HexUtils.bytesToHex(message));
1079 OutputStream dataOut = this.dataOut;
1080 if (dataOut == null) {
1081 throw new CommunicationException("writeCommand failed: output stream is null");
1084 dataOut.write(message);
1086 } catch (IOException e) {
1087 logger.debug("writeCommand failed: {}", e.getMessage());
1088 throw new CommunicationException("writeCommand failed", e);
1093 * Read the response from the input stream
1095 * @return the buffer containing the returned message
1097 * @throws CommunicationException in case of any communication problem
1099 protected abstract byte[] readResponse() throws CommunicationException;
1102 * Validate the content of a returned message
1104 * @param responseMessage the buffer containing the returned message
1105 * @param the projector setting to get or set
1107 * @throws CommunicationException if the message has unexpected content
1109 protected abstract void validateResponse(byte[] responseMessage, SonyProjectorItem item)
1110 throws CommunicationException;
1113 * Extract the value from the returned message
1115 * @param responseMessage the buffer containing the returned message
1117 * @return the value of the projector setting that was requested
1119 protected abstract byte[] getResponseData(byte[] responseMessage);
1121 private int convertDataToInt(byte[] data) {
1122 return ((data[0] & 0x000000FF) << 8) | (data[1] & 0x000000FF);
1125 private byte[] convertIntToData(int value) {
1126 byte[] data = new byte[2];
1127 data[0] = (byte) ((value & 0x0000FF00) >> 8);
1128 data[1] = (byte) (value & 0x000000FF);