Ankündigung

Einklappen
Keine Ankündigung bisher.

Erfolgreich: Nuki Smart Lock mit EibPort und Arduino Fingerprintleser im KNX

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #31
    Batterien:

    Ich habe das Nuki seit 19.12. mit der Hardware-Bridge und den Original-Batterien an der Tür, mehrere Öffnungen täglich und Auto-Unlock an, bisher habe ich noch keine Probleme damit, und das obwohl unsere Wohnungstür etwas klemmt und das Schloss daher ganz schön ackern muss Wenn die alle sind werd ich es mit Eneloops versuchen und berichten.

    Zur Reichweite:
    Bluetooth-LE halt, kommt auf die Gegebenheiten an. Ich vermute für die Stahlbetondecke wird es nicht reichen. 8-10m Luft könnte aber gerade noch gehen.

    Das S in IoT steht für Security

    Kommentar


      #32
      Das ist aber dann schön doof, ich kann ja nicht 3 Bridges dazu kaufen, je Schloss eine...

      8-10m Luft + 24cm Ziegel


      ICh denke, das müsste ich einfach mal testen und ggf. dann ggf. NUKIs dazu kaufen, wenns von der Reichweite her passt. So wie ich das sehe, gibts aber derzeit so gut wie keine brauchbare Alternative auf dem Markt.

      Kommentar


        #33
        Zitat von halloween Beitrag anzeigen
        Das ist aber dann schön doof, ich kann ja nicht 3 Bridges dazu kaufen, je Schloss eine...

        8-10m Luft + 24cm Ziegel
        8-10m zwischen den Türen? Dann setze die Bridge in die Mitte und es sollte klappen. 8m+Wand wird die Bridge nicht packen.

        Kommentar


          #34
          Dann müsste die Bridge in die Garage. Keine Ahnung, ob so ein elektronisches Bauteil die dort vorherrschenden Temperatur und Feuchtigkeitsschwankungen auf Dauer aushält?


          Also sieht so aus:

          Haus -> Nebeneingangstür direkt in die Garage
          direkt darunter: Kellereingangstür in den Keller unter der Garage
          am anderen Ende der Garage ist dann die Tür zum Garten


          Sowas kann man wohl nur ausprobieren. Oder kann man sowas auch mit 2 Smartphones testen? Gibts eine App, welche Bluetooth LE nutzt oder kennt wer sonst eine günstige Möglichkeit, wie man die Reichweite von Bluetooth LE auf die Schnelle ausprobieren könnte?
          Zuletzt geändert von halloween; 18.05.2017, 14:53.

          Kommentar


            #35
            Ich kann nur was sagen zu den Batterien. Hab Eneloops drin seit ca. 2 Monaten. 2-3 Aktivierungen pro Tag.

            Kommentar


              #36
              Kann ich mir mit dem Nuki dann einen Riegelkontakt sparen? Sendet das NUKI seinen Zustand - also kann ich das so konfigurieren, dass ich dann auf der Visu sehe, dass die Tür verschlossen ist?

              Eine Leerdose für einen Magnetkontakt hab ich oberhalb der Tür in der Laibung vorgesehen, aber keine Verbindung von dort zum Schließblech.


              Würde dann heissen, wenn Tür geschlossen und NUKI Zustand verriegelt, dann ist die Tür garantiert zu. Ohne Magnetkontakt könnte die Tür ja auch offen stehen und der Schließriegel ausgefahren sein.

              Kommentar


                #37
                Ja, das Nuki sendet auf Abfrage seinen Status. Das ist ziemlich gut in der API beschrieben. Allerdings kannst du dir ohne Riegelkontakt nicht sicher sein ob die Tür geschlossen und verschlossen oder die Tür offen und verschlossen ist. Das Nuki sendet halt nur seinen Status und schließt natürlich auch zu, wenn die Tür aufsteht.

                Kommentar


                  #38
                  Hallo,

                  ich möchte mehrere Themen ansprechen:
                  • zyklische Statusabfragen: ich halte nicht viel von dieser Methode. Man kann die Nuki Bridge so konfigurieren, dass diese aktiv bei Statusänderungen einen http request abschickt. Diese Methode funktioniert bei mir seit Monaten extrem verlässlich. Ich glaube, dass FHEM mit dieser Methode arbeitet. (Ich verarbeite diese Status Rückmeldungen mit NodeJS auf einem Raspberry PI und schicke den Status mit UDP zum eibport.)
                  • das Schloss: mein Freund hatte wegen dem Nuki ein neues Schloss mit Gefahrenfunktion gekauft. ABER dieses Schloss dreht sich innen nicht mit, wenn man außen aufsperrt. Wenn man also bei einem montierten Nuki - warum auch immer - mit dem Schlüssel aufsperrt, bekommt das Nuki nicht mit und glaubt noch immer, dass geschlossen ist. Beim nächsten Sperrvorgang "spinnt" dann Nuki. Man benötigt also ein Schloss mit Gefahrenfunktion und synchronem drehen der Schlüssel. Dann bekommt das Nuki auch manuelles Sperren mit und schickt die Status-Meldung.
                  • Cloud: ich bin nicht begeistert, dass die Nuki App nur über Bluetooth oder WLAN/Cloud/Bridge/Nuki funktioniert, aber es ist so und funktioniert stabil. Wenn man also zu hause im WLAN außerhalb der Bluetooth-Reichweite ist, kann man mit der Nuki App das Schloß nur über das Internet sperren. Nur die Bridge API funktioniert ohne Internet.
                  • Stabilität: Ich habe das Nuki mit Bridge seit ca. 6 Monaten. Ich verwende die Bridge-API, LockAndGo, Autounlock und Autolock. In Summe bin ich mit allen Funktionen sehr zufrieden!

                  Ich hoffe, die Gedanken helfen manchen Lesern.

                  Beste Grüße,
                  Gero

                  Kommentar


                    #39
                    Gestern kam übrigens bei mir die Batteriewarnung, also ziemlich genau nach 6 Monaten (Zufall?)

                    Unsere Wohnungstür ist aber auch gerade sehr schwergängig. Im Haus hat Nuki leichteres Spiel.

                    Zitat von gero Beitrag anzeigen
                    [*]Cloud: ich bin nicht begeistert, dass die Nuki App nur über Bluetooth oder WLAN/Cloud/Bridge/Nuki funktioniert, aber es ist so und funktioniert stabil. Wenn man also zu hause im WLAN außerhalb der Bluetooth-Reichweite ist, kann man mit der Nuki App das Schloß nur über das Internet sperren. Nur die Bridge API funktioniert ohne Internet.
                    Zumal es über die WIFI API viel schneller reagiert
                    Zuletzt geändert von mawa; 21.06.2017, 19:32.
                    Das S in IoT steht für Security

                    Kommentar


                      #40
                      Zitat von raphaelhuber Beitrag anzeigen
                      Hallo Zusammen

                      Wollte mal kurz von meinen Erfahrungen mit dem Nuki Smart Lock und KNX berichten.

                      Also das Nuki zusammen mit der Nuki Bridge sind bei mir im WiFi. Die Nuki API erlaubt durch das Aufrufen einer speziellen webadresse (192.... + ID des Nuki + Token der Bridge) und speziellen aufrufen das Verriegeln oder Entriegeln des Smartlocks.

                      Der Eibport wiederum erlaubt das Aufrufen von webadressen (inklusive dynamisch ändernden Teilen in der Webadresse) via KNX telegram mit einem http-request Job.

                      Somit ist es kinderleicht das Nuki mit dem EibPort und somit KNX zu integrieren. Die Statusrückmeldung zu bekommen ist ein wenig Tricky, ist mir aber auch gelungen. Bzw. ruft der Eibport den Status alle x Sekunden vom Nuki ab. Ebenfalls via http-request Job und RegEx zum spezifischen Herauslesen des Status aus der Antwort.

                      Dann habe ich einen Arduino mit Fingerprint leser (gibts z.b bei LadyAda inklusive Tutorial.) Der Arduino Micro wird über gelb und weiss auf dem KNX Kabel mit 12V versorgt. Bei erkannten Fingerabdrücken toggelt er das schloss, auf oder zu. Dies macht er in dem er einen Ausgang auf HIGH gehen lässt. dieser Ausgang wiederum schaltet ein kleines relais (gibts als Arduino Zusatzmodule http://tinyurl.com/j4nt8yj) Ein UP 2 Kanal MDT-Tasterinterface (http://www.mdt.de/Tasterinterface.html) wird mit dem Relais geschaltet, das ausgelöste Telegram schaltet via Eibport das Nuki.

                      Das Tasterinterface hat zwei Kanäle. Der andere Kanal ist grad praktisch für die Türklingel.

                      Also. Alles keine grosse Sache. Hatte selbst keine Erfahrung mit Arduino oder RegEx. Ging aber.

                      Fingerprint und Arduino, kann man alles von LadyAda beziehen und mitgelieferten Code fast unangepasst benutzen. Ihr Video sagt alles.
                      https://www.adafruit.com/product/751

                      Falls jemand interesse hat an den http-Request Jobs für den Eibport. Nur fragen. Dann poste ich screen-shots.

                      Viele Grüsse
                      Raphael
                      hast du bilder vom verbauten fingerprint und der elektronik?
                      funktioniert noch immer alles ohne probleme?

                      Kommentar


                        #41
                        Hallo Leute,

                        ich habe keinen Fingerprint, aber Nuki mit Bridge über eibport im KNX integriert. Auch bei mir funktioniert es problemlos.

                        Den Sinn vom Fingerprint verstehe ich nicht ganz, da ja das Schloss über Auto-Unlock über Bluetooth eh von selbst aufsperrt.

                        In mehreren Berichten ist mir aufgefallen, dass der Nuki Status über zyklisches Pollen ermittelt wird. Das geht etwas eleganter.
                        Man kann der Bridge mitteilen, dass sie bei Status-Änderungen einen URL aufruft. Mit einem Raspberry, Nodjs, und einem sehr kleinen Programm kann diese Statusänderung an den eibport weitergeleitet werden. Kein Pollen und immer aktuell.

                        Ich kann das Nuki Schloss nur empfehlen. Ich habe aber eine Türschnalle. Bei einem Knauf bin ich mir nicht sicher, ob Nuki so genau weiß, dass du genau jetzt vor der Türe stehst.

                        Viel Spaß,
                        Gero

                        Kommentar


                          #42
                          Zitat von gero Beitrag anzeigen
                          Mit einem Raspberry, Nodjs, und einem sehr kleinen Programm kann diese Statusänderung an den eibport weitergeleitet werden. Kein Pollen und immer aktuell.
                          Hallo Gero,

                          könntest Du Deinen Mini-Server-Code mal hier posten?

                          Ich habe mir einen Lösung auf dem EIBPORT gebastelt, allerdings ebenfalls mit pollen. Und gestern angefangen, mich ins NodeJS einzulesen, dann kam wieder was dazwischen und schwupps schon ist das Wochenende wieder rum.

                          Sollte doch wirklich fast ein Dreizeiler sein, oder? Listening server (als Service) starten, diesen als callback der Bridge mitteilten, wenn da was ankommt per UDP rausschieben an den EIBPORT.

                          Fände ich nett, wenn Du Deinen Code teilen könntest!

                          Grüße Alex

                          Kommentar


                            #43
                            Zitat von MUCKNXer Beitrag anzeigen

                            Hallo Gero,

                            könntest Du Deinen Mini-Server-Code mal hier posten?

                            Ich habe mir einen Lösung auf dem EIBPORT gebastelt, allerdings ebenfalls mit pollen. Und gestern angefangen, mich ins NodeJS einzulesen, dann kam wieder was dazwischen und schwupps schon ist das Wochenende wieder rum.

                            Sollte doch wirklich fast ein Dreizeiler sein, oder? Listening server (als Service) starten, diesen als callback der Bridge mitteilten, wenn da was ankommt per UDP rausschieben an den EIBPORT.

                            Fände ich nett, wenn Du Deinen Code teilen könntest!

                            Grüße Alex
                            Servus Alex,

                            ich bin kein JavaScript Entwickler, aber bei mir läuft das Script. Zur Inspiration ist es sicher gut!
                            Wenn du weiter Fragen hast, gerne!

                            Beste Grüße,
                            Gero

                            Das Shell-Script:
                            #!/bin/bash

                            PROG=$(basename $0 .sh)
                            DIR=$(dirname $0)

                            # das Port 8044 darf nicht geändert werden, da es dem systemd bekannt gemacht wurde

                            (
                            date
                            NUKI_CALLBACK_PORT=8044 NUKI_UDP_HOST=gero-eibport.fritz.box NUKI_UDP_PORT=8033 node ${DIR}/${PROG}.js
                            ) >>${DIR}/${PROG}.log



                            Das JavaScript:

                            "use strict"

                            // bei Bridge registrieren
                            //curl 'http://gero-nukibridge:8080/callback/add?url=http://gero-RPI.fritz.box:8044&token=xxxxxxx'

                            var http = require('http');
                            var dgram = require('dgram');

                            var NUKI_ID = 113554569
                            var NUKI_Token = 'xxxxxxxx'

                            var CALLBACK_PORT = process.env['NUKI_CALLBACK_PORT']
                            var UDP_HOST = process.env['NUKI_UDP_HOST']
                            var UDP_PORT = process.env['NUKI_UDP_PORT']

                            var states = ['uncalibrated', 'locked', 'unlocking', 'unlocked', 'locking', 'unlatched',
                            'lock and go', 'unlatching' ];
                            states[254] = 'motor blocke';
                            states[255] = 'undefined';

                            var count = 0;




                            console.log('################################');
                            console.log(displayNow(0));
                            console.log('PortListening: ' + CALLBACK_PORT);
                            console.log('UDP-Server: ' + UDP_HOST);
                            console.log('UDP-Port: : ' + UDP_PORT);
                            console.log('################################');




                            function displayNow(actCount) {
                            var jetzt = new Date();
                            return(
                            jetzt.getDate() + '.'
                            + jetzt.getMonth()+1 + '.'
                            + jetzt.getFullYear() + ' '
                            + jetzt.getHours() + ':'
                            + jetzt.getMinutes() + ':'
                            + jetzt.getSeconds() + ' '
                            + '(' + actCount + ') ');
                            }




                            function informEibport(ausloeser, actCount, stateObj) {
                            var batteryCritical;
                            if ( stateObj['batteryCritical']) { batteryCritical = 1 } else { batteryCritical = 0};
                            var message = new Buffer(
                            '"nukiId": ' + stateObj['nukiId']
                            + ', "ausloeser": "' + ausloeser + '"'
                            + ', "state": ' + stateObj['state']
                            + ', "stateName": "' + stateObj['stateName'] + '"'
                            + ', "batteryCritical": ' + batteryCritical
                            );
                            console.log(displayNow(actCount) + 'Meldung an eibport: ' + message);

                            var client = dgram.createSocket('udp4');
                            client.on('error', function(err) {
                            console.log('Fehler bei UDP Socket');
                            });

                            client.send(message, 0, message.length, UDP_PORT, UDP_HOST, function(err, bytes) {
                            if (err) {
                            console.log(displayNow(actCount) + 'ERROR: ' + err);
                            }
                            client.close();
                            console.log(displayNow(actCount) + 'Aktion abgeschlossen');
                            });

                            }


                            var server = http.createServer();
                            server.listen(CALLBACK_PORT);

                            server.on('request', function(request, response) {
                            count += 1;
                            var actCount = count;

                            console.log(displayNow(actCount) + '--------------------');

                            var url = require('url');
                            var urlData = url.parse(request.url, true);

                            console.log(displayNow(actCount) + 'PathName: ' + urlData.pathname);
                            console.log(displayNow(actCount) + 'Aufruf von: ' + request.url);
                            console.log(displayNow(actCount) + 'Parameter: ' + JSON.stringify(urlData.query));

                            switch (urlData.pathname) {
                            case '/callback':
                            if (request.method == 'POST') {
                            var body = '';
                            request.on('data', function(data) {
                            body += data;
                            });
                            request.on('end', function() {
                            var StateObj = JSON.parse(body);
                            // for (var property in StateObj) {
                            // console.log(property + ': ' + StateObj[property]);
                            // }
                            informEibport('Callback', actCount, StateObj);
                            });
                            } else
                            {
                            console.log('kein POST-Methode sondern ' + request.method);
                            }
                            break;
                            default:
                            console.log('Falscher Url: ' + urlData.pathname);
                            }
                            response.end();
                            });

                            server.on('listening', function() {
                            console.log('listening');
                            });

                            server.on('error', function(err) {
                            console.log('Fehler im Serverprozess: ' + err);
                            });

                            Kommentar


                              #44
                              Klasse, Danke gero!

                              Schaue ich mir gleich bei nächster Gelegenheit an und werde berichten...

                              Grüße Alex

                              Kommentar


                                #45
                                gero Nochmal Danke! funktioniert prima. Einzig mir fehlt die Zeit jetzt noch die RegEx-strings wieder zu lernen... da das skript ja eh auf einem OpenHABian läuft, darf der das jetzt auch gleich in KNX übersetzen. Der EIBPORT bleibt in dem Fall also außen vor.

                                Für eventuelle Nachahmer kopiere ich die Skripte noch einmal in eine Code-Box...

                                Shell-Skript

                                Code:
                                #!/bin/bash
                                PROG=$(basename $0 .sh)
                                DIR=$(dirname $0)
                                
                                # Einrichten des callbacks
                                # Callback Port einrichten bzw. löschen im Nuki
                                # Anmelden:
                                # $ curl 'http://Nuki-Bridge-12345678:8080/callback/add?url=http://webserver:8044/callback&token=APITOKEN'
                                #
                                # Anzeigen der eingerichteten Callbacks:
                                # $ curl 'http://Nuki-Bridge-12345678:8080/callback/list&token=APITOKEN'
                                #
                                # Löschen (man darf maximal 3 callbacks haben, ID 0,1 oder 2 entsprechend einsetzen)
                                # $ curl 'http://Nuki-Bridge-12345678:8080/callback/remove?id=0&token=APITOKEN'
                                #
                                (
                                    date
                                    NUKI_CALLBACK_PORT=8044 NUKI_UDP_HOST=eibport NUKI_UDP_PORT=8033 node ${DIR}/${PROG}.js
                                ) >> ${DIR}/${PROG}.log
                                Und der callback-server

                                Code:
                                /*
                                    Nuki to EIBPORT
                                
                                    Provide info to EIBPORT on lock state
                                
                                    credits to gero from KNX-UF
                                */
                                
                                'use strict';
                                
                                var http = require('http');
                                var dgram = require('dgram');
                                
                                // Lock Identifaction
                                // Nuki ID - if in hex, it needs to be 'quoted'
                                var NUKI_ID = 12345678
                                var NUKI_Token = 'APITOKEN'
                                
                                const CALLBACK_PORT = process.env['NUKI_CALLBACK_PORT'] || 8044
                                const UDP_HOST = process.env['NUKI_UDP_HOST'] || 'eibport'
                                const UDP_PORT = process.env['NUKI_UDP_PORT'] || 8033
                                
                                // Array 'states' for possible lock states
                                // ID 0 to 7
                                var states = ['uncalibrated', 'locked', 'unlocking', 'unlocked', 'locking', 'unlatched','lock and go', 'unlatching'];
                                
                                // ID 254 and 255
                                states[254] = 'motor blocked';
                                states[255] = 'undefined';
                                
                                var count = 0;
                                
                                var server = http.createServer();
                                
                                server.listen(CALLBACK_PORT);
                                
                                /*
                                    Format of callback JSON delivered by Nuki bridge 
                                    { nukiId": 12345678, "state": 1, "stateName": "locked", "batteryCritical": 1 
                                */
                                console.log('################################');
                                console.log(displayNow(0));
                                console.log('PortListening: ' + CALLBACK_PORT);
                                console.log('UDP-Server: ' + UDP_HOST);
                                console.log('UDP-Port: : ' + UDP_PORT);
                                console.log('################################');
                                
                                function displayNow(actCount) {
                                    var jetzt = new Date();
                                    return(
                                        jetzt.getDate() + '.'
                                        + (jetzt.getMonth()+1) + '.'
                                        + jetzt.getFullYear() + ' '
                                        + jetzt.getHours() + ':'
                                        + jetzt.getMinutes() + ':'
                                        + jetzt.getSeconds() + ' '
                                        + '(' + actCount + ') ');
                                    }
                                
                                function informEibport(ausloeser, actCount, stateObj) {
                                    var batteryCritical;
                                    if ( stateObj['batteryCritical']) { batteryCritical = 1 } else { batteryCritical = 0};
                                    var message = new Buffer(
                                        // full string, needs to be broken down with RegEx in EIBPORT       
                                        /*        '"nukiId": ' + stateObj['nukiId']
                                        + ', "ausloeser": "' + ausloeser + '"'
                                        + ', "state": ' + stateObj['state']
                                        + ', "stateName": "' + stateObj['stateName'] + '"'
                                        + ', "batteryCritical": ' + batteryCritical
                                        */
                                
                                        // or just the state (locked, unlocked, ...) can be parsed as ASCII
                                        stateObj['stateName']
                                    );
                                
                                    console.log(displayNow(actCount) + 'Meldung an eibport: ' + message);
                                
                                    var client = dgram.createSocket('udp4');
                                
                                    client.on('error', function(err) {
                                        console.log('Fehler bei UDP Socket');
                                    });
                                
                                    client.send(message, 0, message.length, UDP_PORT, UDP_HOST, function(err, bytes) {
                                        if (err) {
                                            console.log(displayNow(actCount) + 'ERROR: ' + err);
                                        }
                                        client.close();
                                        console.log(displayNow(actCount) + 'Aktion abgeschlossen');
                                    });
                                
                                }
                                server.on('request', function(request, response) {
                                    count += 1;
                                    var actCount = count;
                                    var url = require('url');
                                    var urlData = url.parse(request.url, true);
                                
                                    console.log(displayNow(actCount) + '--------------------');
                                    console.log(displayNow(actCount) + 'PathName: ' + urlData.pathname);
                                    console.log(displayNow(actCount) + 'Aufruf von: ' + request.url);
                                    console.log(displayNow(actCount) + 'Parameter: ' + JSON.stringify(urlData.query));
                                    switch (urlData.pathname) {
                                        case '/callback':
                                        if (request.method == 'POST') {
                                            var body = '';
                                            request.on('data', function(data) {body += data;});
                                            request.on('end', function() {
                                                var StateObj = JSON.parse(body);
                                                for (var property in StateObj) {
                                                    console.log(property + ': ' + StateObj[property]);
                                                }
                                                informEibport('Nuki', actCount, StateObj);
                                            });
                                        } else {
                                            console.log('kein POST-Methode sondern ' + request.method);
                                        }
                                        break;
                                        default:
                                        console.log('Falscher Url: ' + urlData.pathname);
                                    }
                                    response.end();
                                });
                                
                                server.on('listening', function() {
                                    console.log('listening');
                                });
                                
                                server.on('error', function(err) {
                                    console.log('Fehler im Serverprozess: ' + err);
                                });

                                Kommentar

                                Lädt...
                                X