2013-05-08 11 views
9

Sto cercando di ottenere l'applicazione node.js per interagire con un lettore di impronte digitali .NET SDK denominato U.are.U. L'SDK fornisce librerie .dll (win32 e x64), Java e .NET. Ho deciso di utilizzare .NET per il semplice utilizzo, avendo tutte le interfacce pronte per l'uso e tutte.Lettore di impronte digitali su node.js tramite .NET SDK

Quindi, il problema corrente che sto affrontando è come chiamare quelle funzioni .NET e conservare ancora la natura asincrona di node.js. Il flusso dell'applicazione (nell'esempio .NET) è piuttosto semplice, 3 chiamate sulla libreria e l'impronta digitale.

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

Come posso cambiarlo in modo che possa essere utilizzabile in node.js, anziché in un programma GUI .NET?

È inoltre necessario notare che il nodo.js non chiama sempre una funzione sul programma .NET per ricevere una funzione. La parte identificativa del programma avviene in modo asincrono e viene attivata quando qualcuno mette un dito sul lettore di impronte digitali, il che significa che la parte node.js non ha idea di quando ciò accadrà. Quindi non posso fare affidamento sul chiedere continuamente dati su .NET. Devo chiamare callback su node.js senza che sia stato richiesto. Quindi, fondamentalmente, è una comunicazione bidirezionale, non solo su richiesta, dal momento che richiedere un utilizzo di un server web sarebbe molto più semplice.

ho trovato una libreria node.js in grado di colmare il divario tra .NET e Node.js chiamato edge.js questo sarebbe di alcun aiuto?


In sostanza, edge.js può farlo funzionare, insieme a node-webkit (che sarò spedendo la mia app), posso chiamare le API dei nodi direttamente nella pagina, così posso aggiornare il DOM a seconda del risultato dalla biblioteca. Devo essere in grado di registrare un'attività asincrona che CAN può notificare dall'interno del CLR alla controparte node.js o emettendo un evento o chiamando un callback!

Secondo l'autore edge.js può essere fatto facilmente https://github.com/tjanczuk/edge/issues/54#issuecomment-17967082 solo che non ho abbastanza competenze .NET di farlo (da un modulo pieno titolo) con tutti i callback.

+1

Puoi spiegare perché stai spingendo te stesso con node.js qui? – vittore

+0

Sto usando node-webkit, che può spedire un "browser" insieme al nodo.js dentro, e posso chiamare le API del nodo direttamente dai tag dello script, c'è un ponte senza soluzione di continuità tra i due, e dal momento che collegherò ogni app tra loro (stile P2P), è un must – pocesar

+0

Si potrebbe voler dare un'occhiata a Reactive.NET (Rx.NET). L'ho usato prima per sparare i callback quando succedono le cose, il che è possibile con il suo concetto di abbonamento, simile agli eventi. – Chris

risposta

1

Dopo un tempo che questa domanda è stata pubblicata, posso utilizzare edge.js facilmente per comunicare IN e OUT mia NET UI (anche controllare node.js raggio nodo-webkit da UI NET), utilizzando emettitore evento nodo :

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

E ora è possibile chiamare in/out da .NET utilizzando gli eventi, invece di chiamare codice nativo (che potrebbe non essere 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; 

possono ora chiamare Emit('error', "My error") da qualsiasi mia derivato classi da Base, in modo asincrono. Basta notare che recentemente ho iniziato a dwelving in C# e il mio codice presentato qui potrebbe non essere la soluzione migliore.

1

Interessante problema. Sarebbe possibile semplicemente rilasciare la funzione che ti interessa in un file ASHX (gestore HTTP personalizzato) e quindi postare quello dall'applicazione del tuo nodo? A seconda di cosa si desidera tornare potrebbe essere necessario fare un po 'di serializzazione/deserializzazione, ma questo sembra come potrebbe essere il modo più semplice per sparare un pezzo di codice C# da un'applicazione Nodo ....

Microsoft ha una bella buona serie di esercitazioni su gestori HTTP personalizzati che possono essere trovati here.

Lo scheletro ASHX base è qui sotto:

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

} 

Si potrebbe sostituire il contenuto di ProcessRequest con una versione modificata della funzione esistente.

0

vorrei creare uno self hosted (servizio ovvero finestre che ha WCF endpoint) servizio WCF o utilizzare framework come OpenRasta o ServiceStack sostituire WCF

In tutti e tre i casi avrei finito per avere il servizio JSON web che risultato restituiscono dell'ultima chiamata a CaptureAndExtractFmd

Quindi avrei consumato quel servizio nel nodo.js

Se hai bisogno di ulteriori informazioni sul modo in cui hai deciso di andare, basta creare un'altra domanda.

codice di esempio con WCF, C# parte

[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 parte

var request = require("request"); 

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

utilizzando la libreria .NET di questo SDK non è la soluzione appropriata per questo problema.

Node.js stessa è un'applicazione C++, e cercando di utilizzare una libreria .NET correttamente è solo per chiedere un mondo di dolore, soprattutto quando l'SDK fornisce anche un nativo C library/C++!

Naturalmente, non è possibile utilizzare direttamente la libreria C++; dovrai scrivere un wrapper C++. Nel mondo dei nodi, questi sono noti come addons. Scrivere un addon non è esattamente semplice, ma anche qualcuno con poca esperienza in C++ dovrebbe essere in grado di seguire gli esempi nella documentazione e ottenere qualcosa lavorando.

Ottenere un addon nativo integrato in Windows può anche essere un po 'complicato; here's some tips to help you get started.

Poiché l'SDK che si sta utilizzando è dietro un paywall, non posso fornire alcun esempio specifico. Tuttavia, immagino che il tuo oggetto wrapper C++ esponga alcuni metodi, e scriverò anche un wrapper JS attorno a questo per esporre un'API pulita. Per esempio:

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 

Ora la vostra applicazione può solo:

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

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

Questo esempio glosse, ovviamente, su un sacco, ma dovrebbe darvi una buona idea di ciò che deve accadere alla fine JS delle cose. Per quanto riguarda il rilevamento di un dito sul lettore, ancora una volta, non posso davvero dire come lo farai senza accedere all'SDK. Scommetto che finirai per fare sondaggi da qualche parte. Questo dovrebbe essere fatto su un thread separato nel tuo addon.


Bonus: andare via nativa significa che probabilmente anche essere compatibile con la versione Linux del SDK, quindi la tua applicazione funziona anche su Linux!

+0

Non riesco a chiamare il codice del nodo dall'interno del wrapper C++, in entrambi i casi. Sembra possibile usando edge.js e l'iniezione di codice .NET – pocesar

+0

@pocesar: Certo che puoi. Vedi l'esempio [callback] (http://nodejs.org/api/addons.html#addons_callbacks). – josh3736

+0

sembra davvero complesso rispetto alla soluzione edge.js ... sembra richiedere conoscenze C++ avanzate che mi mancano. – pocesar

Problemi correlati