Python for Series 60

Propaganda
Python for Series 60
Elvis Pfützenreuter – INdT
[email protected]
Original de Osvaldo Santana Neto ([email protected])
O que são celulares “Série 60”
ou Symbian




Smartphones com capacidade de
processamento respeitável
Sistema operacional Symbian
Plataforma Série 60: Symbian +
interface de usuário + recursos
adicionais
Restou apenas a Nokia no
consórcio Symbian
Desenvolvimento C++ para S60




SDK completo gratuito em http://forum.nokia.com
SDK inclui emulador
Alguns recursos mais avançados são pagos (JTAG)
API C++ do Symbian é sui generis e canhestra

Progressiva adoção de APIs open-source (Qt, OpenC)
_LIT(KFileName, "C:\\file1");
RFile fd;
RFs fs;
fs.Connect();
CleanupClosePushL(fs);
User::LeaveIfError(fd.Open(fs, KFileName,
EFileShareExclusive | EFileWrite));
CleanupClosePushL(fd);
TBuf8<8> buf;
myFile.Read(0, buf);
myFile.Close();
fs.Close();
CleanupStack::PopAndDestroy(2);
char buf[8];
fd = open(“C:\\file1”, O_RDWR);
int len = read(fd, buf, 8);
close(fd);
Por que desenvolver para S60






Mais de 150-200 milhões de celulares vendidos
Distribuição do aplicativo: uma vez assinado,
não sofre qualquer restrição
Previsões ainda apontam como plataforma
dominante para os próximos anos
Várias opções de linguagem: J2ME, C++,
Qt, Python
Plataforma fechada aberta e SDK gratuito
Existe mercado e comunidade de
desenvolvedores
Por que usar Python para S60
Desenvolvimento
C++ é
difícil
Desenvolver para mobile
é ainda mais difícil
As APIs e ferramentas
dos fabricantes não
ajudam
O Python “resolve”
muitos destes problemas
por introduzir uma
camada de abstração

Desvantagens do PyS60

Desempenho pode ser um problema


solução: módulos Python escritos em C/C++
Nem toda a API C++ do Symbian está coberta

solução: idem
Salada de versões dos softwares
Python PyS60
2.2
Série 60
<= 1.4.6 2nd Edition
Symbian
6.x até 8.x
6600, 6681, N70
3rd Edition
9.x
N85, N95, N82, N96
2.5
1.9.7,
2.0
3rd Edition
9.x
N85, N95, N82, N96
5th Edition
N97, XPressMusic
Este curso é baseado no PyS60 1.9.7 para dispositivos 3rd Edition
Obter e instalar o PyS60
https://garage.maemo.org/projects/pys60/
PyS60 para SDK
Versão 3.2
Distribuição
para Windows
Distribuição
genérica
Obter e instalar o PyS60 (cont.)
Interpretador
(inclui OpenC PIPS)
Shell interativo
Auto-assinado
para S60 3.2
Shell interativo
Assinado Nokia
“alta capacidade”

Instalar via Bluetooth ou PC Suite; prefira
instalar no cartão de memória (D:)
Shell interativo PyS60
Terminal Bluetooth via Windows
Terminal Bluetooth via Mac OS X
Celular
conecta
Terminal Bluetooth via Linux
Celular
conecta
Terminal via Bluetooth - PyS60





Aviso: O perfil “Serial Port” do Bluetooth é
temperamental
Tentar conectar algumas vezes
É interessante parear e liberar antes
Se nada mais der certo, tente desligar
celular, computador, ou ambos
Console/terminal via cabo USB
Rodando PyS60 no emulador
Python versus modelo de segurança
Pacote SIS
original
não instalável
Crypto
Certificado
X.509 do
desenvolvedor
Auto-assinado
Assinado CA
Symbian $$$
Capacidades
requisitadas
pelo aplicativo
Vide
Symbian Signed
Open Signed !$
Pacote SIS
assinado e
instalável
Escopo de
distribuição
requisitado
Homologação
$$$$$$$$$
Python versus modelo de segurança
Pacote SIS de aplicativo Python
- é um “executável”
- pode ter menos capacidades que o runtime
- suas capacidades determinam o que os scripts podem fazer
- contém scripts e módulos Python
- PyScriptShell = um simples aplicativo escrito em Python
- FAQ como utilizar o PyScriptShell assinado pela Nokia?
Runtime PyS60
Scripts Python
- arquivos-texto
- elementos
passivos
- Python_1.9.7.sis
- é uma biblioteca
- assinada pela Nokia
- muitas capacidades
Módulo em C/C++
(opcional)
- tem de possuir no
mínimo as mesmas
capacidades do
aplicativo
Python versus modelo de segurança

Shell high-capas assinado pela Nokia
 Instalar script no cartão de memória via USB; ou
 criar um pacote SIS (veremos mais adiante)

Instalar scripts via Bluetooth ou SMS não funciona
 Truque: ZIPar e mandar

IMPORTANTE: instalar PyS60 no cartão de
memória (D:)
 D:\data\python\
 D:\private\20022ee9\
Python versus modelo de segurança
Comprando um celular Série 60
para fins de desenvolvimento




Modelos que já utilizei com PyS60:
N-Gage QD, 6600, 6681, N93, N95, N85
Prefira modelos recentes, 3rd Edition FP1 ou
superior (N95, N85, N82, N96)
Verifique a lista de compatibilidade do PyS60 para
evitar surpresas
Celulares 2nd Edition: última versão do PyS60 que
suporta é a 1.4.6
Módulos Python específicos
para Symbian
http://pys60.garage.maemo.org/doc/s60/
http://wiki.opensource.nokia.com/projects/PyS60_documentation
Módulos Python para Symbian


Relativamente fáceis de usar
Poucos tipos novos



Mesmo método pode ser sync & async


Strings “mágicas”
Protocolos “informais” via listas/tuplas/dicts
Diferença = passar callback como parâmetro
Não esquecer dos módulos padrão Python
Módulo e32



“Caixa de ferramentas” do Symbian
Não serve para muita coisa, isoladamente
Active Objects = análogo a main loop, glib

No futuro, o Qt deve preencher esta função
from e32 import *
get_capabilities()
drive_list()
ao_sleep(1)
ao_yield()
is_ui_thread()
s60_version_info
x = Ao_lock()
x.wait()
# em outro lugar
x.signal()
x = Ao_timer()
x.after(1, funcao)
x.cancel()
Módulo e32 (continuação)
import appuifw
import e32
trava = e32.Ao_lock()
def callback_sair():
print “Apertou botao”
e32.ao_sleep(1)
trava.signal() # acorda
def main():
global trava
appuifw.app.exit_key_handler = callback_sair
trava.wait() # dorme
main()
Módulo sysinfo

Informações diversas sobre o dispositivo:





sysinfo.battery()
sysinfo.imei()
sysinfo.signal_dbm()
sysinfo.signal_bars()
sysinfo.display_pixels()
Módulo appuifw

Acesso à UI, o mais complexo dos módulos S60

Quem já usou PyGTK+, vai achar familiar
appuifw.app: classe Application
appuifw.app.body: Canvas, ListBox ou Text
appuifw.app.menu

Dialogs modais






Form (widget “composto”)
Ligação de eventos/teclas a ações
No futuro, o Qt deve tomar o lugar deste módulo
Layout de uma aplicação S60
Módulo appuifw
>>> import appuifw
>>> appuifw.app.title = u"BLA"
>> def tab_cb(n):
... print "Mudou para tab", n
...
>>> appuifw.app.set_tabs([u"Um", u"Dois"],
tab_cb)
Mudou para tab 1
Mudou para tab 0
>>> appuifw.app.orientation = 'landscape'
>>> appuifw.app.screen = 'large'
Módulo appuifw
>>> def menu_cb(*algo):
...
print algo
...
>>> appuifw.app.menu = \
[(u"Item um", menu_cb),
(u"Item dois", menu_cb)]
>>> ()
>>> appuifw.selection_list([u"AAA",
u"BBB"])
1
>>> appuifw.query(u"Digite texto", u"text")
u'Inconstitucional'
Módulo appuifw
>>> appuifw.note(u"Fora Sarney",
u"error")
>>> def cb(*algo):
... print algo
...
>>> f = appuifw.Form(
[(u'Nome', 'text'),
(u'Idade', 'number')])
>>> f.save_hook = cb
>>> f.execute()
([(u'Nome', 'text', u'Boa'),
(u'Idade', 'number', 18L)],)
Módulo graphics



Classe Image e função screenshot()
Câmera gera imagens da classe Image
Image implementa API drawable

appuifw.Canvas idem
>>> i = graphics.Image.open("E:\\teste.jpg")
>>> i.ellipse((0, 0, 100, 100), fill=0xff0000)
>>> i.save("E:\\teste2.jpg")
Módulo camera


Permite manipular a(s) câmera(s)
Não funciona no emulador Symbian, mas há
extensões para suprir esta função
camera.cameras_available()
i = camera.take_photo()
i.save(u“E:\\imagem.jpg”)
canvas = appuifw.Canvas()
appuifw.app.body = canvas
canvas.blit(i)
# Image
import e32, camera, appuifw, key_codes
def finder_cb(im):
# pode manipular a imagem antes
canvas.blit(im)
camera.start_finder(finder_cb)
...
camera.stop_finder()
i = camera.take_photo(size=(640,480))
Tirar foto usando a 2a câmera
camera.take_photo(position=1)
Não há viewfinder para 2a câmera
Improvisar com take_photo()+blit() periódico
ou tentar com camera.device[1].start_finder()
# Copyright Jurgen Scheible
import e32, camera, appuifw, key_codes
def finder_cb(im):
canvas.blit(im)
def take_picture():
camera.stop_finder()
pic = camera.take_photo(size = (640,480))
w,h = canvas.size
canvas.blit(pic,target=(0, 0, w, 0.75 * w), scale = 1)
pic.save('e:\\teste.jpg')
def quit():
app_lock.signal()
canvas = appuifw.Canvas()
appuifw.app.body = canvas
camera.start_finder(finder_cb)
canvas.bind(key_codes.EKeySelect, take_picture)
appuifw.app.title = u"Camera"
appuifw.app.exit_key_handler = quit
app_lock = e32.Ao_lock()
app_lock.wait()
import e32, camera, appuifw
def finder_cb(im):
canvas.blit(im)
def status_cb(*algo):
print algo
canvas = appuifw.Canvas()
appuifw.app.body = canvas
camera.start_finder(finder_cb)
camera.start_record(“e:\\video.mpeg”, status_cb)
e32.ao_sleep(10)
camera.stop_record()
camera.stop_finder()
camera.release()
Módulos gles/glcanvas




Módulo de acesso ao OpenGL/ES
OpenGL/ES é acelerado por hardware nos
celulares Nokia N93, N95 e N82 (N97?)
Não será abordado aqui
Exemplo: script gles.py
Módulo audio

Funciona no emulador


audio.say(u”Bla”)
Classe audio.Sound


s = Sound.open(u”e:\\arquivo.wav”)
s.record()




Cumulativo, não trunca
Se durante ligação, grava ligação
s.stop()
s.play()
Módulo telephone




telephone.dial(“5551234567”)
telephone.hang_up()
Fazer e atender ligações
Gravação de áudio: vide módulo audio
Módulo sensor


API diferente em FP1 e >= FP2
3rd Edition FP1: Sensor (N95, N93)
from sensor import *
sensor_type = sensors()['RotSensor']
N95_sensor = Sensor(sensor_type['id'],
sensor_type['category'])
N95_sensor.set_event_filter(RotEventFilter())
def get_sensor_data(status):
print status
N95_sensor.connect(get_sensor_data)
Módulo sensor

>= 3rd Edition FP2 (N85, N96, N97...)
import sensor
from sensor import *
accel = RotationData() # AccelerometerXYZAxisData()
>>> accel.start_listening()
True
>>> accel.x
-2
>>> import e32
>>> x = 1000
>>> while x > 0:
... x -= 1
... print accel.x, accel.y, accel.z
... e32.ao_sleep(1)
Módulo messaging

messaging.sms_send(”99845555”, u”Oi”)

messaging.mms_send(...)

Repare na string Unicode!
Permite passar um callback para receber o
status do envio

Módulo positioning
>>> import positioning
>>> positioning.modules()
[{'available': 1, 'id': 270526860,
'name': u'Assisted GPS'},
{'available': 1, 'id': 270526858,
'name': u'Integrated GPS'},
{'available': 1, 'id': 270559509,
'name': u'Network based'}]
>>> positioning.select_module(270526860)
>>> positioning.set_requestors(
[{"type":"service", "format": "application",
"data": "test_app"}])
>>> positioning.last_position()
>>> positioning.position()
>>> # positioning.position(callback=cb)
Módulo inbox


Acesso a mensagens SMS incoming
Callback para ser notificado de novas msgs.
>>> import inbox
>>> i = inbox.Inbox()
>>> m = i.sms_messages()
>>> i.content(m[0])
U'Meet me by 7pm at motel'
>>> i.time(m[0])
1130267365.03125
>>> i.address(m[0])
U'Vulnavia Phibes'
>>> i.delete(m[0]) # SIGWIFE
Módulos contacts/e32calendar


Módulos razoavelmente complexos
Explorar com base na documentação
>>> import contacts
>>> db = contacts.open()
>>> db.find("Ana")
[<Contact #33: "Ana Bolena">]
>>> db[33].as_vcard()
'BEGIN:VCARD\r\n...END:VCARD\r\n'
>>> import e32calendar
>>> db = e32calendar.open()
>>> db.find_instances(time.time(), \
time.time() + 30*86400)
[{'id': 2, 'datetime': 1251226800.0}]
>>> >>> db[2]
<e32calendar.AppointmentEntry>
>>> db[2].content
u'Pendrive'
>>> db[2].get_repeat()
{'end': 4133905200.0, 'interval': 1, }
Módulo btsocket

Soquetes Bluetooth




Controle de access points à Internet



btsocket.socket(AF_BT || AF_INET, ...)
Testar BT no console BT pode falhar
Bug em bt_discover() (3rd Edition FP2)
AP escolhido pelo usuário ou pelo aplicativo
Sockets podem ligados a diferentes Aps
Módulo padrão socket também disponível

socket.set_default_access_point(u”Nome”)
Módulo btsocket
>>> bt_discover() # invoca UI
('00:23:12:3c:ba:a3', {u'Bluetooth-PDA-Sync': 3})
>>> bt_obex_discover()
Traceback (most recent call last):
File "<console>", line 1, in <module>
error: (13, 'Permission denied')
>>> bt_obex_discover('00:23:12:3c:ba:a3')
('00:23:12:3c:ba:a3', {u'OBEX Object Push': 10})
>>> bt_obex_send_file('00:23:12:3c:ba:a3', \
10, u"e:\\teste.jpg")
>>> s.connect(("00:23:12:3c:ba:a3", 10))
# bt_advertise_service
# bt_rfcomm_get_available_server_channel
Módulo btsocket
>>> from btsocket import *
>>> access_points()
[{'iapid': 10, 'name': u'ASP'},
{'iapid': 2, 'name': u'bandalarga.claro.com.br'},
{'iapid': 9, 'name': u'EPX'}]
>>> ap = access_point(9)
>>> set_default_access_point(ap)
>>> ap.start()
>>> ap.ip()
'192.168.141.9'
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.connect(("www.folha.com.br", 80))
>>> s.send("GET /\r\n\r\n")
9
>>> print s.recv(100)
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">...
>>> s.close()
>>> ap.stop()
btsocket X socket

btsocket = “soquetes” Symbian, limitados

Não são aceitos por select()



Não ingressam em grupos multicast etc.
socket = soquetes do OpenC



Limitação inclui soquetes BT
Mais poderosos (multicast funciona)
Única desvantagem: relação com access points
Módulo select


não “repete” notificações
não funciona para write (Symbian)
Módulo scriptext

Platform Services API: acesso neutro a
recursos do sistema (via strings)







>= 3rd FP2, abordaremos “por cima”
Application Manager, Sys Info
Calendário, Contatos
Location, Landmarks
import scriptext
Messaging
m = scriptext.load('Service.Messaging',
Sensors
'Imessaging')
msgs = m.call("GetList",
{"Type": u"Inbox"})
Media Management
for msg in msgs:
print msg['Sender']
Módulos e32db/e32dbm

e32db: mini-banco de dados do Symbian


Mesma idéia do SQLite
e32dbm: Interface DBM para e32db

anydbm é apelido de e32dbm em PyS60
>>>
>>>
>>>
>>>
import anydbm
db = anydbm.open("E:\\teste.dbm", "c")
db["a"] = "b"
db.close()
>>> db = anydbm.open("E:\\teste.dbm")
>>> db
{'a': 'b'}
Outros módulos



logs (registro de ligações e SMS)
keycapture (captura eventos teclado)
topwindow (Janela modal top-level)
Ciclo de desenvolvimento
Teste no PC
(emuladores
de API)
Edição
no PC
Impl. APIs
(pys60-compat)
Teste no
emulador
Symbian
Teste no
celular
Windows
Moroso
Emulador
imperfeito
Testando scripts PyS60 no PC

Use módulos emuladores criadas por terceiros



Muita atenção com o Unicode



PyS60-compat (UI e gráficos)
Lightblue (Bluetooth)
Saiba quais APIs demandam ou retornam strings Unicode
Tire proveito da orientação a objetos Python
Crie módulos ”emuladores” para o PC
PyS60 no emulador
Symbian



Instalar Carbide, Perl e SDK 3rd Edition
FP1 ou FP2
Instalar PyS60 para SDK, casando a
versão (FP1 ou FP2)
Cygwin é muito utilizado por
desenvolvedores Symbian profissionais
EPOC32=C:\s60\devices\S60_3rd_FP2_SDK_v1.1\epoc32
$EPOC32\winscw\c\Data\python
# scripts
$EPOC32\winscw\c\resource\python25
# módulos
PyS60-compat
Distribuindo um aplicativo PyS60


Aplicativo = um script ou uma pasta
Ensymble






Vem na distribuição PyS60
Depende do Python 2.5 (não serve 2.4 ou 2.6)
Gera e assina pacote SIS
Determina módulos Python a embarcar
Não elide necessidade de certificado $$$
Permite embutir outros SIS


...por exemplo, o runtime PyS60
facilita a distribuição de app. Python ao usuário final
Criando um pacote SIS no Windows
Criando um pacote SIS no Linux
Criando um pacote SIS no MacOSX
Instalando pacote SIS do PyS60
Criando extensões em C/C++



Implica em usar Windows e o SDK do S60
src\extras\elemlist ou elemlist.zip (curso)
Capacidades >= aplicativo que vai importá-la
(e.g. nosso “aplicativo” é o PyScriptShell)


Opção 1: usar o PyScriptShell auto-assinado
Opção 2: adquirir um certificado $$$
Links sobre PyS60

http://www.mobilenin.com/pys60/menu.htm
http://sourceforge.net/projects/pys60-compat/
https://garage.maemo.org/projects/pys60
http://pys60.garage.maemo.org/doc/s60/

http://wiki.opensource.nokia.com/projects/PyS60_applications

http://www.hiit.fi/files/fi/da/sdk2unix/
http://www.hiit.fi/files/fi/da/miso/utils/web/




Download