【问题标题】:Fingerprint reader on node.js through .NET SDK通过 .NET SDK 在 node.js 上读取指纹
【发布时间】:2013-05-08 00:28:41
【问题描述】:

我正在尝试让 node.js 应用程序与名为 U.are.U 的 .NET SDK 指纹读取器交互。 SDK 提供 .dll(win32 和 x64)、Java 和 .NET 库。我决定使用 .NET 来简化使用,让所有接口都可以使用。

所以,我当前面临的问题是如何调用这些 .NET 函数并仍然保留 node.js 的异步特性。应用程序流程(在 .NET 示例中)非常简单,对库进行了 3 次调用,指纹就完成了。

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;
    }
}

如何更改它以便它可以在 node.js 中使用,而不是在 .NET gui 程序中使用?

还需要注意的是,node.js 并不总是会调用 .NET 程序上的函数来接收函数。程序的识别部分是异步发生的,当有人将手指放在指纹读取器上时就会触发,这意味着 node.js 部分不知道什么时候会发生。所以我不能一直依赖在 .NET 部分询问数据,它必须在没有被询问的情况下调用 node.js 上的回调。 所以基本上,这是一种双向通信,不仅仅是根据请求,因为使用网络服务器进行请求会容易得多。

我找到了一个 node.js 库,它可以缩小 .NET 和 node.js 之间的差距,名为 edge.js,这有什么帮助吗?


基本上,edge.js 可以使它工作,连同node-webkit(我将发布我的应用程序),我可以直接在页面中调用节点 API,因此我可以根据结果更新 DOM从图书馆。 我需要能够注册一个异步任务,该任务可以通过发出事件或调用回调来从 CLR 内部通知 node.js 对应项!

根据 edge.js 作者的说法,它可以很容易地完成 https://github.com/tjanczuk/edge/issues/54#issuecomment-17967082 我只是没有足够的 .NET 技能来完成所有回调(来自完整的模块)。

【问题讨论】:

  • 你能解释一下为什么你在这里用 node.js 推动自己吗?
  • 我使用的是node-webkit,它可以在里面附带一个“浏览器”和node.js,我可以直接从脚本标签调用node API,两者之间有一个无缝的桥梁,并且因为我会将每个应用程序相互连接(P2P 风格),所以这是必须的
  • 你可能想看看 Reactive.NET (Rx.NET)。我以前用它来在事情发生时触发回调,这可以通过它的订阅概念来实现,类似于事件。
  • 我没有 .NET 的经验,但我有 node 的经验,如何缩小与 reactive.net 的差距?

标签: c# .net node.js fingerprint edge.js


【解决方案1】:

使用此 SDK 的 .NET 库不适合解决此问题。

Node.js 本身是一个 C++ 应用程序,尝试正确使用 .NET 库只会带来伤害,尤其是 SDK 还提供原生 C/C++ 库!

当然,你不能直接使用 C++ 库;您必须编写一个 C++ 包装器。在节点世界中,这些被称为addons。编写插件并不简单,但即使是几乎没有 C++ 经验的人也应该能够按照文档中的示例进行操作。

获得内置于 Windows 中的本机插件也可能有点棘手; here's some tips to help you get started.

由于您使用的 SDK 在付费墙后面,我无法提供任何具体示例。但是,我想您的 C++ 包装器对象将公开一些方法,并且您还将围绕它编写一个 JS 包装器以公开一个干净的 API。例如:

var uareu = require('./uareu.node') // the native C++ addon dll
    , events = require('events')
    , util = require('util');

function FingerprintReader() {
    events.EventEmitter.call(this); // initialize the EventEmitter

    // do stuff with the native module

    // whenever a finger is placed on the reader:
    this.emit('finger', { id: idFromSdk });
}

util.inherits(FingerprintReader, events.EventEmitter); // we want this module
                                                       // to be an EventEmitter

module.exports = FingerprintReader; // export for require()ing in your app

现在您的应用可以:

var FingerprintReader = require('fingerprint')
    , fp = new FingerprintReader();

fp.on('finger', function(d) {
    // do something with `d.id`
});

这个例子显然掩盖了很多,但应该让你很好地了解在 JS 端需要发生什么。至于检测手指何时放在阅读器上,我真的不能说如果不访问 SDK,您将如何做到这一点。我敢打赌,你最终会在某个地方进行投票。这应该在插件中的单独线程上完成。


奖励:走原生路线意味着您可能还与 SDK 的 Linux 版本兼容,因此您的应用也可以在 Linux 上运行!

【讨论】:

  • 无论哪种方式,我都无法从 C++ 包装器内部调用节点代码。似乎可以使用 edge.js 和 .NET 代码注入
  • @pocesar:当然可以。请参阅callback example
  • 与 edge.js 解决方案相比,它似乎真的很复杂......似乎需要我缺乏的高级 C++ 知识。
  • 我也在 Windows 上,它只会发送到 Windows 操作系统。
【解决方案2】:

自从发布这个问题很长时间后,我可以使用 node 事件发射器轻松地使用 edge.js 与我的 .NET UI 进行交流(甚至从 .NET UI 控制 node-webkit 中的 node.js):

// 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')

现在您可以使用事件从 .NET 中调用/调用,而不是调用本机代码(这可能不是线程安全的)

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;

现在可以从任何来自Base 的派生类异步调用Emit('error', "My error")。请注意,我最近开始研究 C#,我在此处提供的代码可能不是最合适的。

【讨论】:

  • 我有你的确切情况......试图通过节点的 .NET sdk 与一些硬件通信......你的解决方案给我带来了 95% 的方式......我是只是想知道您是否还有更多代码可以显示在 .NET Emit 函数的实际实现中。此外,您在 .NET 中的哪个位置接收从节点发出的事件?
【解决方案3】:

有趣的问题。是否可以将您关心的函数放入 ASHX 文件(自定义 HTTP 处理程序)中,然后从您的节点应用程序发布到该文件?根据您想要返回的内容,您可能需要进行一些序列化/反序列化,但这似乎是从 Node 应用程序触发一段 C# 代码的最简单方法......

Microsoft 有一套非常好的关于自定义 HTTP 处理程序的教程,可以在 here 找到。

基本的ASHX骨架如下:

<%@ WebHandler Language="C#" Class="NodeHandler" %>

using System;
using System.Web;

public class NodeHandler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {

        //Handle fingerprint stuff!!!

        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

您可以用现有函数的修改版本替换 ProcessRequest 的内容。

【讨论】:

    【解决方案4】:

    我会创建自托管的 WCF 服务(即具有 wcf 端点的 Windows 服务)或使用 OpenRasta 或 ServiceStack 等框架来替换 WCF

    在所有这三种情况下,我最终都会拥有 json Web 服务,该服务将最后一次调用的结果返回到 CaptureAndExtractFmd

    然后我会在 node.js 中使用该服务

    如果您需要任何有关您决定的方式的更多信息,只需创建另一个问题。

    带有 WCF 的示例代码,C# 部分

    [ServiceContract]
    public interface IFingerprintContrat {
    
       [OperationContract]
       Fmd[] GetLastFeature(); 
    
    }
    
    public class FingerprintService {
      Fmd[] GetLastFeature() {
         return CaptureAndExtractFmd().ToArray()
      }
    }
    
    using (ServiceHost host = new ServiceHost(typeof(FingerprintService), baseAddress))
    {
    // Enable metadata publishing.
      ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
      smb.HttpGetEnabled = true;
      smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
      host.Description.Behaviors.Add(smb);
      host.Open();
    
      Console.WriteLine("The service is ready at {0}", baseAddress);
      Console.WriteLine("Press <Enter> to stop the service.");
      Console.ReadLine();
    
      // Close the ServiceHost.
      host.Close();
    }
    

    Node.js 部分

     var request = require("request");
    
     request.get("baseaddress/GetLastFeature", function (err, res, body) {
       if (!err) {
          var resultsObj = JSON.parse(body);         
          console.log(resultsObj);
       }
     });
    

    【讨论】:

      猜你喜欢
      • 2010-10-01
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 2019-11-22
      • 2020-09-29
      • 2018-11-19
      相关资源
      最近更新 更多