PREMESSA

Riattivando recentemente il mio centralino causa cambio di configurazione della rete di casa (cambio dettato dalla "fulminazione" di una delle due porte della ALIX alt), mi sono messo a spulciare  i vari moduli presenti su Asterisk (operazione necessaria per far caricare al demone solo i moduli realmente usati) ed ho ritrovato un modulo che già anni fa mi aveva incuriosito: ALARMRECEIVER, la cui funzione è quella di ricevere le segnalazioni da apparati di allarme secondo lo standard SIA/Ademco denominato ContactID. La documentazione mette bene in evidenza che questo è un modulo "sperimentale" intendendo con questo che deve essere usato non in ambienti critici (chi ha bisogno di sicurezza assoluta mette combinatori GSM oppure Ponti Radio).

Ciò nonostante, per un'applicazione "casalinga" mi è sembrato assolutamente appropriato ed ho quindi deciso di provare a collegarlo al mio impianto di allarme, costituito da una "centrale" (in termini anglosassoni denominata, non so perchè, PANEL), dotata appunto di interfaccia telefonica: centrale che, essendo prodotta nel continente Nord Americano, ha già a bordo questo meccanismo di segnalazione.

Mi sono quindi procurato un ATA al quale ho collegato la centrale. Nota di colore: essendo la prima volta che usavo un ATA, prima di collegare la centrale ho fatto una prova mandando l'uscita PSTN ad un modem (non ho telefoni analogici in casa!). Risultato: non sembrava funzionare niente! Dopo svariati tentativi (modifica dei vari parametri dell'interfaccia fisica dell'ATA), stavo quasi per abbandonare il campo quando, quasi per scherzo, ho provato a cambiare il cavetto telefonico..... Aggiungo solo che dopo circa 30 secondi il vecchio cavetto ha trovato casa nel cestino, non prima di essere stato tagliuzzato in svariati pezzi..

Ho quindi configurato asterisk per implementare questa funzione, come ben documentato nei manuale (ovvero configurazione di una opportuna "extension" sulla quale attivare l'applicazione alarmreceiver - si rimanda ai siti ufficiali per la documentazione).
L'ATA è stato configurato per utilizzare il G.711 (ALAW/ULAW non fa differenza) e segnalazione DTMF inband, come consigliato sulla documentazione.

UN PO' DI TEORIA
Senza entrare nel dettaglio specifico (in rete si trovano tutt i documenti), è sufficiente dire che lo standard Ademco ContactID prevede l'utilizzo dei toni DTMF per inviare le segnalazioni (dette eventi) dal PANEL alla centrale di controllo (es. istituti di vigilanza privati). Gli eventi sono composti da stringhe di 15 "digit" contententi diversi parametri, tra cui l'ID della centrale, la classe di evento (simile alle classi dei messaggi di errore HTTP) ed un codice di controllo.
Riporto brevemente uno stralcio di comunicazione, dato che poi mi servirà per il proseguo
  1. Il PANEL compone il numero della centrale di controllo
  2. La centrale di controllo "alza la cornetta" ed invia un segnale di Handshake composto da un tono a 1400 Hz, una pausa, ed un tono a 2300 Hz (le tempistiche dei toni e delle pause sono ben definite)
  3. Dopo l'handshake, il client invia gli eventi tramite toni  DTMF (occhio! i toni DTMF non sono soltanto quelli della tastiera ! in generale, i toni DTMF sono 16, di cui solo 12 rappresentati sulla normale tastiera telefonica)
  4. Se la trasmissione è stata correttamente ricevuta (la stringa contiene un codice di controllo), la centrale di controllo invia un KISSOFF tone di conferma (1400 Hz)
  5. Se ci sono altri eventi da trasmettere la centrale cliente prosegue altrimenti "butta già" il collegamento.
A parte i tecnicismi, quello che preme sottolineare sono le frequenze utilizzate (vedi oltre).
 


IL PROBLEMA
Provando a fare una chiamata di test dalla centrale, il modulo alarmreceiver non si attiva e, controllando sul debug, si ottengono questi errori:

    -- Executing [XXX@DIALPLAN] Ringing("SIP/YYY-00000021", "") in new stack
    -- Executing [XXX@DIALPLAN:2] NoCDR("SIP/YYY-00000021", "") in new stack
    -- Executing [XXX@DIALPLAN:3] Wait("SIP/YYY-00000021", "2") in new stack
    -- Executing [XXX@DIALPLAN:4] AlarmReceiver("SIP/YYY-00000021", "") in new stack
       > AlarmReceiver: Setting read and write formats to ULAW
       > AlarmReceiver: Answering channel
       > AlarmReceiver: Waiting for connection to stabilize
[Dec  2 18:44:48] NOTICE[7793]: channel.c:4147 __ast_read: Dropping incompatible voice frame on SIP/YYY-00000021 of format ulaw since our native format has changed to 0x8 (alaw)
       > AlarmReceiver: Waiting for first event from panel
       > AlarmReceiver: Sending 1400Hz 100ms burst (ACK)
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
       > AlarmReceiver: Sending 2300Hz 100ms burst (ACK)
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
  == AlarmReceiver: DTMF digit timeout on SIP/YYY-00000021 
       > AlarmReceiver: Sending 1400Hz 100ms burst (ACK)
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
       > AlarmReceiver: Sending 2300Hz 100ms burst (ACK)
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
[DATA/ORA] WARNING[7793]: utils.c:1389 tvfix: warning too large timestamp 135384448.7155285
  == AlarmReceiver: DTMF digit timeout on SIP/YYY-00000021 
       > AlarmReceiver: App exiting...

P.S. questa catena veniva proposta più volte, è stata riportata 2 volte per semplicità... Analogamente gli warning erano più numerosi tra un messaggio e l'altro.

Guardando questa traccia, l'unico evento che sembrerebbe degno di nota è il warning too large timestamp.
Inutile dire che i vari forum di asterisk riportavano si questo errore ma mai legato al modulo alarmreceiver.

LA SOLUZIONE

Dopo aver fatto numerose e infruttuose ricerche (trovare la pappa pronta è sempre più facile.....) ho iniziato a fare delle prove specifiche per trovare la soluzione.

La prima prova è stata quella di chiamare, da un telefono VOIP, l'estensione associata all'alarm receiver, provando ad inviare i toni DTMF direttamente dalla tastiera (avevo alcuni esempi di eventi tratti da un PDF con le specifiche del ContactID).
La prova è stata molto istruttiva perchè non solo ha funzionato come previsto (ovvero Asterisk ha ricevuto l'evento) ma mi ha anche fatto capire che il warning NON era assolutamente legato al problema dato che si presentava anche inviando manualmente i toni!
In effetti, il messaggio di errore fa riferimento al modulo utils.c che fa parte di asterisk e non dell'alarmreceiver! Sicuramente l'applicazione alarmreceiver chiama una funzione dentro utils.c (guardando il codice sembra che la funzione sia ast_tvdiff_ms) la quale restituisce un warning che comunque non produce alcun problema. Ergo, la segnalazione di WARNIGN era un falso problema!
 
Ho quindi giocato la seconda carta: ho attivato il modulo CHAN_SPY per "spiare" cosa succede durante la chiamata: questa prova mi ha fatto capire che era proprio la centrale a non rispondere dopo l'invio, da parte di asterisk, dei toni di Handshake

Rimaneva che giocare l'ultima carta, ovvero provare a collegare un telefono analogico all'ATA ed inviare i toni da quest'ultimo: la prova è stata decisiva perchè mi ha fatto scoprire che l'ATA si "mangiava" il primo dei due toni di handshake! L'ATA "filtrava" non solo il primo handshake, ma anche tutti quelli successivi. Era quindi ovvio che, mancando una completa sequenza di handshake, la centrale non inviasse alcunchè.

Ho quindi iniziato a spulciare tutti i parametri dell'ATA in mio possesso (un Grandstream, ma credo che la cosa sia applicabile anche ad altre marche) cercando di trovare un parametro che potesse indicare un qualche "blocco" del primo dei due toni (ricordo che il codec era il G.711 ovvero un codec lossless). Alla fine la mia attenzione è caduta su questo parametro:

 

T38

Il T.38 è il protocollo usato per trasmettere i FAX su sistemi VOIP: questo parametro, in pratica, dice all'ATA di attivare il T.38 quando si accorge che la telefonata è in realtà un FAX. Dato che quello non era il mio caso, ho disattivato la funzione (ovvero l'ho messa in Pass Through) e asterisk ha iniziato a ricevere gli eventi!

In altre parole, la configurazione sull'ATA per attivare automaticamente il protocollo T.38 "bloccava" il protocollo ContactID.

Quindi, qualora si utilizzi un ATA per interfacciarsi ad una centrale di allarme usando il protocollo Ademco ContactID è consigliabile, oltre ad usare il G.711 con DTMF inband, anche disattivare la funzione T.38


POSSIBILE SPIEGAZIONE

Le trasmissioni FAX usano toni a 1100 2100 Hz,  valori "relativamente" vicini a quelli usati dall'handshake del protocollo ContactID. Visto che un ATA ha comunque un'elettronica minimale, mi immagino che l'ATA scambiasse il primo tono di handshake per un tono FAX (vero che distano la bellezza di 300 Hz, ma è anche vero che un ATA economico potrebbe tranquillamente sbagliare!) e attivasse quindi il T.38. E' però vero che, in un secondo momento, ho provato un altro modello di ATA (sempre Grandstream, ma per assurdo più semplice) che non mi sembra abba presentato lo stesso problema.


NOTA:  a chi si chiede a cosa possa servire un centralino telefonico a casa, dico solo che lo scopo originale, nel mio caso, era implementare una sorta di "interfono" per poter agevolmente comunicare da una parte all'altra di casa, soprattutto quando la moglie ti chiama per il pranzo e tu sei con le cuffie in testa cercando di collegare in 20 metri una stazione dall'altro capo del mondo - vedi www.ik5pwc.it