sipgate.io Dashboard für Anrufstatistiken erstellen

Julia
22.07.2022 0 10:57 min

Was ist sipgate.io?

SMS oder Faxe versenden und empfangen, den Anrufverlauf abrufen, Anrufe initiieren und manipulieren – das alles kann sipgate.io ! Mit unseren APIs können Sie unsere Telekommunikationsfunktionen flexibel in Ihre Projekte integrieren. Unsere Library und Tutorials unterstützen Sie dabei, Ihre Telefonie möglichst bequem zu gestalten.

In diesem Tutorial

In diesem Tutorial werden wir uns auf die Webhook-Funktionalität konzentrieren und sie verwenden, um einige Statistiken über eingehende Anrufe zu erhalten. Dafür bauen wir eine einfache Dashboard-Schnittstelle, die folgende Informationen anzeigt:

  • alle von einem Benutzer angenommene Anrufe (total answered by a user)
  • alle von der Voicemail angenommene Anrufe (total answered by the voicemail
  • abgelehnte Anrufe (rejected/ busy)
  • verpasste Anrufe (missed)

Für dieses Dashboard verwenden wir die JavaScript-Bibliothek Chart.js.
Um die Daten in Echtzeit zu aktualisieren, werden wir Frontend und Backend über einen Websocket mit der socket.io-Library verbinden.
Das vollständige Projekt finden Sie in unserem Github-Repository.

Voraussetzungen

  • Bevor wir uns mit dem Code auseinandersetzen, richten Sie sich ein sipgate-Konto für sipgate.io ein. Wie das geht, erfahren Sie unter www.sipgate.io/get-started.
  • Um Webhooks für eingehende und ausgehende Anrufe zu aktivieren, gehen Sie zu console.sipgate.com und wählen Sie in der linken Seitenleiste „Webhooks“ aus. Auf der Registerkarte „URLs“ können Sie die Webhook-URLs konfigurieren.
  • In diesem Projekt verwenden wird nur die “eingehenden” URLs, da uns in diesem Fall keine Statistiken über ausgehende Anrufe interessieren.
  • Wenn Sie Webhooks in der Live-Umgebung verwenden, müssen Sie Ihren Code auf einem Webserver mit einer geeigneten Adresse ausführen. Für Entwicklungszwecke empfehlen wir jedoch die Nutzung eines Dienstes, der Ihre lokale Umgebung über das Internet zugänglich macht. Dies erleichtert erheblich das Testen Ihres geschriebenen Codes. Es gibt verschiedene kostenlose Dienste, die dafür genutzt werden können. Einige Beispiele sind localhost.run oderr ngrok.
    Beide stellen Ihnen eine öffentliche URL zur Verfügung, die Sie in die sipgate.io Konsole einfügen können. Achten Sie darauf, dass Sie den richtigen Port weiterleiten (in diesem Tutorial Port 8080) und dass der von Ihnen gewählte Anbieter sichere Verbindungen über HTTPS bietet.

Step 1:  das Projekt aufsetzten

Jetzt, wo Sie Ihr sipgate-Konto eingerichtet haben, können wir mit dem Coden loslegen.

  • Für dieses Projekt werden wir die sipgate.io Node.js-Library verwenden. Die Library erleichtert die Arbeit mit den sipgate-APIs und bietet eine bequeme Gelegenheit, einen Webhook-Server einzurichten.
  • Erstellen Sie ein neues Node-Projekt, indem Sie ein neues Verzeichnis mit unserem Projekt anlegen. Führen Sie danach den Befehl npm init -y aus. Dadurch wird eine package.json-Datei erstellt, die einige Metadaten für das Projekt enthält. Um das Projekt auszuführen, fügen Sie folgenden Befehl in die package.json-Datei ein.
"scripts": {
  "start": "node src/server.js"
}

Um die sipgate.io-Library zu installieren, führen Sie npm install -s sipgateio aus.

Step 2: Webhook-Server einrichten

Los geht’s mit dem Coding!

  • Erstellen Sie eine neue server.js-Datei. Das folgende Snippet erstellt eine Instanz des Webhook-Moduls von sipgate.io und verwendet dieses, um einen Webhook-Server mit zusätzlichen Optionen zu erstellen. Diese Optionen enthalten den Port und die Serveradresse, um Anrufereignisse wie das hangup-Event zu behandeln.
  • Da diese Adresse variieren kann (vor allem, wenn Sie Ihren lokalen Rechner mit einem SSH-Tunnel wie bei ngrok & Co verwenden), ist es eine gute Idee, sie aus einer Umgebungsvariable zu lesen.
const { createWebhookModule } = require("sipgateio");

const webhookServerPort = 8080;
const webhookServerAddress =
  process.env.SIPGATE_WEBHOOK_SERVER_ADDRESS || "YOUR_WEBHOOK_SERVER_ADDRESS";

const webhookModule = createWebhookModule();

webhookModule.createServer({
  port: webhookServerPort,
  serverAddress: webhookServerAddress,
});
  • Die Funktion createServer gibt ein Promise für einen WebhookServer zurück, der dann verwendet werden kann, um Rückruffunktionen für verschiedene Anrufereignisse zu registrieren:
webhookModule
  .createServer({
    port: webhookServerPort,
    serverAddress: webhookServerAddress,
  })
  .then((webhookServer) => {
    console.log(
      `Server running at ${webhookServerAddress}\n` + "Ready for calls ?"
    );
    webhookServer.onNewCall(logCall);
  });
  • Bei newCall-Events gibt logCall lediglich eine lesbare Darstellung des Aufrufs auf der Konsole aus.
const logCall = (newCallEvent) => {
  console.log(`New Call from ${newCallEvent.from} to ${newCallEvent.to}`);
};
  • Jetzt ist es Zeit für einen Testlauf! Starten Sie den Server mit npm start und warten Sie auf die Meldung, dass der Server läuft. Überprüfen Sie, dass die richtige Serveradresse angezeigt wird, und rufen Sie dann Ihre sipgate-Nummer an. Sie sollten nun das Protokoll des newCall -Events sehen.

Step 3: Statistiken sammeln

Unser Ziel ist es, bestimmte Statistiken über verschiedene Anrufszenarien zu sammeln. Diese Szenarien unterscheiden sich durch verschiedene Arten von hangUp-Events. Um diese Ereignisse von der sipgate.io Webhook-API zu erhalten, müssen wir eine Callback-Funktion registrieren:

webhookModule
  .createServer({
    port: webhookServerPort,
    serverAddress: webhookServerAddress,
  })
  .then((webhookServer) => {
    console.log(
      `Server running at ${webhookServerAddress}\n` + "Ready for calls ?"
    );
    webhookServer.onNewCall(logCall);
    webhookServer.onHangUp(handleHangUpEvent);
  });

Für hangUp-Event manipuliert handleHangUpEvent ein Zählerobjekt counters, das wie folgt definiert wird:

const counters = {
  totalAnswered: 0,
  voicemail: 0,
  canceled: 0,
  busy: 0,
};

Da wir uns dafür interessieren, warum ein Anruf aufgelegt wurde, verfolgen wir die verschiedenen Ursachen:

  • normalClearing steht für den Fall, dass ein Anruf angenommen und anschließend von einer der beiden Parteien aufgelegt wurde. Dies bedeutet, dass der Anruf entweder von einer Person entgegengenommen wurde, oder er wurde von der Voicemail beantwortet wurde.
  • forwarded gibt die Umleitung zur Voicemail an, um oben beschriebene Fälle zu unterscheiden.
  • cancel gibt einen verpassten Anruf an.
  • busy bedeutet, dass die angerufene Person sich bereits in einem Gespräch befindet oder den Anruf abgelehnt hat.
const handleHangUpEvent = (hangUpEvent) => {
  if (hangUpEvent.cause === "normalClearing") {
    counters.totalAnswered += 1;
  }

  if (hangUpEvent.cause === "forwarded") {
    counters.voicemail += 1;
    return;
  }

  if (hangUpEvent.cause === "cancel") {
    counters.canceled += 1;
  }

  if (hangUpEvent.cause === "busy") {
    counters.busy += 1;
  }
};

?Anmerkung: das counters– Objekt befindet sich nur im Speicher. Ein Neustart des Servers führt dazu, dass die Daten zurückgesetzt werden. Um sie zu erhalten, müssten Sie die Daten in einer Datenbank oder in einer Datei speichern, aber für dieses Tutorial bleiben wir bei der In-Memory-Lösung.

An dieser Stelle haben Sie vielleicht bemerkt, dass die Daten im counters -Objekt nicht genau das sind, was wir anzeigen wollen. Zuerst trennen wir die Anzahl der von einer Person angenommenen Anrufe von denen, die von der Voicemail angenommen wurden. Dies erreichen wir mit der Anwendung der Funktion
calculateData:

const calculateData = () => {
  const answeredByUser = counters.totalAnswered - counters.voicemail;
  return [answeredByUser, counters.voicemail, counters.busy, counters.canceled];
};

Die Funktion gibt die Daten als Array zurück, was zwar nicht sehr elegant ist, aber bei der Arbeit mit Chart.js sehr nützlich sein wird.

Step 4: Dashboard mit Chart.js erstellen

Nun, da wir die Statistiken gesammelt haben, können wir uns auf ihre Visualisierung konzentrieren. Zu diesem Zweck erstellen wir eine minimale Website mit einem Balkendiagramm. Wir verwenden dafür die Chart.js-Library und erstellen zunächst ein index.html-Script mit dem folgenden Inhalt:

<!-- index.html -->

<html lang="en">
  <head>
    <link rel="stylesheet" href="/style.css" />

    <!-- Load the Chart.js code from a CDN -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>

    <title>Call Statistics Demo</title>
  </head>
  <body>
    <header><h1>Call Statistics Demo</h1></header>
    <section class="statistics">
      <!-- We'll tell Chart.js to render the graph in this canvas -->
      <canvas id="chart"></canvas>
    </section>
    <script src="/script.js"></script>
  </body>
</html>

Als Nächstes erstellen wir eine script.js-Datei.

// script.js

const setupChart = (data) => {
  const context = document.getElementById("chart").getContext("2d");

  return new Chart(context, {
    type: "bar",
    data: {
      labels: data.labels,
      datasets: [
        {
          data: data.data,
          backgroundColor: [
            colors.cyan,
            colors.yellow,
            colors.orange,
            colors.red,
          ],
          borderWidth: 0,
        },
      ],
    },
    options: {
      legend: { display: false },
      tooltip: { position: "average" },
      title: { display: true, text: "Calls today" },
      scales: {
        yAxes: [
          {
            ticks: {
              beginAtZero: true,
              stepSize: 1,
            },
          },
        ],
      },
    },
  });
};

Wir schauen uns diesen Abschnitt genauer Schritt-für-Schritt an:

  • Das colors-Objekt ist nur eine Sammlung von Farben, die wir in unserem Diagramm verwenden.
const colors = {
  cyan: "#00A6A6",
  yellow: "#EFCA08",
  orange: "#F49F0A",
  red: "#FF0000",
};
const context = document.getElementById("chart").getContext("2d");
  • Als Nächstes erstellen wir ein neues Balkendiagramm mit der Chart.js Library. Wir übergeben den 2D-Kontext als ersten Parameter an den Chart.js -Konstruktor.
  • Der zweite Parameter ist ein Objekt, das die Daten des Diagramms, sowie das Aussehen und Verhalten angibt. Die setupChart-Methode akzeptiert einen einzelnen Parameter mit der folgenden Struktur:
{
    labels: [], // Array of labels, one for each value
    data: [] // Array of values (numbers)
}

Diese Struktur macht es einfach, die Daten in unser Diagramm zu integrieren.

data: {
    labels: data.labels,
    datasets: [{
        data: data.data,
        backgroundColor: [colors.cyan, colors.yellow, colors.orange, colors.red],
        borderWidth: 0,
    }],
},

Für unseren Anwendungsfall werden wir nur einen Datensatz mithilfe von Chart.js erstellen, der die bereitgestellten Daten und die zuvor definierten Farben verwendet. Eine Erklärung für die Werte, die in das options-Attribut übergeben werden, finden Sie in der Chart.js-Dokumentation.

Step 5: das Frontend konfigurieren

In diesem Schritt werden wir einen einfachen express Webserver erstellen, um die statischen Dateien unserer Anwendung (index.html, script.js, …) bereitzustellen. Installieren Sie express mit dem Befehl npm install -s express. Fügen Sie anschließend die folgenden Zeilen in die server.js-Datei ein.

// server.js

const path = require("path");
const express = require("express");

const app = express();

app.use(express.static(path.resolve(__dirname, "../public")));

app.get("/", (_, res) => {
  res.sendFile(path.resolve(__dirname, "../public/index.html"));
});

const server = app.listen(3000);

app.use(express.static() …) registriert eine Middleware, die alle Dateien in unserem öffentlichen Verzeichnis bereitstellt, während app.get(‚/‘, …) eine Callback-Funktion registriert, die aufgerufen wird, wenn ein Client die Route / besucht. Diese Funktion gibt dann unsere index.html-Datei zurück.

Step 6: die Websocket-Kommunikation einrichten

Um Daten von unserem Backend zu senden, bauen wir eine Websocket-Verbindung mit socket.io auf. Zuerst installieren wir socket.io mit dem Befehl npm install -s socket.io und richten einen Websocket-Server in unserer server.js-Datei ein.

// server.js

const socketIo = require("socket.io");

const websocketServer = socketIo(server, {
  serveClient: true,
  origins: "*:*",
});

Als Nächstes müssen wir einen VerbindungsHandler einrichten, der Daten an neu verbundene Clients sendet.

// server.js

websocketServer.on("connection", (socket) => {
  socket.emit("init", {
    labels: [
      "Answered by user",
      "Answered by voicemail",
      "Rejected or busy",
      "Missed",
    ],
    data: calculateData(),
  });
});

Wir fügen eine labels-Reihe ein, um unser Diagramm im Browser korrekt beschriften zu können.

Im nächsten Schritt richten wir ein, dass eine Nachricht an alle verbundenen Clients gesendet wird, wenn ein HangUp-Event eintritt. Dazu fügen wir die folgende Zeile in unseren handleHangUpEvent.

websocketServer.emit("data", calculateData());

Step 7: alles zusammenbringen

  • Fügen Sie die folgende Zeile in dieindex.html -Datei ein, um socket.io einzubinden.
<script src="/socket.io/socket.io.js"></script>
  • Wir können dann den Event-Handler für die Events definieren, die von unserem Server gesendet werden.
//script.js
const socket = io("/");

let callChart;

socket.on("init", (data) => {
  callChart = setupChart(data);
});

socket.on("data", (data) => {
  updateChart(callChart, data);
});

const updateChart = (chart, data) => {
  chart.data.datasets[0].data = data;
  chart.update();
};

const setupChart = (data) => {
  // same as above
};

Sie sollten nun ein funktionierendes Beispiel haben, das sipgate.io Webhooks in Kombination mit Websockets verwendet. Das erhaltene Dashboard sieht wie folgt aus.

Fazit

In diesem Tutorial haben Sie gelernt, wie Sie mithilfe unserer sipgate.io-Library einen Überblick über Ihre Anrufstatistiken bekommen und in einem simplen Diagramm visualisieren können.

Das vollständige Projekt finden Sie in unserem GitHub-Repository.

Wenn Sie mehr über die Möglichkeiten unserer sipgate.io-Library erfahren möchten, schauen Sie sich die anderen Tutorials in unserem Blog an.

Keine Kommentare


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert