B4J Question How do I integrate the B4J program with a Fritz Box router?

amorosik

Expert
Licensed User
In my case, I have a Fritz 7530 and 6850
However, from a telephony perspective, they're all similar: they have a radio component that allows you to connect up to six phones, and then via Ethernet you can connect/register other phones, such as desktop landlines or those with their own base station, like Snom's M300 base station
Ask ChatGpt, and it seems it's possible to connect to the router's TCP port 1012, which is what their Call Monitor program does
But I can't find any information on which commands can be received from the router to the PC and vice versa wich command to send from pc to FritzBox
Has anyone ever attempted to connect a Fritz router with the B4J program?
 

Cableguy

Expert
Licensed User
Longtime User
Have you tried sending AT commands... have you tried connecting through a terminal client?
 
Upvote 0

amorosik

Expert
Licensed User
No, there is no way to send an AT command

I have tried this vbs routine to start a call to external phone, fb_dial.vbs
The script starts and runs but without success, the call does not start
Alway error 500 o 501 (TR-064 enabled, user admin or other with permission, extension existing, ecc..)

Anyone have sent a 'call command' to a Fritz Box with success?

For example, this is another code for start a call:


Code:
#!/usr/bin/env python3
import sys
import argparse
from fritzconnection import FritzConnection

def main():
    parser = argparse.ArgumentParser(description="Chiama numero tramite Fritz!Box")
    parser.add_argument("ip", help="IP del Fritz!Box")
    parser.add_argument("user", help="Utente Fritz!Box")
    parser.add_argument("password", help="Password Fritz!Box")
    parser.add_argument("number", help="Numero da chiamare")
    parser.add_argument("port", nargs="?", default="", help="Interno/port (es. 601)")

    args = parser.parse_args()

    try:
        fc = FritzConnection(address=args.ip, user=args.user, password=args.password)

        print("✅ Connesso al Fritz!Box")

        # Numero da comporre
        phone_uri = f"tel:{args.number}"

        if args.port:
            # Forza interno specifico
            phone_uri = f"tel:{args.number};phone={args.port}"

        print(f"📞 Chiamo: {phone_uri}")

        # TR-064 richiede un dict perché il nome del parametro contiene '-'
        result = fc.call_action(
            "X_VoIP:1",
            "X_AVM-DE_DialNumber",
            arguments={
                "NewX_AVM-DE_PhoneNumber": phone_uri
            }
        )

        print("✅ Chiamata inviata al FritzBox")
        print(result)

    except Exception as e:
        print("❌ Errore:", e)
        sys.exit(1)

if __name__ == "__main__":
    main()

Sent to router via batch file:

python call_fritz.py 192.168.1.10 User_Fritz Password_Fritz "3381234567#**610"


✅ Connesso al Fritz!Box
📞 Chiamo: tel:3381234567
❌ Errore: UPnPError:
errorCode: 501
errorDescription: Action Failed
 
Last edited:
Upvote 0

amorosik

Expert
Licensed User
Of course, the problem is finding a Python script that works, or rather, that works on my system
Because I believe the problem lies somewhere in the router's configuration, specifically in the VoIP provider that is registered and used as the "phone number"
I'm writing this because I tried a debug script, which I've attached below, and the response was that the "phone number" isn't detected
It's as if the router doesn't know where to route the call

SCRIPT DEBUG:
#!/usr/bin/env python3
"""
Diagnosi completa configurazione telefonia Fritz!Box
Verifica perché non ci sono interni attivi
"""

import requests
from requests.auth import HTTPDigestAuth
import xml.etree.ElementTree as ET
import argparse

def check_credentials(ip, user, password):
    """Verifica che le credenziali funzionino"""
    print("\n" + "="*60)
    print("TEST 1: VERIFICA CREDENZIALI")
    print("="*60)
 
    url = f"http://{ip}:49000/upnp/control/deviceinfo"
 
    soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetInfo xmlns:u="urn:dslforum-org:service:DeviceInfo:1"/>
</s:Body>
</s:Envelope>'''
 
    headers = {
        'Content-Type': 'text/xml',
        'SOAPAction': 'urn:dslforum-org:service:DeviceInfo:1#GetInfo'
    }
 
    try:
        auth = HTTPDigestAuth(user, password)
        r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
    
        if r.status_code == 200:
            print("✓ Credenziali VALIDE")
            print("✓ Autenticazione riuscita")
        
            # Estrai info dispositivo
            try:
                root = ET.fromstring(r.text)
                for elem in root.iter():
                    if 'ModelName' in elem.tag and elem.text:
                        print(f"✓ Modello: {elem.text}")
                    elif 'SoftwareVersion' in elem.tag and elem.text:
                        print(f"✓ Firmware: {elem.text}")
            except:
                pass
        
            return True
        elif r.status_code == 401:
            print("✗ CREDENZIALI ERRATE")
            print("\nProva con:")
            print(f"  python3 {__file__} --ip {ip} --user admin --password TUA_PASSWORD")
            return False
        else:
            print(f"⚠ Status code inatteso: {r.status_code}")
            return False
    except Exception as e:
        print(f"✗ Errore: {e}")
        return False


def check_voip_service(ip, user, password):
    """Verifica che il servizio VoIP sia disponibile"""
    print("\n" + "="*60)
    print("TEST 2: VERIFICA SERVIZIO VOIP")
    print("="*60)
 
    url = f"http://{ip}:49000/upnp/control/x_voip"
    auth = HTTPDigestAuth(user, password)
 
    # Prova a ottenere il numero di dispositivi VoIP
    soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetInfo xmlns:u="urn:dslforum-org:service:X_VoIP:1"/>
</s:Body>
</s:Envelope>'''
 
    headers = {
        'Content-Type': 'text/xml',
        'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#GetInfo'
    }
 
    try:
        r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
    
        if r.status_code == 200:
            print("✓ Servizio VoIP ATTIVO")
        
            # Cerca numero di telefoni
            try:
                root = ET.fromstring(r.text)
                for elem in root.iter():
                    tag = elem.tag.split('}')[-1] if '}' in elem.tag else elem.tag
                    if elem.text and elem.text.strip() and 'Phone' in tag:
                        print(f"  {tag}: {elem.text.strip()}")
            except:
                pass
        
            return True
        elif r.status_code == 401:
            print("✗ Autenticazione fallita per servizio VoIP")
            print("  L'utente potrebbe non avere i permessi sulla telefonia")
            return False
        else:
            print(f"⚠ Servizio VoIP risponde con status {r.status_code}")
            print(f"  Risposta: {r.text[:200]}")
            return False
    except Exception as e:
        print(f"✗ Errore: {e}")
        return False


def check_phone_numbers(ip, user, password):
    """Verifica se ci sono numeri telefonici configurati"""
    print("\n" + "="*60)
    print("TEST 3: VERIFICA NUMERI TELEFONICI")
    print("="*60)
 
    url = f"http://{ip}:49000/upnp/control/x_voip"
    auth = HTTPDigestAuth(user, password)
 
    numeri_trovati = []
 
    # Prova a leggere fino a 10 numeri telefonici
    for i in range(10):
        soap = f'''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_GetNumberOfNumbers xmlns:u="urn:dslforum-org:service:X_VoIP:1"/>
</s:Body>
</s:Envelope>'''
    
        headers = {
            'Content-Type': 'text/xml',
            'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_GetNumberOfNumbers'
        }
    
        try:
            r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
        
            if r.status_code == 200:
                try:
                    root = ET.fromstring(r.text)
                    for elem in root.iter():
                        if 'NumberOfNumbers' in elem.tag and elem.text:
                            num_count = elem.text.strip()
                            print(f"✓ Numeri telefonici configurati: {num_count}")
                        
                            if int(num_count) > 0:
                                return True
                            else:
                                print("\n⚠ NESSUN NUMERO TELEFONICO CONFIGURATO!")
                                return False
                except:
                    pass
                break
        except:
            pass
 
    print("⚠ Impossibile verificare i numeri telefonici")
    return None


def check_phone_devices(ip, user, password):
    """Verifica dispositivi telefonici configurati"""
    print("\n" + "="*60)
    print("TEST 4: VERIFICA DISPOSITIVI TELEFONICI")
    print("="*60)
 
    url = f"http://{ip}:49000/upnp/control/x_voip"
    auth = HTTPDigestAuth(user, password)
 
    dispositivi_trovati = []
 
    # Prova a leggere info sui dispositivi
    for i in range(10):
        soap = f'''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_GetPhonePort xmlns:u="urn:dslforum-org:service:X_VoIP:1">
<NewIndex>{i}</NewIndex>
</u:X_AVM-DE_GetPhonePort>
</s:Body>
</s:Envelope>'''
    
        headers = {
            'Content-Type': 'text/xml',
            'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_GetPhonePort'
        }
    
        try:
            r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=5)
        
            if r.status_code == 200:
                try:
                    root = ET.fromstring(r.text)
                    phone_name = None
                
                    for elem in root.iter():
                        if 'PhoneName' in elem.tag and elem.text:
                            phone_name = elem.text.strip()
                            break
                
                    if phone_name and phone_name != "":
                        dispositivi_trovati.append((i, phone_name))
                        print(f"✓ Dispositivo {i}: {phone_name}")
                except:
                    pass
        except:
            pass
 
    if dispositivi_trovati:
        return True, dispositivi_trovati
    else:
        print("\n⚠ NESSUN DISPOSITIVO TELEFONICO TROVATO!")
        return False, []


def test_simple_dial(ip, user, password):
    """Testa una chiamata semplicissima senza interno"""
    print("\n" + "="*60)
    print("TEST 5: CHIAMATA SEMPLICE (senza interno)")
    print("="*60)
 
    url = f"http://{ip}:49000/upnp/control/x_voip"
    auth = HTTPDigestAuth(user, password)
 
    # Chiamata senza specificare l'interno
    soap = '''<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:X_AVM-DE_DialNumber xmlns:u="urn:dslforum-org:service:X_VoIP:1">
<NewX_AVM-DE_PhoneNumber>0</NewX_AVM-DE_PhoneNumber>
</u:X_AVM-DE_DialNumber>
</s:Body>
</s:Envelope>'''
 
    headers = {
        'Content-Type': 'text/xml',
        'SOAPAction': 'urn:dslforum-org:service:X_VoIP:1#X_AVM-DE_DialNumber'
    }
 
    try:
        r = requests.post(url, data=soap, headers=headers, auth=auth, timeout=10)
    
        print(f"Status: {r.status_code}")
    
        if r.status_code == 200:
            print("✓ Chiamata ACCETTATA!")
            print("  Il Fritz!Box può effettuare chiamate")
            return True
        else:
            print(f"✗ Chiamata RIFIUTATA")
            print(f"\nRisposta:")
            print(r.text[:500])
        
            # Analizza errore
            try:
                root = ET.fromstring(r.text)
                for elem in root.iter():
                    if 'errorCode' in elem.tag and elem.text:
                        code = elem.text.strip()
                        print(f"\nCodice errore: {code}")
                    
                        if code == "713":
                            print("  Significato: Nessun telefono configurato o disponibile")
                        elif code == "714":
                            print("  Significato: Formato numero non valido")
                        elif code == "501":
                            print("  Significato: Funzione non supportata")
            except:
                pass
        
            return False
    except Exception as e:
        print(f"✗ Errore: {e}")
        return False


def main():
    parser = argparse.ArgumentParser(description='Diagnosi telefonia Fritz!Box')
    parser.add_argument('-i', '--ip', default='192.168.1.10', help='IP Fritz!Box')
    parser.add_argument('-u', '--user', default='user1', help='Username')
    parser.add_argument('-p', '--password', default='pass1', help='Password')
 
    args = parser.parse_args()
 
    print("\n" + "="*60)
    print("DIAGNOSI COMPLETA TELEFONIA FRITZ!BOX")
    print("="*60)
    print(f"\nFritz!Box: {args.ip}")
    print(f"Utente: {args.user}")
 
    # Esegui tutti i test
    cred_ok = check_credentials(args.ip, args.user, args.password)
 
    if not cred_ok:
        print("\n" + "="*60)
        print("ARRESTO: Credenziali non valide")
        print("="*60)
        return
 
    voip_ok = check_voip_service(args.ip, args.user, args.password)
    numbers_ok = check_phone_numbers(args.ip, args.user, args.password)
    devices_ok, devices = check_phone_devices(args.ip, args.user, args.password)
    dial_ok = test_simple_dial(args.ip, args.user, args.password)
 
    # Riepilogo finale
    print("\n" + "="*60)
    print("RIEPILOGO DIAGNOSI")
    print("="*60)
 
    print(f"\n✓ Credenziali: {'OK' if cred_ok else 'ERRORE'}")
    print(f"{'✓' if voip_ok else '✗'} Servizio VoIP: {'ATTIVO' if voip_ok else 'NON DISPONIBILE'}")
    print(f"{'✓' if numbers_ok else '✗'} Numeri telefonici: {'CONFIGURATI' if numbers_ok else 'NON CONFIGURATI'}")
    print(f"{'✓' if devices_ok else '✗'} Dispositivi: {'TROVATI' if devices_ok else 'NON TROVATI'}")
    print(f"{'✓' if dial_ok else '✗'} Capacità chiamata: {'FUNZIONANTE' if dial_ok else 'NON FUNZIONANTE'}")
 
    print("\n" + "="*60)
    print("CONCLUSIONE")
    print("="*60)
 
    if not numbers_ok:
        print("\n❌ PROBLEMA: NESSUN NUMERO TELEFONICO CONFIGURATO")
        print("\nIl Fritz!Box non ha numeri di telefono configurati.")
        print("Senza un numero telefonico, non puoi effettuare chiamate.")
        print("\n📋 COME CONFIGURARE:")
        print("\n1. Accedi al Fritz!Box: http://" + args.ip)
        print("2. Vai su: Telefonia → Numeri telefonici")
        print("3. Clicca 'Nuovo numero'")
        print("4. Segui la procedura guidata per configurare:")
        print("   - Numero VoIP/SIP del tuo provider")
        print("   - Oppure numero fisso se connesso a linea telefonica")
        print("\nSenza numero configurato, le chiamate non funzioneranno!")
    
    elif not devices_ok:
        print("\n❌ PROBLEMA: NESSUN DISPOSITIVO TELEFONICO")
        print("\nHai un numero configurato ma nessun telefono registrato.")
        print("\n📋 COME CONFIGURARE:")
        print("\n1. Accedi al Fritz!Box: http://" + args.ip)
        print("2. Vai su: Telefonia → Dispositivi telefonici")
        print("3. Clicca 'Configura nuovo dispositivo'")
        print("4. Scegli il tipo:")
        print("   - Telefono IP")
        print("   - Telefono analogico (se collegato)")
        print("   - Telefono DECT")
        print("5. Assegna un interno (es: 1, 2, 620)")
    
    elif not voip_ok:
        print("\n❌ PROBLEMA: SERVIZIO VOIP NON DISPONIBILE")
        print("\nPossibili cause:")
        print("1. L'utente non ha permessi sulla telefonia")
        print("2. TR-064 non completamente attivo")
        print("\n📋 SOLUZIONI:")
        print("\n1. Usa l'utente admin:")
        print(f"   python3 {__file__} --ip {args.ip} --user admin --password TUA_PASSWORD")
        print("\n2. Riavvia il Fritz!Box")
        print("\n3. Verifica permessi utente:")
        print("   Sistema → Utenti Fritz!Box")
        print("   Assicurati che l'utente abbia 'Accesso alle impostazioni'")
    
    elif not dial_ok:
        print("\n⚠ PROBLEMA: CHIAMATA RIFIUTATA")
        print("\nPossibili cause:")
        print("1. Configurazione telefonia incompleta")
        print("2. Nessuna linea telefonica attiva")
        print("3. Permessi insufficienti")
    
    else:
        print("\n✓✓✓ TUTTO CONFIGURATO CORRETTAMENTE ✓✓✓")
        print("\nIl Fritz!Box è pronto per le chiamate!")
    
        if devices:
            print("\nDispositivi disponibili:")
            for idx, name in devices:
                print(f"  - {name} (indice {idx})")
        
            print("\n📞 PROVA A CHIAMARE:")
            print(f"\npython3 chiama_minimo.py")
            print("\nModifica:")
            print(f"  INTERNO = '{devices[0][0]}'  # Usa indice primo dispositivo")
            print(f"  # Oppure prova senza interno (usa predefinito)")


if __name__ == "__main__":
    main()

This is the answer

RISPOSTA:
============================================================
DIAGNOSI COMPLETA TELEFONIA FRITZ!BOX
============================================================

Fritz!Box: 192.168.1.10
Utente: user1

============================================================
TEST 1: VERIFICA CREDENZIALI
============================================================
✓ Credenziali VALIDE
✓ Autenticazione riuscita
✓ Modello: FRITZ!Box 7530
✓ Firmware: 164.08.02

============================================================
TEST 2: VERIFICA SERVIZIO VOIP
============================================================
✓ Servizio VoIP ATTIVO

============================================================
TEST 3: VERIFICA NUMERI TELEFONICI
============================================================
✓ Numeri telefonici configurati:
⚠ Impossibile verificare i numeri telefonici

============================================================
TEST 4: VERIFICA DISPOSITIVI TELEFONICI
============================================================
✓ Dispositivo 1: FON1: Telefono
✓ Dispositivo 2: ISDN: DECT all
✓ Dispositivo 3: DECT: PEPPE
✓ Dispositivo 4: DECT: TONI
✓ Dispositivo 5: DECT: CAIO

============================================================
TEST 5: CHIAMATA SEMPLICE (senza interno)
============================================================
Status: 500
✗ Chiamata RIFIUTATA

Risposta:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring>UPnPError</faultstring>
<detail>
<UPnPError xmlns="urn:dslforum-org:control-1-0">
<errorCode>501</errorCode>
<errorDescription>Action Failed</errorDescription>
</UPnPError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>

Codice errore: 501
  Significato: Funzione non supportata

============================================================
RIEPILOGO DIAGNOSI
============================================================

✓ Credenziali: OK
✓ Servizio VoIP: ATTIVO
✗ Numeri telefonici: NON CONFIGURATI
✓ Dispositivi: TROVATI
✗ Capacità chiamata: NON FUNZIONANTE

============================================================
CONCLUSIONE
============================================================

❌ PROBLEMA: NESSUN NUMERO TELEFONICO CONFIGURATO

Il Fritz!Box non ha numeri di telefono configurati.
Senza un numero telefonico, non puoi effettuare chiamate.


But the 'telephone number' is definitely configured and active, since from any extension it's possible to call the public telephone network and receive calls from any phone
I believe the configuration used is probably active and working, but for some reason it's missing some information, and from an external command sent to the router, the 'telephone number' is not visible.
 
Last edited:
Upvote 0
Top