2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.omnilink.internal.handler;
15 import static org.openhab.binding.omnilink.internal.OmnilinkBindingConstants.*;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
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.OnOffType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.types.Command;
32 import org.openhab.core.types.RefreshType;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import com.digitaldan.jomnilinkII.Message;
37 import com.digitaldan.jomnilinkII.MessageTypes.AudioSourceStatus;
38 import com.digitaldan.jomnilinkII.MessageTypes.properties.AudioSourceProperties;
39 import com.digitaldan.jomnilinkII.OmniInvalidResponseException;
40 import com.digitaldan.jomnilinkII.OmniUnknownMessageTypeException;
43 * The {@link AudioSourceHandler} defines some methods that are used to
44 * interface with an OmniLink Audio Source. This by extension also defines the
45 * Audio Source thing that openHAB will be able to pick up and interface with.
47 * @author Brian O'Connell - Initial contribution
48 * @author Ethan Dye - openHAB3 rewrite
51 public class AudioSourceHandler extends AbstractOmnilinkHandler {
52 private final Logger logger = LoggerFactory.getLogger(AudioSourceHandler.class);
53 private final int pollDelaySeconds = 5;
54 private final int thingID = getThingNumber();
55 private @Nullable ScheduledFuture<?> scheduledPolling = null;
56 public @Nullable String number;
58 public AudioSourceHandler(Thing thing) {
63 public void initialize() {
64 final OmnilinkBridgeHandler bridgeHandler = getOmnilinkBridgeHandler();
65 if (bridgeHandler != null) {
66 updateStatus(ThingStatus.ONLINE);
67 if (((Boolean) getThing().getConfiguration().get(THING_PROPERTIES_AUTOSTART)).booleanValue()) {
68 logger.debug("Autostart enabled, scheduling polling for Audio Source: {}", thingID);
71 logger.debug("Autostart disabled, not scheduling polling for Audio Source: {}", thingID);
74 updateAudioSourceProperties(bridgeHandler);
76 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
77 "Received null bridge while initializing Audio Source!");
81 private void updateAudioSourceProperties(OmnilinkBridgeHandler bridgeHandler) {
82 ObjectPropertyRequest<AudioSourceProperties> objectPropertyRequest = ObjectPropertyRequest
83 .builder(bridgeHandler, ObjectPropertyRequests.AUDIO_SOURCE, thingID, 0).selectNamed().build();
85 for (AudioSourceProperties audioSourceProperties : objectPropertyRequest) {
86 updateProperty(THING_PROPERTIES_NAME, audioSourceProperties.getName());
91 public synchronized void dispose() {
96 private synchronized void cancelPolling() {
97 final ScheduledFuture<?> scheduledPolling = this.scheduledPolling;
98 if (scheduledPolling != null) {
99 logger.debug("Cancelling polling for Audio Source: {}", thingID);
100 scheduledPolling.cancel(false);
104 private synchronized void schedulePolling() {
106 logger.debug("Scheduling polling for Audio Source: {}", thingID);
107 scheduledPolling = super.scheduler.scheduleWithFixedDelay(this::pollAudioSource, 0, pollDelaySeconds,
112 public void handleCommand(ChannelUID channelUID, Command command) {
113 logger.debug("handleCommand called for channel: {}, command: {}", channelUID, command);
114 final ScheduledFuture<?> scheduledPolling = this.scheduledPolling;
116 switch (channelUID.getId()) {
117 case CHANNEL_AUDIO_SOURCE_POLLING:
118 if (command instanceof RefreshType) {
119 updateState(CHANNEL_AUDIO_SOURCE_POLLING,
120 OnOffType.from((scheduledPolling != null && !scheduledPolling.isDone())));
121 } else if (command instanceof OnOffType) {
122 handlePolling(channelUID, (OnOffType) command);
124 logger.debug("Invalid command: {}, must be RefreshType or OnOffType", command);
128 logger.warn("Unknown channel for Audio Source thing: {}", channelUID);
132 private void handlePolling(ChannelUID channelUID, OnOffType command) {
133 logger.debug("handlePolling called for channel: {}, command: {}", channelUID, command);
134 if (OnOffType.ON.equals(command)) {
141 public void pollAudioSource() {
143 final OmnilinkBridgeHandler bridge = getOmnilinkBridgeHandler();
144 if (bridge != null) {
147 while ((message = bridge.requestAudioSourceStatus(thingID, position))
148 .getMessageType() == Message.MESG_TYPE_AUDIO_SOURCE_STATUS) {
149 logger.trace("Polling for Audio Source statuses on thing: {}", thingID);
150 AudioSourceStatus audioSourceStatus = (AudioSourceStatus) message;
151 position = audioSourceStatus.getPosition();
154 updateState(CHANNEL_AUDIO_SOURCE_TEXT1, new StringType(audioSourceStatus.getSourceData()));
157 updateState(CHANNEL_AUDIO_SOURCE_TEXT2, new StringType(audioSourceStatus.getSourceData()));
160 updateState(CHANNEL_AUDIO_SOURCE_TEXT3, new StringType(audioSourceStatus.getSourceData()));
163 updateState(CHANNEL_AUDIO_SOURCE_TEXT4, new StringType(audioSourceStatus.getSourceData()));
166 updateState(CHANNEL_AUDIO_SOURCE_TEXT5, new StringType(audioSourceStatus.getSourceData()));
169 updateState(CHANNEL_AUDIO_SOURCE_TEXT6, new StringType(audioSourceStatus.getSourceData()));
174 logger.debug("Received null bridge while polling Audio Source statuses!");
176 } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
177 logger.debug("Exception recieved while polling for Audio Source statuses: {}", e.getMessage());