Avatar for ChrisB

ChrisB

Member since Feb 2014 • Last active May 2014
  • 4 conversations
  • 26 comments

Most recent activity

  • in Interfacing
    Avatar for ChrisB

    And here is some example using the library :
    Async function series (Thanks Gordon) :

    function series(arr,done) {
      var i=0;
      function next(err, result) {
        if (((err!==undefined) && (err!==null)) || i>=arr.length)
          done(err, result);
        else
          setTimeout(function() {arr[i++](next);}, 0);
      }
      next();
    }
    

    Enrollment example :

    function enrollFingerprint(id) {
      series([
        function(done) {
          getImage(function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Image taken");
            done(error);
          });
        },
        function(done) {
          image2Tz(1, function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Image converted");
            done(error);
          });
        },
        function(done) {
          console.log('Remove finger');
          setTimeout(function(e) { console.log(e.time); done(null); }, 2000);
        },
        function(done) {
          console.log('Place same finger again');
          setTimeout(function(e) { console.log(e.time); done(null);}, 2000);
        },
        function(done) {
          getImage(function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Image taken");
            done(error);
          });
        },
        function(done) {
          image2Tz(2, function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Image converted");
            done(error);
          });
        },
        function(done) {
          createModel(function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Prints matched");
            done(error);
          });
        },
        function(done) {
          storeModel(id, function(err, result) {
            var error = getErrorCode(result.responseCode);
            if(error === null && ((result.responseCode & 0xFF) == C.FINGERPRINT_OK)) 
                console.log("Stored");
            done(error);
          });
        }
      ], function (err, result) {
        console.log(err);
      });
    }
    
    connect(Serial4);
    
    enrollFingerprint(8);
    

    Recogniton example :

    function getFingerprintIDez(callback) {
      series([
          function(done) {
            getImage(function(err, result) {
              var error = getErrorCode(result.responseCode);
              done(error);
            });
          },
          function(done) {
            image2Tz(1, function(err, result) {
              var error = getErrorCode(result.responseCode);
              done(error);
            });
          },
          function(done) {
            fingerFastSearch(function(err, result) {
              var error = getErrorCode(result.responseCode);
              done(error, result);
            });
          }
      ], function(err, result) {
           callback(err, result);
        }
      );
    }
    
    connect(Serial4);
    
    getFingerprintIDez(function(err, result) {
      console.log('final');
      console.log('Error : ' + err);
      if(err === null) {
      console.log(result);
        console.log('#ID : ' + result.fingerID);
        console.log('level : ' + result.confidence); 
      }
    });
    
  • in Interfacing
    Avatar for ChrisB

    Hi,
    I finally managed to make the fingerprint sensor working,
    with print recognition and code for enrollment.
    Here is the code :

    var C = {
      FINGERPRINT_OK                 : 0x00,
      FINGERPRINT_PACKETRECIEVEERR   : 0x01,
      FINGERPRINT_NOFINGER           : 0x02,
      FINGERPRINT_IMAGEFAIL          : 0x03,
      FINGERPRINT_IMAGEMESS          : 0x06,
      FINGERPRINT_FEATUREFAIL        : 0x07,
      FINGERPRINT_NOMATCH            : 0x08,
      FINGERPRINT_NOTFOUND           : 0x09,
      FINGERPRINT_ENROLLMISMATCH     : 0x0A,
      FINGERPRINT_BADLOCATION        : 0x0B,
      FINGERPRINT_DBRANGEFAIL        : 0x0C,
      FINGERPRINT_UPLOADFEATUREFAIL  : 0x0D,
      FINGERPRINT_PACKETRESPONSEFAIL : 0x0E,
      FINGERPRINT_UPLOADFAIL         : 0x0F,
      FINGERPRINT_DELETEFAIL         : 0x10,
      FINGERPRINT_DBCLEARFAIL        : 0x11,
      FINGERPRINT_PASSFAIL           : 0x13,
      FINGERPRINT_INVALIDIMAGE       : 0x15,
      FINGERPRINT_FLASHERR           : 0x18,
      FINGERPRINT_INVALIDREG         : 0x1A,
      FINGERPRINT_ADDRCODE           : 0x20,
      FINGERPRINT_PASSVERIFY         : 0x21,
      //
      FINGERPRINT_STARTCODE          : 0xEF01,
      //
      FINGERPRINT_COMMANDPACKET      : 0x1,
      FINGERPRINT_DATAPACKET         : 0x2,
      FINGERPRINT_ACKPACKET          : 0x7,
      FINGERPRINT_ENDDATAPACKET      : 0x8,
      //
      FINGERPRINT_TIMEOUT            : 0xFF,
      FINGERPRINT_BADPACKET          : 0xFE,
      //
      FINGERPRINT_GETIMAGE           : 0x01,
      FINGERPRINT_IMAGE2TZ           : 0x02,
      FINGERPRINT_REGMODEL           : 0x05,
      FINGERPRINT_STORE              : 0x06,
      FINGERPRINT_EMPTY              : 0x0D,
      FINGERPRINT_VERIFYPASSWORD     : 0x13,
      FINGERPRINT_HISPEEDSEARCH      : 0x1B,
      FINGERPRINT_TEMPLATECOUNT      : 0x1D,
      //
      DEFAULTTIMEOUT : 5000 // milliseconds
    };
    
    var serialTTL = null;
    var thePassword = 0;
    var theAddress = 0xFFFFFFFF;
    
    function connect(serial) {
      serialTTL = serial;
      serialTTL.setup(57600);
    }
    
    function checkSensor(callback) {
      var packet = [
        C.FINGERPRINT_VERIFYPASSWORD,
        (thePassword >> 24) & 0xFF,
        (thePassword >> 16) & 0xFF,
        (thePassword >> 8) & 0xFF,
        thePassword & 0xFF
      ];
      sendPacket(packet, callback);
    }
    
    function getImage(callback) {
      sendPacket([C.FINGERPRINT_GETIMAGE], callback);
    }
    
    function image2Tz(slot, callback) {
      sendPacket([C.FINGERPRINT_IMAGE2TZ, (slot & 0xFF)], callback);
    }
    
    function createModel(callback) {
      sendPacket([C.FINGERPRINT_REGMODEL], callback);
    }
    
    function storeModel(id, callback) {
      sendPacket([C.FINGERPRINT_STORE, 0x01, (id >> 8) & 0xFF, id & 0xFF], callback);
    }
    
    function emptyDatabase(callback) {
      sendPacket([C.FINGERPRINT_EMPTY], callback);
    }
    
    function fingerFastSearch(callback) {
      var fingerID = 0xFFFF;
      var confidence = 0xFFFF;
      var packet = [C.FINGERPRINT_HISPEEDSEARCH, 0x01 & 0xFF, 0x00  & 0xFF, 0x00 & 0xFF, 0x00 & 0xFF, 0xA3 & 0xFF];
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
      getReply(packet, function(len, packet) {
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET)) {
          callback(-1, null);
          return;
        }
        fingerID = packet[2];
        fingerID <<= 8;
        fingerID |= packet[3];
        confidence = packet[4];
        confidence <<= 8;
        confidence |= packet[5];
        callback(null, {'responseCode': packet[1], 'fingerID': fingerID, 'confidence': confidence});
      });
    }
    
    function getTemplateCount(callback) {
      var templateCount = 0xFFFF;
      var packet = [C.FINGERPRINT_TEMPLATECOUNT];
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
      getReply(packet, function(len, packet) {
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET)) {
          callback(-1, null);
          return;
        }
        templateCount = packet[2];
        templateCount <<= 8;
        templateCount |= packet[3];
        callback(null, {'responseCode': packet[1], 'templateCount': templateCount});
      });
    }
    
    function writePacket(addr, packetType, packet) {
      var len = packet.length+2;
      serialTTL.write([
        (C.FINGERPRINT_STARTCODE >> 8) & 0xFF,
        C.FINGERPRINT_STARTCODE & 0xFF,
        (addr >> 24) & 0xFF,
        (addr >> 16) & 0xFF,
        (addr >> 8) & 0xFF,
        addr & 0xFF,
        packetType,
        (len >> 8) & 0xFF,
        len &0xFF
      ]);
      var sum = (len>>8) + (len&0xFF) + packetType;
      serialTTL.write(packet);
      for (var i in packet) sum += packet[i];
      serialTTL.write([(sum>>8)&0xFF, sum&0xFF]);
    }
    
    function getReply(packet, callback) {
      var receivedData = [];
    
      serialTTL.onData(function (e) {
        receivedData.push(e.data.charCodeAt(0));
    
        if ( (idx === 0) && (receivedData[0] != ( (C.FINGERPRINT_STARTCODE >> 8) & 0xFF) ))
          return;
    
        if (receivedData.length >= 9) {
          if (( receivedData[0] != (C.FINGERPRINT_STARTCODE >> 8)) ||
              ( receivedData[1] != (C.FINGERPRINT_STARTCODE & 0xFF))) {
            callback(-1, {'responseCode': C.FINGERPRINT_BADPACKET});
            return;
          }
    
          var packettype = receivedData[6];
          var len = receivedData[7];
    
          len <<= 8;
          len |= receivedData[8];
          len -= 2;
    
          if (receivedData.length <= (len+10))
            return;
    
          packet[0] = packettype;
    
          for (var i=0; i<len; i++) {
            packet[1+i] = receivedData[9+i];
          }
    
          callback(len, packet);
        }
      });
    }
    
    function sendPacket(packet, callback) {
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
      getReply(packet, function(len, packet) {
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET))
          callback(-1, null);
        else
          callback(len, {'responseCode': packet[1]});
      });
    }
    
    function getErrorCode(responseCode) {
      var res = null;
      switch (responseCode & 0xFF) {
        case C.FINGERPRINT_OK:
          res = null;
          break;
        case C.FINGERPRINT_NOFINGER:
          res = "No Finger";
          break;
        case C.FINGERPRINT_PACKETRECIEVEERR:
          res = "Communication error";
          break;
        case C.FINGERPRINT_IMAGEFAIL:
          res = "Imaging error";
          break;
        case C.FINGERPRINT_IMAGEMESS:
          res = "Image too messy";
          break;
        case C.FINGERPRINT_FEATUREFAIL:
          res = "Could not find fingerprint features";
          break;
        case C.FINGERPRINT_INVALIDIMAGE:
          res = "Could not find fingerprint features";
          break;
        case C.FINGERPRINT_ENROLLMISMATCH:
          res = "Prints did not match";
          break;
        case C.FINGERPRINT_BADLOCATION:
          res = "Could not store in that location";
          break;
        case C.FINGERPRINT_BADPACKET:
          res = "Communication error";
          break;
        case C.FINGERPRINT_FLASHERR:
          res = "Error writing to flash";
          break;
        default:
          res = "Unknown error";
      }
      return res;
    }
    
    • 8 comments
    • 5,494 views
  • in JavaScript
    Avatar for ChrisB

    I agree that async.js might be a bit heavy for the simple fact of doing series :)
    But this library do a lot more and I had in mine to port this library to have something similar in Espruino, by also adding then the doWhile, etc etc with asynchronous management.... but you are right :)

    Thanks for fixing the first two points.
    Is the first point fixing the line :
    ° callback = callback || function () {};
    ° if (fn)
    ° if(arr.map)

    But for me the for(.... in ... ) is also "wrong" ? In the code I'm ususally do it used to return the value (the item) and not the index (as an integer) in the array.
    what I except is

        for (var i in ["a","b","c"]) console.log(i)link
        "a"
        "b"
        "c"
    

    Is Espruino "standard" javascript ? or is it mine code that is not standard :) ?
    I have to admit that I have worked more with node.js so I might be wrong in some of my comments

  • in JavaScript
    Avatar for ChrisB

    Using the library is working like this :

    var ac = new async();
    
    console.log('start');
    
    ac.series([
        function(done) {
          console.log('func1 called');
          done(null);
        }
      ],
      function(err, result) {
        console.log('end');
      }
    );
    

    but fails like this

    var ac = new async();
    
    console.log('start');
    
    ac.series([
        function(done) {
          console.log('func1 called');
          done(null);
        },
        function(done) {
          console.log('func2 called');
          done(null);
        }
      ],
      function(err, result) {
        console.log('end');
      }
    );
    

    En error message from Espruino says that it reached the stack limitation for recursivity functions.
    I tried to add a setTimeout(fn(function (err) ...., 0) in this.series to 'empty' the stack.
    I used this trick in some of my code to create recursivity :
    using setTimeout allow the stack to continue the program (and do not fill it) and then call the recursive function. But even with this trick this is not wokring.

    Even if I can make the code working, I'm afraid the board has not enough 'power' or memory.

    What do you think ?

  • in JavaScript
    Avatar for ChrisB

    Hi Gordon,
    I used jsfiddle.net in Google Chrome (for the console)
    to test and compare the original code of async library.
    Here is the modified code with comments of portion of code that do not react the same in Espruino. I do not know what should work or not in Espruino, what should be standard or not, but async.js is normally using standard javascript (I think :) ).

    function async() {
    
      var eachSeries = function (arr, iterator, callback) {
    
        //Commented next statement as it fails. callback is always assigned to function () {};
        //even if callback has an value.
        
        //callback = callback || function () {};
    
        if (!arr.length) {
          return callback();
        }
        var completed = 0;
        var iterate = function () {
          iterator(arr[completed], function (err) {
            if (err) {
              callback(err);
              callback = function () {};
            }
            else {
              completed += 1;
              if (completed >= arr.length) {
                callback(null);
              }
              else {
                iterate();
              }
            }
          });
        };
        iterate();
      };
    
      var _map = function (arr, iterator) {
        //commented if(arr.map)fails and never enter the if even if arr has a value
        //if (arr.map) {
          return arr.map(iterator);
        //}
        //this is th original code when previous if is not commented
        //var results = [];
        //_each(arr, function (x, i, a) {
        //  results.push(iterator(x, i, a));
        //});
        //return results;
      };
    
      var _asyncMap = function (eachfn, arr, iterator, callback) {
        var results = [];
        arr = _map(arr, function (x, i) {
          return {index: i, value: x};
        });
        eachfn(arr, function (x, callback) {
          iterator(x.value, function (err, v) {
            results[x.index] = v;
            callback(err);
          });
        }, function (err) {
          callback(err, results);
        });
      };
    
      var doSeries = function (fn) {
        //original code
        //return function () {
        //   var args = Array.prototype.slice.call(arguments);
        //   return fn.apply(null, [async.eachSeries].concat(args));
        //};
    
        return function () {
          //arguments.slice replace Array.prototype.slice.call
          var args = arguments.slice(0);
    
          //the following statements replace [eachSeries].concat(args)
          //as .concat is not recognized
          var r = [eachSeries];
    
          for(var i in args) {
            //i should be the value of args and not an integer 
            //i is equal to 0,1,2 (args has 3 items) and normally should be 
            //the value of args[i], isn't it ???
            r.push(args[i]);
          }
          return fn.apply(null, r);
        };
      };
    
      var mapSeries = doSeries(_asyncMap);
    
      this.series = function (tasks, callback) {
    
        //even if callback has a value, the following line fails
        //callback = callback || function () {};
    
        mapSeries(tasks, function (fn, callback) {
    
          // statement if(fn) fails even if fn has a value, so updated it to if (fn !=== null)
          if (fn !== null) {
              fn(function (err) {
                var args = arguments.slice(1);
                if (args.length <= 1) {
                  args = args[0];
                }
                callback.call(null, err, args);
              });
          }
        }, callback);
      };
    
    }
    
  • in JavaScript
    Avatar for ChrisB

    Used to work with node.js Async library and like this library.
    Having to do lot of asynchronous (so with callback) chaining functions in my project,
    such library might miss in Espruino.
    Example of async.js library transfered :

    function async() {  
      var only_once = function(fn) {
        var called = false;
        return function() {
          if (called) throw new Error("Callback was already called.");
          called = true;
          fn.apply(root, arguments);
        };
      };  
      
      var doSeries = function (fn) {
        return function () {
          var args = Array.prototype.slice.call(arguments);
          return fn.apply(null, [async.eachSeries].concat(args));
        };
      };  
    
      var eachSeries = function (arr, iterator, callback) {
        callback = callback || function () {};
        if (!arr.length) {
          return callback();
        }
        var completed = 0;
        var iterate = function () {
          iterator(arr[completed], function (err) {
            if (err) {
              callback(err);
              callback = function () {};
            }
            else {
              completed += 1;
              if (completed >= arr.length) {
                callback(null);
              }
              else {
                iterate();
              }
            }
          });
        };
        iterate();
      };
      
      var mapSeries = doSeries(_asyncMap);
      
      this.series = function (tasks, callback) {
        callback = callback || function () {};
        if (tasks.constructor === Array) {
          async.mapSeries(tasks, function (fn, callback) {
            if (fn) {
              fn(function (err) {
                var args = Array.prototype.slice.call(arguments, 1);
                if (args.length <= 1) {
                  args = args[0];
                }
                callback.call(null, err, args);
              });
            }
          }, callback);
        }
      };
    }
    
    var async = new async();
    
    async.series([
        function(done) {
          getImage(function(err, result) {
            //some logic)
            done(err, result); 
          });
        },
        function(done) {
          image2Tz(function(err, result) {
            //some ogic
            done(err, result);
          });      
        },
        function(done) {
          fingerFastSearch(function(err, result) {
            //some logic
            done(err, result);
          });
        }
      ],
      function(err, result) {
        if(err !== null) {
          console.log('Error : ' + err);
          //do logic
          return;
        }
                   
        console.log(result);
      }
    );
    

    If something similar is already present in Espruino, let me know...
    Any question or feedback, please let me know...
    I planned to use functions around control flow for the moment.

    [EDITED]
    PS : Sorry.... :(
    the code is not working so well..... I'll update it once fully working

  • in Interfacing
    Avatar for ChrisB

    I will see....
    The logic for enrollment will definitely use the interface module.
    This module have to contains all the logic to interface the sensor.

    But the logic to enroll a fingerID is quite long, as it require for example to take three image, compare, etc etc.
    And I thought that all those code might make the base module heavier in term of size. That's why I thought about additional module.. will see...
    But code example at minimum :)

  • in Interfacing
    Avatar for ChrisB

    I thought about creating a module just for interfacing with the sensor,
    and then another library, module, or code example that automate
    enrollment, and add if possible schedule management like authorize some fingerID only on certain day or so

  • in Interfacing
    Avatar for ChrisB

    And here is the code I have so far.
    Please note it was late, not necessarly optimized and the way the onData is done might change later :)
    Also I will add an 'err' as first parameter for each callback in case,
    and adapt some part of code.
    Once Enroll is done, I will start transforming and prepare for module

    var C = {
      FINGERPRINT_OK                 : 0x00,
      FINGERPRINT_PACKETRECIEVEERR   : 0x01,
      FINGERPRINT_NOFINGER           : 0x02,
      FINGERPRINT_IMAGEFAIL          : 0x03,
      FINGERPRINT_IMAGEMESS          : 0x06,
      FINGERPRINT_FEATUREFAIL        : 0x07,
      FINGERPRINT_NOMATCH            : 0x08,
      FINGERPRINT_NOTFOUND           : 0x09,
      FINGERPRINT_ENROLLMISMATCH     : 0x0A,
      FINGERPRINT_BADLOCATION        : 0x0B,
      FINGERPRINT_DBRANGEFAIL        : 0x0C,
      FINGERPRINT_UPLOADFEATUREFAIL  : 0x0D,
      FINGERPRINT_PACKETRESPONSEFAIL : 0x0E,
      FINGERPRINT_UPLOADFAIL         : 0x0F,
      FINGERPRINT_DELETEFAIL         : 0x10,
      FINGERPRINT_DBCLEARFAIL        : 0x11,
      FINGERPRINT_PASSFAIL           : 0x13,
      FINGERPRINT_INVALIDIMAGE       : 0x15,
      FINGERPRINT_FLASHERR           : 0x18,
      FINGERPRINT_INVALIDREG         : 0x1A,
      FINGERPRINT_ADDRCODE           : 0x20,
      FINGERPRINT_PASSVERIFY         : 0x21,
    
      FINGERPRINT_STARTCODE          : 0xEF01,
    
      FINGERPRINT_COMMANDPACKET      : 0x1,
      FINGERPRINT_DATAPACKET         : 0x2,
      FINGERPRINT_ACKPACKET          : 0x7,
      FINGERPRINT_ENDDATAPACKET      : 0x8,
    
      FINGERPRINT_TIMEOUT            : 0xFF,
      FINGERPRINT_BADPACKET          : 0xFE,
    
      FINGERPRINT_GETIMAGE           : 0x01,
      FINGERPRINT_IMAGE2TZ           : 0x02,
      FINGERPRINT_REGMODEL           : 0x05,
      FINGERPRINT_STORE              : 0x06,
      FINGERPRINT_EMPTY              : 0x0D,
      FINGERPRINT_VERIFYPASSWORD     : 0x13,
      FINGERPRINT_HISPEEDSEARCH      : 0x1B,
      FINGERPRINT_TEMPLATECOUNT      : 0x1D,
    
      DEFAULTTIMEOUT : 5000 // milliseconds
    };
    
    Serial4.setup(57600);
    
    var thePassword = 0;
    var theAddress = 0xFFFFFFFF;
    
    function writePacket(addr, packetType, packet) {
      var len = packet.length+2;
      Serial4.write([
        (C.FINGERPRINT_STARTCODE >> 8) & 0xFF,
        C.FINGERPRINT_STARTCODE & 0xFF,
        (addr >> 24) & 0xFF,
        (addr >> 16) & 0xFF,
        (addr >> 8) & 0xFF,
        addr & 0xFF,
        packetType,
        (len >> 8) & 0xFF,
        len &0xFF
      ]);
    
      var sum = (len>>8) + (len&0xFF) + packetType;
      Serial4.write(packet);
      for (var i in packet) sum += packet[i];
      Serial4.write([(sum>>8)&0xFF, sum&0xFF]);
    }
    
    function getReply(packet, callback) {
    
      var receivedData = [];// new Uint8Array(20);
    
      Serial4.onData(function (e) {
        receivedData.push(e.data.charCodeAt(0));
    
        if ( (idx === 0) && (receivedData[0] != ( (C.FINGERPRINT_STARTCODE >> 8) & 0xFF) ))
          return;
    
        if (receivedData.length >= 9) {
    
          if (( receivedData[0] != (C.FINGERPRINT_STARTCODE >> 8)) ||
              ( receivedData[1] != (C.FINGERPRINT_STARTCODE & 0xFF)))
            console.log('bad packet');
    
          var packettype = receivedData[6];
          var len = receivedData[7];
    
          len = len << 8 & 0xFF;
          len = len | (receivedData[8] & 0xFF);
          len -= 2;
    
          if (receivedData.length <= (len+10))
            return;
    
          packet[0] = packettype;
    
          for (var i=0; i<len; i++) {
            packet[1+i] = receivedData[9+i];
          }
    
          console.log('end');  
          callback(len, packet);
        }
      });
    }
    
    function verifyPassword(callback) {
      var packet = [
        C.FINGERPRINT_VERIFYPASSWORD,
        (thePassword >> 24) & 0xFF,
        (thePassword >> 16) & 0xFF,
        (thePassword >> 8) & 0xFF,
        thePassword & 0xFF
      ];
    
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
    
      getReply(packet, function(len, packet) {
        if ((len == 1) && (packet[0] == C.FINGERPRINT_ACKPACKET) && (packet[1] == C.FINGERPRINT_OK))
          callback(true);
        else
          callback(false);
      });
    }
    
    function getImage(callback) {
      var packet = [C.FINGERPRINT_GETIMAGE];
    
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
    
      getReply(packet, function(len, packet) {
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET))
          callback(-1);
        else
          callback(packet[1]);
      });
    }
    
    function image2Tz(slot, callback) {
      var packet = [C.FINGERPRINT_IMAGE2TZ, (slot & 0xFF)];
    
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
    
      getReply(packet, function(len, packet) {
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET))
          callback(-1);
        else
          callback(packet[1]);
      });
    }
    
    function fingerFastSearch(callback) {
      var fingerID = 0xFFFF;
      var confidence = 0xFFFF;
      var packet = [C.FINGERPRINT_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3];
    
      writePacket(theAddress, C.FINGERPRINT_COMMANDPACKET, packet);
    
      getReply(packet, function(len, packet) {
    
        if ((len != 1) && (packet[0] != C.FINGERPRINT_ACKPACKET)) {
          callback(-1);
          return;
        }
    
        fingerID = packet[2];
        fingerID <<= 8;
        fingerID |= packet[3];
    
        confidence = packet[4];
        confidence <<= 8;
        confidence |= packet[5];
    
        callback(packet[1], fingerID, confidence);
      });
    }
    
    function getFingerprintIDez(callback) {
      getImage(function(f) {
        if (f != C.FINGERPRINT_OK) {
          callback(-1);
          return;
        }
        image2Tz(null, function(g) {
          if (g != C.FINGERPRINT_OK) {
            callback(-1);
            return;
          }
          fingerFastSearch(function(res, fingerID, confidence) {
            if (res != C.FINGERPRINT_OK) {
              callback(-1);
              return;
            }
    
            callback(fingerID);
    
          });
        });
      });
    }
    
    
    //setup
    verifyPassword(function(e) {
      if(e) {
        getFingerprintIDez(function(e) {
          console.log(e);
        });
      }
    });
    
Actions