]> git.basschouten.com Git - openhab-addons.git/blob
6a51b68f34f27e12651ed7cc6525c17bfc735a79
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.omnilink.internal.handler;
14
15 import static org.openhab.binding.omnilink.internal.OmnilinkBindingConstants.*;
16
17 import java.util.Map;
18 import java.util.Optional;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.omnilink.internal.AudioPlayer;
23 import org.openhab.binding.omnilink.internal.discovery.ObjectPropertyRequest;
24 import org.openhab.binding.omnilink.internal.discovery.ObjectPropertyRequests;
25 import org.openhab.binding.omnilink.internal.exceptions.BridgeOfflineException;
26 import org.openhab.core.library.types.DecimalType;
27 import org.openhab.core.library.types.NextPreviousType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.PercentType;
30 import org.openhab.core.library.types.PlayPauseType;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.digitaldan.jomnilinkII.Message;
41 import com.digitaldan.jomnilinkII.MessageTypes.CommandMessage;
42 import com.digitaldan.jomnilinkII.MessageTypes.ObjectStatus;
43 import com.digitaldan.jomnilinkII.MessageTypes.properties.AudioZoneProperties;
44 import com.digitaldan.jomnilinkII.MessageTypes.statuses.ExtendedAudioZoneStatus;
45 import com.digitaldan.jomnilinkII.OmniInvalidResponseException;
46 import com.digitaldan.jomnilinkII.OmniUnknownMessageTypeException;
47
48 /**
49  * The {@link AudioZoneHandler} defines some methods that are used to
50  * interface with an OmniLink Audio Zone. This by extension also defines the
51  * Audio Zone thing that openHAB will be able to pick up and interface with.
52  *
53  * @author Craig Hamilton - Initial contribution
54  * @author Ethan Dye - openHAB3 rewrite
55  */
56 @NonNullByDefault
57 public class AudioZoneHandler extends AbstractOmnilinkStatusHandler<ExtendedAudioZoneStatus> {
58     private final Logger logger = LoggerFactory.getLogger(AudioZoneHandler.class);
59     private final int thingID = getThingNumber();
60     public @Nullable String number;
61
62     public AudioZoneHandler(Thing thing) {
63         super(thing);
64     }
65
66     @Override
67     public void initialize() {
68         super.initialize();
69         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
70         if (bridgeHandler != null) {
71             updateAudioZoneProperties(bridgeHandler);
72         } else {
73             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
74                     "Received null bridge while initializing Audio Zone!");
75         }
76     }
77
78     private void updateAudioZoneProperties(OmnilinkBridgeHandler bridgeHandler) {
79         ObjectPropertyRequest<AudioZoneProperties> objectPropertyRequest = ObjectPropertyRequest
80                 .builder(bridgeHandler, ObjectPropertyRequests.AUDIO_ZONE, thingID, 0).selectNamed().build();
81
82         for (AudioZoneProperties audioZoneProperties : objectPropertyRequest) {
83             Map<String, String> properties = editProperties();
84             properties.put(THING_PROPERTIES_NAME, audioZoneProperties.getName());
85             updateProperties(properties);
86         }
87     }
88
89     @Override
90     public void handleCommand(ChannelUID channelUID, Command command) {
91         logger.debug("handleCommand called for channel: {}, command: {}", channelUID, command);
92
93         if (command instanceof RefreshType) {
94             retrieveStatus().ifPresentOrElse(this::updateChannels, () -> updateStatus(ThingStatus.OFFLINE,
95                     ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Received null status update!"));
96             return;
97         }
98
99         switch (channelUID.getId()) {
100             case CHANNEL_AUDIO_ZONE_POWER:
101                 if (command instanceof OnOffType) {
102                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_ON_AND_MUTE,
103                             OnOffType.OFF.equals(command) ? 0 : 1, thingID);
104                 } else {
105                     logger.debug("Invalid command: {}, must be OnOffType", command);
106                 }
107                 break;
108             case CHANNEL_AUDIO_ZONE_MUTE:
109                 if (command instanceof OnOffType) {
110                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_ON_AND_MUTE,
111                             OnOffType.OFF.equals(command) ? 2 : 3, thingID);
112                 } else {
113                     logger.debug("Invalid command: {}, must be OnOffType", command);
114                 }
115                 break;
116             case CHANNEL_AUDIO_ZONE_VOLUME:
117                 if (command instanceof PercentType) {
118                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_VOLUME, ((PercentType) command).intValue(),
119                             thingID);
120                 } else {
121                     logger.debug("Invalid command: {}, must be PercentType", command);
122                 }
123                 break;
124             case CHANNEL_AUDIO_ZONE_SOURCE:
125                 if (command instanceof DecimalType) {
126                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE, ((DecimalType) command).intValue(),
127                             thingID);
128                 } else {
129                     logger.debug("Invalid command: {}, must be DecimalType", command);
130                 }
131                 break;
132             case CHANNEL_AUDIO_ZONE_CONTROL:
133                 if (command instanceof PlayPauseType) {
134                     handlePlayPauseCommand(channelUID, (PlayPauseType) command);
135                 } else if (command instanceof NextPreviousType) {
136                     handleNextPreviousCommand(channelUID, (NextPreviousType) command);
137                 } else {
138                     logger.debug("Invalid command: {}, must be PlayPauseType or NextPreviousType", command);
139                 }
140                 break;
141             default:
142                 logger.warn("Unknown channel for Audio Zone thing: {}", channelUID);
143         }
144     }
145
146     private void handlePlayPauseCommand(ChannelUID channelUID, PlayPauseType command) {
147         logger.debug("handlePlayPauseCommand called for channel: {}, command: {}", channelUID, command);
148         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
149
150         if (bridgeHandler != null) {
151             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
152             if (audioPlayer.isPresent()) {
153                 AudioPlayer player = audioPlayer.get();
154                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
155                         PlayPauseType.PLAY.equals(command) ? player.getPlayCommand() : player.getPauseCommand(),
156                         thingID);
157             } else {
158                 logger.warn("No Audio Player was detected!");
159             }
160         } else {
161             logger.debug("Received null bridge while sending Audio Zone command!");
162         }
163     }
164
165     private void handleNextPreviousCommand(ChannelUID channelUID, NextPreviousType command) {
166         logger.debug("handleNextPreviousCommand called for channel: {}, command: {}", channelUID, command);
167         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
168
169         if (bridgeHandler != null) {
170             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
171             if (audioPlayer.isPresent()) {
172                 AudioPlayer player = audioPlayer.get();
173                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
174                         NextPreviousType.NEXT.equals(command) ? player.getNextCommand() : player.getPreviousCommand(),
175                         thingID);
176             } else {
177                 logger.warn("Audio Player could not be found!");
178             }
179         } else {
180             logger.debug("Received null bridge while sending Audio Zone command!");
181         }
182     }
183
184     @Override
185     public void updateChannels(ExtendedAudioZoneStatus status) {
186         logger.debug("updateChannels called for Audio Zone status: {}", status);
187         updateState(CHANNEL_AUDIO_ZONE_POWER, OnOffType.from(status.isPower()));
188         updateState(CHANNEL_AUDIO_ZONE_MUTE, OnOffType.from(status.isMute()));
189         updateState(CHANNEL_AUDIO_ZONE_VOLUME, new PercentType(status.getVolume()));
190         updateState(CHANNEL_AUDIO_ZONE_SOURCE, new DecimalType(status.getSource()));
191     }
192
193     @Override
194     protected Optional<ExtendedAudioZoneStatus> retrieveStatus() {
195         try {
196             final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
197             if (bridgeHandler != null) {
198                 ObjectStatus objStatus = bridgeHandler.requestObjectStatus(Message.OBJ_TYPE_AUDIO_ZONE, thingID,
199                         thingID, true);
200                 return Optional.of((ExtendedAudioZoneStatus) objStatus.getStatuses()[0]);
201             } else {
202                 logger.debug("Received null bridge while updating Audio Zone status!");
203                 return Optional.empty();
204             }
205         } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
206             logger.debug("Received exception while refreshing Audio Zone status: {}", e.getMessage());
207             return Optional.empty();
208         }
209     }
210 }