26
May
Pardus 2011'de cep telefonuna Bluetooth üzerinden bağlanıp kısa mesaj göndermek, İnternet'e bağlanmak gibi işlemleri sadece konsol kullanarak yapmak istiyordum. Bugün biraz araştırma ve uğraşma sonucunda bunları başardım.

Aşağıdaki komutların tamamını root yetkisiyle vermek gerekiyor. Önce gerekli araçları kuralım:
pisi it python-gtk bluez -y
Bağlantı kurmak için kullanacağımız Bluetooth arayüzünün ismini öğrenelim:
hciconfig
Bu komut şöyle bir liste verecektir:
hci0: Type: BR/EDR Bus: USB
BD Address: 00:24:D2:C8:F4:A7 ACL MTU: 1021:6 SCO MTU: 64:1
UP RUNNING PSCAN ISCAN

RX bytes:43710 acl:224 sco:0 events:815 errors:0
TX bytes:8544 acl:233 sco:0 commands:176 errors:0
Buradan bilgisayarımızda bir tane Bluetooth arayüzünün bulunduğunu ve isminin hci0 olduğunu anlıyoruz. Bluetooth arayüzünü görünür ve bağlanılabilir duruma geçirmek için şu komutu veriyoruz:
hciconfig hci0 piscan
 Şimdi şu komutu verip telefonun bağlanmasını bekler konuma geçiyoruz:
simple-agent
Telefondan Bluetooth aygıtlarını aratıp bilgisayarımızı buluyoruz ve eşleştirme için seçiyoruz. Seçtikten sonra 0000 gibi kendi seçtiğimiz herhangi bir pin kodu giriyoruz. Telefona pin kodu girdikten sonra simple-agent bunu soracaktır. Ona da aynı pini giriyoruz. Telefon eşleşmeyi onaylayacaktır. İsterseniz bu adımdan sonra telefonun ayarlarından bilgisayara tam yetki vererek iki de bir bağlantıyı onaylamak derdinden kurtulabilirsiniz. Artık simple-agent'tan çıkmak için ctrl+c'ye basabiliriz. Şimdi modem arayüzünün nerede olduğunu öğrenelim:
hcitool scan
Bu komut aşağıdaki gibi bir liste verecektir:

Scanning ...
        00:1C:D4:84:BD:77       jnmbk-n73
Bu listeden bağlanacağımız telefonun MAC adresini (00:1C:D4:84:BD:77) kullanarak bunun hangi kanalda modem hizmeti verdiğini öğreniyoruz:
sdptool browse 00:1C:D4:84:BD:77|grep Dial -C5
Bu komut aşağıdaki gibi bir çıktı verecektir:
Service Name: Dial-Up Networking
Service RecHandle: 0x1000b
Service Class ID List:
  "Dialup Networking" (0x1103)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 2
Language Base Attr List:
  code_ISO639: 0x454e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100
Bu çıktıda bizi ilgilendiren tek şey Channel: 2 olan satırdır. Buradan modem servisinin 2 numaralı kanalda olduğunu öğreniyoruz. Öğrendiğimiz bilgileri kullanarak /etc/bluetooth/rfcomm.conf dosyasını aşağıdaki gibi düzenliyoruz:

rfcomm0 {
    bind yes;
    device 00:1C:D4:84:BD:77;
    channel 2;
    comment "jnmbk-N73";
}
Dosyayı kaydettikten sonra şu komutla modem aygıtını oluşturuyoruz:
rfcomm bind rfcomm0 
Artık /dev/rfcomm0 aygıtını dial-up modem gibi kullanabiliriz. Telefonunuz bilgisayarın Bluetooth alanı (çoğu zaman 10 metre) içinde bulunduğu sürece bağlantınız kopmayacaktır. Telefon uzaklaşıp tekrar yakınlaşırsa da modem aygıtı ek işlem yapmadan tekrar çalışır hale gelecektir. Son komutu /etc/conf.d/local.start dosyasına ekleyerek açılışta modem aygıtının otomatik oluşturulmasını sağlayabilirsiniz.
18
Eki

Nesne tabanlı programlamadan sonra bir başka merak ettiğim konu ise: Konsol tabanlı bir program yaptığımda ona verdiğim komutları, hep uzun uzun yazmam gerekiyordu. Mesela bir oyun yaptınız. Konsoldaki haritanızda ileri,geri,sağ ve sola gitmesi için durmadan “ileri,geri …” yazmanız gerekiyor.

Fakat artık direk “WASD” tuşları olsun klavyedeki her tuşla programa komutlar gönderebileceksiniz. Yapmanız gereken “tty” modülünü kullanmak fakat bu modül çok ilginç ki, programı kapattıktan sonra bile sizin klavye komutlarınızı alıyor.  Bunun yerine hem Linux, hem Windows, hem de Macintosh’larda çalışacak bir yöntem ve sadece “tty” modülüyle değil de başka modülleri de kullanmalı. Çünkü tty modülü sadece Linux’da çalışıyor ve stabil değil.

Küçük bir google araması yaptığınızda karşınıza şöyle bir site geliyor. (Macintosh desteğini denemediğim için örneklere yazmayacağım ama o siteden Macintosh desteğine bakabilirsiniz.)

İlk önce tane .py dosyası oluşturun ve onun içine şunları yazın.

# -*- coding: utf-8 -*-
class _Getch(object):
    """Gets a single character from standard input.
       Does not echo to the screen."""
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()
 
    def __call__(self):
        return self.impl()
 
class _GetchUnix(object):
    def __init__(self):
        import tty, sys
 
    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
 
class _GetchWindows(object):
    def __init__(self):
        import msvcrt
 
    def __call__(self):
        import msvcrt
        return msvcrt.getch()
 
getch = _Getch()

Bunu sonra ana programınıza “form dosyanız import *” şeklinde ekleyin. Sonra kullanırken:

from alici import *
while True:
    karakter = getch().upper()
    print "Tıklanan tuş: %s"  % karakter

şeklinde yazabilirsiniz. Burada “getch().upper()” yazarken “upper()” yazmamızdaki mantık, gelen karakterin büyük ya da küçük problemi yaşamamak için hepsini büyük yapıp öyle işlemektir.  Bu yazdığınız “.getch()” bu haliyle Linux’da ve Windows’da çalışabilir.

Ayrıca bu olay PyGame gibi başka kütüphanelerle yapılabilir fakat eğer tamamen konsol tabanlı bir programda bunu istiyorsanız tek çözüm bu.

Not: Son örnekteki döngüden kurtulamazsanız kurtarıcınız “CTRL-C” olsun.