REST Voice API: new API for TTS (#1017)

* REST Voice API: new API for TTS

Fix #927

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2019-09-02 22:47:50 +02:00 committed by Kai Kreuzer
parent f2d69139e1
commit a1f388065c
3 changed files with 112 additions and 1 deletions

View File

@ -0,0 +1,27 @@
/**
* 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.voice.internal;
import org.eclipse.smarthome.core.voice.Voice;
/**
* A DTO that is used on the REST API to provide infos about {@link Voice} to UIs.
*
* @author Laurent Garnier - Initial contribution
*
*/
public class VoiceDTO {
public String id;
public String label;
public String locale;
}

View File

@ -0,0 +1,39 @@
/**
* 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.voice.internal;
import org.eclipse.smarthome.core.voice.Voice;
/**
* Mapper class that maps {@link Voice} instanced to their respective DTOs.
*
* @author Laurent Garnier - Initial contribution
*/
public class VoiceMapper {
/**
* Maps a {@link Voice} to an {@link VoiceDTO}.
*
* @param voice the voice
*
* @return the corresponding DTO
*/
public static VoiceDTO map(Voice voice) {
VoiceDTO dto = new VoiceDTO();
dto.id = voice.getUID();
dto.label = voice.getLabel();
dto.locale = voice.getLocale().toString();
return dto;
}
}

View File

@ -25,6 +25,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
@ -33,6 +34,7 @@ import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.eclipse.smarthome.core.auth.Role; import org.eclipse.smarthome.core.auth.Role;
import org.eclipse.smarthome.core.voice.Voice;
import org.eclipse.smarthome.core.voice.VoiceManager; import org.eclipse.smarthome.core.voice.VoiceManager;
import org.eclipse.smarthome.core.voice.text.HumanLanguageInterpreter; import org.eclipse.smarthome.core.voice.text.HumanLanguageInterpreter;
import org.eclipse.smarthome.core.voice.text.InterpretationException; import org.eclipse.smarthome.core.voice.text.InterpretationException;
@ -54,6 +56,7 @@ import io.swagger.annotations.ApiResponses;
* This class acts as a REST resource for voice features. * This class acts as a REST resource for voice features.
* *
* @author Kai Kreuzer - Initial contribution and API * @author Kai Kreuzer - Initial contribution and API
* @author Laurent Garnier - add TTS feature to the REST API
*/ */
@Component @Component
@Path(VoiceResource.PATH_SITEMAPS) @Path(VoiceResource.PATH_SITEMAPS)
@ -106,7 +109,7 @@ public class VoiceResource implements RESTResource {
@GET @GET
@Path("/interpreters/{id: [a-zA-Z_0-9]*}") @Path("/interpreters/{id: [a-zA-Z_0-9]*}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets a single interpreters.", response = HumanLanguageInterpreterDTO.class) @ApiOperation(value = "Gets a single interpreter.", response = HumanLanguageInterpreterDTO.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Interpreter not found") }) @ApiResponse(code = 404, message = "Interpreter not found") })
public Response getInterpreter( public Response getInterpreter(
@ -169,6 +172,48 @@ public class VoiceResource implements RESTResource {
} }
} }
@GET
@Path("/voices")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get the list of all voices.", response = VoiceDTO.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response getVoices() {
Collection<Voice> voices = voiceManager.getAllVoices();
List<VoiceDTO> dtos = new ArrayList<>(voices.size());
for (Voice voice : voices) {
dtos.add(VoiceMapper.map(voice));
}
return Response.ok(dtos).build();
}
@GET
@Path("/defaultvoice")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets the default voice.", response = VoiceDTO.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "No default voice was found.") })
public Response getDefaultVoice() {
Voice voice = voiceManager.getDefaultVoice();
if (voice != null) {
VoiceDTO dto = VoiceMapper.map(voice);
return Response.ok(dto).build();
} else {
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Default voice not found");
}
}
@POST
@Path("/say")
@Consumes(MediaType.TEXT_PLAIN)
@ApiOperation(value = "Speaks a given text with a given voice through the given audio sink.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response say(@ApiParam(value = "text to speak", required = true) String text,
@ApiParam(value = "voice id", required = false) @QueryParam("voiceid") String voiceId,
@ApiParam(value = "audio sink id", required = false) @QueryParam("sinkid") String sinkId) {
voiceManager.say(text, voiceId, sinkId);
return Response.ok(null, MediaType.TEXT_PLAIN).build();
}
@Override @Override
public boolean isSatisfied() { public boolean isSatisfied() {
return voiceManager != null && localeService != null; return voiceManager != null && localeService != null;