🔌 DVPX Genel API

Tüm uçlar tek bir adres üzerinden çalışır ve JSON döner. Kimlik doğrulaması gerekmez, CORS her kaynağa açıktır — kendi panonuzu, botunuzu ya da widget'ınızı doğrudan tarayıcıdan besleyebilirsiniz.

Temel adres
https://dvpx.algsoft.net.tr/api.php
Bu sunucuda API anahtarı gerekmez — uçlar herkese açıktır.
GET Son Duyulanlar api.php?action=lastheard&limit=5

Reflektörlerin bildirdiği çağrı geçmişi. Kayıt yayın BAŞLARKEN açılır (o sırada active=true, duration_ms=0) ve bittiğinde kesin süreyle güncellenir — "şu an konuşuyor" göstergesi için active alanını kullanın.

Parametre Varsayılan Açıklama
tg 0 talkgroup numarası. 0/boş = tüm gruplar.
limit 50 kayıt sayısı, 1-200 arası.
since — yalnızca bu andan YENİ kayıtlar. ISO-8601 ya da unix saniye. Artımlı çekim için son gördüğünüz started_at değerini geri verin.

    
GET Bağlı İstasyonlar api.php?action=online

Şu an reflektörlere bağlı istasyonlar. Uygulamalar çağrı hedefini bu listeden seçer. Reflektörler listeyi ~10 saniyede bir yeniler; 90 saniye güncellenmeyen kayıt düşer. İstasyon bir gruba bağlı değilse talkgroup alanı 0 döner.


    
GET Konuşma Grupları api.php?action=talkgroups

Panelde etkin olan talkgroup listesi. dmr_id parametresi verilirse liste o kimliğe göre kişiselleştirilir; parametresiz çağrıda herkese açık liste döner.

Parametre Varsayılan Açıklama
dmr_id — kimliğinizi verirseniz size tanımlı grup listesini alırsınız (ESSID'li kimlik de kabul edilir).

    
GET Reflektörler api.php?action=servers

Bağlanılabilir reflektörler; TCP sinyalleşme ve UDP ses portlarıyla. Bir reflektörün burada görünmesi için çevrimiçi + yönetici tarafından onaylı olması VE son 2 dakika içinde panelle haberleşmiş olması gerekir — yani listedeki her sunucu gerçekten ayaktadır.


    
GET Tümü (varsayılan) api.php

Sunucular + talkgroup'lar + DVPX Ses Motoru ayarları. Uygulamanın açılışta çektiği uç budur.


    
GET Sağlık Kontrolü api.php?action=ping

Veritabanına dokunmadan yanıt verir; izleme/uptime kontrolü için uygundur.


    
lastheard yanıt alanları
Alan Tür Açıklama
id int çağrı kaydının benzersiz numarası
source_id int konuşan istasyonun DMR ID'si
callsign string çağrı işareti (bilinmiyorsa boş)
target_id int hedef: TG numarası ya da özel çağrıda karşı DMR ID
tg_name string talkgroup adı (özel çağrıda boş)
call_type int 0 = talkgroup, 1 = özel çağrı
private bool call_type == 1 için kolaylık alanı
frames int iletilen ses çerçevesi sayısı (çerçeve 20 ms)
duration_ms int yayın süresi, milisaniye. Yayın sürerken 0'dır.
active bool true ise bu yayın HÂLÂ SÜRÜYOR — "şu an konuşuyor" göstergesi için bunu kullanın.
server_id int|null kaydı yazan reflektörün panel id'si
server_name string reflektör adı
started_at string yayın başlangıcı, ISO-8601 UTC
started_at_unix int aynı an, unix saniye — ayrıştırması kolay
Kayıtlar started_at azalan sırada döner (en yeni önce). Aynı istasyon aralıkta birden çok kez konuştuysa birden çok satır gelir — listenizde tek satır gösterecekseniz source_id'ye göre tekilleştirin.
Örnekler
curl — TG 90'ın son 10 çağrısı
curl -s "https://dvpx.algsoft.net.tr/api.php?action=lastheard&tg=90&limit=10"
JavaScript — tarayıcıdan doğrudan (CORS açık)
const r = await fetch("https://dvpx.algsoft.net.tr/api.php?action=lastheard&tg=90");
const { calls } = await r.json();
calls.forEach(c => console.log(c.callsign, c.tg_name, c.duration_ms));
Python — artımlı çekim (yalnızca yeni kayıtlar)
import requests, time

url, since = "https://dvpx.algsoft.net.tr/api.php", None
while True:
    p = {"action": "lastheard", "limit": 200}
    if since:
        p["since"] = since
    calls = requests.get(url, params=p, timeout=10).json()["calls"]
    for c in reversed(calls):          # eskiden yeniye
        print(c["started_at"], c["callsign"], "->", c["target_id"])
    if calls:
        since = calls[0]["started_at"] # en yeni kayıt
    time.sleep(5)
📞 Full-Duplex Çağrı TCP sinyalleşme

Full-duplex, iki istasyonun PTT'ye basmadan aynı anda konuşabildiği özel çağrıdır. SES TAŞIMADA hiçbir şey değişmez — reflektör paketleri zaten yön gözetmeden aktarır, iki yön aynı anda akar. Ek olan tek şey ÇAĞRIYI KURMAKTIR: kim kimi arıyor, karşı taraf kabul etti mi, çağrı ne zaman bitti.

Bu satırlar istemci ile reflektör arasındaki TCP sinyalleşme kanalında geçer; api.php ile ilgisi yoktur.

→ FDX INVITE <hedefDmrId>
← FDX RING <kaynakId> <cagriIsareti>
→ FDX ACCEPT | REJECT | END
← FDX ACCEPTED | REJECTED | ENDED
← FDX FAIL  NO_TARGET | BUSY | SELF | NO_CALL
ACCEPTED İKİ TARAFA da gider — biri PTT beklerse konuşma tek yönlü kalırdı. Güncellenmemiş bir reflektör ERR UNKNOWN_COMMAND döner; istemci bunu "bu reflektör full-duplex desteklemiyor" diye gösterir. Eski istemciler FDX hiç göndermez, onlar için hiçbir şey değişmez.
📡 Reflektör Kontrol API'si token gerekir

Bu bölüm uygulama geliştiricileri için DEĞİL, reflektör işletmecileri içindir. Reflektörler veritabanına bağlanmaz; TG listesini, engelli kullanıcı listesini ve kullanıcı yetkilerini bu uçtan alır, olan biteni (çevrimiçi liste, çağrı kayıtları) buraya bildirir.

Reflektörlerin bağlanacağı adres — config.json → dashboard.url
https://dvpx.algsoft.net.tr/reflector.php
Yöntem Uç Açıklama
GET ?action=ping Token GEREKMEZ. "Adresi doğru mu yazdım?" testi — tarayıcıdan da açabilirsiniz.
GET ?action=snapshot Yalnızca politika: TG listesi, engelli kimlikler, kullanıcı yetkileri. Hata ayıklama için.
POST ?action=heartbeat Asıl uç. Tek istekte bildirim gönderir ve politikayı (yalnızca DEĞİŞTİYSE) alır.
Kimlik doğrulama — üçünden biri yeter
Authorization: Bearer dvpx_xxxxxxxx
X-DVPX-Token: dvpx_xxxxxxxx
{"token": "dvpx_xxxxxxxx", ...}

İkisi birlikte gönderilir çünkü bazı paylaşımlı barındırmalar Authorization başlığını PHP'ye hiç ulaştırmaz. Token panelde yalnızca bir kez gösterilir; veritabanında sadece SHA-256 özeti saklanır.

Bağlantıyı test etmek
# Adres doğru mu? (token gerekmez)
curl -sS "https://dvpx.algsoft.net.tr/reflector.php?action=ping"

# Token geçerli mi? TG listenizi döndürmeli
curl -sS -H "X-DVPX-Token: dvpx_xxxx" "https://dvpx.algsoft.net.tr/reflector.php?action=snapshot"
Hata sözleşmesi — reflektörün davranışını bu belirler
HTTP error fatal Reflektör ne yapar
401unauthorizedtrue KİLİTLENİR: yeni giriş kabul etmez, bağlı kullanıcıları düşürür.
403pending_approvaltrue Kilitli bekler; yönetici onayladığı an KENDİLİĞİNDEN hizmete girer.
503server_errorfalse GEÇİCİ sayar: önbellekteki politikayla ses ve girişlere devam eder, bildirimleri kuyrukta tutar.

Bu ayrım kasıtlıdır: geçici bir veritabanı ya da ağ hatası ASLA ağın girişlerini kapatmaz. Yalnızca panelin açık reddi (401/403) reflektörü kilitler. Reflektör kurulumu: dvpx-reflector/KURULUM.md

Kullanım notları
  • Yanıtlar 5 saniye önbelleklenir (Cache-Control: max-age=5). 5 saniyeden sık sorgulamanın faydası yoktur.
  • Çok sayıda kayıt izleyecekseniz her seferinde 200 kayıt çekmek yerine since parametresini kullanın — hem sunucuyu hem bant genişliğinizi korur.
  • Zaman damgaları UTC'dir. Yerel saate çevirmeyi istemci tarafında yapın.
  • Bir kayıt yayın BAŞLADIĞI anda görünür ve active=true olur; bittiğinde aynı kayıt kesin süreyle güncellenir. Aynı id'yi iki kez görürseniz bu mükerrer kayıt değil, güncellemedir.
  • Hata durumunda gövde {"ok": false, "error": "...", "message": "..."} biçimindedir; HTTP kodu 4xx/5xx olur.