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