]> git.basschouten.com Git - openhab-addons.git/blob
e5501cc60be1005cf290922b50fcbb7534d44922
[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.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
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.OnOffType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.RefreshType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.digitaldan.jomnilinkII.Message;
38 import com.digitaldan.jomnilinkII.MessageTypes.AudioSourceStatus;
39 import com.digitaldan.jomnilinkII.MessageTypes.properties.AudioSourceProperties;
40 import com.digitaldan.jomnilinkII.OmniInvalidResponseException;
41 import com.digitaldan.jomnilinkII.OmniUnknownMessageTypeException;
42
43 /**
44  * The {@link AudioSourceHandler} defines some methods that are used to
45  * interface with an OmniLink Audio Source. This by extension also defines the
46  * Audio Source thing that openHAB will be able to pick up and interface with.
47  *
48  * @author Brian O'Connell - Initial contribution
49  * @author Ethan Dye - openHAB3 rewrite
50  */
51 @NonNullByDefault
52 public class AudioSourceHandler extends AbstractOmnilinkHandler {
53     private final Logger logger = LoggerFactory.getLogger(AudioSourceHandler.class);
54     private final int POLL_DELAY_SECONDS = 5;
55     private final int thingID = getThingNumber();
56     private @Nullable ScheduledFuture<?> scheduledPolling = null;
57     public @Nullable String number;
58
59     public AudioSourceHandler(Thing thing) {
60         super(thing);
61     }
62
63     @Override
64     public void initialize() {
65         final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
66         if (bridgeHandler != null) {
67             updateStatus(ThingStatus.ONLINE);
68             if (((Boolean) getThing().getConfiguration().get(THING_PROPERTIES_AUTO_START)).booleanValue()) {
69                 logger.debug("Autostart enabled, scheduling polling for Audio Source: {}", thingID);
70                 schedulePolling();
71             } else {
72                 logger.debug("Autostart disabled, not scheduling polling for Audio Source: {}", thingID);
73                 cancelPolling();
74             }
75             updateAudioSourceProperties(bridgeHandler);
76         } else {
77             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
78                     "Received null bridge while initializing Audio Source!");
79         }
80     }
81
82     private void updateAudioSourceProperties(OmnilinkBridgeHandler bridgeHandler) {
83         ObjectPropertyRequest<AudioSourceProperties> objectPropertyRequest = ObjectPropertyRequest
84                 .builder(bridgeHandler, ObjectPropertyRequests.AUDIO_SOURCE, thingID, 0).selectNamed().build();
85
86         for (AudioSourceProperties audioSourceProperties : objectPropertyRequest) {
87             Map<String, String> properties = editProperties();
88             properties.put(THING_PROPERTIES_NAME, audioSourceProperties.getName());
89             updateProperties(properties);
90         }
91     }
92
93     @Override
94     public synchronized void dispose() {
95         cancelPolling();
96         super.dispose();
97     }
98
99     private synchronized void cancelPolling() {
100         final ScheduledFuture<?> scheduledPolling = this.scheduledPolling;
101         if (scheduledPolling != null) {
102             logger.debug("Cancelling polling for Audio Source: {}", thingID);
103             scheduledPolling.cancel(false);
104         }
105     }
106
107     private synchronized void schedulePolling() {
108         cancelPolling();
109         logger.debug("Scheduling polling for Audio Source: {}", thingID);
110         scheduledPolling = super.scheduler.scheduleWithFixedDelay(this::pollAudioSource, 0, POLL_DELAY_SECONDS,
111                 TimeUnit.SECONDS);
112     }
113
114     @Override
115     public void handleCommand(ChannelUID channelUID, Command command) {
116         logger.debug("handleCommand called for channel: {}, command: {}", channelUID, command);
117         final ScheduledFuture<?> scheduledPolling = this.scheduledPolling;
118
119         switch (channelUID.getId()) {
120             case CHANNEL_AUDIO_SOURCE_POLLING:
121                 if (command instanceof RefreshType) {
122                     updateState(CHANNEL_AUDIO_SOURCE_POLLING,
123                             OnOffType.from((scheduledPolling != null && !scheduledPolling.isDone())));
124                 } else if (command instanceof OnOffType) {
125                     handlePolling(channelUID, (OnOffType) command);
126                 } else {
127                     logger.debug("Invalid command: {}, must be RefreshType or OnOffType", command);
128                 }
129                 break;
130             default:
131                 logger.warn("Unknown channel for Audio Source thing: {}", channelUID);
132         }
133     }
134
135     private void handlePolling(ChannelUID channelUID, OnOffType command) {
136         logger.debug("handlePolling called for channel: {}, command: {}", channelUID, command);
137         if (OnOffType.ON.equals(command)) {
138             schedulePolling();
139         } else {
140             cancelPolling();
141         }
142     }
143
144     public void pollAudioSource() {
145         try {
146             final OmnilinkBridgeHandler bridge = getOmnilinkBridgeHandler();
147             if (bridge != null) {
148                 Message message;
149                 int position = 0;
150                 while ((message = bridge.requestAudioSourceStatus(thingID, position))
151                         .getMessageType() == Message.MESG_TYPE_AUDIO_SOURCE_STATUS) {
152                     logger.trace("Polling for Audio Source statuses on thing: {}", thingID);
153                     AudioSourceStatus audioSourceStatus = (AudioSourceStatus) message;
154                     position = audioSourceStatus.getPosition();
155                     switch (position) {
156                         case 1:
157                             updateState(CHANNEL_AUDIO_SOURCE_TEXT1, new StringType(audioSourceStatus.getSourceData()));
158                             break;
159                         case 2:
160                             updateState(CHANNEL_AUDIO_SOURCE_TEXT2, new StringType(audioSourceStatus.getSourceData()));
161                             break;
162                         case 3:
163                             updateState(CHANNEL_AUDIO_SOURCE_TEXT3, new StringType(audioSourceStatus.getSourceData()));
164                             break;
165                         case 4:
166                             updateState(CHANNEL_AUDIO_SOURCE_TEXT4, new StringType(audioSourceStatus.getSourceData()));
167                             break;
168                         case 5:
169                             updateState(CHANNEL_AUDIO_SOURCE_TEXT5, new StringType(audioSourceStatus.getSourceData()));
170                             break;
171                         case 6:
172                             updateState(CHANNEL_AUDIO_SOURCE_TEXT6, new StringType(audioSourceStatus.getSourceData()));
173                             break;
174                     }
175                 }
176             } else {
177                 logger.debug("Received null bridge while polling Audio Source statuses!");
178             }
179         } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
180             logger.debug("Exception recieved while polling for Audio Source statuses: {}", e.getMessage());
181         }
182     }
183 }