[Frage] Wie das Anrufprotokoll (CDR) in eine MySQL-Datenbank schreiben?

Freakhouse

Neuer User
Mitglied seit
22 Mai 2015
Beiträge
53
Punkte für Reaktionen
1
Punkte
8
Ich würde gerne meinen Asterisk so konfigurieren, dass über jeden Anruf ein Protokoll in einer MySQL-Datenbank gespeichert wird. Für Asterisk muss wohl ein Addon eingerichtet werden (cdr_addon_mysql.so). Ich habe allerdings das kleine Problem, dass mein Asterisk auf einer Synology Diskstation läuft. Das Asterisk-Paket wird von Synology fix und fertig zur Verfügung gestellt. Ich kann da zwar ohne weiteres in den Config-Dateien eigene Anpassungen vornehmen, allerdings habe ich keine Ahnung, wie ich es schaffe, die Anrufprotokolle in die MySQL-Datenbank zu bekommen.

Ich habe zwar die Datei cdr_mysql.conf schon entsprechend angepasst und auch in der Datenbank die entsprechende Tabelle eingerichtet. Allerdings nützt das ja ohne das Addon recht wenig. In den Asterisk-Modulen ist zumindest keine cdr_addon_mysql.so vorhanden.

Kann mir von euch jemand weiterhelfen? :gruebel:
 
Das native MySQL Zeug ist sowieso deprecated, das geht jetzt über ODBC. Wenn es cdr_odbc (oder so ähnlich) und einen MySQL Treiber für ODBC auf dem System gibt, kannst Du das nutzen. Wenn nicht, kommst Du an MySQL nicht direkt dran.
 
Habe nur die Datei cdr_odbc.conf gefunden. Im Ordner "modules" finden sich bezüglich CDR nur die folgende Dateien:

cdr_csv.so
cdr_custom.so
cdr_manager.so
cdr_sqlite3_custom.so.so
cdr_syslog.so

Viele Grüße
 
Moins

Da seh ich doch: cdr_sqlite3_custom.so.so

Wie wärs damit?
Da ist auch SQL drinne...
Code:
openelec:/var/log/asterisk# [COLOR=#ff0000]sqlite3 /var/log/asterisk/master.db[/COLOR]
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> [COLOR=#ff0000]select * from sqlite_master;[/COLOR]
table|[B][COLOR=#800080]cdr[/COLOR][/B]|cdr|2|CREATE TABLE cdr (AcctId INTEGER PRIMARY KEY, calldate,clid,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield,test)
sqlite> [COLOR=#ff0000]select * from [/COLOR][B][COLOR=#800080]cdr[/COLOR][/B][COLOR=#ff0000];[/COLOR]
1|2015-06-08 18:47:52|"Softphone" <1001>|sas|SIP/1001-00000000||Hangup||4.878189|3.871257|ANSWERED|DOCUMENTATION||1433782072.0||
2|2015-06-08 18:48:19|"Softphone" <1001>|sas|SIP/1001-00000001||Hangup||4.520378|3.514399|ANSWERED|DOCUMENTATION||1433782099.1||
sqlite>
 
Zuletzt bearbeitet:
@koyaanisqatsi: Meintest Du, dass ich statt MySQL einfach SQLite nutzen soll, oder dass man mit SQLite auch in MySQL-Datenbanken schreiben kann? Ich habe mich leider noch nie mit SQLite beschäftigt.
 
SQLite bzw. SQLite3 welches vorwiegend genutzt wird, ist eine brauchbare Alternative und eigentlich nicht schwer.
Hier auf meinen Netbook hab ich Windows7 Starter mit XAMPP (apache + mysql), also kann ich es mal testen...
1. Das SQL für die cdr aus der sqlite_master ins Clipboard kopieren...
2. In PHPMyAdmin als root einloggen und neue Datenbank erstellen: asterisk
3. Dann asterisk anklicken, den Reiter SQL anklicken und den Code
aus dem Clipboard in die Textbox einfügen und anpassen...
PHP:
CREATE  TABLE cdr(AcctId INTEGER PRIMARY  KEY ,
calldate varchar( 255  ) ,
clid varchar( 255  ) ,
dcontext varchar( 255  ) ,
channel varchar( 255  ) ,
dstchannel varchar( 255  ) ,
lastapp varchar( 255  ) ,
lastdata varchar( 255  ) ,
duration varchar( 255  ) ,
billsec varchar( 255  ) ,
disposition varchar( 255  ) ,
amaflags varchar( 255  ) ,
accountcode varchar( 255  ) ,
uniqueid varchar( 255  ) ,
userfield varchar( 255  ) ,
test varchar( 255  ) )
...damit MySQL/PHPMyAdmin nicht meckert. ;)
...und SQL ausführen.

Tja, das jetzt nur mal so als Beispiel.

SQLite2/3 ist serverlos, Dateibasiert.
Die Unterstützung für PHP gibts als PDO, meist unbemerkt mit dabei.
Ein Datenbanköffner (wird einfach inkludiert) sieht dann so aus...
PHP:
<?php
date_default_timezone_set('Europe/Berlin');
$strDatenbank = 'sqlite:/var/log/asterisk/master.db';
$dbh = new PDO($strDatenbank);
?>

Die sqlite_master Tabelle ist genial, da kannst du in 10 Jahren noch erkennen wie die Tabellen heissen und ihre Felder.
...und auch SQL welches blind/automatisch ihre FETCH Ziele aus der sqlite_master extrahiert, ist vorstellbar. ;)

Auch praktisch: CREATE TABLE IF NOT EXISTS cdr(ID TYP, u.s.w.)
...solches SQL führt bei SQLite3 (2 kannste vergessen) dazu dass die Datei auch gleich miterstellt wird, falls nach einem Reboot/Backup oder was auch immer, diese nicht mehr existieren sollte.
...oder schlicht und ergreifend: Die Datei angelegt werden muss
 
Zuletzt bearbeitet:
@koyaanisqatsi: Die Tabelle mit den einzelnen Spalten hatte ich mir in meiner MySQL-Datenbank schon angelegt. Mein Problem ist, wie ich es schaffe, dass Asterisk die CDRs nun in meine MySQL-Datenbank reinschreibt.
 
Ganz plump?

Mit PHP.
Die SQLite3 DB kann jederzeit, auch im Betrieb kopiert/gedownloaded werden (wget).
Dann mit PHP die sqlite3 auslesen und mit PHP in die mysql einlesen.

Ansonsten: mit sqlite3 exportieren (CSV) und in die MySQL Datenbank importieren.
...aber das kannste mit der /var/log/asterisk/cdr-csv/Master.csv ja auch.

Hast du die Master.csv schon erfolgreich importieren können?
 
Zuletzt bearbeitet:
Das mit dem Importieren wäre auf jeden Fall eine Lösung. Ich hätte es nur gerne, dass mir Asterisk mehr oder weniger direkt in die Datenbank schreibt. Ich grüble gerade über folgende Möglichkeit nach:

Wenn ich mich perr SSH auf meine Diskstation einlogge, kann ich über die Kommandozeile die MySQL-Datenbank ansprechen und füttern:

Code:
mysql --user=DB_USER --password=PASSWORT NAME_DATENBANK -e 'INSERT INTO anrufe (ID, callerid) VALUES ("", "12345");'

Eigentlich müsste sich dieser Komplette Befehl in der extensions.conf in den Wählplan integrieren und aufrufen lassen. Ich habe es soeben mal so probiert, aber das klappt leider nicht:

Code:
exten = 01234567,1,NoOp(Eingehender Anruf)
exten = 01234567,n,System(mysql --user=DB_USER --password=PASSWORT NAME_DATENBANK -e 'INSERT INTO anrufe (ID, callerid) VALUES ("", "12345");')
...

Bei der E-Mail-Funktion hat das nämlich auch super geklappt mit System(). Habe ich irgendwo einen Fehler im Code?

[Beitrag 2:]

YEEEAAAHHHHH!!!!! Hab den Fehler. Es muss der vollständige Pfad zum MySQL-Ordner auf der Synology Diskstation angegeben werden:

Code:
exten = 01234567,1,NoOp(Eingehender Anruf)
exten = 01234567,n,System(/usr/syno/mysql/bin/mysql --user=DB_USER --password=PASSWORT  NAME_DATENBANK -e 'INSERT INTO anrufe (ID, callerid) VALUES ("",  "12345")')
...

Damit kann man sich nun seine eigene CDR zusammenstellen (zB die Testzahl 123456 durch ${CALLERID} ersetzen). Es ist zwar nicht so sauber, wie über ODBC zu gehen (was bei der Diskstation ja leider nicht funktioniert). Aber es ist auf jeden Fall ein gangbarer Weg, seine Anruferliste in eine MySQL-Datenbank zu bekommen! Mal sehen, ob sich noch Folgeprobleme auftun (wie will man beispielsweise die Anrufdauer etc. in die Datenbank bekommen?).

gibt zwar noch ein paar Folgeprobleme
 
Zuletzt bearbeitet von einem Moderator:
Moins

OK. Wie war das noch mit den Wegen nach Rom?

Tip: Das System() wird ja nicht weiter ausgewertet?
Dann kann es auch in einem NoOP(System()) rein.
Ist einfach nur besserer Stil und kundige Sourcecodeleser
werden in Jahren sofort erkennen:
"Das läuft Autark und wird innerhalb von Asterisk nicht weiter beachtet."
 
Danke, dass bau ich noch so um. Ein Folgeproblem ist beispielsweise: wo muss ich den Code im Wählplan unterbringen, wenn ich weitere Werte wie beispielsweise die Anrufdauer oder den Zeitstempel des Gesprächendes erfassen will. Direkt am Anfang (also noch vor Entgegennahme des Gesprächs) steht das ja noch nicht fest.
 
Schreibe erst in die Datenbank wenn du die Werte "gesammelt" hast.

Wo du die entsprechenden Werte erfassen kannst, kannst du sie erstmal mit Set(VARIABLENNAME=) zwischenspeichern.
Da wo du in die Datenbank schreiben willst, benutzt du die zuvor mit Set() definierten VARIABLENNAMEn.

Musst dabei aber aufpassen, denn die VARIABLENNAMEn behalten ihre Werte, bis sie sich ändern.
...bis Asterisk neugestartet wird, sozusagen.
Es sei denn, du sorgst selber dafür, und setzt sie an geeigneter Stelle zurück.
 
Zuletzt bearbeitet:
Wichtig ist auch, dass der Aufruf für die MySQL-Eintragung kein Semikolon enthält! Das hat mich eben wieder zur Verzweiflung :mad: gebracht, bis ich entdeckt habe, dass ich einen Strichpunkt verwendet habe. Asterisk nutzt den Strichpunkt aber zum (Aus)Kommentieren. Und auf der Diskstation übernimmt Asterisk dann nichts, was hinter dem Semikolon steht.

Schreibe erst in die Datenbank wenn du die Werte "gesammelt" hast.

Aber wo bringe ich das im Dialplan unter. Denn wenn das Gespräch durch Auflegen beendet wird, wird der Dialplan ja auch nicht mehr weiter durchlaufen.
 
Zuletzt bearbeitet von einem Moderator:
Ruhig. ;)

Schau dir das mal an: KlickKlack

...oder du hilfst uns Allen den hangup_handler zum Laufen zu bringen (Asterisk 11).
Meine Version scheint zu Alt.

PS: Das Semikolonproblem hab ich auch noch nicht im Griff
 
Zuletzt bearbeitet:
Dein Link geht leider nicht. Habe es jetzt so gelöst:

Code:
exten = 01234567,1,NoOp(Eingehender Anruf)
...
exten = h,1,System(/usr/syno/mysql/bin/mysql --user=DB_USER  --password=PASSWORT  NAME_DATENBANK -e 'INSERT INTO anrufe (ID, callerid, callstart, callanswer, callend) VALUES ("", "${CALLERID(num)}", "${CDR(start)}", "${CDR(answer)}", "${CDR(end)}")')

So, nun wieder ein kleines Folgeproblem: wenn der eingehende Anruf an Telefon1 angenommen und an Telefon2 durchgestellt wird, lauten alle Zeitstempel-Einträge (Anrufeingang, Anrufannahme, Anrufende) in der Datenbank gleich (zB: 2015-06-19 17:01:21). Ich bin verwirrt :-D
 
Zuletzt bearbeitet von einem Moderator:
Sorry, Kopierunfall, Link repariert.
Aber genau diese "besondere Extension" meinte ich.
...und, ich schrieb ja schon...
Musst dabei aber aufpassen, denn die VARIABLENNAMEn behalten ihre Werte, bis sie sich ändern.
...bis Asterisk neugestartet wird, sozusagen.
Es sei denn, du sorgst selber dafür, und setzt sie an geeigneter Stelle zurück.
...also, wenn weitergeleitet wird, muss die entsprechende Extension die Variablen setzen.
Nach Datenbankeintrag am Besten mal alle Variablen zurücksetzen.
 
Damit dürfte dann auch ein weiteres kleines Problem zusammenhängen. Ich poste dazu mal meinen kurzen Dialplan:

Code:
[Eingehender_Anruf]
exten = 01234567,1,NoOp(Eingehender Anruf)
exten = 01234567,n,Dial(SIP/1234&SIP/6789,10,t)
exten = 01234567,n,VoiceMail(1234,u)
exten = h,1,System(/usr/syno/mysql/bin/mysql --user=DB_USER   --password=PASSWORT  NAME_DATENBANK -e 'INSERT INTO anrufe (ID,  callerid, callstart, callanswer, callend, callstatus) VALUES ("",  "${CALLERID(num)}", "${CDR(start)}", "${CDR(answer)}", "${CDR(end)}", "${CDR(disposition)}")')

Bei einem eingehenden Anruf klingeln Telefon1 (SIP1234) und Telefon2 (SIP6789). Nimmt Telefon2 den Anruf an, funktioniert alles wunderbar. Beim Auflegen wird alles einwandfrei in die Datenbank eingetragen. Im Feld "callstatus" steht ANSWERED. Wenn nun jedoch der Anruf nicht von Telefon2, sondern von Telefon1 angenommen wird, lautet die Eintragung "NO ANSWER" und im Feld "callanswer" ist "0000-00-00 00:00:00" eingetragen. Das hängt bestimmt mit Dial($EMPFANG) zusammen. Ich beschäftige mich ja nun leider noch nicht so lange mit dem Thema Asterisk, weshalb ich gerade mal wieder etwas ratlos bin, wo ich ansetzen muss, um das Problem zu beheben. Wie du schon schrobst, müsste ich die Variablen entsprechend setzen (wobei die CDR-Variablen ja von Asterisk automatisch gesetzt werden sollten). Die Frage für mich ist nur: wo genau (im Dialplan) muss ich die Variablen setzen?
 
Zuletzt bearbeitet:
Eben, deine h Extension ist "Hartkodiert" du benutzt stumpf im Aufruf die CDR()s.

OK, setz mal so an...
Code:
exten = 01234567,1,NoOp(Eingehender Anruf)
same = n,NoOp(Set(EINGEHEND=${CALLERID(num)}))
...
Code:
exten = h,1,System(/usr/syno/mysql/bin/mysql --user=DB_USER   --password=PASSWORT  NAME_DATENBANK -e 'INSERT INTO anrufe (ID,  callerid, callstart, callanswer, callend, callstatus) VALUES ("",  "[COLOR=#ff0000][B]${EINGEHEND}[/B][/COLOR]", "${CDR(start)}", "${CDR(answer)}", "${CDR(end)}", "${CDR(disposition)}")')

Und ich meine die h Extension gilt für Alle* (im Context) :gruebel:
Deswegen ist so gesehen Anruf <--> Weiterleitung schon ein vollständiger Anruf.
Wenn die erfolgte Weiterleitung auflegt, müsste auch die h Extension ein 2. Mal anspringen.

* Lass die also mal wie die t und i als seperate Extension im Context stehen.
 
Zuletzt bearbeitet:
Danke schon mal für Deine Hilfe! Aber woher kriege ich dann beispielsweise den Zeitpunkt der Anrufannahme durch Telefon1, den Status, was mit dem Anruf passiert ist oder die Dauer des Gesprächs?

exten = 01234567,1,NoOp(Eingehender Anruf)
same = n,NoOp(Set(EINGEHEND=${CALLERID(num)}))
same = n,NoOp(Set(DAUER=${CDR(billsec)}))
...

So würde das zB mit billsec ja nicht funktionieren, da im dem Moment, in dem die Variable $DAUER gesetzt wird, noch gar nicht klar ist, wie lange das Gespräch letztlich dauern wird. Wie kann ich es also schaffen, die tatsächliche Dauer abzugreifen und wo im Dialplan müsste dann die $DAUER Variable gesetzt werden?
 
Zuletzt bearbeitet:
So würde das zB mit billsec ja nicht funktionieren
...setz den Wert erst da wo er Sinn macht, aber bevor in die Datenbank geschrieben wird.

Das gehört zur Auswertung und Fehlerbehebung.

Dafür wird gerne GotoIF() benutzt.

Oder AGI Skripte, hier mal für Andersrum, es wurde eine Verbindung aufgebaut...
Code:
$agi->exec("Dial","SIP/100");
$dialstatus = $agi -> get_variable("DIALSTATUS");if($dialstatus[data]=="ANSWER")
{
    do something…….
}
Quelle

Status

The DIALSTATUS channel variable is created when you attempt to connect to another device or endpoint and bridge the call with the Dial Application. It contains the status of the call reflected in one of the following values:
  • CHANUNAVAIL
  • CONGESTION
  • NOANSWER
  • BUSY
  • ANSWER
  • CANCEL
  • DONTCALL – For the Privacy and Screening Modes. Will be set if the called party chooses to send the calling party to the ‘Go Away’ script.
  • TORTURE – For the Privacy and Screening Modes. Will be set if the called party chooses to send the calling party to the ‘torture’ script.
  • INVALIDARGS
 
Zuletzt bearbeitet:
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.