I’ve tried to write a device handler which would handle text received with speak command and send it to Alexa to play on Sonos speaker.
I’d appreciate if you can check :
/**
* Alexa Simulator
*
*/
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
preferences {
section {
input "sonos", "capability.musicPlayer", title: "On this Speaker", required: true,multiple:true
input "alexaApiKey", "text", title: "Alexa Access Key", defaultValue:"millave"
}
}
metadata {
// Automatically generated. Make future change here.
definition (name: "Alexa Device", namespace: "alexa", author: "ooo") {
capability "Speech Synthesis"
command "speak", ["string"]
}
// Main
standardTile("main", "device.status", width: 1, height: 1, canChangeIcon: true) {
state "playing", label:'Playing', action:"music Player.stop", icon:"st.Electronics.electronics16", nextState:"paused", backgroundColor:"#79b821"
state "stopped", label:'Stopped', action:"music Player.play", icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "paused", label:'Paused', action:"music Player.play", icon:"st.Electronics.electronics16", nextState:"playing", backgroundColor:"#ffffff"
state "no_media_present", label:'No Media', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "no_device_present", label:'No Present', icon:"st.Electronics.electronics16", backgroundColor:"#b6b6b4"
state "grouped", label:'Grouped', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
}
standardTile("status", "device.status", width: 1, height: 1, decoration: "flat", canChangeIcon: true) {
state "playing", label:'Playing', action:"music Player.stop", icon:"st.Electronics.electronics16", nextState:"paused", backgroundColor:"#ffffff"
state "stopped", label:'Stopped', action:"music Player.play", icon:"st.Electronics.electronics16", nextState:"playing", backgroundColor:"#ffffff"
state "no_media_present", label:'No Media', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "no_device_present", label:'No Present', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "paused", label:'Paused', action:"music Player.play", icon:"st.Electronics.electronics16", nextState:"playing", backgroundColor:"#ffffff"
}
valueTile("currentSong", "device.trackDescription", inactiveLabel: true, height:1, width:3, decoration: "flat") {
state "default", label:'${currentValue}', backgroundColor:"#ffffff"
}
standardTile("refreshPlayer", "device.status", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh", icon:"st.secondary.refresh", backgroundColor:"#ffffff"
}
main "main"
details([
"status","refreshPlayer"
])
}
def installed() {
sendEvent(name:"model",value:getDataValue("model"),isStateChange:true)
}
def timer(){
def eventTime = new Date().time
state.gapTime = refreshFrequency > 0 ? (refreshFrequency? (refreshFrequency as Integer):0) * 60 : (parent.refreshMRInterval? (parent.refreshMRInterval as Integer):0) * 60
if ((state.lastRefreshTime ?:0) + (state.lastChange ? state.gapTime * 1000 : 300000) <= eventTime ){
refresh()
}
}
def refresh() {
def eventTime = new Date().time
if( eventTime > state.secureEventTime ?:0)
{
if ((state.lastRefreshTime ?: 0) > (state.lastStatusTime ?:0)){
sendEvent(name: "status", value: "no_device_present", data: "no_device_present", displayed: false)
}
state.lastRefreshTime = eventTime
log.trace "Refresh()"
def result = []
//result << unsubscribe()
//result << delayAction(10000)
result << subscribe()
result << getCurrentStatus()
result << getVolume()
result << getPlayMode()
result << getCurrentMedia()
result.flatten()
}else{
log.trace "Refresh skipped"
}
}
def speak(String msg){
//log.debug ("ALEXA: " + msg)
def speech
speech = safeTextToSpeech(normalizeMessage(message,evt))
sonos.playTrack(speech.uri)
}
def normalizeMessage(message, evt){
if (evt && message){
message = message.replace("#name", evt?.displayName?:"")
message = message.replace("#type", evt?.name?:"")
message = message.replace("#value", evt?.value?:"")
}
if (message){
message = message.replace("#mode", location.mode)
message = message.replace("#location", location.name)
message = message.replace("#s", ttsMode == "Alexa" ? "Alexa, Simon says":"")
}
return message
}
private safeTextToSpeech(message) {
message = message?:"You selected the Text to Speach Function but did not enter a Message"
[uri: "x-rincon-mp3radio://tts.freeoda.com/alexa.php/" + "?key=$alexaApiKey&text=" + URLEncoder.encode(message, "UTF-8").replaceAll(/\+/,'%20') +"&sf=//s3.amazonaws.com/smartapp-" , duration: "${5 + Math.max(Math.round(message.length()/12),2)}"]
}