通过.NET SDK在node.js上进行指纹识别

我试图让一个node.js应用程序与一个名为U.are.U的.NET SDK指纹识别器进行交互。 SDK提供.dll(win32和x64),Java和.NET库。 我决定使用.NET的简单使用,使所有的接口可以使用和所有。

所以,我目前面临的问题是如何调用这些.NET函数,仍然保持node.js的asynchronous性质。 应用程序stream程(在.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程序中调用函数来接收函数。 程序的识别部分是asynchronous发生的,当有人将手指放在指纹读取器上时,程序的识别部分就会出现,这意味着node.js部分不知道什么时候会发生。 所以我不能总是依赖于.NET部分的数据,它必须调用node.js上的callback而没有被问到。 所以基本上,这是一个双向通信,不仅仅是要求,因为请求使用networking服务器会更容易。

我find了一个node.js库,可以closures.NET和node.js之间的差距叫edge.js这将有什么帮助?


基本上, edge.js可以和node-webkit一起工作,我可以在页面中直接调用节点的API,所以我可以根据库的结果更新DOM 。 我需要能够注册一个asynchronous任务,可以通过发送一个事件或调用callback从CLR内部通知给node.js对手!

根据edge.js作者可以很容易地完成https://github.com/tjanczuk/edge/issues/54#issuecomment-17967082我只是没有足够的.NET技能来(从一个完整的模块)与所有的callback。

有趣的问题。 是否有可能把你关心的函数放到一个ASHX文件(自定义的HTTP处理程序)中,然后发布到你的节点应用程序中? 根据你想要返回你可能不得不做一些序列化/反序列化,但是这似乎是从节点应用程序触发一块C#代码的最简单的方法….

微软在这里可以find关于自定义HTTP处理程序的一套相当不错的教程。

基本的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; } } } 

您将用现有函数的修改版本replaceProcessRequest的内容。

使用此SDK的.NET库不是解决此问题的适当解决scheme。

Node.js本身就是一个C ++应用程序,试图正确使用.NET库只是要求一个受到伤害的世界, 特别是当SDK也提供一个本地的C / C ++库的时候!

当然,你不能直接使用C ++库; 你将不得不编写一个C ++包装器。 在节点世界中,这些被称为插件 。 编写一个插件并不是那么简单,但即使是一些C ++小经验的人也应该能够遵循文档中的例子,并且能够开展工作。

获得一个内置的Windows本地插件也可能有点棘手; 这里有一些提示可以帮助你开始 。

由于您使用的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上工作!

在发布这个问题很长一段时间后,我可以使用edge.js轻松地使用节点事件发射器来通信IN和OUT我的.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; 

现在可以asynchronous地从我的派生类的任何地方调用Emit('error', "My error") 。 只要注意我最近开始在C#中使用,我在这里提出的代码可能不是最合适的。

我会创build自己托pipe的WCF服务(即具有wcf端点的windows服务),或使用OpenRasta或ServiceStack等框架来replaceWCF

在所有这三种情况下,我最终都会得到json web服务,并返回最后一次调用CaptureAndExtractFmd

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

如果您需要进一步的信息,那么您可以创build另一个问题。

示例代码与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); } });