From bdf780d575aae3474bc8fb831f5dd8c90c696dac Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 9 Sep 2024 14:48:24 +0200 Subject: [PATCH] [androidTV] fix version parsing for newer Philips TV models (#17373) * [androidTV] fix version parsing for newer Philips TV models Signed-off-by: Marcel Verpaalen Signed-off-by: Ciprian Pascu --- .../philipstv/service/TvChannelService.java | 26 +++-- .../model/channel/AvailableTvChannelsDTO.java | 6 +- .../service/PhilipsTvChannelTest.java | 103 ++++++++++++++++++ 3 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 bundles/org.openhab.binding.androidtv/src/test/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/PhilipsTvChannelTest.java diff --git a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/TvChannelService.java b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/TvChannelService.java index e0479e5630e..f39b3f8242f 100644 --- a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/TvChannelService.java +++ b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/TvChannelService.java @@ -12,11 +12,12 @@ */ package org.openhab.binding.androidtv.internal.protocol.philipstv.service; -import static org.openhab.binding.androidtv.internal.AndroidTVBindingConstants.*; +import static org.openhab.binding.androidtv.internal.AndroidTVBindingConstants.CHANNEL_TV_CHANNEL; import static org.openhab.binding.androidtv.internal.protocol.philipstv.ConnectionManager.OBJECT_MAPPER; import static org.openhab.binding.androidtv.internal.protocol.philipstv.PhilipsTVBindingConstants.*; import java.io.IOException; +import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -39,6 +40,8 @@ import org.openhab.core.types.RefreshType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; + /** * Service for handling commands regarding setting or retrieving the TV channel * @@ -105,17 +108,22 @@ public class TvChannelService implements PhilipsTVService { } private Map getAvailableTvChannelListFromTv() throws IOException { - AvailableTvChannelsDTO availableTvChannelsDTO = OBJECT_MAPPER.readValue( - connectionManager.doHttpsGet(GET_AVAILABLE_TV_CHANNEL_LIST_PATH), AvailableTvChannelsDTO.class); + try { + AvailableTvChannelsDTO availableTvChannelsDTO = OBJECT_MAPPER.readValue( + connectionManager.doHttpsGet(GET_AVAILABLE_TV_CHANNEL_LIST_PATH), AvailableTvChannelsDTO.class); - ConcurrentMap tvChannelsMap = availableTvChannelsDTO.getChannel().stream() - .collect(Collectors.toConcurrentMap(ChannelDTO::getName, ChannelDTO::getCcid, (c1, c2) -> c1)); + ConcurrentMap tvChannelsMap = availableTvChannelsDTO.getChannel().stream() + .collect(Collectors.toConcurrentMap(ChannelDTO::getName, ChannelDTO::getCcid, (c1, c2) -> c1)); - logger.debug("TV Channels added: {}", tvChannelsMap.size()); - if (logger.isTraceEnabled()) { - tvChannelsMap.keySet().forEach(app -> logger.trace("TV Channel found: {}", app)); + logger.debug("TV Channels added: {}", tvChannelsMap.size()); + if (logger.isTraceEnabled()) { + tvChannelsMap.keySet().forEach(app -> logger.trace("TV Channel found: {}", app)); + } + return tvChannelsMap; + } catch (InvalidFormatException e) { + logger.debug("TV Channels loading failed: {}", e.getMessage(), e); } - return tvChannelsMap; + return Collections.emptyMap(); } private String getCurrentTvChannel() throws IOException { diff --git a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/model/channel/AvailableTvChannelsDTO.java b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/model/channel/AvailableTvChannelsDTO.java index fc10fd820cf..bb1d7c376f7 100644 --- a/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/model/channel/AvailableTvChannelsDTO.java +++ b/bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/model/channel/AvailableTvChannelsDTO.java @@ -37,7 +37,7 @@ public class AvailableTvChannelsDTO { private String medium = ""; @JsonProperty("version") - private int version; + private String version; @JsonProperty("listType") private String listType = ""; @@ -75,11 +75,11 @@ public class AvailableTvChannelsDTO { return medium; } - public void setVersion(int version) { + public void setVersion(String version) { this.version = version; } - public int getVersion() { + public String getVersion() { return version; } diff --git a/bundles/org.openhab.binding.androidtv/src/test/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/PhilipsTvChannelTest.java b/bundles/org.openhab.binding.androidtv/src/test/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/PhilipsTvChannelTest.java new file mode 100644 index 00000000000..1a0fde8a12f --- /dev/null +++ b/bundles/org.openhab.binding.androidtv/src/test/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/PhilipsTvChannelTest.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.androidtv.internal.protocol.philipstv.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.openhab.binding.androidtv.internal.AndroidTVBindingConstants.CHANNEL_TV_CHANNEL; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.openhab.binding.androidtv.internal.protocol.philipstv.ConnectionManager; +import org.openhab.binding.androidtv.internal.protocol.philipstv.PhilipsTVConnectionManager; +import org.openhab.core.library.types.StringType; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link PhilipsTvChannelTest} is responsible for testing {@linkTvChannelService} + * + * @author Marcel Verpaalen - Initial contribution + * + */ + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +@NonNullByDefault +public class PhilipsTvChannelTest { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private @Mock @NonNullByDefault({}) PhilipsTVConnectionManager handler; + private @Mock @NonNullByDefault({}) ConnectionManager connectionManager; + + static final String NEW_RESPONSE = "{\"version\":\"84384_293_1\",\"id\":\"all\",\"listType\":\"MixedSources\",\"medium\":\"mixed\",\"operator\":\"Ziggo\",\"installCountry\":\"Netherlands\",\"Channel\":[{\"ccid\":142,\"preset\":\"1\",\"name\":\"NPO 1\",\"onid\":1536,\"tsid\":2098,\"sid\":19401,\"serviceType\":\"audio_video\",\"type\":\"DVB_C\",\"logoVersion\":142},{\"ccid\":143,\"preset\":\"2\",\"name\":\"NPO 2\",\"onid\":1536,\"tsid\":2098,\"sid\":19402,\"serviceType\":\"audio_video\",\"type\":\"DVB_C\",\"logoVersion\":143}]}"; + static final String OLD_RESPONSE = "{\"version\":123,\"id\":\"all\",\"listType\":\"MixedSources\",\"medium\":\"mixed\",\"operator\":\"Ziggo\",\"installCountry\":\"Netherlands\",\"Channel\":[{\"ccid\":142,\"preset\":\"1\",\"name\":\"NPO 1\",\"onid\":1536,\"tsid\":2098,\"sid\":19401,\"serviceType\":\"audio_video\",\"type\":\"DVB_C\",\"logoVersion\":142},{\"ccid\":143,\"preset\":\"2\",\"name\":\"NPO 2\",\"onid\":1536,\"tsid\":2098,\"sid\":19402,\"serviceType\":\"audio_video\",\"type\":\"DVB_C\",\"logoVersion\":143}]}"; + static final String TEST_CHANNEL = "NPO 2"; + + private void testPhilipsTVChannelParsing(String channel, Command command, String ccid) throws IOException { + Map availableTvChannels = Collections.emptyMap(); + + TvChannelService tvChannelService = new TvChannelService(handler, connectionManager); + tvChannelService.handleCommand(channel, command); + ArgumentCaptor> captor = ArgumentCaptor.forClass(Map.class); + verify(handler, atLeastOnce()).updateChannelStateDescription(ArgumentMatchers.eq(CHANNEL_TV_CHANNEL), + captor.capture()); + availableTvChannels = captor.getValue(); + logger.info("Channels found: {}", availableTvChannels); + assertEquals(2, availableTvChannels.size()); + assertEquals(TEST_CHANNEL, availableTvChannels.get(TEST_CHANNEL)); + + ArgumentCaptor captorSwitchChannel = ArgumentCaptor.forClass(String.class); + verify(connectionManager, atLeastOnce()).doHttpsPost(any(), captorSwitchChannel.capture()); + String changeChannelJson = captorSwitchChannel.getValue(); + logger.info("Channel change command: {}", changeChannelJson); + assertEquals("{\"channel\":{\"serviceType\":\"\",\"logoVersion\":0,\"ccid\":\"" + ccid + + "\",\"name\":\"\",\"preset\":\"\",\"tsid\":0,\"type\":\"\",\"onid\":0,\"sid\":0},\"channelList\":{\"id\":\"allter\",\"version\":\"30\"}}", + changeChannelJson); + } + + @Test + public void testNewerPhilipsTVChannelParsing() { + try { + // test compatibility with newer Philips TV's that provide the version as string + when(connectionManager.doHttpsGet(any())).thenReturn(NEW_RESPONSE); + testPhilipsTVChannelParsing(TEST_CHANNEL, new StringType(TEST_CHANNEL), "143"); + } catch (IOException e) { + logger.warn("Test Failed with", e); + } + } + + @Test + public void testOlderPhilipsTVChannelParsing() { + try { + // test compatibility with older Philips TV's that provide the version as int + when(connectionManager.doHttpsGet(any())).thenReturn(OLD_RESPONSE); + testPhilipsTVChannelParsing("NPO 1", new StringType("NPO 1"), "142"); + } catch (IOException e) { + logger.warn("Test Failed with", e); + } + } +}