A few years ago, we transferred a security company, in which I was then working, from the usual “wired” telephony to IP based on Asterisk. It was a separate story, with its own samples, mistakes, epic fails and continuous knowledge of the new. Since then, in terms of voice communication, everything has been debugged, it works without failures and is sufficiently satisfactory for all interested parties.
Until recently, only console equipment operated on wire lines, automatically receiving events from protected objects and transmitting them for processing by dispatchers. And finally, the time came when their own laziness and administrative golem were defeated, and the functions of these glands were also transferred to the telephone server.
Baseline and why it was started
- A SIP trunk with a capacity limitation of 15 channels arrives at the office; we have been assigned 10 numbers by the carrier;
- in the operator’s cabinet, there is an “iron” VoIP gateway, from the FXS ports of which lines are laid to our equipment;
- The actual “equipment” is two pieces of iron from different manufacturers that can receive messages from the object security systems in the Contact ID format and transfer them to the dispatcher's workplace program.
Contact IDContact ID is a protocol developed in 1999 by the Ademco group of companies to transmit information from security systems over public telephone networks, and is the de facto standard for developers of such systems around the world. Data is transmitted in the form of DTMF-sequences with checksum verification for each parcel and confirmation from the receiving party. The full specification can be officially purchased on the developers website, but Google gives it out for free in the very first links.
Cons of the available solution:
- an extra chain of conversions VoIP-gateway → analog line → receiver detector, which does not add quality to the incoming signal, which often suffers from bad telephone lines at the sites;
- the impossibility of receiving data from several objects at the same time, since, when transmitting information, the FXS port is naturally busy and the second call on it will not pass (and the transmission of information from a single object in some cases may take minutes)
- the impossibility of determining incoming numbers - the gateway can theoretically issue them, but the equipment is not able to determine;
- the lack of adequate logs and call recordings and, as a result, certain difficulties in diagnosing and configuring “problem” objects with which communication is periodically lost;
- perceptible in the scale of this organization the cost of console equipment, complicated by the need to keep a reserve in case the receiver goes down.
How and what was configured
In the Asterisk distribution, since 2004, the app_alarmreceiver module has been present, which is intended to emulate a console receiver. It is called as a normal dialplan command, answers an incoming call, processes events and puts them into a text file / files as specified in the path settings, after which it can call an arbitrary system command to process these files. What had to face when setting up:
For a start , when receiving data to the log, messages from channel.c of the form began to fall in batches:
')
[Mar 23 22:58:35] DTMF[636][C-00000009] channel.c: DTMF begin '0' received on SIP/inbound-0000000e [Mar 23 22:58:35] DTMF[636][C-00000009] channel.c: DTMF begin ignored '0' on SIP/inbound-0000000e [Mar 23 22:58:35] DTMF[636][C-00000009] channel.c: DTMF end '0' received on SIP/inbound-0000000e, duration 51 ms [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF end emulation of '4' queued on SIP/inbound-0000000e [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF end '0' received on SIP/inbound-0000000e, duration 51 ms [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF begin emulation of '0' with duration 80 queued on SIP/inbound-0000000e [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF begin '1' received on SIP/inbound-0000000e [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF begin ignored '1' on SIP/inbound-0000000e [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF end '1' received on SIP/inbound-0000000e, duration 51 ms [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF end emulation of '0' queued on SIP/inbound-0000000e [Mar 23 22:58:36] DTMF[636][C-00000009] channel.c: DTMF end '1' received on SIP/inbound-0000000e, duration 51 ms
It turned out that although the DTMF standard supports “digits” with a duration of 40 ms, by default, Asterisk is set to 80 ms, and all parcels of shorter duration are emulated to this value. In Contact ID, the digit duration is defined as 50-60 ms. Fortunately, at the request of the public, since 2012, the corresponding #DEFINE in channel.c was duplicated by the mindtmfduration parameter in asterisk.conf, and after setting it to 50, this issue was resolved.
The second problem turned out to be how the data obtained is stored and transmitted further. By default, the entire transfer session from one object is written to a file of the form:
[metadata] PROTOCOL=ADEMCO_CONTACT_ID CALLINGFROM= CALLERNAME=<unknown> TIMESTAMP=Mon Mar 23, 2015 @ 22:59:17 PDT [events] 6238181401000042 623818340100004C
And then to process it, the command specified in the eventcmd parameter of the alarmreceiver.conf file is called. It did not suit me for two reasons:
First of all, the events will be sent to the dispatcher for processing only after the end of the communication session. If something illegal happens at the facility and the alarm sensors are triggered one after another, each such trigger and subsequent recovery will generate new events, and the communication session will end (and as a result, the fighters will be sent by alarm) , as on the object no one else will be left (and potentially - nothing valuable).
Secondly, the Contact ID events themselves do not provide for any timestamp, and the events appear at the dispatcher and are written to the database of the control program as it is received. When receiving events "one big bundle" in the database, they all will have the same timestamp, which may cause confusion when communicating with the owners of the object and difficult to restore the chronology of real events.
It would seem that to prevent such situations, the logindividualevents parameter was made, in which the alarmreceiver creates a separate file for each event. But even here it was not without a fly in the ointment - it creates separate files, but eventcmd still calls only once at the end of the session. As a result, they refused from the regular processing mechanism and added the inc_inosion rule IN_CLOSE_WRITE for the folder with the event files - now they began to be processed immediately after reception.
Thirdly , the metadata of the event files indicates which number the incoming call came from, but it does not indicate which of our numbers it came from. And because of some organizational features, we have several independent dispatch programs with our own databases and our own protected objects for each. Moreover, data from different objects come to different incoming numbers. I had to fix app_alarmreceiver.c and add there to get the DNID from ast_channel and output it along with the rest of the metadata.
Processing and transfer on
There were no special problems, except for the fact that the dispatching program is very proprietary and does not know how to work with third-party equipment for reasons of principle. But she is able to receive data from her equipment via UDP, and the processing has been reduced to a simple bash script that parses the event files created by Asterisk, packages “from her equipment” and sends them to the appropriate dispatch PC, depending on the DNID:
Profits
Were eliminated all the "cons" listed at the beginning of the article. In addition, after a thoughtful smoking of logs, a problem was solved with a single object, which had previously been “shut up” periodically. It turned out that the ancient equipment installed there transmits the checksum "not quite" in accordance with the standard, and our honest and correct hardware receiver refused to digest it. In the new version, everything worked after a small crutch in the checksum verification procedure in app_alarmreceiver.c.
PS By applying and adding a little to the content of this article, you can make your own receiver from the existing burglar alarm and Asterisk by decoding the event codes into text and then sending them to yourself, beloved via e-mail / SMS / in any other way. Moreover, since the overwhelming majority of the object equipment supports the transmission of events to several numbers at the same time, this can even be combined with the police / PSC guard, and use such a system to monitor the facility and monitor the work of the guard. If anyone is interested, I will gladly share their experience.