📜 ⬆️ ⬇️

Voice autoinformer of date and time, pleasant female voice, Russian, based on asterisk? Easy

On the eve of the weekend, there is nothing to occupy, since according to the regulations grandiose settings are not allowed? On an old, abandoned server, asterisk dusty? Is the subscriber 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 the case of ordinal numbers, since the spoken text must be connected and not cut the ear. Try to achieve the following pronunciation:
The current time is fifteen hours, twenty one hours per minute, twenty seconds. Today is Wednesday, October 15th I am .

or
')
The current time is one in one hour , thirty five minutes, ten seconds. Today is Thursday, the sixteenth of October.

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 whom it became interesting, welcome to habrakat.


What time is it now?


I think you should not even mention that your server should know the exact time, relying, for example, on NTP.

In a nutshell about configuring NTP
Time on servers has the property of being out of sync, if it is not let down. An ntp package is required anyway. For myself, I chose the first option with ntpd, since my other servers are failing within the network.
 #yum -y install ntp

Option number 1 . Add servers to taste , depending on the region in which the asterisk is located. The faster the response from the time server, the more accurately it will be set, all other things being equal. 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 right 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 rise before the final REJECT. Remember 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 teach the lady the Russian language


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

Russian sound pack
For Asterisk 1.4, if you add languageprefix = yes to asterisk.conf, the structure of the audio directories will be as in newer versions by default.
Standard directory: / var / lib / asterisk / in which the subfolders depending on the 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 there is none
  #mkdir / var / lib / asterisk / sounds / ru /


Download 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 / en /
  #cp -R ./asterisk-sounds-master/* / var / lib / asterisk / sounds / en /


You can 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


Specify asterisk, use Russian for SIP by adding language = ru to [general]:
 #cat /etc/asterisk/sip.conf
 [general]
 language = en

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 mark in parentheses, which means that this is a template that we later include in [ru]

Let's try to make out one rule. The first thing you should pay attention to is the characters XZ N. They are interpreted by asterisk as special, and if these letters appear in the title of the reading rules, they should be enclosed 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 data XX is any two digits. We play the file digits / mon- (XX-1), where (XX-1) is an arithmetic operation. With X = 02 (yes, it "digests" even such numbers, which will help us a lot), 02-1 = 1, digits / mon-1: "February".

Separately worth mentioning seconds. First, there is only one entry in the recorded phrases: “seconds”. This means that rounded data must 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 of [informer_100] it’s worth explaining the line where in the variable FreezeEPOCH add 15 seconds to unixtime. This is done to compensate for the time spent on playing files that precede seconds.

Next, we TimeNow date format we need in the TimeNow variable. It contains data in the form: 201410160043.34-4-289 . When reading, we pull the necessary numbers out of the “array”. They are always in their places and extraction is not difficult. More information about the formats can be found in #man strftime .

About working with asterisk variables can be found under the spoiler
The full syntax of the ${AnyVariable:x:y} variable, 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 ${AnyVariable:x:y} construct, you can extract the following data:

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


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

Perhaps some of the readers will want to independently form the rules, 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 following dialplan `th.

dialplan to iterate over numbers / ordinal numbers / something
 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:

Source: https://habr.com/ru/post/240649/


All Articles