2 * Copyright (c) 2010-2021 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.*;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
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;
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;
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.
48 * @author Brian O'Connell - Initial contribution
49 * @author Ethan Dye - openHAB3 rewrite
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;
59 public AudioSourceHandler(Thing thing) {
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);
72 logger.debug("Autostart disabled, not scheduling polling for Audio Source: {}", thingID);
75 updateAudioSourceProperties(bridgeHandler);
77 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
78 "Received null bridge while initializing Audio Source!");
82 private void updateAudioSourceProperties(OmnilinkBridgeHandler bridgeHandler) {
83 ObjectPropertyRequest<AudioSourceProperties> objectPropertyRequest = ObjectPropertyRequest
84 .builder(bridgeHandler, ObjectPropertyRequests.AUDIO_SOURCE, thingID, 0).selectNamed().build();
86 for (AudioSourceProperties audioSourceProperties : objectPropertyRequest) {
87 Map<String, String> properties = editProperties();
88 properties.put(THING_PROPERTIES_NAME, audioSourceProperties.getName());
89 updateProperties(properties);
94 public synchronized void dispose() {
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);
107 private synchronized void schedulePolling() {
109 logger.debug("Scheduling polling for Audio Source: {}", thingID);
110 scheduledPolling = super.scheduler.scheduleWithFixedDelay(this::pollAudioSource, 0, POLL_DELAY_SECONDS,
115 public void handleCommand(ChannelUID channelUID, Command command) {
116 logger.debug("handleCommand called for channel: {}, command: {}", channelUID, command);
117 final ScheduledFuture<?> scheduledPolling = this.scheduledPolling;
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);
127 logger.debug("Invalid command: {}, must be RefreshType or OnOffType", command);
131 logger.warn("Unknown channel for Audio Source thing: {}", channelUID);
135 private void handlePolling(ChannelUID channelUID, OnOffType command) {
136 logger.debug("handlePolling called for channel: {}, command: {}", channelUID, command);
137 if (OnOffType.ON.equals(command)) {
144 public void pollAudioSource() {
146 final OmnilinkBridgeHandler bridge = getOmnilinkBridgeHandler();
147 if (bridge != null) {
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();
157 updateState(CHANNEL_AUDIO_SOURCE_TEXT1, new StringType(audioSourceStatus.getSourceData()));
160 updateState(CHANNEL_AUDIO_SOURCE_TEXT2, new StringType(audioSourceStatus.getSourceData()));
163 updateState(CHANNEL_AUDIO_SOURCE_TEXT3, new StringType(audioSourceStatus.getSourceData()));
166 updateState(CHANNEL_AUDIO_SOURCE_TEXT4, new StringType(audioSourceStatus.getSourceData()));
169 updateState(CHANNEL_AUDIO_SOURCE_TEXT5, new StringType(audioSourceStatus.getSourceData()));
172 updateState(CHANNEL_AUDIO_SOURCE_TEXT6, new StringType(audioSourceStatus.getSourceData()));
177 logger.debug("Received null bridge while polling Audio Source statuses!");
179 } catch (OmniInvalidResponseException | OmniUnknownMessageTypeException | BridgeOfflineException e) {
180 logger.debug("Exception recieved while polling for Audio Source statuses: {}", e.getMessage());