Jump to content

Fehler in IPConnection der JavaScript Bindings


Recommended Posts

Hallo zusammen,

 

ich bastle seit ein paar Tagen an einem Skript, welches die Daten meiner Wetterstationen in ioBroker darstellt. Das muss in JavaScript geschehen, weshalb ich mir die Bindings geschnappt und los gelegt habe.

 

Ich mache zunächst ein enumerate und sammle mir bekannte Bricklets (Temperature, Humidity, Barometer) ein. Diese instanziere ich dann und starte die jeweilige Callback. Die Werte bekomme ich alle ordentlich nach ioBroker übermittelt, es funktioniert also eigentlich alles einwandfrei.

 

Das Problem ist, dass alle 2-3 Minuten das Skript abbricht, und zwar mit folgendem Fehler:

 

2017-09-12 16:00:24.263  - error: javascript.1 TypeError: Cannot read property 'expectedResponses' of undefined
    at IPConnection.handleResponse (/opt/iobroker/node_modules/iobroker.javascript/node_modules/tinkerforge/lib/IPConnection.js:901:47)
    at IPConnection.handlePacket (/opt/iobroker/node_modules/iobroker.javascript/node_modules/tinkerforge/lib/IPConnection.js:1025:18)
    at IPConnection.handleIncomingData (/opt/iobroker/node_modules/iobroker.javascript/node_modules/tinkerforge/lib/IPConnection.js:331:18)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:547:20)

 

Ich habe das gequickfixt indem ich in der IPConnection.js in Zeile 899 (also knapp vor dem Fehler) folgendes eingefügt habe:

 

if (handleResponseDevice === undefined)
    return;

 

Damit läuft alles einwandfrei, mittlerweile seit über 30 Minuten.

 

Hat jemand eine Idee, ob es sich hier um einen Bug in der IPConnection.js handelt oder ob ich eventuell etwas falsch mache?

 

Robin

Link zu diesem Kommentar
Share on other sites

Du hast einen Bug gefunden und dein Fix ist richtig.

 

Was da passiert ist folgendes: Die IPConnection empfängt eine Antwort auf einen Getter oder einen Callback für einen Brick oder Bricklet für das du keine Instanz angelegt hast. Eigentlich sollte die IPConnection Nachrichten von unbekannten Bricks und Bricklets ignorieren. Der Check dafür fehlt aber hier.

 

Danke für den Hinweis, das Problem wird in der nächsten Version behoben sein.

Link zu diesem Kommentar
Share on other sites

Ah, sehr gut. Dann hatte ich da also den richtigen Riecher. Ich habe tatsächlich auch noch ein paar weitere Bricklets (Display, IO4), die ich mit dem JavaScript-Code nicht anfasse. Die werden allerdings noch von Perl-Scripten bedient und da nutze ich auch Callbacks. Das würde also irgendwie passen.

 

Danke schonmal für den Fix!

 

Viele Grüße

Robin

Link zu diesem Kommentar
Share on other sites

Hallo nochmal,

 

da ich das bisher im Netz nirgendwo in der Form finden konnte, hier mein Script. Vielleicht ist es ja für den Ein- oder Anderen ein guter Startpunkt für eigene Implementationen...

 

/*
* TinkerForge Wetterstation
*/

// Configuration:
var hosts = ['tf-1', 'tf-2', 'tf-3'];
var PORT = 4223;
var refresh_secs = 15; // Mindestabstand zwischen Messwerten

var ipcon = [];
var brick = [];
var bricklet = [];
refresh_secs *= 1000;

var Tinkerforge = require('tinkerforge');

function enumerateHosts() {
// Loop over hosts
hosts.forEach(function(HOST) {
    console.log('Host: ' + HOST);
    
    // Create connection and connect to brickd 
    ipcon[HOST] = new Tinkerforge.IPConnection();
    ipcon[HOST].connect(HOST, PORT);

    ipcon[HOST].on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
        function(connectReason) {
            // Trigger Enumerate 
            ipcon[HOST].enumerate();
        }
    );

    // Register Enumerate Callback 
    ipcon[HOST].on(Tinkerforge.IPConnection.CALLBACK_ENUMERATE,
        function(uid, connectedUid, position, hardwareVersion, firmwareVersion,
                 deviceIdentifier, enumerationType) {
            if(enumerationType === Tinkerforge.IPConnection.ENUMERATION_TYPE_DISCONNECTED) {
                return;
            }

            // See https://www.tinkerforge.com/de/doc/Software/Device_Identifier.html for IDs
            var value = null;
            switch (deviceIdentifier) {

                case 216: // Temperature
                    console.log('Temperature: ' + uid);
                    bricklet[uid] = {};
                    bricklet[uid].host = HOST;
                    bricklet[uid].bricklet = new Tinkerforge.BrickletTemperature(uid, ipcon[bricklet[uid].host]);
                    createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.name', 'Temperature Bricklet', { type: 'string' });
                    bricklet[uid].bricklet.getTemperature(function(temperature) {
                        value = temperature / 100.0;
                        createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.temperature', value, {
                            name: 'Temperature',
                            type: 'number',
                            unit: '°C'
                        });
                    });
                    bricklet[uid].bricklet.setTemperatureCallbackPeriod(refresh_secs);
                    bricklet[uid].bricklet.on(Tinkerforge.BrickletTemperature.CALLBACK_TEMPERATURE, function(temperature) {
                        //console.log('T:' + uid + ':' + temperature);
                        setState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.temperature', temperature / 100.0);
                    });
                    break;

                case 27: // Humidity
                    console.log('Humidity: ' + uid);
                    bricklet[uid] = {};
                    bricklet[uid].host = HOST;
                    bricklet[uid].bricklet = new Tinkerforge.BrickletHumidity(uid, ipcon[bricklet[uid].host]);
                    createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.name', 'Humidity Bricklet', { type: 'string' });
                    bricklet[uid].bricklet.getHumidity(function(humidity) {
                        value = humidity / 10.0;
                        createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.humidity', value, {
                            name: 'Humidity',
                            type: 'number',
                            unit: '%RH'
                        });
                    });
                    bricklet[uid].bricklet.setHumidityCallbackPeriod(refresh_secs);
                    bricklet[uid].bricklet.on(Tinkerforge.BrickletHumidity.CALLBACK_HUMIDITY, function(humidity) {
                        //console.log('H:' + uid + ':' + humidity);
                        setState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.humidity', humidity / 10.0);
                    });
                    break;

                case 221: // Barometer
                    console.log('Barometer: ' + uid);
                    bricklet[uid] = {};
                    bricklet[uid].host = HOST;
                    bricklet[uid].bricklet = new Tinkerforge.BrickletBarometer(uid, ipcon[bricklet[uid].host]);
                    createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.name', 'Barometer Bricklet', { type: 'string' });
                    bricklet[uid].bricklet.getAirPressure(function(airPressure) {
                        value = airPressure / 1000.0;
                        createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.AirPressure', value, {
                            name: 'AirPressure',
                            type: 'number',
                            unit: 'mbar'
                        });
                    });
                    bricklet[uid].bricklet.setAirPressureCallbackPeriod(refresh_secs);
                    bricklet[uid].bricklet.on(Tinkerforge.BrickletBarometer.CALLBACK_AIR_PRESSURE, function(airPressure) {
                        //console.log('BaP:' + uid + ':' + airPressure);
                        setState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.AirPressure', airPressure / 1000.0);
                    });
                    bricklet[uid].bricklet.getAltitude(function(altitude) {
                        value = altitude / 100.0;
                        createState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.Altitude', value, {
                            name: 'Altitude',
                            type: 'number',
                            unit: 'm'
                        });
                    });
                    bricklet[uid].bricklet.setAltitudeCallbackPeriod(refresh_secs);
                    bricklet[uid].bricklet.on(Tinkerforge.BrickletBarometer.CALLBACK_ALTITUDE, function(altitude) {
                        //console.log('Bal:' + uid + ':' + altitude);
                        setState('TinkerForge.' + bricklet[uid].host + '.' + uid + '.Altitude', altitude / 100.0);
                    });
                    break;
            } // End switch over brick(let)s
        }
    );
}); // End loop over hosts
} // End enumerateHosts

onStop(function (callback) {
    console.log('Terminating IPConnections');
    hosts.forEach(function(HOST) {
        ipcon[HOST].disconnect();
    });
}, 2000 /* timeout */);

// Start with enumeration
enumerateHosts();

 

Darf gerne als Ausgangspunkt für eigene Projekte benutzt werden.

 

Viele Grüße

Robin

Link zu diesem Kommentar
Share on other sites

  • 9 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...