]> git.basschouten.com Git - openhab-addons.git/blob
53ae7fb3c39aa532d21e0daaf95399f208c649fc
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.androidtv.internal.protocol.philipstv.service;
14
15 import static org.openhab.binding.androidtv.internal.AndroidTVBindingConstants.*;
16 import static org.openhab.binding.androidtv.internal.protocol.philipstv.ConnectionManager.OBJECT_MAPPER;
17 import static org.openhab.binding.androidtv.internal.protocol.philipstv.PhilipsTVBindingConstants.*;
18
19 import java.io.IOException;
20 import java.util.Map;
21 import java.util.Optional;
22 import java.util.concurrent.ConcurrentMap;
23 import java.util.function.Function;
24 import java.util.stream.Collectors;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.androidtv.internal.protocol.philipstv.ConnectionManager;
29 import org.openhab.binding.androidtv.internal.protocol.philipstv.PhilipsTVConnectionManager;
30 import org.openhab.binding.androidtv.internal.protocol.philipstv.service.api.PhilipsTVService;
31 import org.openhab.binding.androidtv.internal.protocol.philipstv.service.model.channel.AvailableTvChannelsDTO;
32 import org.openhab.binding.androidtv.internal.protocol.philipstv.service.model.channel.ChannelDTO;
33 import org.openhab.binding.androidtv.internal.protocol.philipstv.service.model.channel.ChannelListDTO;
34 import org.openhab.binding.androidtv.internal.protocol.philipstv.service.model.channel.TvChannelDTO;
35 import org.openhab.core.library.types.StringType;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingStatusDetail;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.RefreshType;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Service for handling commands regarding setting or retrieving the TV channel
45  *
46  * @author Benjamin Meyer - Initial contribution
47  * @author Ben Rosenblum - Merged into AndroidTV
48  */
49 @NonNullByDefault
50 public class TvChannelService implements PhilipsTVService {
51
52     private final Logger logger = LoggerFactory.getLogger(getClass());
53
54     // Name , ccid of TV Channel
55     private @Nullable Map<String, String> availableTvChannels;
56
57     private final PhilipsTVConnectionManager handler;
58
59     private final ConnectionManager connectionManager;
60
61     public TvChannelService(PhilipsTVConnectionManager handler, ConnectionManager connectionManager) {
62         this.handler = handler;
63         this.connectionManager = connectionManager;
64     }
65
66     @Override
67     public void handleCommand(String channel, Command command) {
68         try {
69             synchronized (this) {
70                 if (isTvChannelListEmpty()) {
71                     availableTvChannels = getAvailableTvChannelListFromTv();
72                     handler.updateChannelStateDescription(CHANNEL_TV_CHANNEL, availableTvChannels.keySet().stream()
73                             .collect(Collectors.toMap(Function.identity(), Function.identity())));
74                 }
75             }
76             if (command instanceof RefreshType) {
77                 // Get current tv channel name
78                 String tvChannelName = getCurrentTvChannel();
79                 handler.postUpdateChannel(CHANNEL_TV_CHANNEL, new StringType(tvChannelName));
80             } else if (command instanceof StringType) {
81                 if (availableTvChannels.containsKey(command.toString())) {
82                     switchTvChannel(command);
83                 } else {
84                     logger.warn(
85                             "The given TV Channel with Name: {} couldn't be found in the local Channel List from the TV.",
86                             command);
87                 }
88             } else {
89                 logger.warn("Unknown command: {} for Channel {}", command, channel);
90             }
91         } catch (Exception e) {
92             if (isTvOfflineException(e)) {
93                 logger.warn("Could not execute command for TV Channels, the TV is offline.");
94                 handler.postUpdateThing(ThingStatus.OFFLINE, ThingStatusDetail.NONE, TV_OFFLINE_MSG);
95             } else if (isTvNotListeningException(e)) {
96                 handler.postUpdateThing(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
97                         TV_NOT_LISTENING_MSG);
98             } else {
99                 logger.warn("Error occurred during handling of command for TV Channels: {}", e.getMessage(), e);
100             }
101         }
102     }
103
104     private boolean isTvChannelListEmpty() {
105         return (availableTvChannels == null) || availableTvChannels.isEmpty();
106     }
107
108     private Map<String, String> getAvailableTvChannelListFromTv() throws IOException {
109         AvailableTvChannelsDTO availableTvChannelsDTO = OBJECT_MAPPER.readValue(
110                 connectionManager.doHttpsGet(GET_AVAILABLE_TV_CHANNEL_LIST_PATH), AvailableTvChannelsDTO.class);
111
112         ConcurrentMap<String, String> tvChannelsMap = availableTvChannelsDTO.getChannel().stream()
113                 .collect(Collectors.toConcurrentMap(ChannelDTO::getName, ChannelDTO::getCcid, (c1, c2) -> c1));
114
115         logger.debug("TV Channels added: {}", tvChannelsMap.size());
116         if (logger.isTraceEnabled()) {
117             tvChannelsMap.keySet().forEach(app -> logger.trace("TV Channel found: {}", app));
118         }
119         return tvChannelsMap;
120     }
121
122     private String getCurrentTvChannel() throws IOException {
123         TvChannelDTO tvChannelDTO = OBJECT_MAPPER.readValue(connectionManager.doHttpsGet(TV_CHANNEL_PATH),
124                 TvChannelDTO.class);
125         return Optional.ofNullable(tvChannelDTO.getChannel()).map(ChannelDTO::getName).orElse("NA");
126     }
127
128     private void switchTvChannel(Command command) throws IOException {
129         ChannelDTO channelDTO = new ChannelDTO();
130         channelDTO.setCcid(availableTvChannels.get(command.toString()));
131
132         ChannelListDTO channelListDTO = new ChannelListDTO();
133         channelListDTO.setId("allter");
134         channelListDTO.setVersion("30");
135
136         TvChannelDTO tvChannelDTO = new TvChannelDTO(channelDTO, channelListDTO);
137         String switchTvChannelJson = OBJECT_MAPPER.writeValueAsString(tvChannelDTO);
138         logger.debug("Switch TV Channel json: {}", switchTvChannelJson);
139         connectionManager.doHttpsPost(TV_CHANNEL_PATH, switchTvChannelJson);
140     }
141
142     public void clearAvailableTvChannelList() {
143         if (availableTvChannels != null) {
144             availableTvChannels.clear();
145         }
146     }
147 }