Page 1 of 1

Make Domoticz speak from a dzVents script

Posted: Thursday 10 August 2017 17:15
by BakSeeDaa
I frequently use a dzVents helper function to have messages spoken. It can be that paper mail arrived, an alarm sensor has been tripped or that a door has been unlocked for a while. This is not a HOWTO. It's just an example how I have done it and it can be done differently.

I have a second Raspberry Pi that streams swedish radio all day using mpc (Command-line client for MPD). This machine is connected to an external speaker.

In a dzVents script, I do this:

Code: Select all

domoticz.helpers.speak(domoticz, 'Hallå eller? Elva miljoner. I Balltorp', 1)
The second argument tells the function that it is allowed to speak at night. If omitted, silence will not be broken.

Then I have defined a dzVents helper function in global_data.lua

Code: Select all

return {
	data = {
	},
	helpers = {

		speak = function(domoticz, speakMessage, canSpeakAtNight)
			local NOTHINGTOSAY = 'Nothing to say'
			speakMessage = speakMessage or NOTHINGTOSAY
			canSpeakAtNight = canSpeakAtNight or 0

			if ((domoticz.security ~=  domoticz.SECURITY_DISARMED) and canSpeakAtNight == 0) then
				return -- Not a good time to speak unless canSpeakAtNight flag was specified
			end
			domoticz.log('Speaking: '..speakMessage, domoticz.LOG_FORCE)
			-- The following will execute as root and it's public key must have been added into authorized_keys
			os.execute('ssh pi@myotherhost \'/home/user/scripts/sh/text2speech.sh ' .. speakMessage .. '\' > /dev/null 2>&1 &')
		end,
	}
}
The command is sent to run in the background and won't delay the Domoticz eventsystem.
My Domoticz host has been allowed to ssh into myotherhost (Authentication SSH-Keygen Keys)

Then on myotherhost I have a script named /home/user/scripts/sh/text2speech.sh :

Code: Select all

#!/bin/bash
ME=`basename "$0"`;
LCK="/var/tmp/${ME}.LCK";
exec 8>$LCK;

flock -x 8;
#echo "I'm in ($$)";

INPUT=$*
STRINGNUM=0

mpc | grep "playing" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "mpc is playing"
    mpc toggle
    MPCPLAYS=1
else
    MPCPLAYS=0
fi
amixer -q set Speaker 80%

ary=($INPUT)
for key in "${!ary[@]}" 
  do
    SHORTTMP[$STRINGNUM]="${SHORTTMP[$STRINGNUM]} ${ary[$key]}"
    LENGTH=$(echo ${#SHORTTMP[$STRINGNUM]})
    #echo "word:$key, ${ary[$key]}"
    #echo "adding to: $STRINGNUM"
    if [[ "$LENGTH" -lt "100" ]]; then
      #echo starting new line
      SHORT[$STRINGNUM]=${SHORTTMP[$STRINGNUM]}
    else
      STRINGNUM=$(($STRINGNUM+1))
      SHORTTMP[$STRINGNUM]="${ary[$key]}"
      SHORT[$STRINGNUM]="${ary[$key]}"
    fi
done
 
for key in "${!SHORT[@]}"
  do
    FILE=/home/pi/domoticz/phrases/$(echo ${SHORT[$key]} | gawk '{x = tolower($0); print x;}' | sed 's/[ \t]*$//' | sed 's/\.$//' | sed -e 's/[^a-z0-9_]/_/g'|sed -e 'y/åäöüé/aaoue/').mp3
    if [ ! -f "$FILE" ]; then
      echo "Requesting the file from google translate"
      #echo "line: $key is: ${SHORT[$key]}"
      #echo "Playing line: $(($key+1)) of $(($STRINGNUM+1))"
      NEXTURL=$(echo ${SHORT[$key]} | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g')
      wget --user-agent='Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0' "http://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&q=$NEXTURL&fl=sv&tl=sv" -O "$FILE"
    fi
  mpg123 -q --buffer 1024 "$FILE"
done
amixer -q set Speaker 40%

if [ "$MPCPLAYS" -eq "1" ]; then
    echo "Restart mpc"
    sleep 1
    mpc toggle
    sleep 1
fi

#echo "I'm done ($$)";
It will pause the radio streaming using MPC in case it's playing. Current state is saved.
It raises the volume using amixer.
Then looks if that phrase has been spoken before.(All spoken phrases are saved on harddisk) If not it asks google translate to make a sound file for us and saves the file. It works for a lot of languages. Swedish works for example so Dutch would probably also be OK.
It plays the sound file(s) and resets the volume to normal.
Finally it restarts the radio streaming using mpc.

That's it. It sounds like it wouldn't work but it works more or less flawlessly.

There may be a lot of solutions out there for having Domoticz speaking. Before I used an old cellphone and tasker app for this. I had problems though that the phone wasn't reliable, it went to sleep sometimes or just disconnected from the WiFi. The TTS voice was nice and clear though.

It was hard to find a good TTS engine for my Raspberry Pi but Google Translate makes a decent work.

Feel free to post in this thread how you have solved the same task.