📜 ⬆️ ⬇️

MiniATS at home

I have a landline phone from Ukrtelecom. And everything would be fine if they did not steal the telephone cable. And once again left without a city connection, I decided to look for alternatives. My Internet is on optics. Having learned that Ukrtelecom provides SIP telephony services, I was already glad to solve the problem with a little blood. However, it turned out that the number will change with me. But the old number is the only thing that stopped me from leaving Ukrtelecom. Well, since I couldn’t avoid losing a number, then I decided to tackle more closely the issue of providing myself with a connection.

Immediately, the first alternative seems to be a CDMA tube, but I have 6 tubes in my house with 3 tubes for 2 bases (4 tubes in the house, 1 in the summer kitchen, 1 in the garage), this is very convenient when the handset is always at hand and not you have to carry it with you. I did not know about the Huawei-1201 CDMA terminal at that time, and if I had known, then this article would not have existed now. That's why I saw my solution in the world of SIP telephony.

I found out that in order to connect analog phones to the SIP line, a VOIP gateway is needed. Well, once the telephony is digital, then why not make a “control panel” to it?

At that moment, I only read about SIP telephony on Habré about Asterisk headers, skipping them, thinking that:
')
1) it is very difficult for me.
2) I do not need it.

In both points I was wrong.

Once upon a time I watched a video by Dmitry Bachilo, about installing OpenWrt on a TP-Link TL-WR842 router, where he reported, among other things, that I installed Asterisk on similar devices. Thanks to Dmitry for his video. And when I chose a router, I decided that I would buy a router, on which Dmitry put OpenWRT, so that there would be no surprise that in case of buying another router, it does not support OpenWRT, the advantage was also the fact that it had a USB port. Installing almost immediately after buying OpenWRT 05/15/1 on the router and inserting a USB flash drive into it, thus making it its home file server. It was about 10-12 months ago. Frankly, with OpenWRT, I have not had a deal with this and I learned about many technologies thanks to Dmitry's video.

I also found articles about screwing GSM modems to Asterisk. Since I had a usb port in the router, I decided to carry out this task as well, though without knowing which side to begin to solve it.

Having found the step-by-step tutorial on installing Asterisk 11 on OpenWrt, I began to carry it out, following each step. However, at the end I was disappointed, when I tried to run Asterisk 11 in OpenWRT 15, I saw an error Segmentation fault. The first question that arises from an unaware reader: why exactly Asterisk 11? Because it is for this version that there is a package chan_dongle, which allows you to hook Huawei GSM modems to Asterisk. After searching the Internet for the cause of the Segmentation fault, I did not find anything intelligible, except for “OpenWRT 15 is bad, OpenWRT 14 is good.” Since I had no experience with this issue, I had to “write to believe”. Having installed the 14th version of OpenWRT, I still managed to install and run Asterisk. But this is not enough, you need to configure it. Searching the Internet again, I came across a SIP provider like Zadarma, whose internal numbers are free. For the test is the most! By registering two accounts, I tried to call from a computer to a smartphone. The call has passed. So I set all the parameters correctly. The site has instructions on how to connect to Asterisk, however, there’s one line missing, which needs to be written in the sip.conf file

register => 111111:password@sip.zadarma.com/111111  111111-  

Having registered the settings of the number 101 on my smartphone, I began to call again from the computer. Having played enough and making sure of the viability of the idea, I began searching for a VOIP gateway. After going through a bunch of options on OLX, I decided to order a gateway in China. Having ordered the Linksys pap2t, I began searching for a suitable GSM modem, all on the same free ad site. The most common modem supporting voice transmission was the Huawei e1550, which I bought. However, since I did not have a USB hub at that time, I tried to install OpenWRT on a memory card inserted into the modem. Unfortunately unsuccessfully. The memory card was initialized after mounting the root file system. But I didn’t give up trying to do it and even deciding to try to completely rebuild OpenWRT from the sources (what if it helps?). Relentlessly compiling in the evenings different versions of OpenWRT I tried to get a modem boot from a memory card, but I achieved a completely different result. It turns out Asterisk 11 under OpenWRT 15 - works !!! If both the firmware and the package compile together. Still, having surrendered, I acquired a USB hub, installed OpenWRT on a USB flash drive, and inserting a modem into the neighboring port, I began to configure chan_dongle. However, since I’m already compiling the firmware myself, chan_dongle decided to build from the sources.

Waiting for the gateway from China, I decided to find out that I can squeeze out my PBX, and first of all I wrote a script on Bash that forms a voice file from the caller’s number, and then when I call from my second Zadarma number, I played this file and I could find out the number of the last person calling me home, even if I was not at home. I also wrote the bash script for the first time and much was not obvious to me. As a result, after conducting experiments, when connecting to a slow Internet channel and calling home to Zadarma number, it was not possible to disassemble many numbers. Yes, and the Bash script was not devoid of errors, for this I’m not going to post it here, I’ll just say that while I was trying to figure out how to call the script I came across such a wonderful thing as AGI. Which allows using PHP, Perl or CGI scripts as a handler.

In parallel with writing scripts, I called my friends and acquaintances through different softphones from a smartphone. The call route was as follows: SoftFon (different SIP clients) => Asterisk => GSM modem => GSM phone. And without exception, everyone talked to me about the terrible quality of my voice, while I heard everyone perfectly. This brought me to the fact that I had to register allowed codecs for each channel. Having tried the G722 codec, I realized that the capacity of my router would obviously not be enough to encode voice and work as the main gateway of my Internet. Therefore, for Asterisk, I decided to purchase a separate router. However, the G711 codecs (alaw / ulaw) came to light with the most optimal sound quality. I stopped at them, although I was clearly dissatisfied with the quality of my voice.

The next step for me was the call detailing, and their recording. Both of these tasks can be solved internally with Asterisk, 1 - CDR, 2 - MixMonitor. CDR - serves to detail calls, and can record them from a CSV file to a MySQL database, which I planned to use as a database. But later, after reading that MySQL would be too voracious for a router, I shifted my choice in favor of SqLite3. Here is my cdr_sqlite3_custom.conf file

 table => cdr columns => calldate, clid, dcontext, channel, dstchannel, lastapp, lastdata, duration, billsec, disposition, amaflags, accountcode, uniqueid, userfield, call_num, dist values => '${CDR(start)}','${CDR(clid)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}','${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(call_num)}','${CDR(dist)}' 

Having wrapped the call in MixMonitor, I record the call, but the recording goes to the wav file, and this format loves a lot of space, that's why I installed the lame package and after recording, I will convert the file to mp3.

In the meantime, my Linksys pap2t has already arrived and I could already connect a regular landline phone instead of a smartphone for the test. And what was my surprise when, when calling through this gateway, the problem with the quality of the outgoing voice disappeared. Those. I was already heard as well as I heard the interlocutor.

In search of a router that will be allocated only for PBX (I decided to look for Ali), my choice fell on OYE-0001 , because it already had a built-in card reader for MicroSD cards and OpenWRT standing out of the box. After placing the order, I sat down again for writing scripts. While writing scripts, it turned out that the Huawei E1550 modem has the ability to go to the astral, and only a complete reset on power helps from this. Those. pulling out and installing the modem back. (Looking ahead, I will say that this problem has not been solved yet, although there is a proposed solution.)

Having received a Chinese router, I again began to try to install the firmware on an external medium, but this time on a memory card inserted into a card reader. On the stock firmware, I managed to do this, but the packages I needed from the OpenWRT repository did not work on it. By this, I tried again to compile the firmware myself. I tried to collect exactly the 15th version. But having tried various pre-settings from similar routers, on the MT7620 processor, I constantly had something, but it did not work as it should. But since there is little experience, I could not solve the problem. However, it turned out that the 16th (trunk, test) version of OpenWRT supports my router out of the box and there is even a firmware on the site, which I hurried to download. And in this firmware I managed to do everything that I had in mind, i.e. install OpenWRT on a memory card, configure the network and install the packages I need. If anyone sets up a 16-trunk, OpenWRT version, it does not have the Luci package. Those. Web-based GUI. And the network settings will need to be made via the console in the / etc / config / network file.

The final stage - connecting the city number.

As a provider for a city number, I chose Intertelecom for myself. This is a CDMA operator that provides SIP telephony services. I saw my home PBX as follows: 2-GSM modem and SIP channel from Intertelecom, since chan_dongle did not know how to work with CDMA modems. But again gathering information, I came across chan_cdma . This library allows you to work with a CDMA modem ZTE AC8710. Thanks a lot to Oleg Zhabko for writing a module for working with this modem. But it was written under Asterisk 1.8, and I used 11. Next, among the ads, I came across a ZTE AC8700 modem (it looks like 1 in 1 AC8710), for 35 UAH. (this is a ball). By this, I decided to invest in this experiment and purchased this modem. Later I found out that chan_cdma was written based on chan_dongle. Therefore, in order to make the modem work under 11 Asterisk, you will need a tedious copy-paste code from one project to another. But having done the most thorough copy-paste, transferring to the project chan_dongle only the sections responsible for working with CDMA, but I didn’t understand the meaning of the code especially. Alas, I could not get the modem to work and call the operator. Then I had to make an effort and still began to delve into the code by constantly inserting debug messages. I began to notice that there are data checking places in the code that are commented out, and the “if (1) {...}” stubs are inserted instead. Then I got to the code that is responsible for checking the registration on the network and also “drowned out” it too. And “lo and behold!”, I was able to make a call to the operator, but since I don’t know the purpose of these checks, I just added the number that my modem returned to the “skip”.



I suffered with the chan_cdma library for about 2 weeks, and during that time I stumbled upon the Huawei-1201 CDMA terminal and since I didn’t believe in an optimistic final with a modem. Then I decided not to depend on the wires, the optical cable can also be stolen. By this decided to organize a "plan B". Purchase a Voip gateway with an FXO port, purchase a Huawei-1201, put a terminal on this port and it will all go through my Asterisk server. Looked again at ads on the site, I came across TP-Link TD-VG3631 . After reading the Internet descriptions, I realized that this is exactly what I need. 2FXS port and 1 FXO. Yes, and in my city for sale, I immediately decided to buy. But after the purchase, having rummaged in the settings, I was very disappointed. Since firstly, it was possible to call on “FXO” only from internal phones, and secondly, for this it was necessary to use a “prefix”. And this is already a “crutch” in my system, since then the call will bypass my PBX and not all houses will remember that to call, "now you need to dial additional numbers." That is why it never came to the purchase of the terminal. Another disappointment was that Tp-Link TD-VG3631 did not recognize SIP numbers, shorter than 3 digits. Before that, my internal numbers were 11 and 22 respectively. By that time, I had already repaired the line of Ukrtelecom and for this reason I decided to leave Tp-Link TD-VG3631, since he could redirect the incoming call to the FXO port to the SIP number.

By that moment, I already had an AGI script for handling incoming calls, the algorithm for its work was as follows. If the number is ringing for the first time, then we check to skip the call in any case and write the number in the phone book, if we have this number in the phone book and it is not on the black list - we skip the call, otherwise we’ll drop it. The phonebook database file decided to place it in the same place where the call detail file in / var / log / asterisk is located. But here again disappointment awaited. After reboot, this folder is cleared. It was necessary in the Asterisk source in the file cdr_sqlite3_custom.c to change the path to the location of the master.db file to / www /. I will also say that the res_agi.ipk package does not work out of the box and requires res_speech.so to work. Then I tried to manually slip this file from the OpenWRT build folder into the / var / lib / asterisk / modules directory and it all worked.

The next change in the incoming call processing file, the number was checked and if it corresponded to my second private number, then the list of the last 5 incoming numbers was sent to it first, with the time they called, and only then the call was made to the internal numbers. This is the code itself.

in.php
 #!/usr/bin/php-cgi -q <?php class MyDB extends SQLite3 { function __construct($filename) { $this->path = "/www/"; $this->filename = $filename; if(!file_exists($this->path.$filename) && $filename == 'phonebook.db'){ $this->create_phonebook_db(); }else{ $this->open($this->path.$filename); } } public function doit($sql) { $result = $this->query($sql); $row = array(); $i=0; while($res = $result->fetchArray(SQLITE3_ASSOC)){ $row[$i] = $res; $i++; } return $row; } private function create_phonebook_db() { $this->open($this->path.'phonebook.db'); $sql="CREATE TABLE phonebook( id INTEGER PRIMARY KEY AUTOINCREMENT, phone_num TEXT, name TEXT, blacklist INTEGER, last_call DATATIME )"; $this->query($sql); $sql="CREATE TABLE sms( id INTEGER PRIMARY KEY AUTOINCREMENT, phone_num TEXT, sms_text TEXT, sms_time DATATIME )"; $this->query($sql); $sql="CREATE TABLE ussd( id INTEGER PRIMARY KEY AUTOINCREMENT, phone_num TEXT, sms_text TEXT, sms_time DATATIME )"; $this->query($sql); } } function show_date_from_base($date) { $time = strtotime($date); $time+=7200; return date('dmY  H:i:s',$time); } set_time_limit(0); require('phpagi.php'); #       AGI $agi = new AGI(); $db = new MyDB('phonebook.db'); $now = date('Ymd H:i:s'); $cid = $agi->request['agi_callerid']; if(substr($cid,0,1) == "+") $cid = substr($cid,1); // + if(strlen($cid) > 10 && substr($cid,0,3) == "380") $cid = substr($cid,2); // 380  0 $agi->set_variable("CDR(call_num)", $cid); if($cid == "XXXXXX"){ //Zadarma $db_cdr = new MyDB('master.db'); $sql="select * from cdr where call_num != 'sms_ussd' AND channel NOT LIKE '%ussd%' AND dist = 'in' GROUP BY call_num ORDER BY calldate DESC LIMIT 0,5"; $calls = $db_cdr->doit($sql); $agi->answer(); $agi->send_text("_____________\n"); $agi->send_text("_____________\n"); for($n = 0; $n < count($calls);$n++){ $agi->send_text($calls[$n]['call_num']."\n"); $agi->send_text(" ".show_date_from_base($calls[$n]['calldate'])."\n"); } $agi->wait_for_digit(10000); } $sql="select * from phonebook where phone_num = '".$cid."'"; $book = $db->doit($sql); if(count($book) == 0) { $agi->exec_dial("SIP/221&SIP/222&SIP/33"); #     $agi->hangup(); #   if(trim($cid)!=""){ $sql="insert into phonebook( phone_num, name, blacklist, last_call) VALUES ('".$cid."', '', '0', '".$now."')"; $db->exec($sql); } }else{ if($book[0]['blacklist'] == 0) { $agi->exec_dial("SIP/221&SIP/222&SIP/33"); #     $agi->hangup(); #   if(trim($cid)!=""){ $sql="UPDATE phonebook SET last_call = '".$now."' where phone_num = '".$cid."'"; $db->exec($sql); } }else{ $agi->hangup(); #   if(trim($cid)!=""){ $sql="UPDATE phonebook SET last_call = '".$now."' where phone_num = '".$cid."'"; $db->exec($sql); } } } ?> 


extensions.conf
[globals]

RECDIR = / var / spool / asterisk / monitor
SAVEMP3DIR = / www / light / monitor

[dongle-incoming-sms]

exten => sms, 1, Noop (Incoming SMS from $ {CALLERID (num)} $ {BASE64_DECODE ($ {SMS_BASE64})} - $ {SMS})
exten => sms, n, Set (CDR (call_num) = sms_ussd)
exten => sms, n, AGI (sms.php, $ {CALLERID (num)}, $ {SMS})
exten => sms, n, hangup ()

[dongle-incoming-ussd]

exten => ussd, 1, Noop (Incoming USSD: $ {BASE64_DECODE ($ {USSD_BASE64})})
exten => ussd, n, Set (CDR (call_num) = sms_ussd)
exten => ussd, n, AGI (ussd.php, ussd, $ {USSD})
exten => ussd, n, hangup ()

[all-in]

include => dongle-incoming-sms
include => dongle-incoming-ussd

exten => X., 1, Set (MON_FILE = $ {UNIQUEID} - $ {STRFTIME ($ {EPOCH} ,,% Y-% m-% d-% H% M)} - $ {CALLERID (num)} - $ {CDR (dst)})
exten => _X., 2, Set (CDR (userfield) = $ {MON_FILE});
exten => _X., 3, Set (CDR (call_num) = $ {CALLERID (num)})
exten => _X., 4, Set (CDR (dist) = in)
exten => _X., 5, MixMonitor ($ {MON_FILE} .wav)
exten => _X., 6, AGI (in.php); sent to the internal number
exten => _X., 7, Hangup ()
exten => _X., 8, StopMixMonitor ()

exten => + X., 1, Set (MON_FILE = $ {UNIQUEID} - $ {STRFTIME ($ {EPOCH} ,,% Y-% m-% d-% H% M)} - $ {CALLERID (num) } - $ {CDR (dst)})
exten => _ + X., 2, Set (CDR (userfield) = $ {MON_FILE});
exten => _ + X., 3, Set (CDR (call_num) = $ {CALLERID (num)})
exten => _ + X., 4, Set (CDR (dist) = in)
exten => _ + X., 5, MixMonitor ($ {MON_FILE} .wav)
exten => _ + X., 6, AGI (in.php); sent to the internal number
exten => _ + X., 7, Hangup ()
exten => _ + X., 8, StopMixMonitor ()

exten => h, 1, System (/ usr / bin / lame -b 16 -silent $ {RECDIR} / $ {MON_FILE} .wav $ {SAVEMP3DIR} / $ {MON_FILE} .mp3> / var / log / asterisk / wav_2_mp3.log)
exten => h, n, System (/ bin / rm -r $ {RECDIR} / $ {MON_FILE} .wav)

Well, to display statistics, he snapped up a web-interface on calls. This is how it looks. And put it in the folder / www / light /.

image

→ Link to githab web interface statistics

→ Link to githab chan_dongle with support for CDMA modems ZTE AC8700 / 8710.

Makefile to compile in the latest version of OpenWRT (you must replace the native Makefile in the folder /package/feeds/telephony/asterisk-11.x-chan-dongle, leave all patches as is).

Makefile
#
# Copyright © 2013 OpenWrt.org
#
# This is a free software licensed under the GNU General Public License v2.
# See / LICENSE for more information.
#

include $ (TOPDIR) /rules.mk

PKG_NAME: = asterisk11-chan-dongle
PKG_VERSION: = 1.1r35
PKG_REV: = ff0a798b8f73b71af328c53862fd33ec5fe9ce85
PKG_RELEASE: = 6

PKG_SOURCE_SUBDIR: = asterisk11-chan-dongle - $ (PKG_VERSION)
PKG_SOURCE: = $ (PKG_SOURCE_SUBDIR) .tar.gz
PKG_SOURCE_URL: = https: //github.com/superl3n1n/asterisk-chan-cdma-gsm-dongle.git
PKG_SOURCE_PROTO: = git
PKG_SOURCE_VERSION: = $ (PKG_REV)

PKG_BUILD_DIR = $ (BUILD_DIR) / $ (PKG_SOURCE_SUBDIR)

PKG_FIXUP: = autoreconf

PKG_LICENSE: = GPL-2.0
PKG_LICENSE_FILES: = COPYRIGHT.txt LICENSE.txt
PKG_MAINTAINER: = Jiri Slachta <jiri@slachta.eu>

include $ (INCLUDE_DIR) /package.mk

define Package / asterisk11-chan-dongle
SUBMENU: = Telephony
SECTION: = net
CATEGORY: = Network
URL: = https: //code.google.com/p/asterisk-chan-dongle/
DEPENDS: = asterisk11 + libiconv-full + kmod-usb-acm + kmod-usb-serial + kmod-usb-serial-option + libusb-1.0 + usb-modeswitch
TITLE: = Huawei UMTS 3G dongle support
endef

define Package / asterisk11-chan-dongle / description
Asterisk channel driver for Huawei UMTS 3G dongle.
endef

MAKE_ARGS: = \
CC = "$ (TARGET_CC)" \
LD = "$ (TARGET_CC)" \
CFLAGS = "$ (TARGET_CFLAGS) -DASTERISK_VERSION_NUM = aks.a. asterisk-11 / include -DHAVE_CONFIG_H -I. -fPIC "\
LDFLAGS = "$ (TARGET_LDFLAGS) -L $ (STAGING_DIR) / usr / lib / libiconv-full / lib -liconv" \
DESTDIR = "$ (PKG_INSTALL_DIR) / usr / lib / asterisk / modules"

CONFIGURE_VARS + = \
ac_cv_type_size_t = yes \
ac_cv_type_ssize_t = yes

define Build / Configure
$ (call Build / Configure / Default, \
--with-asterisk = $ (STAGING_DIR) / usr / include / asterisk-11 / include \
$ (MAKE_ARGS) \
)
endef

define Build / Compile
mkdir -p $ (PKG_INSTALL_DIR) / usr / lib / asterisk / modules
$ (MAKE) -C "$ (PKG_BUILD_DIR)" $ (MAKE_ARGS) all install
endef

define Package / asterisk11-chan-dongle / conffiles
/etc/asterisk/dongle.conf
endef

define Package / asterisk11-chan-dongle / install
$ (INSTALL_DIR) $ (1) / etc / asterisk
$ (INSTALL_DATA) $ (PKG_BUILD_DIR) /etc/dongle.conf $ (1) / etc / asterisk /
$ (INSTALL_DIR) $ (1) / usr / lib / asterisk / modules
$ (INSTALL_BIN) $ (PKG_INSTALL_DIR) /usr/lib/asterisk/modules/chan_dongle.so $ (1) / usr / lib / asterisk / modules /
endef

$ (eval $ (call BuildPackage, asterisk11-chan-dongle))

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


All Articles