aqq
(John)
December 29, 2021, 5:41pm
1
Because of some reasons GoogleTTS doesn’t work properly on first run with specific phrase. Second run is usually ok and appropriate communication is established and voice file for say function is accessible.
To address this problem (and any other problems with communication with service and give a chance to retry say action) I’ve wrote lambda:
val saySomething = [ String ttsMessage |
logInfo("lambda", ttsMessage)
var boolean googleSuccess = false
var i = 0
while((i=i+1) <= 3 && !googleSuccess) {
logInfo("Say info", "{} - familyroom - attempt {}", ttsMessage, i)
try {
say (ttsMessage, "googletts:enUSStandardA", "chromecast:chromecast:familyroom")
logInfo("Say error", "{} - familyroom - attempt {} - after say", ttsMessage, i)
googleSuccess = true
} catch (Throwable e) {
logError("Say error", "{} - familyroom - attempt {}", ttsMessage, i)
}
}
if (googleSuccess) {
logInfo("Say info", "{} - bedroom - attempt {}", ttsMessage, 1)
say (ttsMessage, "googletts:enUSStandardA", "chromecast:chromecast:bedroom")
}
"executed"
]
with excecution in rule:
saySomething.apply("Hello world")
Unfortunately say() function does not return any value (explicit: it is void function) and exception. In case of error WARN messages are present in log, however any exception is not thrown.
In my lambda ‘after say’ log is always present. I have no chance to detect wrong call and retry.
Is any workaround possible? In my opinion proper exception should be thrown.
rossko57
(Rossko57)
December 29, 2021, 6:33pm
2
You might ask for an enhancement to say()
, to get a return value. Trouble is that would become ‘blocking’ - how long should it wait to see if it gets a response from the remote service?
It could be made to work like executeCommandLine()
perhaps, with an optional timeout. Provide a timeout to get the response (or failure).
aqq
(John)
January 2, 2022, 8:09pm
3
I wrote workaround:
val saySomething = [ String ttsMessage |
var boolean googleSuccess = false
var i = 0
while((i=i+1) <= 3 && !googleSuccess) {
logInfo("Say info", "{} - bedroom - attempt {}", ttsMessage, i)
try {
say (ttsMessage, "googletts:enUSStandardA", "chromecast:chromecast:bedroom")
var String result = executeCommandLine (Duration.ofSeconds(10), "/openhab/conf/scripts/GOOGLETTS/detect_error.sh", ttsMessage)
if (result.contains("GoogleOK")) {
googleSuccess = true
}
} catch (Throwable e) {
logError("Say error", "{} - bedroom - attempt {}", ttsMessage, i)
}
}
if (googleSuccess) {
logInfo("Say info", "{} - familyroom - attempt {}", ttsMessage, 1)
say (ttsMessage, "googletts:plPLStandardA", "chromecast:chromecast:familyroom")
}
"executed"
]
To detect GoogleTTS errors (/openhab/conf/scripts/GOOGLETTS/detect_error.sh):
#!/bin/bash +e
PHRASE=$@
cat /openhab/userdata/logs/openhab.log | grep -i "Error saying" | tail -n 1 | grep "$PHRASE"
RET_VAL=$?
if [[ "$RET_VAL" == "0" ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleError - \"$PHRASE\"" | tee -a /openhab/userdata/logs/openhab.log
echo "$(date '+%Y-%m-%d %H:%M:%S') error saying - reset error indicator" | tee -a /openhab/userdata/logs/openhab.log
else
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleOK - \"$PHRASE\"" | tee -a /openhab/userdata/logs/openhab.log
fi
Depends of installation type log path and script path have to be set properly. Not perfect, but works.
aqq
(John)
December 30, 2022, 7:33pm
4
Yet another problem with GoogleTTS and yet another workaround:
Problem statement: After migration to 3.4 and refreshing Google configuration OH started to have problems with configuration:
2022-12-30 20:04:01.801 [WARN ] [core.voice.internal.VoiceManagerImpl] - Error saying 'Hello World': Missing service configuration.
This problem happens after some time after successful execution.
Solution (workaround):
Move GoogleTTS configuration into file (described in documentation)
Effectively change configuration (change one of configuration keys) in case of error detected
After configuration change OH refresh TTS configuration and GoogleTTS starts to work again (for some time).
Scripts:
Rule
val saySomething = [ String ttsMessage, String voice |
var boolean googleSuccess = false
var i = 0
while((i=i+1) <= 3 && !googleSuccess) {
logInfo("Say info", "{} - bedroom - attempt {}", ttsMessage, i)
try {
logInfo("Say info", "------ SAY_START ------")
say (ttsMessage, voice, "chromecast:chromecast:bedroom")
var String result = executeCommandLine (Duration.ofSeconds(10), "/openhab/conf/scripts/GOOGLETTS/detect_error.sh", ttsMessage)
if (result.contains("GoogleOK")) {
googleSuccess = true
}
} catch (Throwable e) {
logError("Say error", "{} - bedroom - attempt {}", ttsMessage, i)
} finally {
logInfo("Say info", "------ SAY_STOP ------")
}
}
"executed"
]
Bash script:
#!/bin/bash +e
PHRASE=$@
LINE_START=$(cat /openhab/userdata/logs/openhab.log | grep -n "SAY_START" | tail -n 1 | awk -F: '{ print$1 }')
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - Line start: $LINE_START" | tee -a /openhab/userdata/logs/openhab.log
LINE_ERROR=$(cat /openhab/userdata/logs/openhab.log | grep -n "Error saying" | tail -n 1 | awk -F: '{ print$1 }')
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - Line error: $LINE_ERROR" | tee -a /openhab/userdata/logs/openhab.log
if [[ "$LINE_ERROR" == "" ]]; then
LINE_ERROR=0
fi
LINE_MISMATCH_SERVICE=$(cat /openhab/userdata/logs/openhab.log | grep -n "Missing service configuration" | tail -n 1 | awk -F: '{ print$1 }')
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - Line mismatch: $LINE_MISMATCH_SERVICE" | tee -a /openhab/userdata/logs/openhab.log
if [[ "$LINE_MISMATCH_SERVICE" == "" ]]; then
LINE_MISMATCH_SERVICE=0
fi
if [[ $LINE_ERROR -gt $LINE_START ]]; then
ERROR_SAY="true"
fi
if [[ $LINE_MISMATCH_SERVICE -gt $LINE_START ]]; then
ERROR_CONF="true"
fi
if [[ "$ERROR_CONF" == "true" ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - Missing configuration detected" | tee -a /openhab/userdata/logs/openhab.log
# Effectively change googletts key pitch 0<->1
cat /openhab/conf/services/googletts.cfg | grep -i "pitch=0"
PITCH=$?
if [[ "$PITCH" == "0" ]]; then
sed -i -r 's/^org.openhab.voice.googletts:pitch=.*/org.openhab.voice.googletts:pitch=1/g' /openhab/conf/services/googletts.cfg
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - pitch to 1" | tee -a /openhab/userdata/logs/openhab.log
else
sed -i -r 's/^org.openhab.voice.googletts:pitch=.*/org.openhab.voice.googletts:pitch=0/g' /openhab/conf/services/googletts.cfg
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - pitch to 0" | tee -a /openhab/userdata/logs/openhab.log
fi
sleep 2
fi
if [[ "$ERROR_SAY" == "true" ]] || [[ "$ERROR_CONF" == "true" ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - GoogleError - \"$PHRASE\"" | tee -a /openhab/userdata/logs/openhab.log
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - Error saying - reset error indicator" | tee -a /openhab/userdata/logs/openhab.log
else
echo "$(date '+%Y-%m-%d %H:%M:%S') GoogleTTS check - GoogleOK - \"$PHRASE\"" | tee -a /openhab/userdata/logs/openhab.log
fi
Not elegant but works. Hope it help someone.
Definitely something is wrong in OH GoogleTTS configuration (releasing configuration after some time).