Archivo de la categoría: Python

Rotación y Auto-Rotación de pantalla (iphone-like) con Linux

La rotación de pantalla es una posibilidad nativa del sistema X, basado claro está en xrandr (un comando de X que permite rotar la pantalla, cambiar resolución, etc), ahora bien, la idea de asociar esto a una tecla o mejor aún, aprovechar las capacidades de nuestro hardware para hacerlo de manera automática es mucho más práctico.

El módulo thinkpad_acpi

En mi caso, al tener una portátil Thinkpad, uso el módulo thinkpad_acpi para controlar los “botones especiales” de la portátil, para “asegurar” la carga de este módulo hemos agregado su nombre a:

/etc/modules

Y listo!, podemos usar el botón thinkVantage, subir y bajar volumen, cambiar de escritorio, etc.

Ahora bien, la Thinkpad tablet PC viene con un botón que se usa “precisamente” en Windows para rotar la pantalla, su combinación de pantalla es “0xc7″ y puede ser asociado fácilmente a cualquier cosa, en la sección SISTEMA > “Preferencias” > “Combinaciones de Teclas” de Gnome, para ello cargamos el selector de combinación de teclas, y presionamos el botón “Añadir”:

Creamos un acceso llamado “Rotar Pantalla” y lo asociamos a un script en python llamado /usr/bin/rotate-screen.py que ya veremos como funciona.

La cosa queda así:

Ahora, a trabajar en el script!.

El Script de rotar la pantalla

El guión de rotar pantalla es un simple script de python, que usa xrandr para rotar la pantalla y usa xsetwacom para rotar el cursor/stylus/puck de la tablet PC, adicionalmente utiliza el módulo HDAPS (Hard Disk Active Protection System) para determinar con el acelerómetro la posición actual (si es izquierda, derecha, normal o invertida), para los que no tengan acelerómetro en el disco duro, simplemente podrían determinar el actual modo de rotación y cambiar al siguiente (para hacer una rueda infinita de rotación normal > izquierda > inverted > derecha).

Es como ejecutar “a mano” los siguientes comandos:

normal=’xrandr –output LVDS –rotate normal’
left=’xrandr –output LVDS –rotate left’
right=’xrandr –output LVDS –rotate right’
inverted=’xrandr –output LVDS –rotate inverted’

También usa el módulo Thinkpad-ACPI para determinar el modo en el que estamos (PC o Tablet PC), ya que solo rotará si estamos en modo Tablet.

cat /sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode

Donde: 0 = laptop y 1 = tablet

Yo ya había hecho este script en bash, sin embargo, me pareció una buena práctica de scripting en python hacerlo por esta vía.

Por ejemplo, rotar la pantalla a la derecha sería en bash:

#!/bin/bash/usr/bin/xrandr -o right
xsetwacom set "Serial Wacom Tablet" Rotate cw
xsetwacom set "Serial Wacom Tablet eraser" Rotate cw

Nota: las rotaciones de la Tablet son: none, cw, ccw e inverted

Pueden descargar el guión de acá: http://depositfiles.com/files/wk2fdee34

Simplemente copian ambos archivos a /usr/bin:

cp * /usr/bin && chmod +x /usr/bin/rotate-screen.py

Y listo!, ya pueden rotar sus pantallas.

Auto-rotación

Para que la auto-rotación funcione, requieren que el módulo tp_smapi esté instalado, en Debian la forma más fácil es instalar el paquete DKMS (auto-construye el módulo):

aptitude install tp-smapi-dkms

Esto ejecutará lo siguiente:

Configurando tp-smapi-dkms (0.40-8) ...
Creating symlink /var/lib/dkms/tp-smapi/0.40/source ->                 /usr/src/tp-smapi-0.40
DKMS: add Completed.
Kernel preparation unnecessary for this kernel.  Skipping...
Building module:cleaning build area....make KERNELRELEASE=2.6.32-5-amd64 -C /lib/modules/2.6.32-5-amd64/build M=/var/lib/dkms/tp-smapi/0.40/build.....cleaning build area....
DKMS: build Completed.
thinkpad_ec.ko:Running module version sanity check. - Original module   - No original module exists within this kernel - Installation   - Installing to /lib/modules/2.6.32-5-amd64/updates/dkms/
tp_smapi.ko:Running module version sanity check. - Original module   - No original module exists within this kernel - Installation   - Installing to /lib/modules/2.6.32-5-amd64/updates/dkms/
hdaps.ko:Running module version sanity check. - Original module - Installation   - Installing to /lib/modules/2.6.32-5-amd64/updates/dkms/
depmod......
DKMS: install Completed.

Nota: Requieren tener instalados los linux-headers de su kernel actual

Si acaso desean instalarlo desde fuentes, entonces usan tp.smapi-sources:

aptitude install tp-smapi-source

Y usar module-assistant para instalarlo:

cd /usr/src/tp-smapi/

Actualizamos:

m-a update

Y auto-instalámos el módulo:

m-a a-i tp-smapi

luego ejecutamos el montaje de los módulos:

modprobe hdaps
modprobe thinkpad_ec
modprobe tp_smapi

Si acaso bajamos los fuentes de la página oficial (y no usamos los de Debian):

Descomprimen y compilan:

#tp_smapi

make
make install HDAPS=1
make load HDAPS=1 FORCE_IO=1

En cualquiera de los 3 casos, ejecutar modinfo tp-smapi devolverá información del módulo cargado:

modinfo tp-smapi
filename:       /lib/modules/2.6.32-5-amd64/updates/dkms/tp_smapi.ko
license:        GPL
version:        0.40
description:    ThinkPad SMAPI Support
author:         Shem Multinymous
srcversion:     F73BBCBD87C5944FFE67105
depends:        thinkpad_ec
vermagic:       2.6.32-5-amd64 SMP mod_unload modversions
parm:           debug:Debug level (0=off, 1=on) (int)

Cuando cargan, veremos esto en el dmesg:

[16848.875565] tp_smapi 0.40 loading...
[16848.876270] tp_smapi successfully loaded (smapi_port=0xb2).
[16855.810653] hdaps: LENOVO ThinkPad X61 detected, setting orientation 6
[16855.811656] hdaps: initial mode latch is 0x05
[16855.811824] hdaps: setting ec_rate=250, filter_order=2
[16855.812048] hdaps: device successfully initialized.
[16855.812811] input: ThinkPad HDAPS joystick emulation as /devices/virtual/input/input12
[16855.814213] input: ThinkPad HDAPS accelerometer data as /devices/virtual/input/input13
[16855.814571] hdaps: driver successfully loaded.

Ya con esto, la auto-rotación es posible!.

Auto-rotación, registrando un servicio

La auto-rotación es un script que queda “cargado en memoria” usando la capacidad de un script python de quedar registrado como un DBusGMainLoop, todo es gracias a esta función main:

def main():
  dbus_loop = DBusGMainLoop(set_as_default = True)
  session = dbus.SessionBus(mainloop = dbus_loop)
  loop = gobject.MainLoop()
  gobject.threads_init()
  gobject.timeout_add(1000,setRotation)
  loop.run()

main()

Que permite ejecutar la función “setRotation” cada 1000 milisegundos, dicha función se encuentra en el script “autorotate-screen.py” y determina la posición de la pantalla por las coordenadas de posición que devuelve el acelerómetro:

* Cuando hdaps está en modo “PC” en mi mesa:

cat /sys/devices/platform/hdaps/position

resultado : (0,-3)

* Cuando hdaps está en modo “tablet” con la posición invertida

cat /sys/devices/platform/hdaps/position

resultado : (-510,637)

Y como registro ese script?

Para que este script se inicie siempre que arranque la computadora (pero SOLO cuando YA haya arrancado las X) el script no debe ir en /etc/rc.local sino en:

/etc/gdm3/Init/Default

Al final de ese archivo agregaremos la línea:

/usr/bin/autorotate-screen.py

Y listo!, la próxima vez que el GDM inicie, podrán rotar la pantalla automáticamente (cuando esté en modo Tablet PC) con solamente girar la pantalla.

[python] usando gammu para enviar SMS

Continuando con el artículo “Enviando SMS usando bluetooth, un celular GSM y python”, voy a mostrar el uso de un toolkit bastante interesante para hacer más cosas con nuestro celular.

Gammu/gWammu es un proyecto que se ha fijado como meta manejar toda la información  de tu celular, cuando este está conectado a tu PC, sea via bluetooth o vía modem (USB, rs-232, etc).

Instalación:

En Debian y derivados es de lo más fácil:

aptitude install gammu gammu-smsd python-gammu

El primero es la aplicación GTK+ (fork de gnokii) para conectar celulares (no solo nokia como en gnokii) y administrar datos, contactos, etc.

La “phone database” es un compendio de todos los teléfonos donde ha sido probado gammu (si logras probar en algún otro, agrégalo como contribución.

Conectándose con Python

Para conectarnos a el teléfono, tenemos primero que configurarlo:

Para ello, creamos un archivo (por defecto, .gammurc  en la raíz del usuario):

[gammu]
port = 00:25:47:BC:8B:7F
connection = blueat

Pueden instalar wammu, y aprovechan el asistente de conexión a teléfonos, para que este descubra el tipo más válido de conexión para el suyo.

En mi caso, ha servido at115200 (USB) Para mi Motorola Rokr E8, para Nokia 5800 XpressMusic, aún no soporta comunicación para SMS.

Luego de conectados al teléfono (por USB, bluetooth), ejecutamos el script:

#!/usr/bin/env python
# Ejemplo de como enviar SMS usando gammu y python

import gammu
import sys

# crea un objeto stateMachine, para hablar con el telefono
sm = gammu.StateMachine()

# Leer la configuracion desde (~/.gammurc)
sm.ReadConfig()

# Iniciamos la conexión con el telefono
sm.Init()

# Preparamos el paquete de mensaje SMS
# SMSC es un numero que se puede obtener interrogando el telefono
message = {
 'Text': 'test SMS',
 'SMSC': {'Location': +584264568828},
 'Number': '+584264568828',
}

# Enviar el mensaje
sm.SendSMS(message)

Usando wammu

Para los que no deseen conectarse programáticamente, sino simplemente deseen conectarse a su teléfono, respaldar contactos o agenda, sms, enviar y recibir sms y demás, pueden usar la interfaz gráfica de gammu, llamada wammu; para instalarla:

aptitude install wammu

Con wammu (y dependiendo de marca, modelo, serie del sistema operativo, etc) podrán hacer “más o menos cosas”, cada vez están agregando más dispositivos a la “phone database”, en mi caso, el Nokia 5800 XpressMusic aún no dialoga muy bien con wammu (pero puedes aún enviar SMS usando py-bluez).

Enviando SMS usando bluetooth, un celular GSM y python

Estuve investigando una manera rápida, sencilla y con pocas líneas de código para poder enviar mensajes de texto usando un script, esto tiene utilidad para muchas aplicaciones, entre ellas el sistema nagios de monitoreo que estamos colocando en el trabajo.

La idea “adicional” de usar bluetooth surge de la posibilidad de evitar el uso de cables para transmitir los mensajes, para darle capacidades “bluetooth” a un equipo desktop convencional, simplemente agregamos un dongle bluetooth (que cuesta como 5 dólares en amazon) como este:

Y agregamos los paquetes necesarios:

aptitude install bluetooth bluez bluez-firmware bluez-utils python-bluez

Descubriendo dispositivos encendidos con python

El siguiente script (discovery.py) permite detectar qué equipos bluetooth están al alcance:

import bluetooth

lista = bluetooth.discover_devices(lookup_names = True)
print 'Lista de Dispositivos Bluetooth'
print 'Se encontraron %d' % len(lista)

for hwaddr, nombre in lista:
     print " %s - %s" % (hwaddr,nombre)

Nos mostrará algo como esto:

Se encontraron 1
 00:25:47:BC:8B:7F - Pheno

Determinación del Servicio:

El servicio Dial-Up Networking es el utilizado para enviar un mensaje SMS, el puerto dependerá del tipo de equipo y la cantidad de servicios asociados; si ejecutamos el comando:

sdptool browse 00:25:47:BC:8B:7F

Obtendremos algo como esto:

Service Name: Dial-Up Networking
Service RecHandle: 0x10019
Service Class ID List:
 "Dialup Networking" (0x1103)
Protocol Descriptor List:
 "L2CAP" (0x0100)
 "RFCOMM" (0x0003)
 Channel: 22
Language Base Attr List:
 code_ISO639: 0x454e
 encoding:    0x6a
 base_offset: 0x100
Profile Descriptor List:
 "Dialup Networking" (0x1103)
 Version: 0x0100

Reportando que el puerto para la conexión será el 22; pero esto también lo podemos hacer con Python, ampliando un poco el script discovery.py:

import bluetooth

lista = bluetooth.discover_devices(lookup_names = True)
print 'Lista de Dispositivos Bluetooth'
print 'Se encontraron %d' % len(lista)

for hwaddr, nombre in lista:
 print " %s - %s" % (hwaddr,nombre)
 services = bluetooth.find_service(address=hwaddr)
   if len(services) > 0:
     port = 0
     for svc in services:
       if  svc["name"] == "Dial-Up Networking":
       port = svc["port"]
       if port != 0:
         print "Encontrado Dial-Up Networking port = %d\n" % (port)

Al ejecutarlo reporta lo siguiente:

Se encontraron 1
00:25:47:BC:8B:7F – Pheno
Encontrado Dial-Up Networking port = 22

Sabiendo que nuestro dongle bluetooth funciona (y obviamente la mac-address de nuestro teléfono GSM con bluetooth), procedemos al siguiente paso, que es enviarnos mensajes de texto.

Enviando SMS con python

Con el siguiente script, podemos enviar un SMS usando GSM:

import bluetooth

#bluetooth address
addr = '00:25:47:BC:8B:7F'

#puerto
port = 22

#telefono
mobile = '584xxxxxxxxx' #de la forma 58 4[operadora][numero]
#mensaje a enviar
data = 'Test SMS'

# crear un socket bluetooth rfcomm
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)

# la funcion connect pide los parametros direccion y puerto (address, port)
socket.connect((addr, port)) #abrir un socket al bt
#inicializamos el dialogo AT con el modem
socket.send('ATZ\r')
print socket.recv(1024)
#valor "1" indica que el SMS es solo texto
socket.send('AT+CMGF=1\r')
print socket.recv(1024)
#Telefono al que enviaremos el SMS
socket.send('AT+CMGS="+\"mobile\""\r')
print socket.recv(1024)
socket.send(data+chr(26)) #data + CTRL+Z
print socket.recv(1024)

socket.close()

La salida del script será algo como esto:

ATZ
OK

AT+CMGF=1
OK

AT+CMGS="+584xxxxxxxxx"
>
Test SMS
OK

Notas adicionales

Pueden agregar la configuración del dispositivo en /etc/bluetooth/rfcomm.conf para que haga enlace automáticamente y no esté solicitando bind+contraseña (y sea una conexión en confianza entre el teléfono y el PC):

rfcomm0 {
# Automatically bind the device at startup
bind yes;

# Bluetooth address of the device
device 11:22:33:44:55:66;

# RFCOMM channel for the connection
channel 1;

# Description of the connection
comment “Mobile Phone Pheno”;
}

Agregan la entrada y reinician el demonio bluetooth

/etc/init.d/bluetooth restart

TODO

* Aprovechar los posixGroups del LDAP y usar py-ldap para iterar sobre todos los miembros de un grupo (ejemplo: Soporte o Redes), extraer su atributo “mobile” y pasarlo al script como número a enviar (pueden ser varios destinatarios).

* Integrar discovery.py y send_sms.py en un único script, así el script descubre la dirección, el puerto, abre el socket, envía el SMS y se desconecta (con import sys podemos hacer sys.exit(0) para salir del script con confianza).

* Agregar excepciones (como el bluetooth.btcommon.BluetoothError 112; Host is Down) para gestión de errores del script.

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 3.227 seguidores

A %d blogueros les gusta esto: