]> git.basschouten.com Git - openhab-addons.git/blob
8d1b1f1571d283921f003d8acc956b26742d0b5a
[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) {
115                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_VOLUME, ((PercentType) command).intValue(),
116                             thingID);
117                 } else {
118                     logger.debug("Invalid command: {}, must be PercentType", command);
119                 }
120                 break;
121             case CHANNEL_AUDIO_ZONE_SOURCE:
122                 if (command instanceof DecimalType) {
123                     sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE, ((DecimalType) command).intValue(),
124                             thingID);
125                 } else {
126                     logger.debug("Invalid command: {}, must be DecimalType", command);
127                 }
128                 break;
129             case CHANNEL_AUDIO_ZONE_CONTROL:
130                 if (command instanceof PlayPauseType) {
131                     handlePlayPauseCommand(channelUID, (PlayPauseType) command);
132                 } else if (command instanceof NextPreviousType) {
133                     handleNextPreviousCommand(channelUID, (NextPreviousType) command);
134                 } else {
135                     logger.debug("Invalid command: {}, must be PlayPauseType or NextPreviousType", command);
136                 }
137                 break;
138             default:
139                 logger.warn("Unknown channel for Audio Zone thing: {}", channelUID);
140         }
141     }
142
143     private void handlePlayPauseCommand(ChannelUID channelUID, PlayPauseType command) {
144         logger.debug("handlePlayPauseCommand called for channel: {}, command: {}", channelUID, command);
145         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
146
147         if (bridgeHandler != null) {
148             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
149             if (audioPlayer.isPresent()) {
150                 AudioPlayer player = audioPlayer.get();
151                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
152                         PlayPauseType.PLAY.equals(command) ? player.getPlayCommand() : player.getPauseCommand(),
153                         thingID);
154             } else {
155                 logger.warn("No Audio Player was detected!");
156             }
157         } else {
158             logger.debug("Received null bridge while sending Audio Zone command!");
159         }
160     }
161
162     private void handleNextPreviousCommand(ChannelUID channelUID, NextPreviousType command) {
163         logger.debug("handleNextPreviousCommand called for channel: {}, command: {}", channelUID, command);
164         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
165
166         if (bridgeHandler != null) {
167             Optional<AudioPlayer> audioPlayer = bridgeHandler.getAudioPlayer();
168             if (audioPlayer.isPresent()) {
169                 AudioPlayer player = audioPlayer.get();
170                 sendOmnilinkCommand(CommandMessage.CMD_AUDIO_ZONE_SET_SOURCE,
171                         NextPreviousType.NEXT.equals(command) ? player.getNextCommand() : player.getPreviousCommand(),
172                         thingID);
173             } else {
174                 logger.warn("Audio Player could not be found!");
175             }
176         } else {
177             logger.debug("Received null bridge while sending Audio Zone command!");
178         }
179     }
180
181     @Override
182     public void updateChannels(ExtendedAudioZoneStatus status) {
183         logger.debug("updateChannels called for Audio Zone status: {}", status);
184         updateState(CHANNEL_AUDIO_ZONE_POWER, OnOffType.from(status.isPower()));
185         updateState(CHANNEL_AUDIO_ZONE_MUTE, OnOffType.from(status.isMute()));
186         updateState(CHANNEL_AUDIO_ZONE_VOLUME, new PercentType(status.getVolume()));
187         updateState(CHANNEL_AUDIO_ZONE_SOURCE, new DecimalType(status.getSource()));
188     }
189
190     @Override
191     protected Optional<ExtendedAudioZoneStatus> retrieveStatus() {
192         try {
193             final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
194             if (bridgeHandler != null) {
195                 ObjectStatus objStatus = bridgeHandler.requestObjectStatus(Message.OBJ_TYPE_AUDIO_ZONE, thingID,
196                         thingID, true);
197                 return Optional.of((ExtendedAudioZoneStatus) objStatus.getStatuses()[0]);
198             } else {
199                 logger.debug("Received null bridge while updating Audio Zone status!");
200                 return Optional.empty();
201             }
202         } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
203             logger.debug("Received exception while refreshing Audio Zone status: {}", e.getMessage());
204             return Optional.empty();
205         }
206     }
207 }