📜 ⬆️ ⬇️

Using Asterisk to receive data from security systems

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



Contact ID
Contact 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:

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:
 #!/bin/bash dialednum="" exec < $1 while read s do if [ "${s:0:10}" = "DIALEDNUM=" ] then dialednum=${s:10} fi if [ "$s" == "[events]" ] then break fi done while read s do if [ "$s" != "" ] then r=<  hex-,    «»    > if [ "$dialednum" == "xxxxxx" ] then echo $r | xxd -r -p > /dev/udp/192.168.1.xxx/3322 fi if [ "$dialednum" == "yyyyyy" ] then echo $r | xxd -r -p > /dev/udp/192.168.1.yyy/3322 fi break fi done rm -f $1 


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.

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


All Articles