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(
142 {"heos": {"command": "player/get_players", "result": "success", "message": ""}, "payload": [\
143 {"name": "Kantoor HEOS 3", "pid": -831584083, "model": "HEOS 3", "version": "1.520.200", "ip": "192.168.1.230", "network": "wired", "lineout": 0, "serial": "ACNG9180110887"}, \
144 {"name": "HEOS Bar", "pid": 1958912779, "model": "HEOS Bar", "version": "1.520.200", "ip": "192.168.1.195", "network": "wired", "lineout": 0, "serial": "ADAG9180917029"}]}\
148 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
149 assertEquals(HeosCommand.GET_PLAYERS, response.heosCommand.command);
150 assertTrue(response.result);
152 assertEquals(2, response.payload.length);
153 Player player0 = response.payload[0];
155 assertEquals("Kantoor HEOS 3", player0.name);
156 assertEquals(-831584083, player0.playerId);
157 assertEquals("HEOS 3", player0.model);
158 assertEquals("1.520.200", player0.version);
159 assertEquals("192.168.1.230", player0.ip);
160 assertEquals("wired", player0.network);
161 assertEquals(0, player0.lineout);
162 assertEquals("ACNG9180110887", player0.serial);
164 Player player1 = response.payload[1];
166 assertEquals("HEOS Bar", player1.name);
167 assertEquals(1958912779, player1.playerId);
168 assertEquals("HEOS Bar", player1.model);
169 assertEquals("1.520.200", player1.version);
170 assertEquals("192.168.1.195", player1.ip);
171 assertEquals("wired", player1.network);
172 assertEquals(0, player1.lineout);
173 assertEquals("ADAG9180917029", player1.serial);
177 public void get_player_info() {
178 HeosResponseObject<Player> response = subject.parseResponse(
179 "{\"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\"}}",
182 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
183 assertEquals(HeosCommand.GET_PLAYER_INFO, response.heosCommand.command);
184 assertTrue(response.result);
186 assertEquals("HEOS Bar", response.payload.name);
187 assertEquals(1958912779, response.payload.playerId);
188 assertEquals("HEOS Bar", response.payload.model);
189 assertEquals("1.520.200", response.payload.version);
190 assertEquals("192.168.1.195", response.payload.ip);
191 assertEquals("wired", response.payload.network);
192 assertEquals(0, response.payload.lineout);
193 assertEquals("ADAG9180917029", response.payload.serial);
197 public void get_now_playing_media() {
198 HeosResponseObject<Media> response = subject.parseResponse(
200 {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=1958912779"}, "payload": \
201 {"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": []}
205 assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup);
206 assertEquals(HeosCommand.GET_NOW_PLAYING_MEDIA, response.heosCommand.command);
207 assertTrue(response.result);
209 assertEquals(Long.valueOf(1958912779), response.getNumericAttribute(PLAYER_ID));
211 assertEquals("song", response.payload.type);
212 assertEquals("Solo (feat. Demi Lovato)", response.payload.song);
213 assertEquals("What Is Love? (Deluxe)", response.payload.album);
214 assertEquals("Clean Bandit", response.payload.artist);
216 "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",
217 response.payload.imageUrl);
218 assertEquals("", response.payload.albumId);
220 "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a",
221 response.payload.mediaId);
222 assertEquals(1, response.payload.queueId);
223 assertEquals(1024, response.payload.sourceId);
227 public void browse_playlist() {
228 HeosResponseObject<BrowseResult[]> response = subject.parseResponse(
230 {"heos": {"command": "browse/browse", "result": "success", "message": "sid=1025&returned=6&count=6"}, "payload": [\
231 {"container": "yes", "type": "playlist", "cid": "132562", "playable": "yes", "name": "Maaike Ouboter - En hoe het dan ook weer dag wordt", "image_url": ""}, \
232 {"container": "yes", "type": "playlist", "cid": "132563", "playable": "yes", "name": "Maaike Ouboter - Vanaf nu is het van jou", "image_url": ""}, \
233 {"container": "yes", "type": "playlist", "cid": "162887", "playable": "yes", "name": "Easy listening", "image_url": ""}, \
234 {"container": "yes", "type": "playlist", "cid": "174461", "playable": "yes", "name": "Nieuwe muziek 5-2019", "image_url": ""}, \
235 {"container": "yes", "type": "playlist", "cid": "194000", "playable": "yes", "name": "Nieuwe muziek 2019-05", "image_url": ""}, \
236 {"container": "yes", "type": "playlist", "cid": "194001", "playable": "yes", "name": "Clean Bandit", "image_url": ""}]}\
238 BrowseResult[].class);
240 assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup);
241 assertEquals(HeosCommand.BROWSE, response.heosCommand.command);
242 assertTrue(response.result);
244 assertEquals(Long.valueOf(1025), response.getNumericAttribute(SOURCE_ID));
245 assertEquals(Long.valueOf(6), response.getNumericAttribute(RETURNED));
246 assertEquals(Long.valueOf(6), response.getNumericAttribute(COUNT));
248 BrowseResult result = response.payload[5];
250 assertEquals(YesNoEnum.YES, result.container);
251 assertEquals(BrowseResultType.PLAYLIST, result.type);
252 assertEquals(YesNoEnum.YES, result.playable);
253 assertEquals("194001", result.containerId);
254 assertEquals("Clean Bandit", result.name);
255 assertEquals("", result.imageUrl);
259 public void browse_favorites() {
260 HeosResponseObject<BrowseResult[]> response = subject.parseResponse(
262 {"heos": {"command": "browse/browse", "result": "success", "message": "sid=1028&returned=3&count=3"}, "payload": [\
263 {"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"}, \
264 {"container": "no", "mid": "s2967", "type": "station", "playable": "yes", "name": "Classic FM Nederland (Classical Music)", "image_url": "http://cdn-radiotime-logos.tunein.com/s2967q.png"}, \
265 {"container": "no", "mid": "s1993", "type": "station", "playable": "yes", "name": "BNR Nieuwsradio", "image_url": "http://cdn-radiotime-logos.tunein.com/s1993q.png"}], \
266 "options": [{"browse": [{"id": 20, "name": "Remove from HEOS Favorites"}]}]}\
268 BrowseResult[].class);
270 assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup);
271 assertEquals(HeosCommand.BROWSE, response.heosCommand.command);
272 assertTrue(response.result);
274 assertEquals(Long.valueOf(1028), response.getNumericAttribute(SOURCE_ID));
275 assertEquals(Long.valueOf(3), response.getNumericAttribute(RETURNED));
276 assertEquals(Long.valueOf(3), response.getNumericAttribute(COUNT));
278 BrowseResult result = response.payload[0];
280 assertEquals(YesNoEnum.NO, result.container);
281 assertEquals("s6707", result.mediaId);
282 assertEquals(BrowseResultType.STATION, result.type);
283 assertEquals(YesNoEnum.YES, result.playable);
284 assertEquals("NPO 3FM 96.8 (Top 40 %26 Pop Music)", result.name);
285 assertEquals("http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268", result.imageUrl);
287 // TODO validate options
291 public void get_groups() {
292 HeosResponseObject<Group[]> response = subject.parseResponse(
294 {"heos": {"command": "group/get_groups", "result": "success", "message": ""}, "payload": [ \
295 {"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"}]}, \
296 {"name": "Group 2", "gid": "2142432342", "players": [ {"name": "HEOS 3", "pid": "32432423432", "role": "member"}, {"name": "HEOS 5", "pid": "342423564", "role": "member"}]}]}\
300 assertEquals(HeosCommandGroup.GROUP, response.heosCommand.commandGroup);
301 assertEquals(HeosCommand.GET_GROUPS, response.heosCommand.command);
302 assertTrue(response.result);
304 Group group = response.payload[0];
306 assertEquals("Group 1", group.name);
307 assertEquals("214243242", group.id);
309 List<Group.Player> players = group.players;
311 Group.Player player0 = players.get(0);
312 assertEquals("HEOS 1", player0.name);
313 assertEquals("2142443242", player0.id);
314 assertEquals(GroupPlayerRole.LEADER, player0.role);
316 Group.Player player1 = players.get(1);
317 assertEquals("HEOS 3", player1.name);
318 assertEquals("32432423432", player1.id);
319 assertEquals(GroupPlayerRole.MEMBER, player1.role);