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