]> git.basschouten.com Git - openhab-addons.git/commitdiff
[androidTV] fix version parsing for newer Philips TV models (#17373)
authorMarcel <marcel@verpaalen.com>
Mon, 9 Sep 2024 12:48:24 +0000 (14:48 +0200)
committerGitHub <noreply@github.com>
Mon, 9 Sep 2024 12:48:24 +0000 (14:48 +0200)
* [androidTV] fix version parsing for newer Philips TV models

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/TvChannelService.java
bundles/org.openhab.binding.androidtv/src/main/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/model/channel/AvailableTvChannelsDTO.java
bundles/org.openhab.binding.androidtv/src/test/java/org/openhab/binding/androidtv/internal/protocol/philipstv/service/PhilipsTvChannelTest.java [new file with mode: 0644]

index e0479e5630e43dc80dcad3edcf4eb3f69aaab7b0..f39b3f8242f9e0d2156be435acf144df5c3e8c8a 100644 (file)
  */
 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<String, String> 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<String, String> tvChannelsMap = availableTvChannelsDTO.getChannel().stream()
-                .collect(Collectors.toConcurrentMap(ChannelDTO::getName, ChannelDTO::getCcid, (c1, c2) -> c1));
+            ConcurrentMap<String, String> 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 {
index fc10fd820cf76f66486fdf102ae6b7da619a80d9..bb1d7c376f7fa2aff954bff0bf1826f1f643019f 100644 (file)
@@ -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 (file)
index 0000000..1a0fde8
--- /dev/null
@@ -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<String, String> availableTvChannels = Collections.emptyMap();
+
+        TvChannelService tvChannelService = new TvChannelService(handler, connectionManager);
+        tvChannelService.handleCommand(channel, command);
+        ArgumentCaptor<Map<String, String>> 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<String> 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);
+        }
+    }
+}