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