]> git.basschouten.com Git - openhab-addons.git/blob
fd93b8a9d3852a0b7ab15fa2e312270215a9ef80
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.Optional;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.omnilink.internal.AudioPlayer;
22 import org.openhab.binding.omnilink.internal.discovery.ObjectPropertyRequest;
23 import org.openhab.binding.omnilink.internal.discovery.ObjectPropertyRequests;
24 import org.openhab.binding.omnilink.internal.exceptions.BridgeOfflineException;
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             updateProperty(THING_PROPERTIES_NAME, audioZoneProperties.getName());
83         }
84     }
85
86     @Override
87     public void handleCommand(ChannelUID channelUID, Command command) {
88         logger.debug("handleCommand called for channel: {}, command: {}", channelUID, command);
89
90         if (command instanceof RefreshType) {
91             retrieveStatus().ifPresentOrElse(this::updateChannels, () -> updateStatus(ThingStatus.OFFLINE,
92                     ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Received null status update!"));
93             return;
94         }
95
96         switch (channelUID.getId()) {
97             case CHANNEL_AUDIO_ZONE_POWER:
98                 if (command instanceof OnOffType) {
99                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_ON_AND_MUTE,
100                             OnOffType.OFF.equals(command) ? 0 : 1, thingID);
101                 } else {
102                     logger.debug("Invalid command: {}, must be OnOffType", command);
103                 }
104                 break;
105             case CHANNEL_AUDIO_ZONE_MUTE:
106                 if (command instanceof OnOffType) {
107                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_ON_AND_MUTE,
108                             OnOffType.OFF.equals(command) ? 2 : 3, thingID);
109                 } else {
110                     logger.debug("Invalid command: {}, must be OnOffType", command);
111                 }
112                 break;
113             case CHANNEL_AUDIO_ZONE_VOLUME:
114                 if (command instanceof PercentType percentCommand) {
115                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_VOLUME, percentCommand.intValue(), thingID);
116                 } else {
117                     logger.debug("Invalid command: {}, must be PercentType", command);
118                 }
119                 break;
120             case CHANNEL_AUDIO_ZONE_SOURCE:
121                 if (command instanceof DecimalType decimalCommand) {
122                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE, decimalCommand.intValue(), thingID);
123                 } else {
124                     logger.debug("Invalid command: {}, must be DecimalType", command);
125                 }
126                 break;
127             case CHANNEL_AUDIO_ZONE_CONTROL:
128                 if (command instanceof PlayPauseType playPauseCommand) {
129                     handlePlayPauseCommand(channelUID, playPauseCommand);
130                 } else if (command instanceof NextPreviousType nextPreviousCommand) {
131                     handleNextPreviousCommand(channelUID, nextPreviousCommand);
132                 } else {
133                     logger.debug("Invalid command: {}, must be PlayPauseType or NextPreviousType", command);
134                 }
135                 break;
136             default:
137                 logger.warn("Unknown channel for Audio Zone thing: {}", channelUID);
138         }
139     }
140
141     private void handlePlayPauseCommand(ChannelUID channelUID, PlayPauseType command) {
142         logger.debug("handlePlayPauseCommand called for channel: {}, command: {}", channelUID, command);
143         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
144
145         if (bridgeHandler != null) {
146             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
147             if (audioPlayer.isPresent()) {
148                 AudioPlayer player = audioPlayer.get();
149                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
150                         PlayPauseType.PLAY.equals(command) ? player.getPlayCommand() : player.getPauseCommand(),
151                         thingID);
152             } else {
153                 logger.warn("No Audio Player was detected!");
154             }
155         } else {
156             logger.debug("Received null bridge while sending Audio Zone command!");
157         }
158     }
159
160     private void handleNextPreviousCommand(ChannelUID channelUID, NextPreviousType command) {
161         logger.debug("handleNextPreviousCommand called for channel: {}, command: {}", channelUID, command);
162         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
163
164         if (bridgeHandler != null) {
165             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
166             if (audioPlayer.isPresent()) {
167                 AudioPlayer player = audioPlayer.get();
168                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
169                         NextPreviousType.NEXT.equals(command) ? player.getNextCommand() : player.getPreviousCommand(),
170                         thingID);
171             } else {
172                 logger.warn("Audio Player could not be found!");
173             }
174         } else {
175             logger.debug("Received null bridge while sending Audio Zone command!");
176         }
177     }
178
179     @Override
180     public void updateChannels(ExtendedAudioZoneStatus status) {
181         logger.debug("updateChannels called for Audio Zone status: {}", status);
182         updateState(CHANNEL_AUDIO_ZONE_POWER, OnOffType.from(status.isPower()));
183         updateState(CHANNEL_AUDIO_ZONE_MUTE, OnOffType.from(status.isMute()));
184         updateState(CHANNEL_AUDIO_ZONE_VOLUME, new PercentType(status.getVolume()));
185         updateState(CHANNEL_AUDIO_ZONE_SOURCE, new DecimalType(status.getSource()));
186     }
187
188     @Override
189     protected Optional<ExtendedAudioZoneStatus> retrieveStatus() {
190         try {
191             final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
192             if (bridgeHandler != null) {
193                 ObjectStatus objStatus = bridgeHandler.requestObjectStatus(Message.OBJ_TYPE_AUDIO_ZONE, thingID,
194                         thingID, true);
195                 return Optional.of((ExtendedAudioZoneStatus) objStatus.getStatuses()[0]);
196             } else {
197                 logger.debug("Received null bridge while updating Audio Zone status!");
198                 return Optional.empty();
199             }
200         } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
201             logger.debug("Received exception while refreshing Audio Zone status: {}", e.getMessage());
202             return Optional.empty();
203         }
204     }
205 }