lunes, noviembre 12

Proyecto: pyemb

Desde hace un tiempo me entró la curiosidad por los formatos de archivo de bordado, instigado por mi suegra, que me pedía que le arreglara/convirtiera/escalara los archivos de bordado para su Janome MemoryCraft 200E. Como era de esperarse, hay muchas alternativas de software para hacer esto, desde software de pago (de varios miles de dólares), gratis (con algunas limitaciones), y open source. De las pagadas, ni pensar en comprar alguna, mucho derroche. De las gratis, la mejor que encontré es Wilcom TrueSizer E4, sólo hay que registrarse como usuario y descargarlo. Pero aún así no estaba conforme. En el mundillo open source encontré un proyecto que me llamó poderosamente la atención: Embroidermodder. Por lo visto está bastante desarrollada, pero con el inconveniente de que nadie mantiene la versión para Windows, ni tampoco encontré alguna instrucción clara de que se requería para compilarlo, por lo que decidí comenzar a portar el código original de Embroidermodder a lenguaje Python. Por el momento no hay nada completo, pero espero de a poco ir completando esta transformación. Pueden ver el poco código que llevo desarrollado en GitHub. Por el momento tengo implementado lo básico del formato JEF, y me gustaría avanzar con más formatos, y algunas herramientas anexas para el análisis de los archivos. Eso sería por hoy, cambio y fuera!

De vuelta al blog

Hace muuuchos años que no escribía en esta plataforma, y muchas cosas han cambiado. Han pasado varias pegas, pololié, me casé, y tengo dos hermosos perros, me cambié de ciudad. Hoy mientras pensaba y revisaba mi código python sobre un proyecto personal que estoy llevando a cabo, me entró la duda de dónde poner mis notas mentales y de código, dejar cosas documentadas para un futuro, para mí o cualquiera que le interese el tema, y así me recordé de este sitio. Espero esta vez no dejarlo tanto tiempo botado sin ninguna clase de aviso.

viernes, marzo 11

Manteniendo más de una versión de python en ubuntu

Tratando de probar como corría un script con diferentes versiones de python, me encontré con update-alternatives, un sistema para mantener las diferentes "versiones" de distintos programas, que se puedan cambiar fácilmente, recordando donde se encuentran cada una de ellas.

Para agregar al sistema las diferentes versiones del programa (en mi caso, python):
update-alternatives --install /usr/bin/python python /usr/bin/python2.7 2
update-alternatives --install /usr/bin/python python /usr/bin/python2.6 1


Para resumir un poco el manual, le decimos que vamos a instalar una opción ("--install"), el segundo argumento es el enlace simbólico (symlink) que se desea administrar (el nombre genérico del programa), el tercero es al grupo que agregaremos esta opción, el cuarto es la ruta que nos provee el programa real y finalmente un número para asignar prioridad, a mayor número, mayor prioridad.

Luego, cuando queremos cambiar de una versión a otra, simplemente hacemos
update-alternatives --config python
y el sistema nos muestra la lista de opciones que tiene registradas y pregunta que versión queremos utilizar.

Fácil y bonito! ;)

viernes, enero 28

Python NTP client

Después de buscar un poco como funcionaba el protocolo NTP (Network Time Protocol), no encontré una implementación que fuera simple de entender, así que decidí hacerme una propia. Necesitaba entenderla para implementarla en un "Single board computer" (un microcontrolador con periféricos) Encontré una implementación básica en ActiveState, pero no me respondía a que correspondía cada campo del paquete.

Continuando con la búsqueda, encontré la implementación de OpenBSD de su cliente NTP y en el archivo ntp.h hay una buena descripción de que es cada campo. También ayudaron algunas páginas como ésta y ésta.

Finalmente, llegué a una implementación, simple pero a la vez. La dejo a continuación.


#!/usr/bin/python
# NTP client class for python, based on OpenBSD's ntp C code and ActiveState code recipe 117211
# v 0.1 (2011-01-28) Initial release
# Features:
# Conversion from/to NTP timestamp
# Ability to query NTP servers
# Calculation of delay and offset

import socket
import struct
import time
TIME1970 = 2208988800L # seconds from 1900

def NTPtimestamp2time(ts):
# print '%016X' % ts
# print '%016X' % (ts >>32)
ia = (ts >> 32) - TIME1970
fa = ts & 0x0000FFFF
return float(ia)+float(fa)/2**32
def time2NTPtimestamp(time):
ia = int(time)
fa = int((time-ia)*2**32)
return (ia<<32 | fa)+(TIME1970<<32)

class ntpclient:
def __init__(self):
self.sockt = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.server = None
self.port = 123
self.data = '\x1b' + 47* '\0'
#packet fields
self.leapIndicator = None
self.versionNumber = None
self.mode = None
self.stratum = None
self.pollInterval = None
self.precision = None
self.rootDelay = None
self.rootDispersion = None
self.referenceIdentifier = None
self.referenceTimestamp = None
self.originateTimestamp = None
self.recieveTimestamp = None
self.transmitTimestamp = None
self.destinationTimestamp = None
self.keyIdentifier = None
self.messageDigest = None
self.keyAlgorithmIdentifier = None
self.messageHash = None
def poll(self,server=None):
if server == None:
return
self.server = server
self.sockt.sendto(self.makeReqPackt(),(self.server,self.port))
data,address = self.sockt.recvfrom(1024)
self.destinationTimestamp = time2NTPtimestamp(time.time())
# print len(data)
if data and len(data) == 60:
smallfields, \
self.stratum, \
self.pollInterval, \
self.precision, \
self.rootDelay, \
self.rootDispersion, \
self.referenceIdentifier, \
self.referenceTimestamp, \
self.originateTimestamp, \
self.recieveTimestamp, \
self.transmitTimestamp, \
self.keyIdentifier, \
self.messageDigest, \
self.keyAlgorithmIdentifier, \
self.messageHash = \
struct.unpack('!BBBBIIIQQQQI8s',data)

self.leapIndicator = smallfields & 0b11000000 >> 6
self.versionNumber = smallfields & 0b00111000 >> 3
self.mode = smallfields & 0b00000111

if data and len(data) == 48:
smallfields, \
self.stratum, \
self.pollInterval, \
self.precision, \
self.rootDelay, \
self.rootDispersion, \
self.referenceIdentifier, \
self.referenceTimestamp, \
self.originateTimestamp, \
self.recieveTimestamp, \
self.transmitTimestamp = \
struct.unpack('!BBBBIIIQQQQ',data)

self.leapIndicator = smallfields & 0b11000000 >> 6
self.versionNumber = smallfields & 0b00111000 >> 3
self.mode = smallfields & 0b00000111
def toCtime(mytime):
return time.ctime((mytime>>32)-TIME1970)

def offset(self):
# t1 = self.referenceTimestamp
# t2 = self.originateTimestamp
# t3 = self.recieveTimestamp
# t4 = self.transmitTimestamp

t1 = NTPtimestamp2time(self.originateTimestamp)
t2 = NTPtimestamp2time(self.recieveTimestamp)
t3 = NTPtimestamp2time(self.transmitTimestamp)
t4 = NTPtimestamp2time(self.destinationTimestamp)

return ((t2-t1)+(t3-t4))/2

def delay(self):

t1 = NTPtimestamp2time(self.originateTimestamp)
t2 = NTPtimestamp2time(self.recieveTimestamp)
t3 = NTPtimestamp2time(self.transmitTimestamp)
t4 = NTPtimestamp2time(self.destinationTimestamp)

return ((t4-t1)-(t2-t3))

def makeReqPackt(self):
leapind = 0b00
version = 0b100 # NTP V4
mode = 0b011 # client mode

# a = time.time()
# ia = int(a)
# fa = int((a-ia)*2**32)
# tt = (ia<<32 | fa)+(TIME1970<<32)
tt = time2NTPtimestamp(time.time())
#print '%16X' % TIME1970
#print '%16X' % tt

return struct.pack('!BBBBIIIQQQQ',
leapind <<6 | version <<3 | mode,
0, #unspecified stratum
0, #poll interval
0, # local clock precision
0, # root delay
0, # root dispersion
0, # reference clock identifier
0, #reference timestamp
0, #originating timestamp
0, #recieve timestamp
tt #transmit timestamp
)

if __name__ == '__main__':
from sys import argv
c = ntpclient()
# print repr(c.makeReqPackt())
# c.poll('time.tigo.cl')
c.poll(argv[1])
# print c.versionNumber
# print c.stratum
# print '%016X'%(c.referenceTimestamp)
# print '%016X'%(c.originateTimestamp)
# print '%016X'%(c.recieveTimestamp)
# print '%016X'%(c.transmitTimestamp)
# print '%016X'%(c.destinationTimestamp)
# print c.delay()>>32, c.offset()>>32
print c.delay(), c.offset()


Espero que le sirva a alguien.

jueves, agosto 19

Hammer: Instalando linux en un dispositivo embebido

Me compré un nail kit en TinCanTools, para experimentar que tal funcionaba correr un pequeño linux en un sistema embebido.

La cosa es que una vez que lo tuve, me propuse instalar el entorno de desarrollo en una máquina virtual con ubuntu minimal (pura consola), lo cual no anduvo tan suavemente como hubiese querido.

Siguiendo el paso a paso encontrado en el Hammer Hello World Tutorial ocurrieron un par de detalles que hubo que resolver antes de tener el entorno andando.

Primero, había que bajar las fuentes para compilar el kernel:
wget http://www.elinux.org/upload/b/b6/Buildroot-01082008.tar.gz
wget http://www.elinux.org/images/f/ff/Hammer-linux-2.6.22-09122007.diff.gz
wget http://www.elinux.org/images/e/ef/Hammer-kernel-config
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.22.tar.gz
En el siguiente paso, comenzamos con la compilación de Buildroot:
tar xvzf Buildroot-01082008.tar.gz
cd buildroot
cp Hammer-config .config
make clean
make oldconfig
make
cd ..
Al hacer el make del paso anterior, se caía en un error en el archivo unifdef.c, en la cual la función getline ya está definida (conflicto de nombre con la función de stdio). Esto simplemente se soluciona renombrando la función a getline2.

Al hacer nuevamente un make, se caía en la parte donde trataba de bajar uClibc, esto se solucionó editando el valor de UCLIBC_SITE en ./toolchain/uClibc/uclibc.mk de http://www.uclibc.org/downloads a http://www.uclibc.org/downloads/old-releases

Otro make más, y ahora el sistema se caía al intentar bajar fakeroot, y de acuerdo a la instrucción del tutorial sólo bastaba con cambiar el número de la versión. Revisando en el FTP de debian me encontré que la última versión era la 1.14.4, pero viene empaquetada de una manera diferente del clásico tar.gz, por lo que decidí utilizar la 1.12.4 que viene empaquetada de esa manera y evitar mayores enredos con los scripts que lo procesan.

Al hacer nuevamente make, me arrojaba un error al parchar los archivos Makefile.in y Makefile.am, para salvar este obstáculo, reemplazamos el contenido de package/fakeroot/fakeroot-doc.patch con lo siguiente:
--- fakeroot/Makefile.am.orig 2006-04-19 11:50:35.000000000 -0600
+++ fakeroot/Makefile.am 2006-04-19 11:50:59.000000000 -0600
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS=foreign
ACLOCAL_AMFLAGS = -I build-aux
-SUBDIRS=scripts doc test
+SUBDIRS=scripts test

noinst_LTLIBRARIES = libcommunicate.la
libcommunicate_la_SOURCES = communicate.c
--- fakeroot/Makefile.in.orig 2006-04-19 11:50:43.000000000 -0600
+++ fakeroot/Makefile.in 2006-04-19 11:51:21.000000000 -0600
@@ -244,4 +244,4 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I build-aux
-SUBDIRS = scripts doc test
+SUBDIRS = scripts test
noinst_LTLIBRARIES = libcommunicate.la
Antes de realizar nuevamente el make, hay que borrar los archivos que *.rej que quedaron en build_arm/fakeroot-1.12.4

Luego, al hacer make, aparece un error en makedevs.c, el cual se soluciona reemplazando en la linea 531, el código
system("/bin/sync");
por
if(system("/bin/sync")) bb_error_msg("sync failed, continuing anyway");
con esto, finalmente, funcionó el make.

miércoles, julio 14

Más paletas de colores en NCView

Resolviendole el problema al Osvaldo, que no podía compilar el NCView, con un parche que incluye paletas de colores adicionales (como se describe aquí). El problema es que buscaba unas librerías de netcdf y con algunas llamadas a funciones de curl, pero la librería que había compilado a mano al parecer no las tenía.

Bueno, la cosa es que se me ocurrió hacerlo de la forma Ubuntu. ¿El resultado? Funcionó a la primera. Veamos el paso a paso.

Como nunca antes había compilado paquetes en esta máquina, tuve que instalar algunos paquetes para tal propósito:
sudo apt-get install dpkg-dev devscripts
Creamos una carpeta para trabajar y bajamos las fuentes (habiendo activado el repositorio, yo lo hice en synaptic)
mkdir ncview-deb
cd ncview-deb
apt-get source ncview
Sobreescribí los archivos fuente con los que estaban modificados para incluir los nuevos colormap
cp ../ncview_colormaps/* .
Descargamos las dependencias de compilación y recompilamos.
sudo apt-get build-dep ncview
debuild -us -uc
Y finalmente, instalamos el paquete ya parchado
sudo dpkg -i ../ncview_1.93g-1_amd64.deb
Voilà!! Fácil y bonito :D

martes, diciembre 22

Sistema nervioso terrestre

Me parece bastante ambicioso... pero genial!! Un pequeño sistema capaz de sentir una variedad de variables terrestres.

Para un poco más de detalles ver aqui

martes, septiembre 15

Soldar o pegar?

De pronto me asaltó el bichito de si habría alguna alternativa a soldar un circuito integrado. La respuesta fue positiva. ¿Las opciones? Polímeros conductivos y adhesivos conductivos.

Los primeros son polímeros que presentan conductividad, pero el problema que tienen es que generalmente son anisótropos (la conductividad no es la misma en todas las direcciones).

La segunda opción son los adhesivos conductivos, que son polímeros mezclados con partículas metálicas que forman los conductores, pero tienen las desventaja de que a medida que aumenta la cantidad de partículas metálicas y mejora la conductividad, la resistencia mecánica del polímero disminuye.

La gran ventaja es que el curado es a alrededor de 160 °C , bastante menos que las soldaduras de plomo-estaño 0 las soldaduras sin plomo (generalmente de AgCuSn).

Un análisis más detallado está en http://www.et-trends.com/files/SMTA-East_CondAdh.pdf

Interesante tema.