]> git.basschouten.com Git - openhab-addons.git/blob
118cabb70e586ad2faeaf520833aa8277019931c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.amazonechocontrol.internal;
14
15 import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*;
16
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
20 import java.util.Locale;
21 import java.util.Map;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
27 import org.openhab.binding.amazonechocontrol.internal.handler.EchoHandler;
28 import org.openhab.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler;
29 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.BluetoothState;
30 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonBluetoothStates.PairedDevice;
31 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device;
32 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonMusicProvider;
33 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonNotificationSound;
34 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists;
35 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonPlaylists.PlayList;
36 import org.openhab.core.thing.Channel;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingRegistry;
39 import org.openhab.core.thing.ThingUID;
40 import org.openhab.core.thing.binding.ThingHandler;
41 import org.openhab.core.thing.type.ChannelTypeUID;
42 import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
43 import org.openhab.core.types.StateDescription;
44 import org.openhab.core.types.StateDescriptionFragmentBuilder;
45 import org.openhab.core.types.StateOption;
46 import org.osgi.service.component.annotations.Activate;
47 import org.osgi.service.component.annotations.Component;
48 import org.osgi.service.component.annotations.Reference;
49
50 /**
51  * Dynamic channel state description provider.
52  * Overrides the state description for the controls, which receive its configuration in the runtime.
53  *
54  * @author Michael Geramb - Initial contribution
55  */
56 @Component(service = { DynamicStateDescriptionProvider.class, AmazonEchoDynamicStateDescriptionProvider.class })
57 @NonNullByDefault
58 public class AmazonEchoDynamicStateDescriptionProvider implements DynamicStateDescriptionProvider {
59     private final ThingRegistry thingRegistry;
60
61     @Activate
62     public AmazonEchoDynamicStateDescriptionProvider(@Reference ThingRegistry thingRegistry) {
63         this.thingRegistry = thingRegistry;
64     }
65
66     public @Nullable ThingHandler findHandler(Channel channel) {
67         Thing thing = thingRegistry.get(channel.getUID().getThingUID());
68         if (thing == null) {
69             return null;
70         }
71         ThingUID accountThingId = thing.getBridgeUID();
72         if (accountThingId == null) {
73             return null;
74         }
75         Thing accountThing = thingRegistry.get(accountThingId);
76         if (accountThing == null) {
77             return null;
78         }
79         AccountHandler accountHandler = (AccountHandler) accountThing.getHandler();
80         if (accountHandler == null) {
81             return null;
82         }
83         Connection connection = accountHandler.findConnection();
84         if (connection == null || !connection.getIsLoggedIn()) {
85             return null;
86         }
87         return thing.getHandler();
88     }
89
90     @Override
91     public @Nullable StateDescription getStateDescription(Channel channel,
92             @Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
93         ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
94         if (channelTypeUID == null || !BINDING_ID.equals(channelTypeUID.getBindingId())) {
95             return null;
96         }
97         if (originalStateDescription == null) {
98             return null;
99         }
100
101         if (CHANNEL_TYPE_BLUETHOOTH_MAC.equals(channel.getChannelTypeUID())) {
102             EchoHandler handler = (EchoHandler) findHandler(channel);
103             if (handler == null) {
104                 return null;
105             }
106             BluetoothState bluetoothState = handler.findBluetoothState();
107             if (bluetoothState == null) {
108                 return null;
109             }
110             PairedDevice[] pairedDeviceList = bluetoothState.pairedDeviceList;
111             if (pairedDeviceList == null) {
112                 return null;
113             }
114
115             List<StateOption> options = new ArrayList<>();
116             options.add(new StateOption("", ""));
117             for (PairedDevice device : pairedDeviceList) {
118                 if (device == null) {
119                     continue;
120                 }
121                 final String value = device.address;
122                 if (value != null && device.friendlyName != null) {
123                     options.add(new StateOption(value, device.friendlyName));
124                 }
125             }
126             StateDescription result = StateDescriptionFragmentBuilder.create(originalStateDescription)
127                     .withOptions(options).build().toStateDescription();
128             return result;
129         } else if (CHANNEL_TYPE_AMAZON_MUSIC_PLAY_LIST_ID.equals(channel.getChannelTypeUID())) {
130             EchoHandler handler = (EchoHandler) findHandler(channel);
131             if (handler == null) {
132                 return null;
133             }
134
135             JsonPlaylists playLists = handler.findPlaylists();
136             if (playLists == null) {
137                 return null;
138             }
139
140             List<StateOption> options = new ArrayList<>();
141             options.add(new StateOption("", ""));
142             Map<String, PlayList @Nullable []> playlistMap = playLists.playlists;
143             if (playlistMap != null) {
144                 for (PlayList[] innerLists : playlistMap.values()) {
145                     if (innerLists != null && innerLists.length > 0) {
146                         PlayList playList = innerLists[0];
147                         final String value = playList.playlistId;
148                         if (value != null && playList.title != null) {
149                             options.add(new StateOption(value,
150                                     String.format("%s (%d)", playList.title, playList.trackCount)));
151                         }
152                     }
153                 }
154             }
155             StateDescription result = StateDescriptionFragmentBuilder.create(originalStateDescription)
156                     .withOptions(options).build().toStateDescription();
157             return result;
158         } else if (CHANNEL_TYPE_PLAY_ALARM_SOUND.equals(channel.getChannelTypeUID())) {
159             EchoHandler handler = (EchoHandler) findHandler(channel);
160             if (handler == null) {
161                 return null;
162             }
163
164             JsonNotificationSound[] notificationSounds = handler.findAlarmSounds();
165             if (notificationSounds == null) {
166                 return null;
167             }
168
169             List<StateOption> options = new ArrayList<>();
170             options.add(new StateOption("", ""));
171
172             for (JsonNotificationSound notificationSound : notificationSounds) {
173                 if (notificationSound != null && notificationSound.folder == null
174                         && notificationSound.providerId != null && notificationSound.id != null
175                         && notificationSound.displayName != null) {
176                     String providerSoundId = notificationSound.providerId + ":" + notificationSound.id;
177                     options.add(new StateOption(providerSoundId, notificationSound.displayName));
178                 }
179             }
180             StateDescription result = StateDescriptionFragmentBuilder.create(originalStateDescription)
181                     .withOptions(options).build().toStateDescription();
182             return result;
183         } else if (CHANNEL_TYPE_CHANNEL_PLAY_ON_DEVICE.equals(channel.getChannelTypeUID())) {
184             FlashBriefingProfileHandler handler = (FlashBriefingProfileHandler) findHandler(channel);
185             if (handler == null) {
186                 return null;
187             }
188             AccountHandler accountHandler = handler.findAccountHandler();
189             if (accountHandler == null) {
190                 return null;
191             }
192             List<Device> devices = accountHandler.getLastKnownDevices();
193             if (devices.isEmpty()) {
194                 return null;
195             }
196
197             List<StateOption> options = new ArrayList<>();
198             options.add(new StateOption("", ""));
199             for (Device device : devices) {
200                 final String value = device.serialNumber;
201                 if (value != null && device.capabilities != null
202                         && Arrays.asList(device.capabilities).contains("FLASH_BRIEFING")) {
203                     options.add(new StateOption(value, device.accountName));
204                 }
205             }
206             return StateDescriptionFragmentBuilder.create(originalStateDescription).withOptions(options).build()
207                     .toStateDescription();
208         } else if (CHANNEL_TYPE_MUSIC_PROVIDER_ID.equals(channel.getChannelTypeUID())) {
209             EchoHandler handler = (EchoHandler) findHandler(channel);
210             if (handler == null) {
211                 return null;
212             }
213             List<JsonMusicProvider> musicProviders = handler.findMusicProviders();
214             if (musicProviders == null) {
215                 return null;
216             }
217
218             List<StateOption> options = new ArrayList<>();
219             for (JsonMusicProvider musicProvider : musicProviders) {
220                 List<String> properties = musicProvider.supportedProperties;
221                 String providerId = musicProvider.id;
222                 String displayName = musicProvider.displayName;
223                 if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase")
224                         && StringUtils.isNotEmpty(providerId)
225                         && StringUtils.equals(musicProvider.availability, "AVAILABLE")
226                         && StringUtils.isNotEmpty(displayName) && providerId != null) {
227                     options.add(new StateOption(providerId, displayName));
228                 }
229             }
230             return StateDescriptionFragmentBuilder.create(originalStateDescription).withOptions(options).build()
231                     .toStateDescription();
232         } else if (CHANNEL_TYPE_START_COMMAND.equals(channel.getChannelTypeUID())) {
233             EchoHandler handler = (EchoHandler) findHandler(channel);
234             if (handler == null) {
235                 return null;
236             }
237             AccountHandler account = handler.findAccount();
238             if (account == null) {
239                 return null;
240             }
241             List<FlashBriefingProfileHandler> flashbriefings = account.getFlashBriefingProfileHandlers();
242             if (flashbriefings.isEmpty()) {
243                 return null;
244             }
245
246             List<StateOption> options = new ArrayList<>();
247             options.addAll(originalStateDescription.getOptions());
248
249             for (FlashBriefingProfileHandler flashBriefing : flashbriefings) {
250                 String value = FLASH_BRIEFING_COMMAND_PREFIX + flashBriefing.getThing().getUID().getId();
251                 String displayName = flashBriefing.getThing().getLabel();
252                 options.add(new StateOption(value, displayName));
253             }
254             return StateDescriptionFragmentBuilder.create(originalStateDescription).withOptions(options).build()
255                     .toStateDescription();
256         }
257         return null;
258     }
259 }