2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.heos.internal.json;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute.*;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.junit.jupiter.api.Test;
22 import org.openhab.binding.heos.internal.json.dto.HeosCommand;
23 import org.openhab.binding.heos.internal.json.dto.HeosCommandGroup;
24 import org.openhab.binding.heos.internal.json.dto.HeosErrorCode;
25 import org.openhab.binding.heos.internal.json.dto.HeosResponseObject;
26 import org.openhab.binding.heos.internal.json.payload.BrowseResult;
27 import org.openhab.binding.heos.internal.json.payload.BrowseResultType;
28 import org.openhab.binding.heos.internal.json.payload.Group;
29 import org.openhab.binding.heos.internal.json.payload.GroupPlayerRole;
30 import org.openhab.binding.heos.internal.json.payload.Media;
31 import org.openhab.binding.heos.internal.json.payload.Player;
32 import org.openhab.binding.heos.internal.json.payload.YesNoEnum;
35 * Tests to validate the functioning of the HeosJsonParser specifically for response objects
37 * @author Martin van Wingerden - Initial Contribution
40 public class HeosJsonParserResponseTest {
42 private final HeosJsonParser subject = new HeosJsonParser();
45 public void sign_in() {
46 HeosResponseObject<Void> response = subject.parseResponse(
47 "{\"heos\": {\"command\": \"system/sign_in\", \"result\": \"success\", \"message\": \"signed_in&un=test@example.org\"}}",
50 assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup);
51 assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command);
52 assertTrue(response.result);
54 assertEquals("test@example.org", response.getAttribute(USERNAME));
55 assertTrue(response.hasAttribute(SIGNED_IN));
59 public void sign_in_under_process() {
60 HeosResponseObject<Void> response = subject.parseResponse(
61 "{\"heos\": {\"command\": \"system/sign_in\", \"message\": \"command under process\"}}", Void.class);
63 assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup);
64 assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command);
65 assertFalse(response.result);
66 assertFalse(response.isFinished());
70 public void sign_in_failed() {
71 HeosResponseObject<Void> response = subject.parseResponse(
72 "{\"heos\": {\"command\": \"system/sign_in\", \"message\": \"eid=10&text=User not found\"}}",
75 assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup);
76 assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command);
77 assertFalse(response.result);
78 assertTrue(response.isFinished());
80 assertEquals(HeosErrorCode.USER_NOT_FOUND, response.getError().code);
84 public void get_mute() {
85 HeosResponseObject<Void> response = subject.parseResponse(
86 "{\"heos\": {\"command\": \"player/get_mute\", \"result\": \"success\", \"message\": \"pid=1958912779&state=on\"}}",
89 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
90 assertEquals(HeosCommand.GET_MUTE, response.heosCommand.command);
91 assertTrue(response.result);
93 assertEquals(Long.valueOf(1958912779), response.getNumericAttribute(PLAYER_ID));
94 assertTrue(response.getBooleanAttribute(STATE));
98 public void get_mute_error() {
99 HeosResponseObject<Void> response = subject.parseResponse(
100 "{\"heos\": {\"command\": \"player/get_mute\", \"result\": \"fail\", \"message\": \"eid=2&text=ID Not Valid&pid=null\"}}",
103 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
104 assertEquals(HeosCommand.GET_MUTE, response.heosCommand.command);
105 assertFalse(response.result);
107 assertEquals(HeosErrorCode.INVALID_ID, response.getError().code);
111 public void browse_browse_under_process() {
112 HeosResponseObject<Void> response = subject.parseResponse(
113 "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"command under process&sid=1025\"}}",
116 assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup);
117 assertEquals(HeosCommand.BROWSE, response.heosCommand.command);
118 assertTrue(response.result);
120 assertEquals(Long.valueOf(1025), response.getNumericAttribute(SOURCE_ID));
121 assertFalse(response.isFinished());
125 public void incorrect_level() {
126 HeosResponseObject<Void> response = subject.parseResponse(
127 "{\"heos\": {\"command\": \"player/set_volume\", \"result\": \"fail\", \"message\": \"eid=9&text=Parameter out of range&pid=-831584083&level=OFF\"}}",
130 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
131 assertEquals(HeosCommand.SET_VOLUME, response.heosCommand.command);
132 assertFalse(response.result);
134 assertEquals(HeosErrorCode.PARAMETER_OUT_OF_RANGE, response.getError().code);
135 assertEquals("#9: Parameter out of range", response.getError().code.toString());
139 public void get_players() {
140 HeosResponseObject<Player[]> response = subject.parseResponse(
141 "{\"heos\": {\"command\": \"player/get_players\", \"result\": \"success\", \"message\": \"\"}, \"payload\": ["
142 + "{\"name\": \"Kantoor HEOS 3\", \"pid\": -831584083, \"model\": \"HEOS 3\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.230\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ACNG9180110887\"}, "
143 + "{\"name\": \"HEOS Bar\", \"pid\": 1958912779, \"model\": \"HEOS Bar\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.195\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ADAG9180917029\"}]}",
146 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
147 assertEquals(HeosCommand.GET_PLAYERS, response.heosCommand.command);
148 assertTrue(response.result);
150 assertEquals(2, response.payload.length);
151 Player player0 = response.payload[0];
153 assertEquals("Kantoor HEOS 3", player0.name);
154 assertEquals(-831584083, player0.playerId);
155 assertEquals("HEOS 3", player0.model);
156 assertEquals("1.520.200", player0.version);
157 assertEquals("192.168.1.230", player0.ip);
158 assertEquals("wired", player0.network);
159 assertEquals(0, player0.lineout);
160 assertEquals("ACNG9180110887", player0.serial);
162 Player player1 = response.payload[1];
164 assertEquals("HEOS Bar", player1.name);
165 assertEquals(1958912779, player1.playerId);
166 assertEquals("HEOS Bar", player1.model);
167 assertEquals("1.520.200", player1.version);
168 assertEquals("192.168.1.195", player1.ip);
169 assertEquals("wired", player1.network);
170 assertEquals(0, player1.lineout);
171 assertEquals("ADAG9180917029", player1.serial);
175 public void get_player_info() {
176 HeosResponseObject<Player> response = subject.parseResponse(
177 "{\"heos\": {\"command\": \"player/get_player_info\", \"result\": \"success\", \"message\": \"pid=1958912779\"}, \"payload\": {\"name\": \"HEOS Bar\", \"pid\": 1958912779, \"model\": \"HEOS Bar\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.195\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ADAG9180917029\"}}",
180 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
181 assertEquals(HeosCommand.GET_PLAYER_INFO, response.heosCommand.command);
182 assertTrue(response.result);
184 assertEquals("HEOS Bar", response.payload.name);
185 assertEquals(1958912779, response.payload.playerId);
186 assertEquals("HEOS Bar", response.payload.model);
187 assertEquals("1.520.200", response.payload.version);
188 assertEquals("192.168.1.195", response.payload.ip);
189 assertEquals("wired", response.payload.network);
190 assertEquals(0, response.payload.lineout);
191 assertEquals("ADAG9180917029", response.payload.serial);
195 public void get_now_playing_media() {
196 HeosResponseObject<Media> response = subject.parseResponse(
197 "{\"heos\": {\"command\": \"player/get_now_playing_media\", \"result\": \"success\", \"message\": \"pid=1958912779\"}, \"payload\": "
198 + "{\"type\": \"song\", \"song\": \"Solo (feat. Demi Lovato)\", \"album\": \"What Is Love? (Deluxe)\", \"artist\": \"Clean Bandit\", \"image_url\": \"http://192.168.1.230:8015//m-browsableMediaUri/getImageFromTag/mnt/326C72A3E307501E47DE2B0F47D90EB8/Clean%20Bandit/What%20Is%20Love_%20(Deluxe)/03%20Solo%20(feat.%20Demi%20Lovato).m4a\", \"album_id\": \"\", \"mid\": \"http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a\", \"qid\": 1, \"sid\": 1024}, \"options\": []}\n",
201 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
202 assertEquals(HeosCommand.GET_NOW_PLAYING_MEDIA, response.heosCommand.command);
203 assertTrue(response.result);
205 assertEquals(Long.valueOf(1958912779), response.getNumericAttribute(PLAYER_ID));
207 assertEquals("song", response.payload.type);
208 assertEquals("Solo (feat. Demi Lovato)", response.payload.song);
209 assertEquals("What Is Love? (Deluxe)", response.payload.album);
210 assertEquals("Clean Bandit", response.payload.artist);
212 "http://192.168.1.230:8015//m-browsableMediaUri/getImageFromTag/mnt/326C72A3E307501E47DE2B0F47D90EB8/Clean%20Bandit/What%20Is%20Love_%20(Deluxe)/03%20Solo%20(feat.%20Demi%20Lovato).m4a",
213 response.payload.imageUrl);
214 assertEquals("", response.payload.albumId);
216 "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a",
217 response.payload.mediaId);
218 assertEquals(1, response.payload.queueId);
219 assertEquals(1024, response.payload.sourceId);
223 public void browse_playlist() {
224 HeosResponseObject<BrowseResult[]> response = subject.parseResponse(
225 "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"sid=1025&returned=6&count=6\"}, \"payload\": ["
226 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"132562\", \"playable\": \"yes\", \"name\": \"Maaike Ouboter - En hoe het dan ook weer dag wordt\", \"image_url\": \"\"}, "
227 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"132563\", \"playable\": \"yes\", \"name\": \"Maaike Ouboter - Vanaf nu is het van jou\", \"image_url\": \"\"}, "
228 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"162887\", \"playable\": \"yes\", \"name\": \"Easy listening\", \"image_url\": \"\"}, "
229 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"174461\", \"playable\": \"yes\", \"name\": \"Nieuwe muziek 5-2019\", \"image_url\": \"\"}, "
230 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"194000\", \"playable\": \"yes\", \"name\": \"Nieuwe muziek 2019-05\", \"image_url\": \"\"}, "
231 + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"194001\", \"playable\": \"yes\", \"name\": \"Clean Bandit\", \"image_url\": \"\"}]}",
232 BrowseResult[].class);
234 assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup);
235 assertEquals(HeosCommand.BROWSE, response.heosCommand.command);
236 assertTrue(response.result);
238 assertEquals(Long.valueOf(1025), response.getNumericAttribute(SOURCE_ID));
239 assertEquals(Long.valueOf(6), response.getNumericAttribute(RETURNED));
240 assertEquals(Long.valueOf(6), response.getNumericAttribute(COUNT));
242 BrowseResult result = response.payload[5];
244 assertEquals(YesNoEnum.YES, result.container);
245 assertEquals(BrowseResultType.PLAYLIST, result.type);
246 assertEquals(YesNoEnum.YES, result.playable);
247 assertEquals("194001", result.containerId);
248 assertEquals("Clean Bandit", result.name);
249 assertEquals("", result.imageUrl);
253 public void browse_favorites() {
254 HeosResponseObject<BrowseResult[]> response = subject.parseResponse(
255 "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"sid=1028&returned=3&count=3\"}, \"payload\": ["
256 + "{\"container\": \"no\", \"mid\": \"s6707\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"NPO 3FM 96.8 (Top 40 %26 Pop Music)\", \"image_url\": \"http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268\"}, "
257 + "{\"container\": \"no\", \"mid\": \"s2967\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"Classic FM Nederland (Classical Music)\", \"image_url\": \"http://cdn-radiotime-logos.tunein.com/s2967q.png\"}, "
258 + "{\"container\": \"no\", \"mid\": \"s1993\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"BNR Nieuwsradio\", \"image_url\": \"http://cdn-radiotime-logos.tunein.com/s1993q.png\"}], "
259 + "\"options\": [{\"browse\": [{\"id\": 20, \"name\": \"Remove from HEOS Favorites\"}]}]}",
260 BrowseResult[].class);
262 assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup);
263 assertEquals(HeosCommand.BROWSE, response.heosCommand.command);
264 assertTrue(response.result);
266 assertEquals(Long.valueOf(1028), response.getNumericAttribute(SOURCE_ID));
267 assertEquals(Long.valueOf(3), response.getNumericAttribute(RETURNED));
268 assertEquals(Long.valueOf(3), response.getNumericAttribute(COUNT));
270 BrowseResult result = response.payload[0];
272 assertEquals(YesNoEnum.NO, result.container);
273 assertEquals("s6707", result.mediaId);
274 assertEquals(BrowseResultType.STATION, result.type);
275 assertEquals(YesNoEnum.YES, result.playable);
276 assertEquals("NPO 3FM 96.8 (Top 40 %26 Pop Music)", result.name);
277 assertEquals("http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268", result.imageUrl);
279 // TODO validate options
283 public void get_groups() {
284 HeosResponseObject<Group[]> response = subject.parseResponse(
285 "{\"heos\": {\"command\": \"group/get_groups\", \"result\": \"success\", \"message\": \"\"}, \"payload\": [ "
286 + "{\"name\": \"Group 1\", \"gid\": \"214243242\", \"players\": [ {\"name\": \"HEOS 1\", \"pid\": \"2142443242\", \"role\": \"leader\"}, {\"name\": \"HEOS 3\", \"pid\": \"32432423432\", \"role\": \"member\"}, {\"name\": \"HEOS 5\", \"pid\": \"342423564\", \"role\": \"member\"}]}, "
287 + "{\"name\": \"Group 2\", \"gid\": \"2142432342\", \"players\": [ {\"name\": \"HEOS 3\", \"pid\": \"32432423432\", \"role\": \"member\"}, {\"name\": \"HEOS 5\", \"pid\": \"342423564\", \"role\": \"member\"}]}]}",
290 assertEquals(HeosCommandGroup.GROUP, response.heosCommand.commandGroup);
291 assertEquals(HeosCommand.GET_GROUPS, response.heosCommand.command);
292 assertTrue(response.result);
294 Group group = response.payload[0];
296 assertEquals("Group 1", group.name);
297 assertEquals("214243242", group.id);
299 List<Group.Player> players = group.players;
301 Group.Player player0 = players.get(0);
302 assertEquals("HEOS 1", player0.name);
303 assertEquals("2142443242", player0.id);
304 assertEquals(GroupPlayerRole.LEADER, player0.role);
306 Group.Player player1 = players.get(1);
307 assertEquals("HEOS 3", player1.name);
308 assertEquals("32432423432", player1.id);
309 assertEquals(GroupPlayerRole.MEMBER, player1.role);