Queue

Install DotSIP, open the web admin, connect real SIP, and decide each call from your own HTTP API.

The caller hears a WAV in a loop until a phone in the group is idle. Your server does not poll the phones. It only tells DotSIP the group id, the file name, and the timeout, all read from your table. DotSIP connects the first idle extension. On timeout it runs on_fail.

A group in the admin is a named list of extension users. The list alone does not ring anyone. The queue command does.

1. Records in DotSIP

  1. Under SIP phones, users 201 and 202, enabled, each with a password.
  2. Under Groups, id reception, label Reception. Members 201 and 202. all is built in and is not this group.
  3. Put queue.wav and queue-end.wav in data/media. Mono PCM16, 8000, 16000, or 24000 Hz.
  4. Under SIP accounts, the trunk that receives the call. Set its inbound route to route-tools, or leave that field empty so the call uses route-tools.
  5. route-tools URL http://127.0.0.1:9099/route.

2. Your database

CREATE TABLE queues (
  id TEXT PRIMARY KEY,
  group_id TEXT NOT NULL,
  media TEXT NOT NULL,
  timeout_ms INTEGER NOT NULL,
  fail_media TEXT NOT NULL
);
INSERT INTO queues(id, group_id, media, timeout_ms, fail_media) VALUES
  ('main', 'reception', 'queue.wav', 60000, 'queue-end.wav');

The group_id must be the group id in DotSIP. The members are the phones in that group, capped at 8 by the queue command.

3. The server

<?php
$db = new PDO("sqlite:" . __DIR__ . "/operator.sqlite");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("CREATE TABLE IF NOT EXISTS queues (id TEXT PRIMARY KEY, group_id TEXT NOT NULL, media TEXT NOT NULL, timeout_ms INTEGER NOT NULL, fail_media TEXT NOT NULL)");
$db->exec("INSERT OR IGNORE INTO queues(id, group_id, media, timeout_ms, fail_media) VALUES ('main', 'reception', 'queue.wav', 60000, 'queue-end.wav')");
$body = json_decode(file_get_contents("php://input"), true);
header("Content-Type: application/json");
if (!is_array($body) || (isset($body["format"]) ? $body["format"] : "") !== "dotsip.route") {
    http_response_code(400);
    echo json_encode(array("error" => "bad request"));
    return;
}
$row = $db->query("SELECT group_id, media, timeout_ms, fail_media FROM queues WHERE id = 'main'")->fetch(PDO::FETCH_ASSOC);
echo json_encode(array(
    "format" => "dotsip.route-result",
    "format_version" => 2,
    "commands" => array(
        array("do" => "answer"),
        array(
            "do" => "queue",
            "group" => $row["group_id"],
            "media" => $row["media"],
            "timeout_ms" => (int) $row["timeout_ms"],
            "on_fail" => array(
                array("do" => "play", "media" => $row["fail_media"], "barge_in" => false),
                array("do" => "hangup"),
            ),
        ),
    ),
));

DotSIP polls line status and transfers to the first idle member of reception. queue.wav loops while it waits. After 60 seconds, queue-end.wav plays and the call hangs up. Default timeout if you omit it is 120000, from 1000 to 300000. You can send phones instead of group.