mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-11 05:41:52 +01:00
[automation] Added Actions for Play and Say which sets the volume (#1854)
* Added Actions for Play and Say which sets the volume Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
parent
c5f133b3e9
commit
0e7563c901
@ -16,13 +16,12 @@ import static java.util.Comparator.comparing;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -42,14 +41,15 @@ import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* This class dynamically provides the Play action type.
|
||||
* This class dynamically provides the Play and Say action types.
|
||||
* This is necessary since there is no other way to provide dynamic config param options for module types.
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Simon Kaufmann - added "say" action
|
||||
* @author Christoph Weitkamp - Added parameter volume
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(immediate = true)
|
||||
@Component(service = ModuleTypeProvider.class)
|
||||
public class MediaActionTypeProvider implements ModuleTypeProvider {
|
||||
|
||||
private final AudioManager audioManager;
|
||||
@ -62,43 +62,45 @@ public class MediaActionTypeProvider implements ModuleTypeProvider {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @Nullable ModuleType getModuleType(String UID, @Nullable Locale locale) {
|
||||
if (PlayActionHandler.TYPE_ID.equals(UID)) {
|
||||
return getPlayActionType(locale);
|
||||
} else if (SayActionHandler.TYPE_ID.equals(UID)) {
|
||||
return getSayActionType(locale);
|
||||
} else {
|
||||
return null;
|
||||
switch (UID) {
|
||||
case PlayActionHandler.TYPE_ID:
|
||||
return getPlayActionType(locale);
|
||||
case SayActionHandler.TYPE_ID:
|
||||
return getSayActionType(locale);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModuleType> getModuleTypes(@Nullable Locale locale) {
|
||||
return Stream.of(getPlayActionType(locale), getSayActionType(locale)).collect(Collectors.toList());
|
||||
return List.of(getPlayActionType(locale), getSayActionType(locale));
|
||||
}
|
||||
|
||||
private ModuleType getPlayActionType(@Nullable Locale locale) {
|
||||
return new ActionType(PlayActionHandler.TYPE_ID, getConfigPlayDesc(locale), "play a sound",
|
||||
"Plays a sound file.", null, Visibility.VISIBLE, new ArrayList<>(), new ArrayList<>());
|
||||
"Plays a sound file. Optionally sets the volume.", null, Visibility.VISIBLE, null, null);
|
||||
}
|
||||
|
||||
private ModuleType getSayActionType(@Nullable Locale locale) {
|
||||
return new ActionType(SayActionHandler.TYPE_ID, getConfigSayDesc(locale), "say something",
|
||||
"Speaks a given text through a natural voice.", null, Visibility.VISIBLE, new ArrayList<>(),
|
||||
new ArrayList<>());
|
||||
"Speaks a given text through a natural voice. Optionally sets the volume.", null, Visibility.VISIBLE,
|
||||
null, null);
|
||||
}
|
||||
|
||||
private List<ConfigDescriptionParameter> getConfigPlayDesc(@Nullable Locale locale) {
|
||||
ConfigDescriptionParameter param1 = ConfigDescriptionParameterBuilder
|
||||
.create(PlayActionHandler.PARAM_SOUND, Type.TEXT).withRequired(true).withLabel("Sound")
|
||||
.withDescription("the sound to play").withOptions(getSoundOptions()).withLimitToOptions(true).build();
|
||||
return List.of(param1, getAudioSinkConfigDescParam(locale));
|
||||
return List.of(
|
||||
ConfigDescriptionParameterBuilder.create(PlayActionHandler.PARAM_SOUND, Type.TEXT).withRequired(true)
|
||||
.withLabel("Sound").withDescription("the sound to play").withOptions(getSoundOptions())
|
||||
.withLimitToOptions(true).build(),
|
||||
getAudioSinkConfigDescParam(locale), getVolumeConfigDescParam(locale));
|
||||
}
|
||||
|
||||
private List<ConfigDescriptionParameter> getConfigSayDesc(@Nullable Locale locale) {
|
||||
ConfigDescriptionParameter param1 = ConfigDescriptionParameterBuilder
|
||||
.create(SayActionHandler.PARAM_TEXT, Type.TEXT).withRequired(true).withLabel("Text")
|
||||
.withDescription("the text to speak").build();
|
||||
return List.of(param1, getAudioSinkConfigDescParam(locale));
|
||||
return List.of(
|
||||
ConfigDescriptionParameterBuilder.create(SayActionHandler.PARAM_TEXT, Type.TEXT).withRequired(true)
|
||||
.withLabel("Text").withDescription("the text to speak").build(),
|
||||
getAudioSinkConfigDescParam(locale), getVolumeConfigDescParam(locale));
|
||||
}
|
||||
|
||||
private ConfigDescriptionParameter getAudioSinkConfigDescParam(@Nullable Locale locale) {
|
||||
@ -109,6 +111,14 @@ public class MediaActionTypeProvider implements ModuleTypeProvider {
|
||||
return param2;
|
||||
}
|
||||
|
||||
private ConfigDescriptionParameter getVolumeConfigDescParam(@Nullable Locale locale) {
|
||||
ConfigDescriptionParameter param3 = ConfigDescriptionParameterBuilder
|
||||
.create(SayActionHandler.PARAM_VOLUME, Type.INTEGER).withLabel("Volume")
|
||||
.withDescription("the volume to use").withMinimum(BigDecimal.ZERO).withMaximum(BigDecimal.valueOf(100))
|
||||
.withStepSize(BigDecimal.ONE).build();
|
||||
return param3;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates one option for every file that is found in the sounds directory.
|
||||
* As a label, the file extension is removed and the string is capitalized.
|
||||
|
@ -15,6 +15,8 @@ package org.openhab.core.automation.module.media.internal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.audio.AudioManager;
|
||||
import org.openhab.core.automation.Action;
|
||||
import org.openhab.core.automation.Module;
|
||||
@ -22,6 +24,7 @@ import org.openhab.core.automation.handler.BaseModuleHandlerFactory;
|
||||
import org.openhab.core.automation.handler.ModuleHandler;
|
||||
import org.openhab.core.automation.handler.ModuleHandlerFactory;
|
||||
import org.openhab.core.voice.VoiceManager;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
@ -29,13 +32,22 @@ import org.osgi.service.component.annotations.Reference;
|
||||
/**
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Christoph Weitkamp - Added parameter volume
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ModuleHandlerFactory.class)
|
||||
public class MediaModuleHandlerFactory extends BaseModuleHandlerFactory {
|
||||
|
||||
private static final Collection<String> TYPES = List.of(SayActionHandler.TYPE_ID, PlayActionHandler.TYPE_ID);
|
||||
private VoiceManager voiceManager;
|
||||
private AudioManager audioManager;
|
||||
private final VoiceManager voiceManager;
|
||||
private final AudioManager audioManager;
|
||||
|
||||
@Activate
|
||||
public MediaModuleHandlerFactory(final @Reference AudioManager audioManager,
|
||||
final @Reference VoiceManager voiceManager) {
|
||||
this.audioManager = audioManager;
|
||||
this.voiceManager = voiceManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deactivate
|
||||
@ -49,7 +61,7 @@ public class MediaModuleHandlerFactory extends BaseModuleHandlerFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModuleHandler internalCreate(Module module, String ruleUID) {
|
||||
protected @Nullable ModuleHandler internalCreate(Module module, String ruleUID) {
|
||||
if (module instanceof Action) {
|
||||
switch (module.getTypeUID()) {
|
||||
case SayActionHandler.TYPE_ID:
|
||||
@ -62,22 +74,4 @@ public class MediaModuleHandlerFactory extends BaseModuleHandlerFactory {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setAudioManager(AudioManager audioManager) {
|
||||
this.audioManager = audioManager;
|
||||
}
|
||||
|
||||
protected void unsetAudioManager(AudioManager audioManager) {
|
||||
this.audioManager = null;
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setVoiceManager(VoiceManager voiceManager) {
|
||||
this.voiceManager = voiceManager;
|
||||
}
|
||||
|
||||
protected void unsetVoiceManager(VoiceManager voiceManager) {
|
||||
this.voiceManager = null;
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,16 @@
|
||||
*/
|
||||
package org.openhab.core.automation.module.media.internal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.audio.AudioException;
|
||||
import org.openhab.core.audio.AudioManager;
|
||||
import org.openhab.core.automation.Action;
|
||||
import org.openhab.core.automation.handler.BaseActionModuleHandler;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -25,28 +29,39 @@ import org.slf4j.LoggerFactory;
|
||||
* This is an ModuleHandler implementation for Actions that play a sound file from the file system.
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Christoph Weitkamp - Added parameter volume
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PlayActionHandler extends BaseActionModuleHandler {
|
||||
|
||||
public static final String TYPE_ID = "media.PlayAction";
|
||||
public static final String PARAM_SOUND = "sound";
|
||||
public static final String PARAM_SINK = "sink";
|
||||
public static final String PARAM_VOLUME = "volume";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PlayActionHandler.class);
|
||||
|
||||
private final AudioManager audioManager;
|
||||
|
||||
private final String sound;
|
||||
private final String sink;
|
||||
private final @Nullable PercentType volume;
|
||||
|
||||
public PlayActionHandler(Action module, AudioManager audioManager) {
|
||||
super(module);
|
||||
this.audioManager = audioManager;
|
||||
|
||||
this.sound = module.getConfiguration().get(PARAM_SOUND).toString();
|
||||
this.sink = module.getConfiguration().get(PARAM_SINK).toString();
|
||||
|
||||
Object volumeParam = module.getConfiguration().get(PARAM_VOLUME);
|
||||
this.volume = volumeParam instanceof BigDecimal ? new PercentType((BigDecimal) volumeParam) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> execute(Map<String, Object> context) {
|
||||
String sound = module.getConfiguration().get(PARAM_SOUND).toString();
|
||||
String sink = (String) module.getConfiguration().get(PARAM_SINK);
|
||||
public @Nullable Map<String, Object> execute(Map<String, Object> context) {
|
||||
try {
|
||||
audioManager.playFile(sound, sink);
|
||||
audioManager.playFile(sound, sink, volume);
|
||||
} catch (AudioException e) {
|
||||
logger.error("Error playing sound '{}': {}", sound, e.getMessage());
|
||||
}
|
||||
|
@ -12,35 +12,50 @@
|
||||
*/
|
||||
package org.openhab.core.automation.module.media.internal;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.automation.Action;
|
||||
import org.openhab.core.automation.handler.BaseActionModuleHandler;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.voice.VoiceManager;
|
||||
|
||||
/**
|
||||
* This is an ModuleHandler implementation for Actions that trigger a TTS output through "say".
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Christoph Weitkamp - Added parameter volume
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SayActionHandler extends BaseActionModuleHandler {
|
||||
|
||||
public static final String TYPE_ID = "media.SayAction";
|
||||
public static final String PARAM_TEXT = "text";
|
||||
public static final String PARAM_SINK = "sink";
|
||||
public static final String PARAM_VOLUME = "volume";
|
||||
|
||||
private final VoiceManager voiceManager;
|
||||
|
||||
private final String text;
|
||||
private final String sink;
|
||||
private final @Nullable PercentType volume;
|
||||
|
||||
public SayActionHandler(Action module, VoiceManager voiceManager) {
|
||||
super(module);
|
||||
this.voiceManager = voiceManager;
|
||||
|
||||
text = module.getConfiguration().get(PARAM_TEXT).toString();
|
||||
sink = module.getConfiguration().get(PARAM_SINK).toString();
|
||||
|
||||
Object volumeParam = module.getConfiguration().get(PARAM_VOLUME);
|
||||
this.volume = volumeParam instanceof BigDecimal ? new PercentType((BigDecimal) volumeParam) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> execute(Map<String, Object> context) {
|
||||
String text = module.getConfiguration().get(PARAM_TEXT).toString();
|
||||
String sink = (String) module.getConfiguration().get(PARAM_SINK);
|
||||
voiceManager.say(text, null, sink);
|
||||
public @Nullable Map<String, Object> execute(Map<String, Object> context) {
|
||||
voiceManager.say(text, null, sink, volume);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user