Comments on: Ruby para leer datos en tiempo real http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/ La Cara Oscura del Desarrollo de Software Tue, 09 Sep 2008 23:45:47 +0000 http://wordpress.org/?v=2.6.1 By: Luis Lavena http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-649 Luis Lavena Thu, 15 Feb 2007 02:39:54 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-649 Aún podes hacerlo más bonito: <code> request = [0, 0, 0, 0, 0, 6, @devaddress, @funcode, byte8, byte9, byte10, byte11].pack("c12") </code> #pack permite agrugar series de tipos de datos, asi que en lugar de decir N veces un tipo byte (o char), le indicas "un tipo char 12 veces". Además, como estas trabajando con un Array, podes expandirte en más de una linea si es necesario para darle claridad. Un ejemplo seria si los primeros bytes (que ahora estan en cero) fueran otras variables de tu instancia de clase. Pero bueno, siempre se puede refinar todo un poquito más, esa es la magia del refactoring :-) Aún podes hacerlo más bonito:


request = [0, 0, 0,
0, 0, 6,
@devaddress, @funcode, byte8,
byte9, byte10, byte11].pack(”c12″)

#pack permite agrugar series de tipos de datos, asi que en lugar de decir N veces un tipo byte (o char), le indicas “un tipo char 12 veces”.

Además, como estas trabajando con un Array, podes expandirte en más de una linea si es necesario para darle claridad.

Un ejemplo seria si los primeros bytes (que ahora estan en cero) fueran otras variables de tu instancia de clase.

Pero bueno, siempre se puede refinar todo un poquito más, esa es la magia del refactoring :-)

]]>
By: Rómulo Rodríguez http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-648 Rómulo Rodríguez Wed, 14 Feb 2007 19:33:29 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-648 Con el método pack de la clase array todo el primer chorizo de armar el arreglo request quedaría reducido a esta línea: [ruby]request = [0, 0, 0, 0, 0, 6, @devaddress, @funcode, byte8, byte9, byte10, byte11].pack("cccccccccccc")[/ruby] Más bonito como lo recomienda Luis. Con el método pack de la clase array todo el primer chorizo de armar el arreglo request quedaría reducido a esta línea:

RUBY:
  1. request = [0, 0, 0, 0, 0, 6, @devaddress, @funcode, byte8, byte9, byte10, byte11].pack("cccccccccccc")

Más bonito como lo recomienda Luis.

]]>
By: Rómulo Rodríguez http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-647 Rómulo Rodríguez Wed, 14 Feb 2007 18:32:08 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-647 Markus, tal como dice Luis a eso es lo que los ingenieros de automatización llamamos tiempo real. Lo interesante es que estos dispositivos pudieran etiquetar los datos con marcas de tiempo que al ser interrogados por un programita como este permitiría analizar los datos tal como ocurrieron. Otra cosa interesante es la resolución a la que se muestrean los datos. Evidentemente dado lo lento de Ruby nunca se podrá obtener una resolución de tiempo lo suficientemente buena como para ciertos procesos críticos, pero siguen habiendo muchas aplicaciones donde los procesos son lentos y quizás no te interese saber en que milisegundo ocurrió el evento sino nada más en que segundo o en que minuto. Caronte, voy a probar a ver. Luis, en algún momento pensé en serializar los datos usando pack pero no lo he probado. Markus, tal como dice Luis a eso es lo que los ingenieros de automatización llamamos tiempo real. Lo interesante es que estos dispositivos pudieran etiquetar los datos con marcas de tiempo que al ser interrogados por un programita como este permitiría analizar los datos tal como ocurrieron. Otra cosa interesante es la resolución a la que se muestrean los datos. Evidentemente dado lo lento de Ruby nunca se podrá obtener una resolución de tiempo lo suficientemente buena como para ciertos procesos críticos, pero siguen habiendo muchas aplicaciones donde los procesos son lentos y quizás no te interese saber en que milisegundo ocurrió el evento sino nada más en que segundo o en que minuto.

Caronte, voy a probar a ver.

Luis, en algún momento pensé en serializar los datos usando pack pero no lo he probado.

]]>
By: Luis Lavena http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-646 Luis Lavena Wed, 14 Feb 2007 17:03:35 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-646 @Markus Sorensson: Lo que creo que se refiere es obtener los datos de un dispositivo que SI los obtiene en tiempo real. Generalmente esos dispositivos poseen un buffer circular y puedes consultar las ultimas N operaciones (o registros de operaciones). Estaciones meteorologicas o redes de sensores funcionan de esa manera. Algunos consideran eso tiempo real, otros no. Yo por mi parte hago control de flujos MPEG2 e inserción de publicidad de video en tiempo real (pero no con ruby). @Rómulo: No pensaste usar el método pack de la clase Array? "ruby-doc":http://www.ruby-doc.org/core/classes/Array.html#M002272, es mas al estilo de Ruby que el codigo estás empleando (sprintf... malos recuerdos de C). Saludos, Luis @Markus Sorensson:

Lo que creo que se refiere es obtener los datos de un dispositivo que SI los obtiene en tiempo real.

Generalmente esos dispositivos poseen un buffer circular y puedes consultar las ultimas N operaciones (o registros de operaciones).

Estaciones meteorologicas o redes de sensores funcionan de esa manera.

Algunos consideran eso tiempo real, otros no. Yo por mi parte hago control de flujos MPEG2 e inserción de publicidad de video en tiempo real (pero no con ruby).

@Rómulo:

No pensaste usar el método pack de la clase Array? "ruby-doc":http://www.ruby-doc.org/core/classes/Array.html#M002272, es mas al estilo de Ruby que el codigo estás empleando (sprintf... malos recuerdos de C).

Saludos,

Luis

]]>
By: Caronte http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-645 Caronte Wed, 14 Feb 2007 16:49:15 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-645 Rómulo, a mi me funciona: Prueba este fragmento tal y como está: ------------------------ require 'timeout' require 'socket' HH='www.google.es' sock = TCPSocket.new(HH, 80) Timeout::timeout(2) do begin sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r\n") #sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r") puts sock.gets #solo recupera el status: HTTP/1.1 200 OK sock.close rescue Exception => bum puts "Time out: " + bum.to_s end end ---------------------- Despues, prueba comentando la linea: sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r\n") y descomentando: #sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r") El protocolo, en este segundo caso es incorrecto (el servidor web se queda esperando \r\n\r\n indefinidamente), y se sale por 'Time out: execution expired'. De todas formas, la clase Timeout supongo que en la práctica hace lo que haces tú; ejecutar en una hebra el bloque y lanzar una excepción si la hebra no ha terminado en el tiempo dado. Rómulo, a mi me funciona:

Prueba este fragmento tal y como está:
------------------------
require 'timeout'
require 'socket'
HH='www.google.es'
sock = TCPSocket.new(HH, 80)
Timeout::timeout(2) do
begin
sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r\n")
#sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r")
puts sock.gets #solo recupera el status: HTTP/1.1 200 OK
sock.close
rescue Exception => bum
puts "Time out: " + bum.to_s
end
end
----------------------
Despues, prueba comentando la linea:
sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r\n")
y descomentando:
#sock.print("GET / HTTP/1.1\r\nHost: #{HH}\r\n\r")
El protocolo, en este segundo caso es incorrecto (el servidor web se queda esperando \r\n\r\n indefinidamente), y se sale por 'Time out: execution expired'.

De todas formas, la clase Timeout supongo que en la práctica hace lo que haces tú; ejecutar en una hebra el bloque y lanzar una excepción si la hebra no ha terminado en el tiempo dado.

]]>
By: Markus Sorensson http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-644 Markus Sorensson Wed, 14 Feb 2007 15:34:51 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-644 Lo que no veo en todo esto es donde está el tiempo real. Ruby no es concurrente, por eso que digas que es tiempo real no me parece adecuado . Los datos están generándose en tiempo real, cierto, pero no se están leyendo en tiempo real. Cómo garantizas eso con Ruby? Lo que no veo en todo esto es donde está el tiempo real. Ruby no es concurrente, por eso que digas que es tiempo real no me parece adecuado . Los datos están generándose en tiempo real, cierto, pero no se están leyendo en tiempo real. Cómo garantizas eso con Ruby?

]]>
By: Rómulo Rodríguez http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-643 Rómulo Rodríguez Wed, 14 Feb 2007 13:35:35 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-643 caronte, eso fue lo primero que pensé, pero la lectura del buffer no levanta ninguna excepción. Al parecer pasa por ahí y devuelve un nil nada más, por eso fue que se me ocurrió abrir un hilo que contara un par de segundos. Pero por supuesto que el código ni de broma está terminado, la versión que tengo ahora es ligeramente diferente ya que incluye un poco de más control sobre la ejecución de los hilos. Otra cosa que no se ve en esta muestra que publiqué es que todo esto corre dentro de un hilo maestro que está continuamente corriendo en un lazo infinito haciendo barridos. Allí tuve que considerar el manejo de las excepciones que ocurren si se interrumpe la comunicación, o si el PLC se apaga y el socket se destruye, cosas así. Supongo que falta mucho para que sea óptimo, pero al menos funciona como prototipo. caronte, eso fue lo primero que pensé, pero la lectura del buffer no levanta ninguna excepción. Al parecer pasa por ahí y devuelve un nil nada más, por eso fue que se me ocurrió abrir un hilo que contara un par de segundos. Pero por supuesto que el código ni de broma está terminado, la versión que tengo ahora es ligeramente diferente ya que incluye un poco de más control sobre la ejecución de los hilos. Otra cosa que no se ve en esta muestra que publiqué es que todo esto corre dentro de un hilo maestro que está continuamente corriendo en un lazo infinito haciendo barridos. Allí tuve que considerar el manejo de las excepciones que ocurren si se interrumpe la comunicación, o si el PLC se apaga y el socket se destruye, cosas así. Supongo que falta mucho para que sea óptimo, pero al menos funciona como prototipo.

]]>
By: caronte http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-642 caronte Wed, 14 Feb 2007 12:03:45 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-642 mejor usar esto para controlar el timeout? require 'timeout' . . Timeout::timeout(2) do begin result = @socket.recv(@nobytes) @exc = "Reading fine!" rescue Exception @exc = "Time out" end end mejor usar esto para controlar el timeout?

require 'timeout'
.
.
Timeout::timeout(2) do
begin
result = @socket.recv(@nobytes)
@exc = "Reading fine!"
rescue Exception
@exc = "Time out"
end
end

]]>
By: Kodegeek http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-641 Kodegeek Wed, 14 Feb 2007 05:21:32 +0000 http://www.lacaraoscura.com/2007/02/13/ruby-para-leer-datos-en-tiempo-real/#comment-641 Muy interesante la aplicación, al fin veo algo escrito en RUby que no sea Rails :) El ejemplo está genial, espero ver más código como este por el blog. Lo que no me quedó muy claro es como sincronizas a las hebras de ejecución y evitas condiciones de carrera... Saludos. Muy interesante la aplicación, al fin veo algo escrito en RUby que no sea Rails :)

El ejemplo está genial, espero ver más código como este por el blog. Lo que no me quedó muy claro es como sincronizas a las hebras de ejecución y evitas condiciones de carrera...

Saludos.

]]>