Voice auto-informer for date and time, in a pleasant female voice, Russian language, based on asterisk? Easy

In anticipation of the weekend, there is nothing to occupy yourself with, because according to the regulations grandiose settings are not allowed? On an old, abandoned server, asterisk got dusty? Does the subscriber have nothing to test the telephone line? For those who have no one to talk to and for those who are lost in time .



In this publication, we will focus on cases of ordinal numbers, since the spoken text should be connected and not cut the ear. Let's try to achieve the following pronunciation:
Current time fifteen hour s twenty odes to minutes and twenty seconds. Today is Wednesday, the fifteenth th October I .

or

All times are GMT od Ying hour , thirty-five minutes, ten seconds. Today is Thursday, October 16th.

For simplicity and transparency of implementation, we will not use AGI and ask the iron lady to tell us the date and time, by and large, after working only with dialplan and say.conf. And if your asterisk still does not speak Russian - it does not matter, we will teach it to that. To whom it became interesting, welcome under habrakat.


What time is it now?


I think it’s not even worth mentioning that your server should know the exact time, relying, for example, on NTP.

In a nutshell about setting up NTP
Time on servers has the property of being out of sync, if not failed. The ntp package is required anyway. For myself, I chose the first option with ntpd, as my other servers let the time inside the network.
#yum -y install ntp

Option number 1 . We add the server to taste , depending on the region in which asterisk is located. The faster the response from the time server, the more accurately it will be set, ceteris paribus. I will choose the Russian pool.
#grep "^ server" /etc/ntp.conf
server 0.ru.pool.ntp.org
server 1.ru.pool.ntp.org
server 2.ru.pool.ntp.org
server 3.ru.pool.ntp.org
#chkconfig ntpd on
#service ntpd start

Check that the daemon is listening on the correct ports:
#netstat -putln | grep ntpd

If you want to distribute time to your servers, do not forget to check the firewall, UDP / 123 port. The rule must stand before the final REJECT. Do not forget to save.

#iptables -nL --line-numbers
#iptables -I INPUT 4 -s 10.0.0.0/255.0.0.0 -p udp --dport 123 -j ACCEPT
#service iptables save


Option number 2 . For a one-time adjustment, the ntpdate utility included in the same ntp package is suitable. This option is suitable if the distribution of time from the server is not planned.

#ntpdate ru.pool.ntp.org
9 Oct 17:08:41 ntpdate [32744]: adjust time server 85.21.78.8 offset -0.183259 sec

You can add to cron:
#echo -e "\ n47 * / 1 * * * root / usr / sbin / ntpdate pool.ntp.org> / dev / null \ n" >> / etc / crontab



We will teach the lady Russian


Further, suppose that asterisk is installed, but if it is not, then there is a lot of material on this topic. We also assume that the initial configuration of at least one SIP-phone or softphone has already been made.

Package of Russian sounds
For Asterisk 1.4, if you add languageprefix = yes to asterisk.conf, the sound directory structure will be the same as in newer versions by default.
Standard directory: / var / lib / asterisk / in which subfolders that depend on two "xx" letters of the ISO country code (ru, nl, fr, de, it, pt, es ...)
        sounds / xx
        sounds / xx / digits
        sounds / xx / letters
        sounds / xx / phonetic

Create a directory if it is not
 #mkdir / var / lib / asterisk / sounds / ru /


Loading Russian sounds:
 #wget -O asterisk-sounds-additional-master.zip https://github.com/pbxware/asterisk-sounds-additional/archive/master.zip
 #wget -O asterisk-sounds-master.zip https://github.com/pbxware/asterisk-sounds/archive/master.zip


Unpack:
 #unzip asterisk-sounds-additional-master.zip
 #unzip asterisk-sounds-master.zip


Copy to your place:
 #cp -R ./asterisk-sounds-additional-master/* / var / lib / asterisk / sounds / ru /
 #cp -R ./asterisk-sounds-master/* / var / lib / asterisk / sounds / ru /


See which phrases are recorded in the following files:
 #less ./asterisk-sounds-additional-master/additional-sounds-ru.txt
 #less ./asterisk-sounds-master/core-sounds-ru.txt



sip.conf


We tell asterisk to use the Russian language for SIP by adding language = ru to [general]:
#cat /etc/asterisk/sip.conf
[general]
language = ru

Apply settings:
#asterisk -rx "sip reload"

say.conf


#cat /etc/asterisk/say.conf
[ru-base](!)
    _[n]um:0X		=> num:${SAY:1}
    _[n]um:X 		=> digits/${SAY}
    _[n]um:[1-2]f	=> digits/${SAY:0:1}f
    _[n]um:[3-9]f	=> digits/${SAY:0:1}
    ; Tens
    _[n]um:1X		=> digits/${SAY:0:2}
    _[n]um:1Xf		=> digits/${SAY:0:2}
    _[n]um:[2-9]0       => digits/${SAY:0:2}
    _[n]um:[2-9]0f      => digits/${SAY:0:2}
    _[n]um:[2-9][1-2]   => digits/${SAY:0:1}0, num:${SAY:1}
    _[n]um:[2-9][1-2]f  => digits/${SAY:0:1}0, num:${SAY:1}
    _[n]um:[2-9][3-9]   => digits/${SAY:0:1}0, num:${SAY:1}
    _[n]um:[2-9][3-9]f  => digits/${SAY:0:1}0, num:${SAY:1}
    ; Hundreds
    _[n]um:0XX		=>	num:${SAY:1}
    _[n]um:0XXf		=>	num:${SAY:1}
    _[n]um:[1-9]00	=>	digits/${SAY:0:1}00
    _[n]um:[1-9]00f	=>	digits/${SAY:0:1}00
    _[n]um:XXX		=>	num:${SAY:0:1}00, num:${SAY:1}
    _[n]um:XXXf		=>	num:${SAY:0:1}00, num:${SAY:1}
    ; enumeration
    _e[n]um:X			=>	digits/h-${SAY}
    _e[n]um:X[n]		=>	digits/h-${SAY}
    _e[n]um:0X			=>	enum:${SAY:1}
    _e[n]um:0X[n]		=>	enum:${SAY:1}
    _e[n]um:1X			=>	digits/h-${SAY}
    _e[n]um:1X[n]		=>	digits/h-${SAY}
    _e[n]um:[2-9]0		=>	digits/h-${SAY}
    _e[n]um:[2-9]0[n]		=>	digits/h-${SAY}
    _e[n]um:[2-9][1-9]		=>	num:${SAY:0:1}0, digits/h-${SAY:1}
    _e[n]um:[2-9][1-9][n]	=>	num:${SAY:0:1}0, digits/h-${SAY:1}
    _e[n]um:[1-9]00		=>	digits/h-${SAY}
    _e[n]um:[1-9]00[n]		=>	digits/h-${SAY}
    _e[n]um:[1-9]XX		=>	num:${SAY:0:1}00, enum:${SAY:1}
    _e[n]um:[1-9]XX[n]		=>	num:${SAY:0:1}00, enum:${SAY:1}
[ru](ru-base)
    _chas:0		=>	num:${SAY}, digits/hours
    _chas:1		=>	digits/${SAY}, digits/hour
    _chas:[2-4]		=>	num:${SAY}, digits/hours-a
    _chas:[5-9]		=>	num:${SAY}, digits/hours
    _chas:0X		=>	chas:${SAY:1}
    _chas:1X		=>	num:${SAY}, digits/hours
    _chas:20		=>	num:${SAY}, digits/hours
    _chas:2[1-4]	=>	num:${SAY:0:1}0, chas:${SAY:1}
    _mi[n]uta:0		=>	num:${SAY}, digits/minutes
    _mi[n]uta:1		=>	digits/1f, digits/minute
    _mi[n]uta:2		=>	digits/2f, digits/minutes-i
    _mi[n]uta:[3-4]	=>	num:${SAY}, digits/minutes-i
    _mi[n]uta:[5-9]	=>	num:${SAY}, digits/minutes
    _mi[n]uta:0X	=>	minuta:${SAY:1}
    _mi[n]uta:1X	=>	num:${SAY}, digits/minutes
    _mi[n]uta:[2-5]0	=>	num:${SAY}, digits/minutes
    _mi[n]uta:[2-5][1-9]	=>	num:${SAY:0:1}0, minuta:${SAY:1}
    _seku[n]da:0	=>	num:${SAY}, seconds
    _seku[n]da:[5-9]	=>	num:${SAY}, seconds
    _seku[n]da:0X	=>	sekunda:${SAY:1}
    _seku[n]da:1X	=>	num:${SAY}, seconds
    _seku[n]da:[2-5]0	=>	num:${SAY}, seconds
    _dayofweek:[0-6]	=>	digits/day-${SAY} 
    _dayofmo[n]th:X	=>	enum:${SAY}n
    _dayofmo[n]th:XX	=>	enum:${SAY}n
    _mo[n]th:X		=>	digits/mon-$[${SAY} - 1]
    _mo[n]th:XX		=>	digits/mon-$[${SAY} - 1]


Apply settings:
#asterisk -rx "module reload app_playback.so"



The context [ru-base] in say.conf has a trailing (!)exclamation point in brackets means that this is a pattern that we will include in the future. [ru]

Let's try to parse one rule. The first thing you should pay attention to is the characters of XZ N. They are interpreted by asterisk as special and if these characters appear in the name of the reading rule, they should be taken in square brackets, for example mo [n] th.

_mo[n]th:XX		=>	digits/mon-$[${SAY} - 1]


The syntax is quite simple and the rule is the same if the input XX is any two digits. Play the file digits / mon- (XX-1), where (XX-1) is an arithmetic operation. At X = 02 (yes, it’s “digesting” even such numbers that it will help us a lot), 02-1 = 1, digits / mon-1: “February”.

Separately, it is worth mentioning the seconds. Firstly, in the recorded phrases there is only one record: “seconds”. This means that rounded data should come to the input of this function, for example 0, 10, 20, and so on. And secondly, according to the author, this will facilitate the perception of the information received.

extensions.conf


#cat /etc/asterisk/extensions.conf
[my_regular_context]  ; Там где живет ваш SIP абонент/телефон.
exten => 100,1,Goto(informer_100,s,1)
[informer_100]
exten => s,1,Set(FreezeEPOCH=$[${EPOCH} + 15]) ; Добавляем 15 секунд к unixtime.
 same => n,Set(TimeNow=${STRFTIME(${FreezeEPOCH},,%Y%m%d%H%M.%S-%w-%j)})
 same => n,Playback(silence/1&at-tone-time-exactly) ;Тишина 1 секунда + Текущее время
 same => n,Playback(chas:${TimeNow:8:2},say) ; десять + часов
 same => n,Playback(minuta:${TimeNow:10:2},say) ; сорок + одна + минута
 same => n,Playback(sekunda:${TimeNow:13:1}0,say) ; двадцать + секунд
 same => n,Playback(silence/1&digits/today) ; тишина 1 секунда + сегодня
 same => n,Playback(dayofweek:${TimeNow:16:1},say) ; четверг
 same => n,Playback(dayofmonth:${TimeNow:6:2},say) ; шестнадцатое
 same => n,Playback(month:${TimeNow:4:2},say) ; октября
 same => n,Playback(silence/1&beep) ; тишина 1 секунда + короткий гудок
 same => n,Hangup()

Apply settings:
#asterisk -rx "dialplan reload"


same => n,Set(FreezeEPOCH=$[${EPOCH} + 15])

In the context, [informer_100]it’s worth explaining the line where we FreezeEPOCHadd 15 seconds to unixtime in a variable . This is done to compensate for the time spent playing files before seconds.

Next, we form the date format we need in a variable TimeNow. It contains data in the form 201410160043.34-4-289. When reading, we pull out the necessary numbers from the "array". They are always in their places and extraction is not difficult. For more information on formats, see #man strftime.

About working with asterisk variables can be found under the spoiler
The full syntax of the variable ${AnyVariable:x:y}, where x is the starting position and y is the number of digits to be returned. Let the string be given:
201410160043.34-4-289

Using the construction ${AnyVariable:x:y}, we can extract the following data:

${AnyVariable:0:4}- string 2014 will be returned. Skip the zero characters on the left and take four characters.
${AnyVariable:4:8}- the line 10160043 will be returned.
${AnyVariable:-3:3}- the line will begin with the third character, counting from the end and include three characters, which will give 289.
${AnyVariable:2}- if the number of digits to be returned is not specified, the entire remaining line will be returned, we get 1410160043.34-4- 289.


Based on say.conf, the seconds should be rounded off. From the two-digit seconds format, we select the first digit and add a zero to it: ${TimeNow:13:1}0

Perhaps some of the readers will want to formulate rules on their own, for example, to read rubles. The volume of ready-made examples should be enough to cope with this task. And to check the pronunciation, you can use the dialplan below.

dialplan to iterate over digits / serial numbers / anything
exten => 101,1,Set(Number=0) ; от нуля
	same=>n(start),playback(enum:0${Number}n,say) ; читать enum с предшествующим нулем
	same=>n,Set(Number=$[ ${Number} + 1  ]) ; шаг в единицу
	same=>n,GotoIf($[${Number} <= 9 ]?start) ; до девяти
	same=>n,Hangup()



Bonus : you can listen to the finished result live by phone:

Also popular now: