Bluetooth Proximity

Wpis zamieszczony o 21:47:49, 15 listopada 2007 Trackback


Posiadasz laptopa z wbudowanym interfejsem BlueTooth? Korzystasz z telefonu//palmtopa z Bluetooth? Ten artykuł może Ciebie zainteresować.

Gdy tylko zakupiłem nowego laptopa zamarzyła mi się dodatkowa funkcja wykorzystująca BlueTooth. Chciałem, aby laptop automatycznie blokował ekran gdy tylko odejdę od niego po czym logował się automatycznie gdy zasiądę przy klawiaturze. Troszkę szperania w google, troszeczkę własnej inwencji i oto jest :-). Skrypt BlueTooth Proximity:

#!/bin/bash

DEVICE="MAC"
CHECK_INTERVAL=2
THRESHOLD="-1"
PID=0
START_CMD='true'
FAR_CMD='dcop kdesktop KScreensaverIface lock'
NEAR_CMD='dcop kdesktop KScreensaverIface quit'
HCITOOL="/usr/bin/hcitool"
DEBUG="/tmp/logi"

connected=1

function msg {
    echo "$1" >> $DEBUG
}

function check_connection {
    connected=0;
    found=0

    for s in `$HCITOOL con`; do
        if [[ "$s" == "$DEVICE" ]]; then
            found=1;
        fi
    done
    if [[ $found == 1 ]]; then
        connected=1;
    else
       msg 'Attempting connection...'
        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
            msg 'Connected.'
            connected=1;
        else
            connected=0;
        fi
    fi
}

function check_xscreensaver {
    PID=`ps -C xscreensaver --no-heading | awk '{ print $1 }'`
    if [ "$PID" == "" ];  then
        $START_CMD &
    fi
}

name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";

state="near"
while /bin/true; do

    check_xscreensaver
    check_connection

    if [[ $connected -eq 1 ]]; then
        rssi=`$HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g'`

        if (( "$rssi" <= $THRESHOLD )); then
            if [[ "$state" == "near" ]]; then
                msg "*** Device \"$name\" [$DEVICE] has left proximity"
                state="far"
                echo "daleko - wlaczam screena"
                $FAR_CMD
                echo $?
            fi
        else
            if [[ "$state" == "far" ]]; then
                msg "*** Device \"$name\" [$DEVICE] is within proximity"
                state="near"
                sleep 7;
                $NEAR_CMD
                kdialog --passivepopup "Urządzenie w zasięgu Bluetooth, odblokowanie ekranu" 5
                $START_CMD &
            fi
        fi
        msg "state = $state, RSSI = $rssi, PID = $PID"

    else
        if [[ "$state" == "near" ]]; then
            msg "*** Device \"$name\" [$DEVICE] has been disconnected"
            state="far"
            $FAR_CMD > /dev/null 2>&1
        fi
    fi

    sleep $CHECK_INTERVAL
done

Oryginał znajduje się pod tym adresem, ja jednakże nieznacznie go zmodyfikowałem aby odpowiadał moim preferencjom. W konfiguracji skryptu znajdujemy następujące parametry:

  • DEVICE="MAC" - MAC zastępujemy MAC'iem naszego urządzenia
  • CHECK_INTERVAL=2 - jak często ma być sprawdzane połączenie
  • THRESHOLD="-1" - odległość, wartość dobrana eksperymentalnie
  • FAR_CMD='dcop kdesktop KScreensaverIface lock' - komenda wywołana gdy urządzenie nie jest w zasięgu
  • NEAR_CMD='dcop kdesktop KScreensaverIface quit' - analogicznie komenda wykonana przy "wejściu" w zasięg
  • DEBUG="/tmp/logi" - gdzie zrzucane będą logi

Skrypt najlepiej umieścić w /bin/btprox

# cp btprox /bin/btprox

Ostatnim krokiem jest udostępnienie użytkownikowi bez uprawnień korzystania z hcitool i l2ping.

# chmod +s /usr/bin/hcitool
# chmod +s /usr/bin/l2ping

I tyle. Odpalamy btprox i sprawdzamy działanie skryptu :-).

Podobną funkcjonalność oferuje nam bluez-utils wersji >3.0 jednak u mnie i kilku moich kolegów to po prostu nie działa. Ekran zostaje zablokowany gdy komórka całkowicie wyjdzie poza zasięg BlueTooth co może sprawdza się w gorszych chipsetach, jednak u mnie BT łapie na ponad 10 metrów przez dwie ściany...

Komentarze do “Bluetooth Proximity”


  1. Hmm na kde-apps.org było coś podobnego ;-]

    BTW, powiększ troszkę czcionkę w kodzie (<pre>), bo jest ciut za mała ;]


  2. Czcionka była 1.1em, teraz jest 100%. ;-)

    Na kde-apps.org pewnie było bo to znany ‘hack’, jednak doszedłem do wniosku że skoro tak wielu osobom nie działa natywne rozwiązanie w kbluetooth//gnome-bluetooth to trzeba przypomnieć starą metodę. Lepszą moim zdaniem…


  3. U mnie dopiero przy 150% widzę ok :-]


  4. http://browsershots.org/http://night.jogger.pl/
    Wszędzie jest ok – może coś u Ciebie? Sprawdzałem na 5 kompach :] Jak ustawiam na 150% to dostaję potwory…


  5. Po zmienieniu czcionki widać wszystko ok. U mnie chyba coś monospace jest nie ten tego ;/


  6. Pewnie monospace z Redmont miałeś :P A tak na serio to już się z tym spotkałem. Niektóre czcionki z serii ‘mono’ nie reagują zbyt dobrze na skalowanie. Odeszliśmy od tematu :-) Jak jesteś ciekaw jak to działa to poustawiaj sobie ‘konsole’ z różnymi fontami i zwiększaj//zmniejszaj ich rozmiar. Znam ‘monospace’ który reaguje tylko na 4,8,16 i 32 font-size ;-)


  7. Teraz pozostaje mi tylko owinąć adapter(mam na USB) żeby zmniejszyć zasięg :D

    UPDATE: Ok, nie zauważyłem jednej zmiennej ;)


  8. @jachacy – rssi pozwala na zmianę odległości na której blokowany jest ekran. rssi=”-1” pozwala mi blokować ekran z +-3 metrów w momencie jak BT mam jeszcze na kolejne 7-10 metrów. Sprawdź sam ;-)


  9. Niestety:
    bq. $ ./htprox
    ./htprox: 15: function: not found
    ./htprox: 17: Syntax error: „}” unexpected


  10. @jachacy – jakieś dziwne sh masz.. :P U mnie wskazuje na bash. Zmień początek:

    #!/bin/sh na: #!/bin/bash

    Powinno pójść. Już edytuje wpis.


  11. Package: bluemon

    Description: Activate or deactivate programs based on Bluetooth link quality BlueMon monitors the quality of the link to a Bluetooth device and can start or stop programs when the threshold drops below a certain value. This can be used to perform actions like locking the terminal when you walk away from it. . Bluemon uses the DBus system bus to alert other applications to the presence of Bluetooth devices. A user binary can then start or stop programs when such signals are received.


  12. Teraz działa :)


  13. Bardzo mi się to podoba. Komórka, jako klucz do komputera :D Rozwiązanie jest na tyle efektowne i praktyczne, że aż chce się mieć komórkę z BT.


  14. Jak to się ma do możliwości podsłuchania jakie są maki w okolicy i udawania jakimś urządzeniem wszystkich znalezionych?


  15. Zapewne zmiana MACa nie jest trudna przy lepiej konfigurowalnym urządzeniu. Niemniej jednak, taka prosta autoryzacja to całkiem wygodne i oryginalne rozwiązanie ;] I może być częścią bardziej skomplikowanego systemu.


  16. Czyli to nie jest problem dla porządnego smartfona… dzięki, mam kolejny powód do kupienia openmoko.


  17. Sprytne. Nigdy nawet bym nie pomyślał o takim zastosowaniu. Ciekawe co będzie dalej.


  18. @Cezary – spójrz na koniec wpisu. Stoi jak byk że rozwiązania które przyniósł za sobą bluetooth-utils w wersjach ponad 3.0 nie działają. No chyba że chcesz mieć blokowanie ekranu po odejściu na 10 metrów. I nie tylko mi to nie działa.

    @Liori – ma to się nijak… Można podszywać się pod inny MAC niestety. Można to jednak sprytnie obejść. Wysłanie do telefonu sygnału//powiadomienia o wejściu w zasięg + info „czy połączyć z zasobem”. Wtedy tylko sparowane urządzenia mogą odblokować ekran. Jednak taka prosta „autoryzacja” wystarcza. Nie odchodzi się od laptopa na dłużej niż kilka minut zazwyczaj – na dłuzsze wypady zabiera się sprzęt ze sobą :)

    @Seban – dalej? :) Mam kilka fajnych zastosowań BT w ‘szkicach” na joggerze :] Jak dojrzeją to się zamieści :)


  19. No to pilnuj swojego laptopa jak wpadnę do 1.10 ;-)

    A na serio, IMHO wersja bez automatycznego odblokowywania ekranu po pojawieniu się urządzenia w zasięgu miałaby sens. W przeciwnym wypadku to zbyt proste do złamania…


  20. Najpierw ktoś musi poznać MAC’a Twojego urządzenia. Ustawiasz w dobrej klasy telefonie „Make device not discoberable”, czyli dokładniej „nie pozwalaj na parowanie jeśli nie sparowane” i koniec. Nikt MAC’a nie podejrzy. Tyle – rozwiązanie zaprezentowane nie jest żadnym ‘proof of concept’ – to po prostu działa. I to dobrze. Jak wiesz najsłabszym ogniwem w zabezpieczeniach jest człowiek, nie maszyna. Algorytm + pomysł jest dobry. Nie mogę odpowiadać za umiejętności człowieka do bezpiecznego skonfigurowania telefonu.


  21. Eee… w takim razie jak twoja maszyna rozpozna urządzenie, jeśli komórka nie będzie wysyłała maca?


  22. @Liori – przecież już będzie sparowana, więc maszyna będzie znała MAC. Discoverable czyli będzie niepodatna na skanowanie otoczenia. W SonyEricssonach opcja nazywa się „Ukryj Telefon”. Jak się ją włączy to btprox dalej działa ale komórki nie wykryjesz niczym. Tylko sparowane z nią urządzenia będą mogły się dalej łączyć. Poczytaj o BlueTooth.


  23. Ok, chyba już rozumiem. Czekam na wersję skryptu z parowaniem.


  24. @Liori – skrypt jest taki sam. Dokładnie taki sam. Poczytaj o parowaniu i BlueTooth to zrozumiesz mechanizm działania. Ustawienia telefonu tu się liczą.


  25. Czy zamiast while true -> sleep nie lepiej by było wrzucić do crona?

    Poza tym to zaraz będę testował, ale fajnie za zaje* pomysł – i za implementację też :)


  26. @MySZ – cron niech lepiej się takimi rzeczami nie zajmuje. Sam btprox powinien udawać demona, który działa cały czas. Cron wywołujący co sekundę skrypt sprawdzający? To by za bardzo obciążyło laptopa.. while true jest o wiele efektywniejsze. Oczywiście – można było napisać program jako typowego demona odpalanego przez /etc/init.d/, jednak nie opłaca się armatą zabijać muchy :)

    Dla przykładu mam u siebie w prawym dolnym rogu paska KDE 2 ikonki – jedna włącza skrypt, druga wyłącza. Gdy potrzebuję btprox’a – 1 kliknięcie i działa. A nie zawsze go potrzebuję, więc nie zawsze on działa. Easy :-)

    Zapomniałem dodać – jeśli ktoś ma GNOME’a skrypt będzie się troszkę różnić. Jeśli ktoś chce mogę zamieścić wersję dla tego środowiska graficznego :-).


  27. @night: to nie takie proste – cron działa chba na każdym linuksowym kompie, czyli korzystając z niego (w końcu do tego jest przeznaczony – do cyklicznego uruchamiania programów) wyrzucamy jednego while-a/demona z systemu. Włączać i wyłączać można bardzo prosto – sprawdzanie pliku pid – na początku skryptu: [ -f /tmp/btprox.lock ] || exit

    A wersję do gnome sobie zrobiłem, też mogę udostępnić (kilka drobnych zmian, chyba 3 linijki…). Jeśli możesz, wytłumacz mi tylko proszę co dokładnie wyświetla kdialog —passivepopup? Bo ja w swojej przeróbce użyłem zenity —notification :)


  28. @Marcin – no rzeczywiście, przekonałeś mnie że cron też sobie z tym cudactwem poradzi :-). Cóż – jak zawsze w linuksie istnieje kilka różnych dróg, ja tylko zaproponowałem jedną z nich. A prawda jest taka że dla takiego małego i nie obciążającego skryptu nie robi wielkiej różnicy czy użyjemy cron czy while true. W większym projekcie nie zastosowałbym takiego 31337 hacku, tutaj jednak można sobie na to pozwolić :P

    Rzeczywiście modyfikacja dla GNOME’a to 2-3 linijki. FAR_CMD, NEAR_CMD i ten kdialog. A cóż on robi. Wyświetla w lewym górnym rogu popupa wyglądającego jak „dymek” z komiksów z wybranym napisem :-) Dymek chwilę wisi i znika, automatycznie.


  29. ->night: Zgadza się, jest kilka dróg, ale ja mam zboczenie zawodowe: ma być lepiej, szybciej, lżej… :P a przynajmniej trzeba o tym podyskutować ;)
    ad. włączanie z crona – można zamiast sprawdzania w skrypcie, robić to już w cronie: [-f /tmp/btprox.lock ] && btprox czy jakoś podobnie :)
    ad. kdialog – czyli dobrze zgadłem, najbliższym tego odpowiednikiem w zenity jest właśnie notification ;)

    Jeszcze raz dzięki za sam skrypt, może się przydać :)


  30. Tak sobie myślę, co dalej. Teraz telefon, a za kilka lat w jaki sposób rozpozna nas nasz komputer?
    Ciekawe czy da rade/czy jest coś takiego. Takie mini BT (albo coś innego co można wykoszytać jako klucz) co można zawiesić na szyji przy smyczy, albo nosić na ręce, zasilane mała bateryjką.


  31. @Seban: RFID?


  32. RFID – to samo miałem pisać :-) O! I to jest pomysł na kolejny wpis :]


  33. Z całym szacunkiem – dlaczego suid? Używaj sudo, suid to bardzo złe rozwiązanie i tak naprawdę można policzyć na palcach rąk, gdzie jest rzeczywiście konieczny.


  34. @alchemyx – mam 3 kompy. Na żadnym nie mam zainstalowanego ‘sudo’. Nie jestem fanem tego rozwiązania i nie używam go. Co więcej – zdarza mi się odpalać X’y na roocie i normalnie tak pracować. Nie widzę w tym nic złego ;) Jak komuś nie pasuje można zmienić. l2ping i hcitool nie są jakimiś tam krytycznymi programami i można im dać suida imho :)


  35. Zmienie tego na sudo zajmie jakieś 2 minuty łącznie z odpowiednią linią w sudoers. Po prostu nie powinno się dawać niektórych uprawnień, które są zbędne. Teraz każdy będzie mógł manipulować Twoim bluetoothem jeśli ma tylko konto na serwerze :).


  36. Tylko po co wylogowywanie ekranu (KDE/GNOME) na serwerze? :)))) To rozwiązanie dla laptopów gdzie nikt oprócz mnie konta nie ma (i mieć nie będzie) :). Na serwer bym czegoś takiego w życiu nie wrzucił!

    Jeśli już rozmawiamy o bezpieczeństwie – masz 100% rację. Z suid trzeba bardzo uważać. Nie boję się jednak go używać wiedząc, że mam system ‘single-user’.


  37. Ktos poda ustawienia dla GNOME ????


  38. Dla Gnome. Zamień odpowiednie wiersze:

    START_CMD='/usr/bin/xscreensaver -nosplash'
    FAR_CMD='/usr/bin/xscreensaver-command -activate'
    NEAR_CMD='/bin/killall xscreensaver'

    Skasuj linijkę:
    kdialog --passivepopup (...)


  39. poprawcie mnie, jezeli sie myle ale proponowany suid na l2ping wydaje sie niepotrzebny, bo l2ping nie jest uzywany w kodzie.. Przerobilem (i skrocilem) troche skrypt, bo u mnie zdarzalo sie, ze ekran samoczynnie sie blokowal, pomimo ze bylem w zasiegu.. jakas niezidentyfikowana chwilowa przerwa w komunikacji. Ponizszy skrypt po nieudanym polaczeniu czeka $DOUBLE_CHECK_BEFORE_LOCK_INTERVAL sekund i probuje ponownie, dopiero po dwoch nieudanych probach - blokuje ekran. Dodatkowo przed kazdym sprawdzeniem RSSI obowiazkowo nawiazuje polaczenie, gdyz u mnie (nie wiem dlaczego, mozliwe ze tak powinno byc) zrywa polaczenie po kilku sekundach.

    #!/bin/bash

    DEVICE="MAC" #wstawic mac adres urzadzenia
    CHECK_INTERVAL=3
    THRESHOLD="-1"
    FAR_CMD='/usr/bin/gnome-screensaver-command -a'
    NEAR_CMD='/usr/bin/gnome-screensaver-command -d'
    HCITOOL="/usr/bin/hcitool"
    DOUBLE_CHECK_BEFORE_LOCK_INTERVAL=1


    ZABLOKOWANY=0
    while /bin/true; do

    if [[ $ZABLOKOWANY == 1 ]]; then
    [ "`$HCITOOL cc $DEVICE; $HCITOOL rssi $DEVICE | cut -d\ -f4`" -gt $THRESHOLD ] &&
    $NEAR_CMD &&
    ZABLOKOWANY=0
    else
    [ "`$HCITOOL cc $DEVICE; $HCITOOL rssi $DEVICE | cut -d\ -f4`" -le $THRESHOLD ] &&
    sleep $DOUBLE_CHECK_BEFORE_LOCK_INTERVAL &&
    [ "`$HCITOOL cc $DEVICE 2>/dev/null; $HCITOOL rssi $DEVICE 2>/dev/null | cut -d\ -f4`" -le $THRESHOLD ] &&
    $FAR_CMD &&
    ZABLOKOWANY=1
    fi

    sleep $CHECK_INTERVAL
    done


  40. ponizej sformatowany poprawnie kod, wyzej wycielo spacje gdzie nie trzeba..

    <code>
    #!/bin/bash

    DEVICE="MAC" #wstawic mac adres urzadzenia
    CHECK_INTERVAL=3
    THRESHOLD="-1"
    FAR_CMD='/usr/bin/gnome-screensaver-command -a'
    NEAR_CMD='/usr/bin/gnome-screensaver-command -d'
    HCITOOL="/usr/bin/hcitool"
    DOUBLE_CHECK_BEFORE_LOCK_INTERVAL=1


    ZABLOKOWANY=0
    while /bin/true; do

    if [[ $ZABLOKOWANY == 1 ]]; then
    [ "`$HCITOOL cc $DEVICE; $HCITOOL rssi $DEVICE | cut -d\ -f4`" -gt $THRESHOLD ] &&
    $NEAR_CMD &&
    ZABLOKOWANY=0
    else
    [ "`$HCITOOL cc $DEVICE; $HCITOOL rssi $DEVICE | cut -d\ -f4`" -le $THRESHOLD ] &&
    sleep $DOUBLE_CHECK_BEFORE_LOCK_INTERVAL &&
    [ "`$HCITOOL cc $DEVICE 2>/dev/null; $HCITOOL rssi $DEVICE 2>/dev/null | cut -d\ -f4`" -le $THRESHOLD ] &&
    $FAR_CMD &&
    ZABLOKOWANY=1
    fi

    sleep $CHECK_INTERVAL
    done
    </code>


  41. nie potrafie tego zrobic ;/ zignorujcie mnie..


  42. @redloff - rzeczywiście tnie składnię. Skontaktuj się ze mną na Jabbera to dodam Twoją implementację do wpisu + jakieś creditsy :-)

Dodaj komentarz

Textile jest włączony. Zobacz składnię (wiki.jogger.pl)

code