Lector Dactilar desde Java

Entrada no corta …

Como siempre, en el trabajo me pidieron hacer algo que no tenía ni idea de cómo hacer lo que tenía que hacer. 8O

En resumen, vamos a leer huellas dactilares (en el tuto usando el u.are.u 4000B de digitalPersona) desde Java. El modelo del lector, pues, porque ese me pasaron aquí …

Entonces, empezamos por instalar el SDK. Asumo que, si tienen un lector, tienen el SDK. Si no tienen un lector, pues, lean a modo de conocimiento general …

TODO el post se basa en lo leído en la gran serie de Jair Rios en su blog. De modo que, si algo no lo entienden y yo no puedo contestarlo, diríjanse a él :)

Nos vamos con una app de escritorio. Si quisiéramos hacerlo web, necesitaríamos un applet (que básicamente es lo mismo 8O ).

Personalmente, utilizo IntelliJ como IDE, y le agregué el plugin de jFormBuilder para la interfaz gráfica. En su caso, pueden hacerlo como quieran/puedan.

La ventana es algo así Dibujo

Ok. Tenemos lo siguiente Dibujo

Importamos los .jar del SDK Dibujo

Y los imports

import com.digitalpersona.onetouch.*;
import com.digitalpersona.onetouch.capture.DPFPCapture;
import com.digitalpersona.onetouch.capture.event.*;
import com.digitalpersona.onetouch.processing.DPFPEnrollment;
import com.digitalpersona.onetouch.processing.DPFPFeatureExtraction;
import com.digitalpersona.onetouch.processing.DPFPImageQualityException;
import com.digitalpersona.onetouch.verification.DPFPVerification;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.GroupLayout;
import javax.swing.border.*;

Ahora si. Primero vamos a las variables globales (estamos en una clase que herede de un jPanel o jFrame).

<br />//Nos sirve para identificar al dispositivo<br />private DPFPCapture Lector = DPFPGlobal.getCaptureFactory().createCapture();<br />//Nos sirve para leer a modo de enrrolar, y crear una plantilla nueva, a base de 4 huellas.<br />private DPFPEnrollment Reclutador = DPFPGlobal.getEnrollmentFactory().createEnrollment();<br />//Nos sirve para leer a modo de verificar o comparar, a base de una plantilla creada anteriormente<br />private DPFPVerification Verificador = DPFPGlobal.getVerificationFactory().createVerification();<br />//La plantilla, nueva o rescatada<br />private DPFPTemplate template;<br />//A modo de CONSTANTE para crear plantillas<br />public String TEMPLATE_PROPERTY = "template";<br />//Para leer la huella, y definirla como un enrrolamiento<br />public DPFPFeatureSet featureSetInscripcion;<br />//Para leer la huella, y definirla como una verificación<br />public DPFPFeatureSet featureSetVerificacion;<br />

Siguiente, el constructor

<br />public Enrrolar() {
  try{
    for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
      if ("Nimbus".equals(info.getName())) {
        UIManager.setLookAndFeel(info.getClassName());
        break;
      }
    }
  }catch(Exception e){
    JOptionPane.showMessageDialog(null, 
      "No es posible cambiar tema visual", 
      "LookAndFeel inválido", 
      JOptionPane.ERROR_MESSAGE);
  }
  initComponents();
  Iniciar();
  start();
  EstadoHuellas();
  btnGuardar.setEnabled(false);
  btnIdentificar.setEnabled(false);
  btnVerificar.setEnabled(false);
  btnSalir.grabFocus();
  txtMensaje.setEditable(false);
}
  1. Cambiar el estilo (es opcional, pero hace que sea vea cool 8) )
  2. Carga de los elementos. Esta función la genera el IDE.
  3. Iniciamos todos sus parámetros y eventos del lector.
  4. Iniciamos el lector.
  5. Abajo.
  6. Ordenamos que todos los botones, salvo el de salida, queden desactivados.

Entonces, ahora vamos con Iniciar. El lector tiene sus propios eventos, los cuales linkeamos desde esta función. Nosotros vamos a usar 4:

  • dataAcquired, desde Lector.addDataListener
  • readerConnected, desde Lector.addReaderStatusListener
  • readerDisconnected, desde Lector.addReaderStatusListener también
  • errorReader, desde Lector.addErrorListener

Dice:

protected void Iniciar(){
  Lector.addDataListener(new DPFPDataAdapter(){
    @Override public void dataAcquired(final DPFPDataEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("La huella ha sido capturada");
          ProcesarCaptura(e.getSample());}
        });
      }
    });
  Lector.addReaderStatusListener(new DPFPReaderStatusAdapter(){
    @Override public void readerConnected(final DPFPReaderStatusEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("El sensor de huella dactilar se encuentra Activado");
        }
      });
    }
    @Override public void readerDisconnected(final DPFPReaderStatusEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("El sensor de huella dactilar se encuentra Desactivado");
        }
      });
    }
  });
  Lector.addErrorListener(new DPFPErrorAdapter(){
    public void errorReader(final DPFPErrorEvent e){
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          EnviarTexto("Error: " + e.getError());
        }
      });
    }
  });
}

En todos ocupamos EnviarTexto, pero en el primero al leer la huella, llamamos a otra función.
Vamos a comenzar con EnviarTexto. Únicamente tiene

public void EnviarTexto(String mensaje){
  txtMensaje.append(mensaje + "\n");
}

Y txtMensaje es el JTextArea en la parte inferior de la ventana.

Ahora vamos con start (y de paso stop), después EstadoHuellas y luego saltamos a ProcesarCaptura.

public void start(){
  Lector.startCapture();
  EnviarTexto("Utilizando lector de huella dactilar");
}
public void stop(){
  Lector.stopCapture();
  EnviarTexto("Lector detenido");
}

Iniciamos y terminamos la captura del lector y, además, mostramos un mensaje por cada evento.

Seguimos con EstadoHuellas

public void EstadoHuellas(){
  EnviarTexto("Muestra de huellas necesarias para guardar plantilla: " + Reclutador.getFeaturesNeeded());
}

Únicamente muestra un mensaje con la cantidad de huellas que faltan para completar la plantilla, que por defecto son 4.

Vamos con ProcesarCaptura.

public void ProcesarCaptura(DPFPSample muestra){
  featureSetInscripcion = extraerCaracteristicas(muestra, DPFPDataPurpose.DATA_PURPOSE_ENROLLMENT);
  featureSetVerificacion = extraerCaracteristicas(muestra, DPFPDataPurpose.DATA_PURPOSE_VERIFICATION);
  if(featureSetInscripcion != null){
    try {
      System.out.println("Las características de la huella han sido creadas");
      Reclutador.addFeatures(featureSetInscripcion);
      DibujarHuella(CrearImagenHuella(muestra));
      btnVerificar.setEnabled(true);
      btnIdentificar.setEnabled(true);
    } catch (DPFPImageQualityException e) {
      System.err.println("Error: "+e.getMessage());
    }finally {
    EstadoHuellas();
      switch (Reclutador.getTemplateStatus()){
        case TEMPLATE_STATUS_READY:
          stop();
          setTemplate(Reclutador.getTemplate());
          EnviarTexto("La plantilla de huella ha sido creada. Puede Verificar o Identificarla");
          btnIdentificar.setEnabled(false);
          btnVerificar.setEnabled(false);
          btnGuardar.setEnabled(true);
          btnGuardar.grabFocus();
          break;
        case TEMPLATE_STATUS_FAILED:
          Reclutador.clear();
          stop();
          EstadoHuellas();
          setTemplate(null);
          JOptionPane.showMessageDialog(Enrrolar.this,
            "La plantilla de la huella no pudo ser creada. Repita el proceso",
            "Inscripción de Huellas Dactilares",
            JOptionPane.ERROR_MESSAGE);
          start();
          break;
      }
    }
  }
}

Las 2 primeras líneas son para guardar las plantillas que, acabamos de leer o rescatar. Cada una donde corresponde. Las identificamos con el enum DATA_PURPOSE_ENROLLMENT o DATA_PURPOSE_VERIFICATION.

Las 2 las obtenemos llamando a la función extraerCaracteristicas, que tiene lo siguiente:

public DPFPFeatureSet extraerCaracteristicas(DPFPSample muestra, DPFPDataPurpose motivo){
  DPFPFeatureExtraction extractor = DPFPGlobal.getFeatureExtractionFactory().createFeatureExtraction();
  try{
    return extractor.createFeatureSet(muestra, motivo);
  } catch (DPFPImageQualityException e) {
    System.out.println(e.getMessage());
    return null;
  }
}

Recibimos el la plantilla con las 4 huellas y si es para guardar o leer. Nada más que eso.

Siguiendo con ProcesarCaptura, en el if, se puede dar el caso que la huella no quede bien leída u ocupemos otro dedo. En esos caso, no cae en la condición porque sería un null.

Al contrario, si todo sale ok, agregamos la huella a la plantilla, y además mostramos la huella en el jLabel que creamos. En realidad, le agregamos un ícono. Dicho paso lo creamos con estas 2 funciones:

public Image CrearImagenHuella(DPFPSample muestra){
  return DPFPGlobal.getSampleConversionFactory().createImage(muestra);
}
public void DibujarHuella(Image image){
  lblHuella.setIcon(
    new ImageIcon(
      image.getScaledInstance(
        lblHuella.getWidth(),
        lblHuella.getHeight(),
        Image.SCALE_DEFAULT
      )
    )
  );
}

Simplemente tomamos la huella, la “transformamos” en imagen y la agregamos en el label. Debo decir que hacer esto es muuuucho más simple en Java que en C# (primero aprendí a trabajar con huellas en C#)

Luego habilitamos los botones.

Si pos A, B, o C motivo algo pasa, entramos al catch y simplemente levantamos el error.

Siguiendo con la lógica del sistema, Imprimimos el estado (cuantos nos faltan de los 4). Y luego entramos a un switch y vemos si completamos las 4 lecturas o si algo malo ocurrió.

De estar terminado el proceso (4 lecturas), detenemos el lector y actualizamos la plantilla con las nuevas huellas leídas.

public void setTemplate(DPFPTemplate template) {
  DPFPTemplate antigua = this.template;
  this.template = template;
  firePropertyChange(TEMPLATE_PROPERTY, antigua, template);
}

Luego habilitamos los botónes.

En caso de error, detenemos el lector, limpiamos las huellas que teníamos, vaciamos la plantilla, informamos del error, y luego reiniciamos la lectura.

En el caso de que aún falten huellas, no se hace nada y simplemente seguimos marcando con el dedo.

Y eso es todo :D

Una vez que aprenda a guardar la info en una BD, agrego el post correspondiente.

Publicado en Java, Tutoriales | Dejar un comentario

Usando LINQ en JavaScript

En un módulo nuevo para la intranet aquí en mi trabajo, me pidieron un sistema para manejar la alimentación (entre otras cosas, precios) de pacientes, médicos, y personal.

Es posible que un “mismo” producto tenga distintos precios; considerando que, por ejemplo, el desayuno para un paciente tiene un precio de $ 111 y el desayuno para los médicos tenga un precio de $ 222.

Internamente la cosa es fácil, tengo una estructura como esta:

[
  {"IDTipoProducto":1,"ID":2,"Monto":111,"Nombre":"DESAYUNO"},
  {"IDTipoProducto":2,"ID":10,"Monto":222,"Nombre":"ALMUERZO"},
  {"IDTipoProducto":1,"ID":3,"Monto":333,"Nombre":"ALMUERZO"},
  {"IDTipoProducto":2,"ID":9,"Monto":444,"Nombre":"DESAYUNO"},
  {"IDTipoProducto":2,"ID":11,"Monto":555,"Nombre":"ONCE"},
  {"IDTipoProducto":1,"ID":4,"Monto":777,"Nombre":"ONCE"}
]

Todo ok.
Y si quiero saber el precio del desayuno para médicos (IDTipoProducto:1) ??

Eso fue lo que me descolocó x_X no se me ocurría como hacerlo … recorrer TODO el array ? No tendría sentido … por ahora son unos 20 productos, pero en un futuro pueden aumentar …

Fue cuando recordé al gran LINQ ! Peeeero esto lo estoy manejando desde JavaScript x_X así que buscando en google, encontré una librería que porta LINQ a JavaScript :)

Entonces, la bajamos y agregamos (yo uso la jquery) y manos a la obra.

Siguiendo la misma lista de arriba, es tan simple como hacer esto:

$.Enumerable.
  From(productos).
  Where("$.IDTipoProducto==1").
  Select("$.Nombre + ' ' + $.Monto").
  WriteLine();

Y tenemos como respuesta:
DESAYUNO 111
ALMUERZO 333
ONCE 777

Tadaaaa tenemos un “SQL” dentro de una lista “JSON” :)

Obviamente tenemos muchas opciones, que pueden ver en la documentación oficial.
Pero, para mi, esto es suficiente por ahora.

Actualización !

Encontré otra librería que me gustó más. La descargamos/linkeamos y escribimos:

var x_producto = JSLINQ(productos).
  Where(function(producto){return producto.ID==parseInt($("#cmb_editar_producto_producto").val())}).
  Select(function(producto){return producto}); 

Donde productos, sigue siendo nuestra lista de productos; producto es el objeto a revisar.

En Where, el producto.ID tiene que ser igual a un valor en un select; en Select, tomamos el producto que cumple los requisitos y podemos escoger qué devolver: el objeto entero, uno nuevo seleccionando ciertos atributos, o cualquier cosa :)

Publicado en JavaScript, LINQ, Tutoriales | Dejar un comentario

Reportes Simples usando Word-Correspondencia

Entrada mega corta, simplemente para compartir esta “forma” de generar reportes desde Word, usando la herramienta de Correspondencia.

Para un sistema que me pidieron, tuve que imprimir ciertos datos sobre una hoja de papel a modo de plantilla.

Originalmente pensé hacerlo con Crystal Reports, pero no tenía el instalador, y no quería descargar/aprender a usarlo.

Así que se me ocurrió la forma de generar los reportes desde Word :D

Ahora, esta forma es casi a Fuerza Bruta … así que no es muy eficiente que digamos, pero hace el trabajo ;)

Primero, generamos un diccionario (en mi caso C#) con el key/value correspondiente:

Dictionary<String, String> Data = new Dictionary<String, String>();
Data["FECHAINRESO"] = "01-01-2013";
Data["CUI"] = 12345;
Data["blabla"] = "blabla";

Y así con todas las variables que necesitamos.

Luego, pasamos el diccionario a un archivo .csv, de esta forma:

StringBuilder header = new StringBuilder();
StringBuilder values = new StringBuilder();
foreach (var value in this.DataNacimiento)
  {
    header.Append(value.Key).Append(";");
    values.Append(value.Value).Append(";");
  }
try
  {
    String RutaActa = @"C:\\DocActas\\Acta.csv";
    using (StreamWriter outfile = new StreamWriter(RutaActa))
    {
      outfile.Write(header.ToString()+"\n"+values.ToString());
    }
  }
catch (Exception ex)
  {
    Message.Show(ex.ToString());
  }

Y eso es todo, nos sale algo así: Captura

Ahora, vamos a Word y en Correspondencia, vamos a Seleccionar destinatarios y Usar lista existente. buscamos el archivo .csv que generamos.

Ahora, bajo Insertar campo combinado nos aparecen todas las variables. Es cosa de darle click a la que queramos y listo !

Un ejemplo: Captura

De esta forma, sabemos dónde insertar el campo cosa que, al imprimir quede sobre la plantilla.

Antes, obviamente, tenemos que eliminar la imagen de fondo y listo :)

Para ver cómo va quedando, darle click a Vista previa de resultados

Publicado en C#, Tips | Dejar un comentario

Python + GTK3 – Glade

Hace unos años atrás, le dedique una entrada a Eric, un IDE para python, y vimos lo básico para crear/usar una GUI bajo QT.

Ahora, lo mismo pero usando GTK, diseñando en Glade. Específicamente una ventana que muestra google en un navegador, y un botón que dice hola por consola.

Primero, y lo más importante … tener instalado Glade en su sistema.

Segundo, creamos una interfaz arrastrando y soltando controles dentro, algo así: Selección_007

Ahora, fijamos los eventos (click al botón) : Selección_008

Guardamos y vamos a python. Mi estructura es así: Selección_009

Donde autenticar.glade es el archivo que creamos en glade y Twittukos.py es el archivo raíz.

Entonces, en Twittukos.py tengo lo siguiente:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Mario Cares <mcares@puertosolutions.cl>'

try:
    with open('config/credenciales.js'): pass
    print 'hola'
except IOError:
    print 'Credenciales no existen ! Cargando Autorizacion'
    from Ventanas.Autentificacion import Class_Autentificacion
    ventana = Class_Autentificacion()
    ventana.mostrar()

Lo que hace el código es buscar un archivo. Si no lo encuentra llama a una clase y ejecuta su evento mostrar.

En dicha clase, tengo lo siguiente:

__author__ = 'Mario Cares <mcares@puertosolutions.cl>'

try:
    from gi.repository import Gtk
    from gi.repository import WebKit
except:
    print 'GTK o WebKit no disponible'

class Class_Autentificacion:

    def mostrar(self):
        Gtk.main()

    def on_autenti_window_delete_event(self, *args):
        Gtk.main_quit(*args)

    def on_btn_auth_pressed(self, *args):
        print 'hola :D  '

    def __init__(self):
        import os.path
        self.builder = Gtk.Builder()
        self.builder.add_from_file(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Glades/autenticar.glade")))
        self.builder.connect_signals(self)
        self.window = self.builder.get_object('autenti_window')
        self.window.set_size_request(800,600)
        self.webview = WebKit.WebView()
        self.scrolledwindow1 = self.builder.get_object('scrolledwindow1')
        self.scrolledwindow1.add(self.webview)
        self.webview.open("http://google.cl")
        self.window.show_all()

Importamos las librerías de Gtk (interfaz) y Webkit (navegador).

Luego definimos la clase y sus eventos:

  • mostrar para abrir la ventana
  • on_autenti_window_delete_event para cerrar la ventana
  • on_btn_auth_pressed para el evento del click al botón.

Las 2 últimas funciones/eventos las fijamos en el diseñador, y se guardan en el archivo .glade de esta forma:



  <!-- interface-requires gtk+ 3.0 -->

<!-- SIGUE -->

Bajo la etiqueta signal. Y eso es todo :)  Selección_010

Es importante agregar el evento para cerrar la aplicación. Si no lo hacen va a quedar “abierta” para siempre.

Eso por ahora. Hice el post porque estoy aprendiendo y creando mi cliente para twitter de hace tiempo.

Fuentes:

Publicado en Gtk, Python | Dejar un comentario

Usando el Framework Aggregate de MongoDB en C#

Para un sistema que estoy haciendo (control bodega), tengo el siguiente esquema para los ingresos o egresos: 
Captura

De modo que si necesito obtener el historial del producto “Betún” lo hacía con un:

Movimiento m = _collection.find(Query.EQ("Detalle._idProducto", new ObjectId("identificador")));

Pero, obtenía TODO el detalle, incluyendo todos los demás productos ingresados en el movimiento junto al betún… Por lo que no era para nada eficiente. Es ahí cuando entra el famoso aggregation para hacerme la vida más simple.

En la shell, simple como esto:

db.Movimientos.aggregate(
  [
    {$unwind: "$Detalle"},
    {$match:
      {"Detalle._idProducto": ObjectId("51590da5a3e2c816101bb6f3")}
    }
  ]
)
  1. $unwind para decirle que separe todos los documentos bajo “Detalle” y los haga independientes.
  2. $match sobre el id del producto (bajo Detalle._idProducto). En este caso el id del betún.

Obteniendo lo que quiero Captura

Ahora lo movemos a C#

public IEnumerable<BsonDocument> getMovimientos(ObjectId producto)
{
  try
  {
    var unwind = new BsonDocument {{"$unwind", "$Detalle"}};
    var match = new BsonDocument {{"$match",new BsonDocument{{"Detalle._idProducto", producto}}}};

    var pipeline = new[] { unwind, match };
    var result = this._Collection.Aggregate(pipeline);
    return result.ResultDocuments;
  }
  catch (Exception e)
  {
    throw new Exception("Error al consultar Movimientos. \n"+e.Message);
  }
}

Y la ocupamos, por ejemplo, así (desde un cambio de item en combobox):

private void cmb_productos_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
  try
  {
    IEnumerable<MongoDB.Bson.BsonDocument> result = HM.getMovimientos(
      ((ClasesProClean.Producto)cmb_productos.SelectedItem).Id
    );
    foreach (var documento in result)
    {
      MessageBox.Show(documento.ToString());
    }
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message, "Error !", MessageBoxButton.OK, MessageBoxImage.Error);
  }
}

Eso sería todo :) Agregar que tengo problemas con $project … me da un error sobre _id , pero no es nada indispensable :D

Ahora, digamos que queremos mostrar el historial en una grilla, lo hacemos así:

//ARMAMOS LA GRILLA
DataGridTextColumn fecha = new DataGridTextColumn();
DataGridTextColumn movimiento = new DataGridTextColumn();
DataGridTextColumn producto = new DataGridTextColumn();
DataGridTextColumn cantidad = new DataGridTextColumn();
grid_historial.Columns.Add(fecha);
grid_historial.Columns.Add(movimiento);
grid_historial.Columns.Add(producto);
grid_historial.Columns.Add(cantidad);
fecha.Binding = new Binding("Fecha");
movimiento.Binding = new Binding("Movimiento");
producto.Binding = new Binding("Producto");
cantidad.Binding = new Binding("Cantidad");
fecha.Header = "Fecha";
movimiento.Header = "Tipo Movimiento";
producto.Header = "Producto";
cantidad.Header = "Cantidad";

//Enviamos los datos
foreach (var documento in result)
{
  grid_historial.Items.Add(
    new {
      Fecha = documento.GetValue("Fecha").AsDateTime.ToString(),
      Movimiento = (documento.GetValue("Ingreso").AsBoolean) ? "Ingreso" : "Egreso",
      Producto = documento.GetValue("Detalle").AsBsonDocument.GetValue("Producto"),
      Cantidad = documento.GetValue("Detalle").AsBsonDocument.GetValue("Cantidad")
    }
  );
} 

;)  Captura

Fuentes:

Publicado en C#, MongoDB, Tutoriales | Etiquetado , | Dejar un comentario

Select para obtener todos los movimientos de X tabla en la semana (Oracle)

Si queremos hacer un select a una tabla con un rango de fechas que sea en la semana actual (entre primer día de la semana y último), corremos esto:

select * from XXXX where fecha between (select TRUNC(SYSDATE, 'Day') from dual) and (select TRUNC(SYSDATE, 'Day')+4 from dual)

Donde XXXX es la tabla y fecha es la columna que va a contener las fechas (dah 8O )

Publicado en Oracle | Dejar un comentario

Usando el Scanner desde C#

Para un sistema que estoy haciendo, necesitaba scannear documentos y guardarlos en una BD (la ruta). Pero no tenía ni idea de cómo hacerlo … Hasta que llegué a la solución aquí :D

Entonces, lo primero es agregar la referencia a WIA (Windows Image Acquisition) a nuestro proyecto Captura

Ahora, agregamos una nueva ventana que tenga un ListBox, un Image y un Button.

En el evento OnLoad de la ventana, metemos todos scanners que tengamos linkeados al equipo. Esto lo hacemos así:

Devices.Items.Clear();
var deviceManager = new DeviceManager();
for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++)
{
    if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType)
    {
        return;
    }
    Devices.Items.Add(new Scanner(deviceManager.DeviceInfos[i]));
}

Suponiendo que el ListBox se llama Devices. Como ven, necesitamos de la clase Scanner:

using WIA;

namespace Consulado
{
    public class Scanner
    {
        private readonly DeviceInfo _deviceInfo;

        public Scanner(DeviceInfo deviceInfo)
        {
            this._deviceInfo = deviceInfo;
        }

        public ImageFile Scan()
        {
            var device = this._deviceInfo.Connect();
            var item = device.Items[1];
            var imageFile = (ImageFile)item.Transfer("{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}");
            return imageFile;
        }

        public override string ToString()
        {
            return this._deviceInfo.Properties["Name"].get_Value().ToString();
        }
    }
}

Ahora que tenemos todo, al botón para scannear:

var device = Devices.SelectedItem as Scanner;
if (device == null)
{
    MessageBox.Show("Please select a device.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
    return;
}
var image = device.Scan();
var path = @"c:\scan.jpeg";
if (File.Exists(path))
{
    File.Delete(path);
}
try
{
    image.SaveFile(path);
    BitmapImage BImage = new BitmapImage(new Uri(path, UriKind.Absolute));
    img.Source = BImage;
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
} 

Y listo ! La imagen se guarda en la raíz y mostramos la imagen en el imageBox :)

Publicado en Aplicación, C#, Tutoriales | 4 comentarios

Oracle SQL Developer y conexiones TNS

Para variar, Oracle dando la hora … al menos me hace publicidad al blog 8O

No podía conectarme a una BD aquí en el trabajo, y mi jefe me “sugirió” que instalara el cliente de Oracle… Lamentablemente, únicamente tenían el instalador para Windows (estamos hablando de Oracle 7 … unos 20 años atrás), así que me tocó reiniciar y entrar con Windows XP.

Ok, creé la conexión con el SQL Net Easy Configuration y tenía listo el TNSNAMES.ORA

cli_iquique.world = 
  (DESCRIPTION = 
    (ADDRESS_LIST = 
        (ADDRESS = 
          (COMMUNITY = tcp.world)
          (PROTOCOL = TCP)
          (Host = 10.0.0.10)
          (Port = 1521)
        )
        (ADDRESS = 
          (COMMUNITY = tcp.world)
          (PROTOCOL = TCP)
          (Host = 10.0.0.10)
          (Port = 1526)
        )
    )
    (CONNECT_DATA = (SID = ORCL)
    )
  )

Ahora al querer conectarme, me daba error Dibujo Considerando que el “driver” de Oracle para Java no ha llegado a la versión 11, no tenía ni idea qué era el famoso error… Tampoco me mostraba el alias que había definido.

Metiendo mano, llegué aquíDibujo dónde puedes agregar el directorio de los TNS. Reiniciar el SQL Developer y : Dibujo

Bien, ahora si ! Pero no 8O … me seguía dando el mismo error … pero al menos ya me identificaba los alias.

En la misma ventana de preferencias, simplemente des.tickear donde dice “Controlador Thick/OCI” y Ahora si :D

Espero les sirva ;)

Publicado en Oracle, Windows | 1 comentario

Poblar Tablas HTML desde JavaScript (jQuery)

Entrada corta.

La escribo porque es segunda vez que tengo que buscar en mis otros sistemas para ver cómo re diantres se hacía D:

Digamos que tenemos el siguiente json

[
    {
        "PERSONA":"Juanito Perez ",
        "RUT_PERSONA":"12345678-0",
        "ID_URGENCIA":"141600",
        "CREACION":"12:33 14-FEBRERO -2013"
    },
    {
        "PERSONA":"Marito Cares",
        "RUT_PERSONA":"87654321-0",
        "ID_URGENCIA":"141597",
        "CREACION":"12:33 14-FEBRERO -2013"
    }
]

Y lo queremos dejar en una tabla de manera dinámica (osea que si, en vez de ser 2 registros fueran 3, se llenara solo :D )

Simple, primero definimos una tabla vacía, dándole un ID

<table class="table table-hover" id="tabla_aTraspasar">
    <thead>
        <tr>
            <th>FOLIO</th>
            <th>RUT</th>
            <th>Persona</th>
            <th>Fecha</th>
            <th>Recepcionar</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table> 

Ahora usando jQuery:

for(x in parse){
    $("#tabla_aTraspasar").find('tbody')
        .append($('<tr>')
            .append($('<td>').text(parse[x]["ID_URGENCIA"]))
            .append($('<td>').text(parse[x]["RUT_PERSONA"]))
            .append($('<td>').text(parse[x]["PERSONA"]))
            .append($('<td>').text(parse[x]["CREACION"]))
        );
}

Donde parse es el objeto json previamente parseado.

Eso es todo. Lo que hacemos es ir al tbody de la tabla con id tabla_aTraspasar y agregarle un nodo tr. A ese tr agregarle un td

Publicado en JavaScript, Tips | Dejar un comentario

Guardar Fecha y Hora en Oracle con Java

Entrada corta.

Estuve casi 2 horas peleando con Oracle para que me guardara una fecha con la hora respectiva. Pero siempre me guardaba la fecha, sin horas D:

Buscando por medio mundo, llegué a la solución. En vez de guardar un Date, guardar un TimeStamp.

Y el código sería así:

parametros.add(new java.sql.Timestamp(new java.util.Date().getTime()));

Donde parametros es un List<Object> usado por el HandlerOracle.

Y el HandlerOracle ahora tiene lo siguiente (última sentencia):

private PreparedStatement getStatement(String sql, List<Object> parametros) throws SQLException, Exception{
    if(this.conexion.isClosed()){ this.conexion = this.Conectar(); }
    PreparedStatement pstmt = conexion.prepareStatement(sql);
    int count = 1;
    for(Object p : parametros){
        if(p.getClass().equals(String.class)){
            pstmt.setString(count, (String)p);
        }else if(p.getClass().equals(Integer.class)){
            pstmt.setInt(count, (Integer)p);
        }else if(p.getClass().equals(Boolean.class)){
            pstmt.setBoolean(count, (Boolean)p);
        }else if (p.getClass().equals(Date.class)){
            pstmt.setDate(count, (Date) p);
        }else if(p.getClass().equals(java.sql.Timestamp.class)){
            pstmt.setTimestamp(count, (java.sql.Timestamp) p);
        }
        count++;
    }
    return pstmt;
}

Y eso es todo :)

Publicado en Java, Oracle, Tips | 1 comentario