/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.sonos; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.openhab.binding.sonos.internal.Direction; import org.openhab.binding.sonos.internal.SonosBinding; import org.openhab.core.items.Item; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.StringType; import org.openhab.core.types.Type; import org.quartz.Job;; /** * Represents all valid commands which could be processed by this binding * * @author Karel Goderis * @since 1.1.0 */ public enum SonosCommandType { PLAY { { command = "play"; service = "AVTransport"; action = "Play"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, PAUSE { { command = "pause"; service = "AVTransport"; action = "Pause"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, STOP { { command = "stop"; service = "AVTransport"; action = "Stop"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, NEXT { { command = "next"; service = "AVTransport"; action = "Next"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, PREVIOUS { { command = "previous"; service = "AVTransport"; action = "Previous"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, SETLED { { command = "led"; service = "DeviceProperties"; action = "SetLEDState"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, GETLED { { command = "led"; service = "DeviceProperties"; action = "GetLEDState"; variable = "CurrentLEDState"; typeClass = OnOffType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.LedJob.class; } }, ZONENAME { { command = "zonename"; service = null; action = "GetZoneAttributes"; variable = "CurrentZoneName"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.ZoneInfoJob.class; } }, ZONEINFO { { command = null; service = "DeviceProperties"; action = null; variable = null; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.ZoneInfoJob.class; } }, ZONEGROUP { { command = "zonegroup"; service = "ZoneGroupTopology"; action = null; variable = "ZoneGroupState"; typeClass = StringType.class; direction = Direction.IN; } }, GROUPUUID { { command = "zonegroupid"; service = "GroupManagement"; action = null; variable = "LocalGroupUUID"; typeClass = StringType.class; direction = Direction.IN; } }, // TODO : GroupManagement, AddMember does not seem to work correctly ADDMEMBER { { command = "add"; // service = "GroupManagement"; // action = "AddMember"; service = "AVTransport"; action = "SetAVTransportURI"; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, // TODO: GroupManagement, RemoveMember does not seem to work properly. REMOVEMEMBER { { command = "remove"; // service = "GroupManagement"; // action = "RemoveMember"; service = null; action = null; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, COORDINATORLOCAL { { command = "localcoordinator"; service = "GroupManagement"; action = null; variable = "GroupCoordinatorIsLocal"; typeClass = OnOffType.class; direction = Direction.IN; } }, BECOMESTANDALONEGROUP { { command = "standalone"; service = "AVTransport"; action = "BecomeCoordinatorOfStandaloneGroup"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, // // Not implemented yet // BECOMEZONEGROUPCOORDINATOR { // { // command = "coordinator"; // service = "AVTransport"; // action = "BecomeGroupCoordinator"; // variable = null; // typeClass = OnOffType.class; // direction = Direction.OUT; // } // }, // Not implemented yet CHANGECOORDINATOR { { command = "coordinator"; service = "AVTransport"; action = "ChangeCoordinator"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, // Not implemented yet BECOMEZONEGROUPSOURCE { { command = "source"; service = "AVTransport"; action = "BecomeGroupCoordinatorAndSource"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, PLAYURI { { command = "playuri"; service = "AVTransport"; action = "SetAVTransportURI"; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, PLAYLINEIN { { command = "playline"; service = "AVTransport"; action = "SetAVTransportURI"; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, GETVOLUME { { command = "volume"; service = "RenderingControl"; action = null; variable = "VolumeMaster"; typeClass = PercentType.class; direction = Direction.IN; } }, SETVOLUME { { command = "volume"; service = "RenderingControl"; action = "SetVolume"; variable = null; typeClass = PercentType.class; direction = Direction.OUT; } }, GETMUTE { { command = "mute"; service = "RenderingControl"; action = null; variable = "MuteMaster"; typeClass = OnOffType.class; direction = Direction.IN; } }, SETMUTE { { command = "mute"; service = "RenderingControl"; action = "SetMute"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, TRANSPORTSTATE { { command = "transportstate"; service = "AVTransport"; action = null; variable = "TransportState"; typeClass = StringType.class; direction = Direction.IN; } }, PA { { // public address, e.g. bring all Sonos in one group, and stream audio from the line-in from the player that // received the ON command command = "publicaddress"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, // Not yet implemented STARTGROUPTRANSMISSION { { command = "transmit"; service = "AudioIn"; action = "StartTransmissionToGroup"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, // Not yet implemented STOPGROUPTRANSMISSION { { command = "transmit"; service = "AudioIn"; action = "StopTransmissionToGroup"; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, LINEINCONNECTED { { command = "linein"; service = "AudioIn"; action = null; variable = "LineInConnected"; typeClass = OnOffType.class; direction = Direction.IN; } }, BROWSE { { command = null; service = "ContentDirectory"; action = "Browse"; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, RADIO { { command = "radio"; service = null; action = null; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, FAVORITE { { command = "favorite"; service = null; action = null; variable = null; typeClass = StringType.class; direction = Direction.OUT; } }, SAVEALL { { command = "saveall"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, RESTOREALL { { command = "restoreall"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, SAVE { { command = "save"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, RESTORE { { command = "restore"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, SETALARM { { command = "alarm"; service = null; action = null; variable = null; typeClass = OnOffType.class; direction = Direction.OUT; } }, ALARMRUNNING { { command = "alarmrunning"; service = "AVTransport"; action = ""; variable = "AlarmRunning"; typeClass = OnOffType.class; direction = Direction.IN; } }, SNOOZE { { command = "snooze"; service = "AVTransport"; action = "SnoozeAlarm"; variable = null; typeClass = DecimalType.class; direction = Direction.OUT; } }, RUNNINGALARMPROPERTIES { { command = "alarmproperties"; service = "AVTransport"; action = null; variable = "RunningAlarmProperties"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.RunningAlarmPropertiesJob.class; } }, MEDIAINFO { { command = null; service = "AVTransport"; action = null; variable = null; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.MediaInfoJob.class; } }, CURRENTTRACK { { command = "currenttrack"; service = "AVTransport"; action = null; variable = "CurrentURIFormatted"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.CurrentURIFormattedJob.class; } }, CURRENTTITLE { { command = "currenttitle"; service = "AVTransport"; action = null; variable = "CurrentTitle"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.CurrentURIFormattedJob.class; } }, CURRENTARTIST { { command = "currentartist"; service = "AVTransport"; action = null; variable = "CurrentArtist"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.CurrentURIFormattedJob.class; } }, CURRENTALBUM { { command = "currentalbum"; service = "AVTransport"; action = null; variable = "CurrentAlbum"; typeClass = StringType.class; direction = Direction.IN; polling = true; jobClass = SonosBinding.CurrentURIFormattedJob.class; } }, PLAYLIST { { command = "playlist"; service = null; action = null; variable = null; typeClass = StringType.class; direction = Direction.OUT; } } ; /** Represents the Sonos command as it will be used in *.items configuration */ // openhab command associated with this upnp cpmmand, e.g. used in items String command; // name of upnp service template String service; // name of upnp action/command, must be defined in service template. put null for complex commands that go beyond // simple assynchronous execution // WARNING: NOT USED ANYMORE BUT I KEPT IT IN HERE TO MAKE THE CODE / UPNP MORE READABLE String action; // if action == null, then variable indicates the name of the GENA variable we need to process/use String variable; // type of the item supported by this command Class<? extends Type> typeClass; // direction of the openhab command, eg IN, OUT or BIDIRECTIONAL. that we will accept in conjunction with this // command Direction direction; // true if a variable need to be polled pro-actively, e.g. values are not returned as part of a GENA subscription boolean polling = false; // class of the Job that will fetch the value(s) for this command. Class<? extends Job> jobClass; public String getSonosCommand() { return command; } public String getService() { return service; } public String getAction() { return action; } public String getVariable() { return variable; } public Direction getDirection() { return direction; } /** * @return the polling */ public boolean isPolling() { return polling; } public Class<? extends Type> getTypeClass() { return typeClass; } /** * Gets the job class. * * @return the job class */ public Class<? extends Job> getJobClass() { return jobClass; } /** * * @param SonosCommand command string e.g. message, volume, channel * @param action class to validate * @return true if item class can bound to SonosCommand */ public static boolean validateBinding(SonosCommandType type, Item item) { if (type != null && item != null && item.getAcceptedDataTypes().contains(type.getTypeClass())) { return true; } else { return false; } } /** * * @param sonosCommand command string e.g. message, volume, channel * @return simple name of all valid item classes */ public static String getValidItemTypes(String sonosCommand) { String ret = ""; for (SonosCommandType c : SonosCommandType.values()) { if (sonosCommand.equals(c.getSonosCommand()) && c.getSonosCommand() != null) { if (StringUtils.isEmpty(ret)) { ret = c.getTypeClass().getSimpleName(); } else { if (!ret.contains(c.getTypeClass().getSimpleName())) { ret = ret + ", " + c.getTypeClass().getSimpleName(); } } } } return ret; } public static List<SonosCommandType> getSubscriptions() { List<SonosCommandType> result = new ArrayList<SonosCommandType>(); for (SonosCommandType c : SonosCommandType.values()) { if (c.getVariable() != null && c.getSonosCommand() != null && c.isPolling() == false) { result.add(c); } } return result; } public static List<SonosCommandType> getPolling() { List<SonosCommandType> result = new ArrayList<SonosCommandType>(); for (SonosCommandType c : SonosCommandType.values()) { if (c.isPolling()) { result.add(c); } } return result; } public static SonosCommandType getCommandType(String sonosCommand, Direction direction) throws SonosIllegalCommandTypeException { if ("".equals(sonosCommand)) { return null; } for (SonosCommandType c : SonosCommandType.values()) { if (sonosCommand.equals(c.getSonosCommand()) && c.getDirection().equals(direction)) { return c; } } throw new SonosIllegalCommandTypeException("Cannot find sonosCommandType for '" + sonosCommand + "' with direction '" + direction.toString() + "'"); } public static List<SonosCommandType> getCommandByVariable(String stateVariable) { List<SonosCommandType> result = new ArrayList<SonosCommandType>(); for (SonosCommandType c : SonosCommandType.values()) { if (c.getVariable() != null && c.getVariable().equals(stateVariable)) { result.add(c); } } return result; } }