Skip to content

Commit

Permalink
[rest] New audio API (#1020)
Browse files Browse the repository at this point in the history
* New Audio REST API

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo authored and cweitkamp committed Sep 15, 2019
1 parent bb4b041 commit cf4b752
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 0 deletions.
6 changes: 6 additions & 0 deletions bom/openhab-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.audio</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest.auth</artifactId>
Expand Down
27 changes: 27 additions & 0 deletions bundles/org.openhab.core.io.rest.audio/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
23 changes: 23 additions & 0 deletions bundles/org.openhab.core.io.rest.audio/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.io.rest.audio</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
14 changes: 14 additions & 0 deletions bundles/org.openhab.core.io.rest.audio/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
This content is produced and maintained by the openHAB project.

* Project home: https://www.openhab.org

== Declared Project Licenses

This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.

== Source Code

https://github.com/openhab/openhab-core

29 changes: 29 additions & 0 deletions bundles/org.openhab.core.io.rest.audio/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.reactor.bundles</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.core.io.rest.audio</artifactId>

<name>openHAB Core :: Bundles :: Audio REST Interface</name>

<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.audio</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.io.rest</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.audio.internal;

import java.util.Locale;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.core.audio.AudioSink;
import org.eclipse.smarthome.core.audio.AudioSource;

/**
* Mapper class that maps {@link AudioSink} and {@link AudioSource} instanced to their respective DTOs.
*
* @author Laurent Garnier - Initial contribution
*
*/
@NonNullByDefault
public class AudioMapper {

/**
* Maps a {@link AudioSource} to an {@link AudioSourceDTO}.
*
* @param source the audio source
* @param locale the locale to use for the DTO
*
* @return the corresponding DTO
*/
public static AudioSourceDTO map(AudioSource source, Locale locale) {
return new AudioSourceDTO(source.getId(), source.getLabel(locale));
}

/**
* Maps a {@link AudioSink} to an {@link AudioSinkDTO}.
*
* @param sink the audio sink
* @param locale the locale to use for the DTO
*
* @return the corresponding DTO
*/
public static AudioSinkDTO map(AudioSink sink, Locale locale) {
return new AudioSinkDTO(sink.getId(), sink.getLabel(locale));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.audio.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.audio.AudioManager;
import org.eclipse.smarthome.core.audio.AudioSink;
import org.eclipse.smarthome.core.audio.AudioSource;
import org.eclipse.smarthome.core.auth.Role;
import org.eclipse.smarthome.io.rest.JSONResponse;
import org.eclipse.smarthome.io.rest.LocaleService;
import org.eclipse.smarthome.io.rest.RESTResource;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

/**
* This class acts as a REST resource for audio features.
*
* @author Laurent Garnier - Initial contribution
*/
@Component
@Path(AudioResource.PATH_SITEMAPS)
@RolesAllowed({ Role.USER, Role.ADMIN })
@Api(value = AudioResource.PATH_SITEMAPS)
@NonNullByDefault
public class AudioResource implements RESTResource {

static final String PATH_SITEMAPS = "audio";

private @Nullable AudioManager audioManager;
private @Nullable LocaleService localeService;

@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
public void setAudioManager(AudioManager audioManager) {
this.audioManager = audioManager;
}

public void unsetAudioManager(AudioManager audioManager) {
this.audioManager = null;
}

@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
protected void setLocaleService(LocaleService localeService) {
this.localeService = localeService;
}

protected void unsetLocaleService(LocaleService localeService) {
this.localeService = null;
}

@GET
@Path("/sources")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get the list of all sources.", response = AudioSourceDTO.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response getSources(
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
final Locale locale = localeService.getLocale(language);
Collection<AudioSource> sources = audioManager.getAllSources();
List<AudioSourceDTO> dtos = new ArrayList<>(sources.size());
for (AudioSource source : sources) {
dtos.add(AudioMapper.map(source, locale));
}
return Response.ok(dtos).build();
}

@GET
@Path("/defaultsource")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get the default source if defined or the first available source.", response = AudioSourceDTO.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Source not found") })
public Response getDefaultSource(
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
final Locale locale = localeService.getLocale(language);
AudioSource source = audioManager.getSource();
if (source != null) {
return Response.ok(AudioMapper.map(source, locale)).build();
} else {
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Source not found");
}
}

@GET
@Path("/sinks")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get the list of all sinks.", response = AudioSinkDTO.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response getSinks(
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
final Locale locale = localeService.getLocale(language);
Collection<AudioSink> sinks = audioManager.getAllSinks();
List<AudioSinkDTO> dtos = new ArrayList<>(sinks.size());
for (AudioSink sink : sinks) {
dtos.add(AudioMapper.map(sink, locale));
}
return Response.ok(dtos).build();
}

@GET
@Path("/defaultsink")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get the default sink if defined or the first available sink.", response = AudioSinkDTO.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Sink not found") })
public Response getDefaultSink(
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
final Locale locale = localeService.getLocale(language);
AudioSink sink = audioManager.getSink();
if (sink != null) {
return Response.ok(AudioMapper.map(sink, locale)).build();
} else {
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Sink not found");
}
}

@Override
public boolean isSatisfied() {
return audioManager != null && localeService != null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.audio.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.audio.AudioSink;

/**
* A DTO that is used on the REST API to provide infos about {@link AudioSink} to UIs.
*
* @author Laurent Garnier - Initial contribution
*
*/
@NonNullByDefault
public class AudioSinkDTO {
public String id;
public @Nullable String label;

public AudioSinkDTO(String id, @Nullable String label) {
this.id = id;
this.label = label;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.audio.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.audio.AudioSource;

/**
* A DTO that is used on the REST API to provide infos about {@link AudioSource} to UIs.
*
* @author Laurent Garnier - Initial contribution
*
*/
@NonNullByDefault
public class AudioSourceDTO {
public String id;
public @Nullable String label;

public AudioSourceDTO(String id, @Nullable String label) {
this.id = id;
this.label = label;
}

}
Loading

0 comments on commit cf4b752

Please sign in to comment.