Text-to-Speech in openHAB
In my ongoing endeavor to improve our home, a while ago I added a notification when the washing machine and the dryer are finished. The notification is send to a Telegram channel. Over the summer vacation I added a number new ChromeCast Audio devices (Google no longer offers the Audio CC, if you need one get one now). One is placed in the kitchen. Not only can I listen to music while eating breakfast, I can also output notifications, by using the CC as an audio sink in openHAB.
To make that useful, I decided to use a Text-to-Speech system. openHAB offers a couple different TTS systems, however most of them need a cloud integration, and therefore a working Internet connection. The "Pico TTS" works standalone, and was my favorite choice for this implementation.
Installation
The default Debian installation in Raspbian does not have Pico TTS available, it's in the "non-free" repository. So I had to install that first. The Ansible Playbook:
- name: add Debian non-free signing key
apt_key:
url: https://ftp-master.debian.org/keys/release-10.asc
keyring: /etc/apt/trusted.gpg.d/debian-10.gpg
state: present
- name: add Debian non-free repository
apt_repository:
repo: "deb http://deb.debian.org/debian {{ ansible_distribution_release }} non-free"
filename: "non-free"
state: present
update_cache: yes
register: non_free_repository
Then install the Pico TTS package:
- name: Install TTS packages
apt:
name:
- libttspico-utils
state: present
And configure it in openHAB:
- name: Set TTS settings
lineinfile:
dest: /etc/openhab2/services/runtime.cfg
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: "{{ item.state }}"
loop:
- { regexp: '^#? ?org.eclipse.smarthome.voice:defaultTTS=', line: 'org.eclipse.smarthome.voice:defaultTTS=PicoTTS', state: present }
- { regexp: '^#? ?org.eclipse.smarthome.voice:defaultVoice=', line: 'org.eclipse.smarthome.voice:defaultVoice=picotts:enUS', state: present }
notify:
- restart openhab2
Rules
In my rules file for the washing machine and the dryer I expanded the notification a bit:
if (now.isAfter(now.withTimeAtStartOfDay.plusHours(6).plusMinutes(0)) && now.isBefore(now.withTimeAtStartOfDay.plusHours(23).plusMinutes(0))) {
if ({{ CC_Kitchen_Audio|replace(':','_') }}_volume.state != 50) {
{{ CC_Kitchen_Audio|replace(':','_') }}_volume.sendCommand(50)
}
playSound("{{ CC_Kitchen_Audio }}", "computerbeep_55.mp3")
Thread::sleep(500)
say("Washing machine is finished", "picotts:enUS", "{{ CC_Kitchen_Audio }}")
}
The "{{ CC_Kitchen_Audio }}" is replaced by Ansible with the actual details of the ChromeCast. I described the details in this blog posting.
The "say()" command accepts 3 parameters:
- The text
- The language (US english here)
- The audio sink (the ChromeCast)
Before the text is spoken, I also output a short beep, to raise attention and activate the ChromeCast. And I set the volume to 50 percent if that is not yet the case.
Finally all of this only happens if the time is between 6 in the morning and 11 in the evening. Don't want the system to talk in the middle of the night, if someone might sleep in the next room.
Comments
Display comments as Linear | Threaded