Search code examples
c#.netnode.jsfingerprintedge.js

Fingerprint reader on node.js through .NET SDK


I'm trying to get a node.js app to interact with a .NET SDK fingerprint reader called U.are.U. The SDK provides .dll (win32 and x64), Java and .NET libraries. I decided to use .NET for the simple of use, having all the interfaces ready to use and all.

So, the current problem I'm facing is how to call those .NET functions and still preserve the asynchronous nature of node.js. The application flow (on the .NET example) is pretty straight forward, 3 calls on the library, and the fingerprint is done.

private IEnumerable<Fmd> CaptureAndExtractFmd()
{
    while (!reset)
    {
        DataResult<Fmd> resultConversion;

        try
        {
            if (count >= 8)
            {
                SendMessage("Enrollment was unsuccessful.  Please try again.");
                count = 0;
                break;
            }

            Fid fid = null;
            if (!_sender.CaptureFinger(ref fid))
                break;

            if (fid == null)
                continue;

            count++;

            resultConversion = FeatureExtraction.CreateFmdFromFid(fid, Constants.Formats.Fmd.ANSI);

            SendMessage("A finger was captured.  \r\nCount:  " + (count));

            if (resultConversion.ResultCode != Constants.ResultCode.DP_SUCCESS)
                break;
        }
        catch (Exception)
        {
            break;
        }

        yield return resultConversion.Data;
    }
}

How can I change it so it can be usable in node.js, instead of a .NET gui program?

It also need to be noted that the node.js isn't always going to call a function on the .NET program to receive a function. The identification part of the program happens asynchronously and is set off when someone places a finger on the fingerprint reader, that means that the node.js part have no idea when that is going to happen. So I cannot rely on asking data on the .NET part all the time, it must call callbacks on the node.js without having been asked. So basically, it's a bidirectional communication, not only on request, since requesting using a webserver would be much easier.

I've found a node.js library that can close the gap between .NET and node.js called edge.js would this be of any help?


Basically, edge.js can make it work, along with node-webkit (which I'll be shipping my app), I can call the node APIs directly in the page, so I can update the DOM depending on the result from the library. I need to be able to register an async task that CAN notify from inside the CLR to the node.js counterpart either by emitting an event or calling a callback!

According to the edge.js author it can be done easily https://github.com/tjanczuk/edge/issues/54#issuecomment-17967082 I just don't have enough .NET skills to do so (from a full fledged module) with all the callbacks.


Solution

  • After a long time since this question was posted, I can use edge.js easily to communicate IN and OUT my .NET UI (even control node.js within node-webkit from .NET UI), using node event emitter:

    // demo basic code in node.js
    
    var 
      edge = require('edge'), 
      Bridge = edge.func('../path/to/compiled.dll'),
      callback,
      ev = new require('events').EventEmitter();
    
    ev.on('acquire', function(fingerdata){
      console.log(fingerdata);
    });
    
    ev.on('error', function(){
    }); 
    
    callback = function(event, report){
      // report the result of the event emitter back to .NET
      // you can even pass the "report" to the event handler, so you can return anything you want back to .NET, not just a boolean
      report(null, ev.emit(event.name, event.data));
      //ev.emit(event.name, {data: event.data, report: report});
    };
    
    var bridge = Bridge(callback, true);
    
    // calling bridge(null, true); "releases" my device, should be called on process.on('exit')
    

    And now you can call in/out from .NET using events, instead of calling native code (that might not be thread safe)

    namespace Bridge
    {
        public class Startup
        {
            public async Task<object> Invoke(Func<object, Task<object>>callback)
            {
                Bridge.Base.setCallback(callback);
    
                MainForm mainForm = new Bridge.MainForm();
    
                Task.Run(async () =>
                {
                    Application.Run(mainForm);
                });
    
                return (Func<object, Task<object>>)(async (i) => { Bridge.Base.release(); return null; });
            }
        }
    }
    
    // inside Bridge.Base
    
    
    static public void setCallback(Func<object, Task<object>> cb)
    {
        if (callback == null)
        {
            callback = cb;
        }
    }
    
    static public async void Emit(string name, object data)
    {
        return await Task.Run(async () =>
        {
            return await callback(new {
                name = name,
                data = data
            });
        });
    }
    
    static public Func<object, Task<object>> callback = null;
    

    can now call Emit('error', "My error") from anywhere my derived classes from Base, asynchronously. Just notice that I recently started dwelving in C#, and my code presented here might not be the best fit.