NEWS

Pegelwerte Fritzbox 6490 Cable auslesen?


  • @arndl
    Habe mich extra wegen deinem Post hier angemeldet 🙂
    Das ist ne Klasse Sache.
    Auch ich habe hier teilweise massive Störungen, die aber sehr sporatisch sind 😞
    Mein Upload Moduliert hier manchmal nur auf 8 QAM. Habe natürlich auch schon mehrfach die Hotline bemüht, leider bisher ohne Erfolg.
    Es wäre nett wenn du mir auch das Script zur Verfügung stellen könntest.
    Dann muss ich mich hier noch einlesen, wie man das ganze dann "installiert" bzw. zum laufen bringt 😉

    Ich habe hier die Mietbox in Betrieb, dort ist aktuell die 07.21 aktiv


  • @sugram
    Das Script läuft inzwischen ganz gut bei Mike0185 und mir mit der 7.22. Ich muss da allerdings noch ein wenig aufräumen und dann wohl auch mal ins Github packen.

    Installation:

    • Der Javascript-Adapter muss installiert sein und unter „Zusätzliche NPM-Module“ die iconv-lite und crypto Module eingetragen sein.
    • In der Fritzbox einen weiteren Benutzer „ioBroker“ anlegen und mit einem Passwort versehen. Das muss im Script (siehe unten) angegeben werden.
    • Dann das unten stehende Script anlegen und dauerhaft laufen lassen. Die Variablen werden automatisch angelegt und jede Minute gefüllt.
    var logging = true;
    const iconv = require('iconv-lite');
    const crypto = require('crypto');
    
    var DOCSIS30DSChannels = 0;
    var DOCSIS31DSChannels = 0;
    var DOCSIS30USChannels = 0;
    var DOCSIS31USChannels = 0;
    
    var sid;
    var fritzBenutzer = 'ioBroker';
    var fritzPasswort = 'passwort';
    var loginURL = 'http://fritz.box/login_sid.lua?username=';
    var docsisURL = 'http://fritz.box/data.lua';
    
    // Downstream DOCSIS 3.0
    for (var i = 1; i <= 31; i++){
        var Channel = 'C' + (i < 10 ? '0' + i.toString() : i.toString());
        createState('Internet.Docsis.DS.' + Channel + '.Frequency',                    0, false, {name: 'Frequency',  unit: 'MHz',      type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.Modulation',                   0, false, {name: 'Modulation', unit: 'QAM',      type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.PowerLevel',                   0, false, {name: 'PowerLevel', unit: 'dBmV',     type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.MSE',                          0, false, {name: 'MSE',        unit: 'dB',       type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.Latency',                      0, false, {name: 'Latency',    unit: 'ms',       type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.CorrectableErrors',            0, false, {name: 'CorrectableErrors',            type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.CorrectableErrorsPerMinute',   0, false, {name: 'CorrectableErrorsPerMinute',   type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.UncorrectableErrors',          0, false, {name: 'UncorrectableErrors',          type: 'mixed', role: 'state'});
        createState('Internet.Docsis.DS.' + Channel + '.UncorrectableErrorsPerMinute', 0, false, {name: 'UncorrectableErrorsPerMinute', type: 'mixed', role: 'state'});
    }
    
    // Upstream DOCSIS 3.0
    for (var i = 0; i <= 5; i++){
        var Channel = 'C0' + i.toString();
        createState('Internet.Docsis.US.' + Channel + '.Frequency',       0, false, {name: 'Frequency',  unit: 'MHz',  type: 'mixed', role: 'state'});
        createState('Internet.Docsis.US.' + Channel + '.Modulation',      0, false, {name: 'Modulation', unit: 'QAM',  type: 'mixed', role: 'state'});
        createState('Internet.Docsis.US.' + Channel + '.MultiplexMethod', 0, false, {name: 'MultiplexMethod',          type: 'mixed', role: 'state'});
        createState('Internet.Docsis.US.' + Channel + '.PowerLevel',      0, false, {name: 'PowerLevel', unit: 'dBmV', type: 'mixed', role: 'state'});
    }
    
    // Downstream DOCSIS 3.1
    createState('Internet.Docsis31.DS.C01.Frequency',      0, false, {name: 'Frequency',  unit: 'MHz',    type: 'mixed', role: 'state'});
    createState('Internet.Docsis31.DS.C01.Type',           0, false, {name: 'Modulation', unit: 'K',      type: 'mixed', role: 'state'});
    createState('Internet.Docsis31.DS.C01.PowerLevel',     0, false, {name: 'PowerLevel', unit: 'dBmV',   type: 'mixed', role: 'state'});
    
    // Upstream DOCSIS 3.1
    createState('Internet.Docsis31.US.C00.Frequency',      0, false, {name: 'Frequency',  unit: 'MHz',    type: 'mixed', role: 'state'});
    createState('Internet.Docsis31.US.C00.Type',           0, false, {name: 'Modulation', unit: 'K',      type: 'mixed', role: 'state'});
    createState('Internet.Docsis31.US.C00.MultiplexMethod',0, false, {name: 'MultiplexMethod',            type: 'mixed', role: 'state'});
    createState('Internet.Docsis31.US.C00.PowerLevel',     0, false, {name: 'PowerLevel', unit: 'dBmV',   type: 'mixed', role: 'state'});
    
    /**
     * Simple XML parser
     * @param {String} xml
     * @return {Object}
     */
    function parseXML(xml) {
    
        var beg = -1;
        var end = 0;
        var tmp = 0;
        var current = [];
        var obj = {};
        var from = -1;
    
        while (true) {
    
            beg = xml.indexOf('<', beg + 1);
            if (beg === -1)
                break;
    
            end = xml.indexOf('>', beg + 1);
            if (end === -1)
                break;
    
            var el = xml.substring(beg, end + 1);
            var c = el[1];
    
            if (c === '?' || c === '/') {
    
                var o = current.pop();
    
                if (from === -1 || o !== el.substring(2, el.length - 1))
                    continue;
    
                var path = current.join('.') + '.' + o;
                var value = xml.substring(from, beg);
    
                if (typeof(obj[path]) === 'undefined')
                    obj[path] = value;
                else if (obj[path] instanceof Array)
                    obj[path].push(value);
                else
                    obj[path] = [obj[path], value];
    
                from = -1;
                continue;
            }
    
            tmp = el.indexOf(' ');
            var hasAttributes = true;
    
            if (tmp === -1) {
                tmp = el.length - 1;
                hasAttributes = false;
            }
    
            from = beg + el.length;
    
            var isSingle = el[el.length - 2] === '/';
            var name = el.substring(1, tmp);
    
            if (!isSingle)
                current.push(name);
    
            if (!hasAttributes)
                continue;
    
            var match = el.match(/\w+\=\".*?\"/g);
            if (match === null)
                continue;
    
            var attr = {};
            var length = match.length;
    
            for (var i = 0; i < length; i++) {
                var index = match[i].indexOf('"');
                attr[match[i].substring(0, index - 1)] = match[i].substring(index + 1, match[i].length - 1);
            }
    
            obj[current.join('.') + (isSingle ? '.' + name : '') + '[]'] = attr;
        }
    
        return obj;
    };
    
    function loginAndGetSID(){
    
        sid = null;
    
        // Challenge holen
        var options = {
            url: loginURL + fritzBenutzer,
            method: 'GET'
        };
        request(options, function(error, response, body) {
        if (!error && response.statusCode == 200) {
            //if (logging) log('error: ' + error + ', response: ' + JSON.stringify(response) + ', body: ' + body, 'info');
            var result = parseXML(body);
            var challenge = result['SessionInfo.Challenge'];
    
            // Einloggen und SID holen
            var utf16le_encoded = iconv.encode(challenge + '-' + fritzPasswort, 'UTF-16LE', {addBOM: false});
            var challengeResponse = crypto.createHash('md5').update(utf16le_encoded).digest('hex');
    
            options = {
                url: loginURL + '/login_sid.lua?username=' + fritzBenutzer + '&response=' + challenge + '-' + challengeResponse,
                method: 'GET'
            };
            request(options, function(error, response, body) {
                if (!error && response.statusCode == 200) {
                    var result = parseXML(body);
                    sid = result['SessionInfo.SID'];
                    if (logging) log('Logged in. SID = ' + sid, 'info');
                }
                else {
                    log('error: ' + error + ', response: ' + response.statusCode.toString(), 'info');
                }
            });
        }
        else {
            log('error: ' + error + ', response: ' + response.statusCode.toString(), 'info');
        }
        });
    }
    
    // Wenn keine Daten abgerufen werden konnten, werden die States auf NULL gesetzt
    function setStates2NullValues(){
    
        var NullValue = null;
    
        // DOCSIS 3.0 Downstream Channels
        for (i = 0; i < DOCSIS30DSChannels; i++) {
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.Frequency', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.Modulation', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.PowerLevel', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.MSE', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.Latency', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.CorrectableErrors', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.CorrectableErrorsPerMinute', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.UncorrectableErrors', NullValue, true);
            setState('Internet.Docsis.DS.C' + (i < 10 ? '0' : '') + i.toString() + '.UncorrectableErrorsPerMinute', NullValue, true);
        }
    
        // DOCSIS 3.1 Downstream Channel
        setState('Internet.Docsis31.DS.C01.PowerLevel', NullValue, true);
        setState('Internet.Docsis31.DS.C01.Type', NullValue, true);
        setState('Internet.Docsis31.DS.C01.Frequency', NullValue, true);
    
        // DOCSIS 3.0 Upstream Channels
        for (i = 0; i < DOCSIS30USChannels; i++) {
            setState('Internet.Docsis.US.C' + (i < 10 ? '0' : '') + i.toString() + '.Frequency', NullValue, true);
            setState('Internet.Docsis.US.C' + (i < 10 ? '0' : '') + i.toString() + '.Modulation', NullValue, true);
            setState('Internet.Docsis.US.C' + (i < 10 ? '0' : '') + i.toString() + '.MultiplexMethod', NullValue, true);
            setState('Internet.Docsis.US.C' + (i < 10 ? '0' : '') + i.toString() + '.PowerLevel', NullValue, true);
        }
    
        // DOCSIS 3.1 Upstream Channel
        setState('Internet.Docsis31.US.C00.PowerLevel', NullValue, true);
        setState('Internet.Docsis31.US.C00.Type', NullValue, true);
        setState('Internet.Docsis31.US.C00.MultiplexMethod', NullValue, true);
        setState('Internet.Docsis31.US.C00.Frequency', NullValue, true);
    }
    
    // Holt die Informationen von der Fritzbox Benutzeroberfläche. Ab fritz.OS Version 7.2x werden die Informationen als JSON-String übermittelt (getCableModemChannelInfos Version 2)
    function getCableModemChannelInfosV2(){
    
        var NullValue = null;
        var tableData;
    
        var options = {
            url: docsisURL,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: 'xhr=1&sid=' + sid + '&lang=de&page=docInfo&xhrId=all&no_sidrenew='
        };
        request(options, function(error, response, body) {
            if (!error && response.statusCode == 200) {
                tableData = JSON.parse(body);
                if(tableData){
                    //log(JSON.stringify(tableData), 'info');
                    
                    // DOCSIS 3.0 Downstream Channels
                    DOCSIS30DSChannels = Object.entries(tableData.data.channelDs.docsis30).length;
                    for (i = 0; i < DOCSIS30DSChannels; i++) {
    
                        var channelID = parseInt(tableData.data.channelDs.docsis30[i].channelID);
    
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.Frequency', parseInt(tableData.data.channelDs.docsis30[i].frequency), true);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.Modulation', parseInt(tableData.data.channelDs.docsis30[i].type.replace('QAM', '')), true);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.PowerLevel', parseFloat(tableData.data.channelDs.docsis30[i].powerLevel), true);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.MSE', parseFloat(tableData.data.channelDs.docsis30[i].mse), true);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.Latency', parseFloat(tableData.data.channelDs.docsis30[i].latency), true);
    
                        var correctableErrors = getState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.CorrectableErrors');
                        var lastValue = correctableErrors.val;
                        var ts_diff = new Date().getTime() - correctableErrors.ts;
                        var newValue = parseInt(tableData.data.channelDs.docsis30[i].corrErrors);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.CorrectableErrors', newValue, true);
                        // Die Differenz zum letzten Wert nur dann speichern, wenn dieser ca. 1 Min. alt ist
                        if (ts_diff > 50000 && ts_diff < 70000){
                            if (newValue > lastValue){
                                setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.CorrectableErrorsPerMinute', newValue - lastValue, true);
                            }
                        }
                        else {
                            setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.CorrectableErrorsPerMinute', NullValue, true);
                        }
    
                        var uncorrectableErrors = getState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.UncorrectableErrors');
                        var lastValue = uncorrectableErrors.val;
                        var ts_diff = new Date().getTime() - uncorrectableErrors.ts;
                        var newValue = parseInt(tableData.data.channelDs.docsis30[i].nonCorrErrors);
                        setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.UncorrectableErrors', newValue, true);
                        // Die Differenz zum letzten Wert nur dann speichern, wenn dieser ca. 1 Min. alt ist
                        if (ts_diff > 50000 && ts_diff < 70000){
                            if (newValue > lastValue){
                                setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.UncorrectableErrorsPerMinute', newValue - lastValue, true);
                            }
                        }
                        else {
                            setState('Internet.Docsis.DS.C' + (channelID < 10 ? '0' : '') + tableData.data.channelDs.docsis30[i].channelID + '.UncorrectableErrorsPerMinute', NullValue, true);
                        }
                    }
    
                    // DOCSIS 3.1 Downstream Channel
                    if (tableData.data.channelDs.docsis31 != null){
                        DOCSIS31DSChannels = 1;
                        setState('Internet.Docsis31.DS.C01.PowerLevel', parseFloat(tableData.data.channelDs.docsis31[0].powerLevel), true);
                        setState('Internet.Docsis31.DS.C01.Type', parseInt(tableData.data.channelDs.docsis31[0].type.replace('K', '')), true);
                        setState('Internet.Docsis31.DS.C01.Frequency', tableData.data.channelDs.docsis31[0].frequency, true);
                    }
    
                    // DOCSIS 3.0 Upstream Channels
                    DOCSIS30USChannels = Object.entries(tableData.data.channelUs.docsis30).length;
                    for (i = 0; i < DOCSIS30USChannels; i++) {
                        var channelID = parseInt(tableData.data.channelUs.docsis30[i].channelID);
                        setState('Internet.Docsis.US.C' + (channelID < 10 ? '0' : '') + tableData.data.channelUs.docsis30[i].channelID + '.Frequency', parseInt(tableData.data.channelUs.docsis30[i].frequency), true);
                        setState('Internet.Docsis.US.C' + (channelID < 10 ? '0' : '') + tableData.data.channelUs.docsis30[i].channelID + '.Modulation', parseInt(tableData.data.channelUs.docsis30[i].type.replace('QAM', '')), true);
                        setState('Internet.Docsis.US.C' + (channelID < 10 ? '0' : '') + tableData.data.channelUs.docsis30[i].channelID + '.MultiplexMethod', tableData.data.channelUs.docsis30[i].multiplex, true);
                        setState('Internet.Docsis.US.C' + (channelID < 10 ? '0' : '') + tableData.data.channelUs.docsis30[i].channelID + '.PowerLevel', parseFloat(tableData.data.channelUs.docsis30[i].powerLevel), true);
                    }
    
                    // DOCSIS 3.1 Upstream Channel
                    if (tableData.data.channelUs.docsis31 != null){
                        DOCSIS31USChannels = 1;
                        setState('Internet.Docsis31.US.C00.PowerLevel', parseFloat(tableData.data.channelUs.docsis31[0].powerLevel), true);
                        setState('Internet.Docsis31.US.C00.Type', parseInt(tableData.data.channelUs.docsis31[0].type.replace('K', '')), true);
                        setState('Internet.Docsis31.US.C00.MultiplexMethod', tableData.data.channelUs.docsis31[0].multiplex, true);
                        setState('Internet.Docsis31.US.C00.Frequency', parseInt(tableData.data.channelUs.docsis31[0].frequency), true);
                    }
    
                }
                else{
                    log('Empty response', 'error');
                    setStates2NullValues();
                    loginAndGetSID();
                }
            }
            else {
                log('error: ' + error + ', response: ' + response.statusCode.toString(), 'error');
                setStates2NullValues();
                loginAndGetSID();
            }
        });
    
    }
    
    if (logging) log('DocsisInfo starting', 'info');
    
    // SID holen und merken (User Token)
    loginAndGetSID();
    var getSIDinterval = setInterval(loginAndGetSID, 900000);   // Alle 15 Minuten neue SID holen
    
    schedule("* * * * *", function() {                          // Zu jeder vollen Minute die Fritzbox DOCSIS-Daten abfragen
        getCableModemChannelInfosV2();
    });
    
  • Forum Testing Most Active

    @arndl

    javascript.0	2021-04-04 18:56:00.699	error	(14740) script.js.Fritz.UID: error: null, response: 403
    

    Modell: FRITZ!Box 6590 Cable
    Aktueller Energieverbrauch: 30 %
    FRITZ!OS: 07.20

    Muss der Benutzer ioBroker heißen?


  • @arndl said in Pegelwerte Fritzbox 6490 Cable auslesen?:

    Erstmal vielen Dank für das Script.
    Ich muss mich hierzu dann erst einmal zurechtfinden, habe mit dem IoBroker bisher noch keinerlei Erfahrung.
    Wie ist das

    Der Javascript-Adapter muss installiert sein und unter „Zusätzliche NPM-Module“ die iconv-lite und crypto Module eingetragen sein.

    Mit den "Zusätzlichen NPM-Modulen zu verstehen?
    Ich finde diesen Punkt nicht auf der Oberfläche.
    Tante google hat mich bisher auch nicht wirklich weitergebracht.


  • @sigi234
    Nein, der Login-Name ist egal. Muss natürlich passend im Script in der Variablen fritzBenutzer angepasst werden.


  • @sugram
    Hier auf den Schraubenschlüssel klicken:
    JavascriptInstanz.PNG

    Dann findest Du diese Konfiguration hier oben links:
    ScreenshotJavascriptAdapter.PNG


  • @arndl VIELEN DANK!!!!!

    Die Meldung im Logfile ist aber jetzt nicht weiter schlimm, oder?!

    javascript.0	2021-04-04 19:58:34.922	error	(1129) WARN deprecated crypto@1.0.1: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.
    

    ich erhalte im Scriptfenster nun folgende Fehlermeldung:

    20:05:00.101	error	javascript.0 (1129) script.js.AVM: error: null, response: 403
    

  • @sugram
    Interessant. Dann lass es in der Konfiguration mal weg. Wenn es dann immer noch geht, ist alles gut.


  • @sugram
    Dann macht die integrierte crypto Bibliothek offensichtlich irgendwas anders.
    Sie wird in der Zeile

    var challengeResponse = crypto.createHash('md5').update(utf16le_encoded).digest('hex');
    

    verwendet. Stimmt die Response nicht, dann lehnt die Fritzbox das Login ab.


  • @arndl wenn ich das crypto Modul wieder entferne, bekomme ich nach wie vor die gleiche Fehlermeldung

    Wie kann ich denn dann die Daten überhaupt abgreifen / ansehen?!

Suggested Topics

  • 6
  • 1
  • 1
  • 14
  • 30
  • 82
  • 6
  • 4

2.0k
Online

38.3k
Users

43.8k
Topics

611.7k
Posts