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