Listar los grupos de un usuario de Active Directory en C#

Proyectos Sin comentarios

Queremos hacer una aplicación para windows (o para la Web) en .NET donde debemos comprobar si un usuario pertenece o no a unos grupos determinados del dominio.  Esto nos sirve para saber si el usuario puede entrar en la aplicación y qué permisos tiene. Lo normal es que un grupo contenga a un usuario directamente, pero, ¿que sucede si un usuario no pertenece directamente a un grupo A, sino que pertenece a un grupo B que a su vez pertenece al grupo A?.

Para que funcione en todos los casos se debe buscar el aributo tokenGroups de la cuenta del usuario en el Directorio Activo. Este atributo contiene todos los SIDs de los grupos a los que pertenece el usuario directa o indirectamente.

Aquí pongo un ejemplo comentando de cómo se puede hacer:

// Creamos un objeto DirectoryEntry para conectarnos al directorio activo
DirectoryEntry adsRoot = new DirectoryEntry("LDAP://" + Environment.GetEnvironmentVariable("USERDOMAIN"));
// Creamos un objeto DirectorySearcher para hacer una búsqueda en el directorio activo
DirectorySearcher adsSearch = new DirectorySearcher(adsRoot);
 
try
{
    // Ponemos como filtro que busque el usuario actual
    adsSearch.Filter = "samAccountName=" + Environment.GetEnvironmentVariable("USERNAME");
 
    // Extraemos la primera coincidencia
    SearchResult oResult;
    oResult = adsSearch.FindOne();
 
    // Obtenemos el objeto de ese usuario
    DirectoryEntry usuario = oResult.GetDirectoryEntry();
 
    // Obtenemos la lista de SID de los grupos a los que pertenece
    usuario.RefreshCache(new string[] { "tokenGroups" });
 
    // Creamos una variable StringBuilder donde ir añadiendo los SID para crear un filtro de búsqueda
    StringBuilder sids = new StringBuilder();
    sids.Append("(|");
    foreach (byte[] sid in usuario.Properties["tokenGroups"])
    {
        sids.Append("(objectSid=");
        for (int indice = 0; indice < sid.Length; indice++)
        {
            sids.AppendFormat("\\{0}", sid[indice].ToString("X2"));
        }
        sids.AppendFormat(")");
    }
    sids.Append(")");
 
    // Creamos un objeto DirectorySearcher con el filtro antes generado y buscamos todas la coincidencias
    DirectorySearcher ds = new DirectorySearcher(adsRoot, sids.ToString());
    SearchResultCollection src = ds.FindAll();
 
    // Recorremos toda la lista de grupos devueltos
    foreach (SearchResult sr in src)
    {
        String sGrupo = (String) sr.Properties["samAccountName"][0];
        // A partir de aquí hacer lo que corresponda con cada grupo
        ...
    }
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}

Manifiesto por una Red Neutral

Proyectos Sin comentarios

Los ciudadanos y las empresas usuarias de Internet adheridas a este texto manifestamos:

  1. Que Internet es una Red Neutral por diseño, desde su creación hasta su actual implementación, en la que la información fluye de manera libre, sin discriminación alguna en función de origen, destino, protocolo o contenido.
  2. Que las empresas, emprendedores y usuarios de Internet han podido crear servicios y productos en esa Red Neutral sin necesidad de autorizaciones ni acuerdos previos, dando lugar a una barrera de entrada prácticamente inexistente que ha permitido la explosión creativa, de innovación y de servicios que define el estado de la red actual.
  3. Que todos los usuarios, emprendedores y empresas de Internet han podido definir y ofrecer sus servicios en condiciones de igualdad llevando el concepto de la libre competencia hasta extremos nunca antes conocidos.
  4. Que Internet es el vehículo de libre expresión, libre información y desarrollo social más importante con el que cuentan ciudadanos y empresas. Su naturaleza no debe ser puesta en riesgo bajo ningún concepto.
  5. Que para posibilitar esa Red Neutral las operadoras deben transportar paquetes de datos de manera neutral sin erigirse en “aduaneros” del tráfico y sin favorecer o perjudicar a unos contenidos por encima de otros.
  6. Que la gestión del tráfico en situaciones puntuales y excepcionales de saturación de las redes debe acometerse de forma transparente, de acuerdo a criterios homogéneos de interés público y no discriminatorios ni comerciales.
  7. Que dicha restricción excepcional del tráfico por parte de las operadoras no puede convertirse en una alternativa sostenida a la inversión en redes.
  8. Que dicha Red Neutral se ve amenazada por operadoras interesadas en llegar a acuerdos comerciales por los que se privilegie o degrade el contenido según su relación comercial con la operadora.
  9. Que algunos operadores del mercado quieren “redefinir” la Red Neutral para manejarla de acuerdo con sus intereses, y esa pretensión debe ser evitada; la definición de las reglas fundamentales del funcionamiento de Internet debe basarse en el interés de quienes la usan, no de quienes la proveen.
  10. Que la respuesta ante esta amenaza para la red no puede ser la inacción: no hacer nada equivale a permitir que intereses privados puedan de facto llevar a cabo prácticas que afectan a las libertades fundamentales de los ciudadanos y la capacidad de las empresas para competir en igualdad de condiciones.
  11. Que es preciso y urgente instar al Gobierno a proteger de manera clara e inequívoca la Red Neutral, con el fin de proteger el valor de Internet de cara al desarrollo de una economía más productiva, moderna, eficiente y libre de injerencias e intromisiones indebidas. Para ello es preciso que cualquier moción que se apruebe vincule de manera indisoluble la definición de Red Neutral en el contenido de la futura ley que se promueve, y no condicione su aplicación a cuestiones que poco tienen que ver con ésta.

La Red Neutral es un concepto claro y definido en el ámbito académico, donde no suscita debate: los ciudadanos y las empresas tienen derecho a que el tráfico de datos recibido o generado no sea manipulado, tergiversado, impedido, desviado, priorizado o retrasado en función del tipo de contenido, del protocolo o aplicación utilizado, del origen o destino de la comunicación ni de cualquier otra consideración ajena a la de su propia voluntad. Ese tráfico se tratará como una comunicación privada y exclusivamente bajo mandato judicial podrá ser espiado, trazado, archivado o analizado en su contenido, como correspondencia privada que es en realidad.

Europa, y España en particular, se encuentran en medio de una crisis económica tan importante que obligará al cambio radical de su modelo productivo, y a un mejor aprovechamiento de la creatividad de sus ciudadanos. La Red Neutral es crucial a la hora de preservar un ecosistema que favorezca la competencia e innovación para la creación de los innumerables productos y servicios que quedan por inventar y descubrir. La capacidad de trabajar en red, de manera colaborativa, y en mercados conectados, afectará a todos los sectores y todas las empresas de nuestro país, lo que convierte a Internet en un factor clave actual y futuro en nuestro desarrollo económico y social, determinando en gran medida el nivel de competitividad del país. De ahí nuestra profunda preocupación por la preservación de la Red Neutral. Por eso instamos con urgencia al Gobierno español a ser proactivo en el contexto europeo y a legislar de manera clara e inequívoca en ese sentido.

(Si te sientes cómodo y representado por este texto, dale toda la difusión que puedas y quieras: reprodúcelo, enlázalo, tradúcelo, compártelo, vótalo… todas esas cosas que puedes hacer con total tranquilidad y libertad gracias, precisamente, al hecho de que tenemos todavía una red neutral. Hagamos posible el seguir teniéndola)

Convertir un fichero wav comprimido con el codec G729A

Informática, Proyectos 2 Comentarios

Recientemente me ha surgido la necesidad de convertir unos ficheros de audio que estaban en formato .WAV comprimido con el codec G729A a un formato .WAV reproducible en cualquier PC para hacer unas pruebas. Se trataba de poder escuchar ficheros .WAV que estaban comprimidos con ese codec, pero dada la dificultad de encontrar el codec gratuitamente para poder instalarlo en Windows he encontrado una alternativa que sirve igualmente.

En la página de Voice Age he encontrado una librería gratuita para windows con ejemplos y ejecutables de cómo extraer el audio comprimido con un codec G729A. Si se va a usar comercialmente se debe pedir una licencia a sipro que es quien tiene los derechos de licenciamiento.

El problema con los ejecutables de Voice Age es que convierte de formato G729A a formato RAW, pero ni el origen tiene los datos por sí sólo (están embebidos en un fichero .wav) ni en la conversión se pasa a un fichero .wav reproducible en windows.

Por ello he creado un programa de consola en Visual C++ 6.0 que hace uso de la librería .lib que ofrece VoiceAge para hacer esos dos pasos. La idea es leer unos datos del fichero wav y moverse hasta el byte 44 del fichero wav de origen, accediendo así a los datos de audio directamente; crear un fichero .wav de destino,  introduciendo en este la cabecera de un fichero .wav con el tamaño de los datos de audio descomprimido e indicando que tiene formato PCM; finalmente leer los datos de audio comprimido, descomprimirlos con la librería y escribirlos en el fichero de destino.

Este es el código fuente del mismo:

#include "stdafx.h"
#include "va_g729.h"
#include <stdio.h>
#include <memory.h>
 
int main(int argc, char* argv[])
{
	FILE *entrada;
	FILE *salida;
	unsigned char	serial[L_FRAME_COMPRESSED];
	short			synth[L_FRAME];
	int				bfi;
	unsigned char cabecera[] = {0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x40,0x1F,0x00,0x00,0x80,0x3E,0x00,0x00,0x02,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00};
	unsigned long longitud;
	unsigned long *puntero;
 
	puts("SISTEMAS O.R.P.\nConvertidor de WAVs G729A a PCM\n");
 
	// Se comprueban los parámetros
	if(argc != 3)
	{
		puts("Debe introducir el archivo wav de origen y el archivo wav de destino.");
		return 1;
	}
 
	// Se abre el fichero de origen
	entrada = fopen(argv[1], "rb");
	if(entrada == NULL)
	{
		puts("No se pudo abrir el fichero de origen");
		return 2;
	}
 
	// Se abre el fichero de destino
	salida = fopen(argv[2], "wb");
	if(salida == NULL)
	{
		puts("No se pudo abrir el fichero de destino");
		fclose(entrada);
		return 2;
	}
 
	// Se comprueba que el fichero origen es un .wav
	fread(serial, sizeof(char), 4, entrada);
	if(memcmp(serial, "RIFF", 4) != 0)
	{
 
		puts("El fichero de entrada no es un wav");
		fclose(entrada);
		fclose(salida);
		return 3;
	}
 
	// Se lee el tamaño de los datos de audio del fichero origen
	// y se calcula el tamaño de los datis de audio del fichero destino
	fread(&longitud, sizeof(unsigned long), 1, entrada);
	puntero = (unsigned long *)(cabecera + 4);
	*puntero = 36 + (longitud - 36) * L_FRAME / L_FRAME_COMPRESSED * 2;
	puntero = (unsigned long *)(cabecera + 40);
	*puntero = (longitud - 36) * L_FRAME / L_FRAME_COMPRESSED * 2;
	// Se escribe la cabecera wav al fichero de destino
	fwrite(cabecera, sizeof(char), sizeof(cabecera), salida);
	// Saltamos al byte 44 donde se encuentran los datos de audio comprimido
	fseek(entrada, 44, SEEK_SET);
 
	// Se inicializa el descompresor
	va_g729a_init_decoder();
 
	// Se lee un grupo de bytes comprimidos y se escriben descomprimidos
	while (fread(serial, sizeof(char), L_FRAME_COMPRESSED, entrada) == L_FRAME_COMPRESSED)
	{
		bfi = 0;
		va_g729a_decoder(serial, synth, bfi);
		fwrite(synth, sizeof(short), L_FRAME, salida);
	}
 
	fclose(entrada);
	fclose(salida);
 
	puts("Proceso terminado");
 
	return 0;
}

Y aquí dejo el fichero ejecutable:

G729AtoPCM

Alarma con un pic 16f628, un transceptor ds275, sensor de movimiento y un modem antiguo

Electrónica, Proyectos 72 Comentarios

Tenía un modem externo antiguo de 2400 b.p.s. que me regalaron y se me ocurrió la idea de usarlo para crear una alarma. Los bueno de los modems es que puedes interactuar con la línea telefónica para hacer llamadas.

La idea consiste en que un sensor de movimiento piroeléctrico de infrarrojos (PIR) detecte el movimiento de una persona en una sala, este informaría de la detección a un pic y este sería el encargado de llamar a un número de teléfono a través del modem.

El matería que he usado es:

Para hacer el circuito lo más sencillo posible he usado un pic 16f628a dado que con él podemos ahorrarnos el poner un cristal de cuarzo externo, poder desactivar el pin MCLR y usar la USART que trae consigo (podría haber usado un pic 16f88 igualmente). También he usado el transceptor ds275 porque se puede comunicar con un puerto serie como el del modem sin añadirle ningún condensador como ocurre con el MAX232. Como no quería depender de una fuente de alimentación externa, he soldado unos cables al modem para obtener de este los 5 voltios necesarios para el pic y el transceptor y para la alimentación de 9 voltios del sensor PIR.

Este es el esquema del circuito:

El sensor PIR tiene una salida digital que va conectada al pin RB0 del pic, que se puede programar como interrupción, por lo que el pic puede permanecer en modo sleep hasta que recibe la interrupción del sensor y empezar a mandar los comandos AT para hacer la llamada de alarma. Como el PIC no puede por sí sólo interactuar con un puerto serie, el transceptor convierte las señales del PIC a señales RS232 para enviárselas al puerto serie del modem y viceversa. Una vez que se ha hecho la llamada y el modem detecta que se ha colgado la linea, devolverá un código numérico que el pic recibirá para volver a dejar el sistema en modo de detección.

Foto del conjunto:

Un video de demostración:

Lo que sucede en el video es lo siguiente: Se enciende el modem y el pic configura este para que no tenga eco los comandos, para que devuelva respuestas numéricas y que el altavoz esté desactivado, después de 15 segundos de espera para que el usuario pueda abandonar la habitación el pic se pone a esperar la detección de movimiento, cuando la detecta llama a un número de móvil prefijado para que el usuario reciba la alerta.

El código fuente del pic esta programado en CCS y es el siguiente:

main.h

#include <16F628A.h>
 
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
 
#use delay(clock=4000000)
#use fast_io(b)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
 
typedef enum {INICIO, DETECTA, ALARMA, LLAMADO} ESTADOS;

main.c

#include "main.h"
 
ESTADOS estado;
volatile int8 dato;
 
// se ha detectado un movimiento y se pasa al estado de alarma
#INT_EXT
void movimiento()
{
   if(estado == DETECTA)
   {
      estado = ALARMA;
   }
}
 
// se ha detectado un carácter en la cola la USART
#INT_RDA
void lectura()
{
   int8 valor;
   if(kbhit())
   {
      valor = getc();
      if(valor != '\r')
      {
         dato = valor;
      }
   }
}
 
// función genérica que pasa al estado de detección borrando cualquier interrupción anterior y activándola 
void deteccion()
{
   estado = DETECTA;
   clear_interrupt(int_ext);
   enable_interrupts(int_ext);
}
 
void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ);
   // Ponemos a todos los pines del puerto B como entrada excepto el de salida de la USART 
   set_tris_b(0xFB);
   // Empezamos por el estado de inicio
   estado = INICIO;
   // La interrupción debe ser cuando pasa de nivel bajo a nivel alto
   ext_int_edge( L_TO_H );
   enable_interrupts(int_rda);
   enable_interrupts(global);
 
   // TODO: USER CODE!!
 
   for(;;)
   {
      switch(estado)
      {
         // En el estado de inicio inicializamos el modem para que no haga eco de los comandos, 
         // los valores de respuesta sean numéricos y apague el altavoz del modem, esperando
         // 15 segundos para dejar salir al usuario de la sala y pasamos al estado de detección
         case INICIO:
            delay_ms(2000);
            printf("ATE0V0M0\r");
            delay_ms(13000);
            deteccion();
            break;
         // En el estado de detección esperamos la interrupción en modo sleep para consumir menos
         case DETECTA:
            sleep();
            break;
         // Se desactiva la interrupción y marcamos el número de teléfono que queramos alertar
         case ALARMA:
            disable_interrupts(int_ext);
            dato = 'A';
            printf("ATDTXXXXXXXXX\r");
            estado = LLAMADO;
            break;
         // Esperamos a que termine la llamada para que vuelva al estado de detección
         case LLAMADO:
            if(dato != 'A')
            {
               deteccion();
            }
      }
   }
 
}

Sólo comentar que XXXXXXXXX hay que sustituirlo por el número de teléfono al que queramos dar la alarma.

Robot con arduino, motorshield, módulo bluetooth y cámara portatil

Electrónica, Proyectos 17 Comentarios

Hace tiempo que hice mi primer robot, pero este se quedó en el olvido y recientemente he querido retomarlo para un proyecto de orientación por GPS. De momento lo he estado montando para que detecte colisiones con objetos, pero además me comunique mediante bluetooth cuando detecta esas colisiones. He aquí los pasos que he ido siguiendo para montarlo:

Primero extraemos la electronica y nos quedamos con los cables de los motores del coche teledirigido, después añadimos un conector tamiya con fusible para la batería LIPO:

Nos hacemos con una placa Arduino y un motorshield, en la cual se pueden acoplar en sus pines los cables de los motores:

En el mercado existen multitud de módulos bluetooth, yo he comprado el de sure electronics por su sencillez tanto de montaje como de comunicaciones (va a 9600 bps). Dos cables van a los pines RX y TX de la arduino y otros dos van a la salida de 3,3 voltios y GND de la arduino. Para comunicarse con él en windows basta con el putty accediendo al puerto COM que se haya asociado a vuestra conexión bluetooth;  si se trata de linux o mac podeis conectaros desde la consola con screen /dev/<dispositivo> 9600 siendo <dispositivo> el tty asociado a la conexión:

Montamos los bumpers. El cable suelto va a uno de los pines GND de la arduino, los otros dos cables van conectados a los pines EC1 y EC2 de la motorshield, que a su vez están conectados a los pines 4 y 5 de la arduino, por lo que se deberá activar la resistencia pull-up interna de esos pines:

Una batería LIPO para alimentar el conjunto, pegada con velcro para que se sujete bien a la vez que sea fácil quitarla para cargarla o sustituirla:

Aunque no es necesario, he puesto una cámara wireless alimentada con una pila de 9 voltios para grabar los movimientos. Al final el conjunto queda así:

Como el movimiento se demuestra andando, pongo un video de su funcionamiento (recomiendo agrandarlo para ver mejor los detalles). A la izquierda el putty mostrando los mensajes que envía la arduino a través de bluetooth, en el centro un video del cómo responde el robot y a la derecha otro video desde dentro del robot:

Finalmente dejo el código fuente del robot para el entorno Arduino:

int dirA = 12; // sentido
int dirB = 13;  // direccion 
int speedA = 10; // velocidad del motor
int speedB = 11; // parada o encendido de la dirección
int bumperI = 5; // bumper izquierdo
int bumperD = 4; // bumper derecho
int boton2 = 6; // boton 2 de la motorshield
int boton1 = 7; // boton 1 de la motorshield
 
// El robot va hacia atrás
void atras()
{
  digitalWrite (dirA, HIGH);
}
 
// El robot va hacia alante
void alante()
{
  digitalWrite (dirA, LOW);
}
 
// El robot tuerce a la izquierda
void izquierda()
{
  digitalWrite (dirB, LOW);
}
 
// El robot tuerce a la derecha
void derecha()
{
  digitalWrite (dirB, HIGH);
}
 
 
void setup() 
{
  // Configuración de los pines de la motorshield
  pinMode (dirA, OUTPUT); 
  pinMode (dirB, OUTPUT); 
  pinMode (speedA, OUTPUT); 
  pinMode (speedB, OUTPUT);
 
  // Configuración de los pines de los bumpers
  pinMode (bumperI, INPUT);
  pinMode (bumperD, INPUT);
 
  // Configuración de los botones de la motorshield
  pinMode (boton1, INPUT);
  pinMode (boton2, INPUT);
 
  // Configuración de las comunicaciones por bluetooth
  Serial.begin(9600);
}
 
 
void loop() 
{ 
  // Si se ha pulsado el boton de arranque
  if(digitalRead(boton1) == 0)
  {
    delay(200); // para evitar rebotes en el boton
    Serial.println("empiezo");  
    analogWrite(speedA, 100); // PWM a 100
  }
  // Si se ha pulsado el boton de parada
  else if(digitalRead(boton2) == 0)
  {
    delay(200); // para evitar rebotes en el boton
    Serial.println("termino");
    analogWrite(speedA, 0); // PWM a 0
  }  
  alante();
  // Si se ha detectado una colisión por el flanco derecho
  if(digitalRead(bumperD) == 0)
  {
    Serial.println("choque derecha");
    digitalWrite(speedB, HIGH); 
    // Va hacia atrás a la derecha durante 1 segundo    
    derecha();
    atras();
    delay(1000);
    // Va hacia alante a la izquierda durante medio segundo
    alante();
    izquierda();
    delay(500);
    digitalWrite(speedB, LOW); 
  }
  // Si se ha detectado una colisión por el flanco izquierdo
  else if(digitalRead(bumperI) == 0)
  {
    Serial.println("choque izquierda");
    digitalWrite(speedB, HIGH); 
    // Va hacia atrás a la izquierda durante 1 segundo
    izquierda();
    atras();
    delay(1000);
    // Va hacia alante a la derecha durante medio segundo    
    alante();
    derecha();
    delay(500);
    digitalWrite(speedB, LOW); 
  }
}

Programar la cámara IP Zaapa CIPRW (ZA-CIPRW) en .NET

Informática, Proyectos 11 Comentarios

Uno de los problemas que veo con la cámara IP Zaapa que me compré es que sólo se puede manejar desde un navegador Internet Explorer, y la verdad es que eso le quita mucho potencial a una cámara tan completa y barata como esta. Por eso me he puesto manos a la obra para desengranar un poco el funcionamiento y poder crear una aplicación de escritorio para poder manejarla.

Todo el trabajo de investigación ha estado centrado en ver cómo funciona el código fuente javascript de la página web que ofrece la cámara zaapa, ya que buscando por internet no he encontrado nada sobre cómo manejarla.

Lo primero que nos encontramos es que instancia un objeto llamado DVM_IPCam2.ocx. Buscando por internet he encontrado muy poca información sobre ese fichero en cuestión y mucho menos de la API OLE que encierra.

Por suerte el Visual Studio .NET puede incorporar ocx y ver de una tacada todos los métodos, propiedades y eventos que maneja el control ocx. Para ello dentro del Cuadro de herramientas, se pulsa con el botón derecho en Componentes y se selecciona Elegir Elementos… Después se pulsa sobre la pestaña Componentes COM y se selecciona DVM_IPCam2 Control.

dvmipcam2

Si no existiese es que no está registrado en Windows. Entonces habría que descargar el ocx desde la dirección http://<ip de la camara>/codebase/DVM_IPCam2.ocx, guardarlo en c:\windows\system32 y desde una consola de ms-dos ejecutar regsvr32 c:\windows\system32\DVM_IPCam2.ocx y después volver a repetir el proceso de Visual Studio.

Con esto ya tendremos el componente ocx para insertarlo en el formulario. Ahora para acceder a la cámara hay que seguir los siguientes pasos:

  • Conectar con la cámara usando el método MonitorConnect, pasándole como parámetros la dirección host o ip de la cámara, el puerto por el que escucha (normalmente el 80), el usuario y la contraseña.
  • Capturar el evento OnMonitorConnectResult y si la conexión ha sido satisfactoria pasar al siguiente punto
  • Empezar a recibir las imágenes dentro del control ocx usando el método PlayVideo.
  • Esperar a recibir las imágenes con el evento OnPlayVideoResult.
  • Hacer el resto de operaciones: mover la cámara con el método DecoderControl, hacer fotografías con el método Photo2, grabar un video con el método StartRecord2, reiniciar la cámara con el método RebootCamera, etc.
  • Cuando se termine de trabajar con la cámara llamar a los métodos StopVideo, StopRecord y MonitorDisconnect.

He desarrollado una pequeña aplicación que muestra estos conceptos. No hace comprobaciones de errores para simplificar el código:

aplicacioncamara

Podeis descargar el código fuente en c# y un ejecutable desde aquí.

El siguiente paso sería tratar de hacer que funcionase el firefox para windows y en un futuro conocer el protocolo para manejarlo desde linux, desde un iphone o desde cualquier otro entorno.

Capturar el escritorio o una ventana de windows con .NET

Informática, Proyectos Sin comentarios

En el trabajo los usuarios nos envían incidencias de las aplicaciones, pero en muy pocas ocasiones adjuntan un “pantallazo” del error. Entiendo que el proceso de pulsar Impr Pant, irse al paint, pegar la imágen, guardarla en JPG y adjuntarla a la incidencia es algo que no saben muchos usuarios.

Por eso se me ocurrió crear una aplicación sencilla en c# que gestionase todo ese proceso (excepto adjuntar la imágen a la incidencia). Tomando como base este artículo he desarrollado la aplicación CapturaVentana (ciertamente no me he escornado buscando el nombre) debido a que el escritorio o una ventana son lo mismo para windows.

ventana

Su uso es muy sencillo. Elegimos si queremos copiar el resultado al portapapeles o a un fichero jpg y pulsamos sobre el botón correspondiente de lo que queremos capturar (escritorio entero o una ventana individual). En el caso de capturar el escritorio la aplicación se esconde momentaneamente para que no aparezca en la “foto”. Si se trata de capturar una ventana hay que pulsar con el ratón sobre la ventana que queremos fotografiar después de haber pulsado el botón.

El código fuente se puede descargar desde aquí.

alarma

Electrónica, Informática, Proyectos 6 Comentarios

Hacía tiempo que no desarrollaba un proyecto con la fonera. En esta ocasión voy a hacer un sistema de alarma, la cual se activa cuando se pulsa un botón. Para ello me he hecho con lo siguientes materiales:

Emisor de 1 canal

Receptor de 1 canal

Fonera

getfile

Cuando alguien pulse el mando emisor, el receptor (alimentado por la fonera) recibirá la señal e informará a la fonera que se ha activado. Después la fonera se conectará a una página web para mandar un mensaje sms a un número de teléfono. Esto es útil por ejemplo para ancianos que desean solicitar asistencia, con sólo llevar el emisor colgado ya pueden enviar la alarma. Otra aplicación es una tienda donde se solicite ayuda en caso de robo, guardando el emisor debajo del mostrador o en el suelo.

Para ello, lo primero que se debe tener es la fonera con el firmware openwrt. Los pasos se pueden seguir aquí.

Después hay que instalar el módulo gpio. Los pasos se pueden seguir aquí.

A continuación hay que hacer que la fonera sea independiente del cable de red y se conecte como cliente al router wireless. Primero editamos el fichero /etc/config/wireless y ponemos lo siguiente:

config wifi-device  wifi0
option type     atheros
option channel  5

config wifi-iface
option device   wifi0
option mode     sta
option ssid     <SSID>
option encryption wep
option key      <CLAVE HEX>

Donde SSID es el nombre de la red wireless y CLAVE HEX la clave wep en hexadecimal (Para otras configuraciones mirar el documento de configuración aquí)

Segundo editamos el fichero /etc/config/network y ponemos lo siguiente:

# Copyright (C) 2006 OpenWrt.org

config interface loopback
option ifname   lo
option proto    static
option ipaddr   127.0.0.1
option netmask  255.0.0.0

config interface lan
option ifname   eth0
option proto    static
option ipaddr   192.168.1.200
option netmask  255.255.255.0

config interface wifi0
option ifname   ath0
option proto    dhcp

Con estas configuraciones hacemos que el router de la fonera se conecte al punto de acceso como cliente y coja una ip mediante dhcp, sin la necesidad de tener un cable de red, por lo que podemos ponerla en cualquier lado. Por si acaso se deja una ip 192.168.1.200 en el puerto ethernet por si hubiera que conectarse a ella y no funcionase el wifi.

El siguiente paso es crear el script que recibirá por el gpio la señal del receptor. Creamos el fichero /usr/bin/alarma.sh con este contenido (poniendo el usuario, contraseña, numero de móvil y el mensaje a enviar):

echo 1 > /proc/gpio/2_dir
echo 0 > /proc/gpio/1_dir
while true
do
        estado=`cat /proc/gpio/1_in`
        echo $estado > /proc/gpio/2_out
        if [ $estado -eq 1 ]
        then
                wget -q "http://www.sistemasorp.es/alarma.php?login=<USUARIO>&password=<CLAVE>&destino=<Nº MOVIL>&mensaje=<MENSAJE>"
                while true
                do
                        sleep 1
                done
        fi
        sleep 1
done

Lo que hace el script es comprobar la salida del receptor cada segundo, si está activada enciende el led wlan de la fonera y accede a una página web php que envía mensajes sms con la API de envío de SMS del open movil forum, este es el código fuente:

<?php
include 'SMSSenderAPI.php';
 
$SMS = New SMSSender;
$SMS->SendMessage($_GET["login"], $_GET["password"], $_GET["destino"], $_GET["mensaje"]);
?>

El fichero SMSSenderAPI.php lo podeis descargar aquí. Los campos LOGIN y PASSWORD son para la api de open movilforum, el campo DESTINO es el número de móvil del destinatario y el campo MENSAJE el texto que se le enviará.

Después se edita el fichero /etc/firewall.user y se añade al final la siguiente linea sh /usr/bin/programa.sh &.

En la parte hardware he sacado los cables de GPIO de la fonera y alimentación y masa al exterior:

imgp0885imgp0886

Igualmente he quitado en el receptor el integrado 7805 para alimentar el circuito directamente desde la fonera con dos cables (alimentación y masa):

imgp0887

Y soldado al pin 1 (el que se pone a 5 voltios si el circuito ha recibido una señal) del chip HEF4013BP un cable que irá directamente conectado al gpio 1 de la fonera:

imgp0888

Y como colofón un video demostrativo:

En el vídeo se puede ver como pulso el botón del emisor, después el led de la fonera se pone en verde y finalmente se recibe un mensaje de texto indicando Alarma activada.

robot

Electrónica, Proyectos 1 Comentario

¿Qué se puede hacer con un 16f84a, un l293d, un 7806, un 7805 y un coche teledirigido barato?. Pues esto:

robot

Pronto más…

Reloj termómetro con PIC 16F628

Electrónica, Proyectos 37 Comentarios

Recientemente he creado un reloj-termómetro hecho con un PIC 16F628A, un sensor de temperatura i2c DS1624, un reloj en tiempo real i2c DS1307 y un LCD de 16×2 compatible con Hitachi HD44780.

El sistema, una vez encendido, muestra la fecha y hora, la temperatura junto con los valores máximo y mínimo que alcanza y finalmente un mensaje personalizado. Aquí hay un video que he grabado del mismo:

El esquema del circuito es el siguiente:

Y desde aquí os podeis bajar el .hex y el código fuente (CCS C)

proyecto

La fecha y hora se configuran con sólo un botón pulsador que está conectado a RB0 y que funciona por temporización e indexación. Es decir, si tu pulsas la primera vez el botón, se mostrará en el LCD la fecha y hora y el indice 0, que indica que vas a modificar el día, entónces si pulsas dentro de los dos segundos siguientes el botón, el día se incrementará, si no lo pulsas, el indice se incrementará a 1 y se podrán modificar los meses de igual manera. Así hasta llegar al indice 5 que son los segundos y después mostrará la fecha y hora actualizadas renovandose cada segundo.

A los diez segundos de mostrar la fecha y hora se muestra la temperatura actual junto con los valores máximo (M) y minimo (m) que se han alcanzado. Si son los 30 primeros segundos de medianoche se resetearán esos valores.

A los diez segundos de mostrar la temperatura, se mostrará un mensaje personalizado que se ha guardado en la EEPROM al programar el PIC. Pasados cinco segundos vuelve a mostrar la fecha y hora.

El PIC usa el oscilador interno de 4Mhz. El programa ocupa un 98% de su memoria de código. Aunque en el video vereis que hay un interruptor de encendido/apagado, un led indicador de encendido/apagado y unas resistencias variables para el LCD, con lo que hay en el esquema es suficiente para funcionar. Vcc son 5 voltios conseguidos a través de un 7805.

« Artículos anteriores Siguientes artículos »