Bot SMS pod Linuksem

Ostatnio w firmie pojawił się temat stworzenia SMS bota. Zacząłem więc szukać rozwiązań. Jeden z pomysłów, to postawienienie komputera z Linuksem na pokładzie, podłączenie do niego telefonu z ofertą, w której jest miliard darmowych SMS-ów i uruchomienie czegoś magicznego, co zajmie się odbieraniem i wysyłaniem wiadomości. I to magiczne coś właśnie zamierzam opisać.

Rozwiązanie które można zastosować, okazało się prostsze niż myślałem. Można użyć do tego świetnego programu, który jest dostępny zarówno pod Linuksem jak i Windowsem - mowa o Gammu. Jest to program, który komunikuje się z telefonem, lub modemem i służy do różnego rodzaju cznności, takich jak odbieranie/wysyłanie SMS-ów, zarządzanie kontaktami, zadaniami, kalenarzem itp. Ja oczywiście skupię się na odbieraniu i wysyłaniu SMS-ów.

Tak więc do komunikacji użytkownika z botem posłużę się Gammu - to już ustaliliśmy. Żeby było ciekawiej, Gammu posiada demona do wysyłania i odbierania SMS-ów - gammu-smsd. Jako backend do przechowywania danych można użyć zwykłych plików lub bazy danych (obsługiwany jest MySQL, PostgreSQL i SQLite). Pliki odradzam, bo to nieco ogranicza funkcjonalność - przykładowo nie jest możliwe wysyłanie wiadomości przy użyciu polecenia gammu-smsd-inject lub nie można przekazać żadnego id wiadomości do skryptu, który można uruchomić po otrzymaniu wiadomości (o tym w dalszej części). Lepiej zatem skorzystać z bazy danych. Ja wybrałem PostgreSQL.

Konfiguracja Gammu oraz SMSD

Najpierw trzeba zacząć od komunikacji Gammu z telefonem. Mój telefon to Sony Ericsson k800i. Pomijam fakt, że trzeba podłączyć telefon do komputera przez kabel USB ;) Poniżej zamieszczam źródła plików konfiguracyjnych:

~/.gammurc

[gammu] 
port = /dev/ttyACM0 
model = 
connection = at19200 
synchronizetime = no 
logfile = 
logformat = errorsdate 
use_locking = 
gammuloc =

/etc/gammu_smsdrc

[gammu] 
port = /dev/ttyACM0 
model = 
connection = at19200 
synchronizetime = no 
logfile = 
logformat = errorsdate 
use_locking = 
gammuloc = 

[smsd] 
Service = pgsql 
LogFile = syslog 
DebugLevel = 255 
DeliveryReport = log 
RunOnReceive = /home/jaro/bin/sms_trigger.py 
User = uzytkownik_bazy 
Password = haslo_bazy 
PC = localhost 
Database = gammu

Poprawność konfiguracji połączenia z telefonem można sprawdzić przez polecenie gammu identify. U mnie wyjście wyglądało tak:

# gammu identify 
Manufacturer : Sony Ericsson 
Model : K800i (AAD-3022031-BV) 
Firmware : R8BF003 080130 2133 CXC1250212_ORANGE_WI 
IMEI : WOLE_NIE_POKAZYWAĆ 
Kod produktu : AAD-3022031-BV 
SIM IMSI : WOLE_NIE_POKAZYWAĆ

Przed uruchomieniem demona smsd, trzeba utworzyć odpowiednie tabele w bazie danych. W dokumentacji znajduje się przykładowy plik ze skryptem SQL, który tworzy te tabele. U mnie znajduje się on w lokalizacji: /usr/share/doc/gammu/examples/sql/pgsql.sql Wystarczy uruchomić skrypt i voila!

Skrypt (bot)

W pliku gammu_smsdrc jest opcja RunOnReceive, która, jak się można domyślić, wskazuje skrypt uruchamiany po odebraniu wiadomości. Skrypt jest uruchamiany z parametrem, który zawiera id wiersza w bazie danych w tabeli inbox. Wiersz zawiera dane przesłanej wiadomości. Napisałem w Pythonie przykładowy skrypt, który odczytuje odebraną wiadomość, sprawdza jaki tekst wysłano i na jego podstawie wysyła odpowiedź.

#!/usr/bin/python

import psycopg2 as db, sys, os

db_user = 'nazwa_uzytkownika'
db_password = 'haslo_do_bazy'
db_host = 'localhost'
db_name = 'gammu'


def main(argv=None):
        try:
                sms_id = sys.argv[1]
        except IndexError:
                print 'Za malo parametrow'
                sys.exit()
        
        try:
                conn = db.connect("dbname=%s user=%s password=%s host=%s" % (db_name, db_user, db_password, db_host))
        except:
                print 'Blad podczas polaczenia z baza'
                
        if not sms_id.isdigit():
                print 'Niepoprawny parametr'
                sys.exit()
        
        cur = conn.cursor()
        cur.execute("SELECT * FROM inbox WHERE id=%s" % sms_id)
        
        row = cur.fetchone()
        
        if not row:
                print 'Nie znaleziono wiadomosci sms o podanym id'
                sys.exit()
                
                
        rcp_num = row[3]
        command = row[8].strip().lower()
        
        if command == 'jezyk':
                response = "Python"
        elif command == 'system':
                response = "Linux"
        else:
                response = "Nieznana komenda"
        
        
        os.system("gammu-smsd-inject TEXT %s -text '%s'" % (rcp_num, response)) 
        


if __name__ == '__main__':
        main()
        

Finał - uruchomienie demona

Wreszcie przechodzimy do puenty - uruchomienia demona. Wystarczy krótkie:

gammu-smsd --daemon

I w ten oto sposób, telefon jest gotowy do odbierania i wysyłania wiadomości.

Komentarze

  1. xyz
    20 listopada 2009 | #

    Jeśli chcesz robić coś sensowniejszego niż prowizorki to zapoznaj się z http://www.kannel.org/

  2. 20 listopada 2009 | #

    Nieźle, tylko napisz jeszcze która sieć i w jakiej taryfie ma dość dużą, darmową ilość smsów :)

  3. 20 listopada 2009 | #

    Problem w tym, że taki telefon potrafi wysłać/odebrać koło 20 SMS-ów na minutę. To troszkę mało, żeby zastosować to do czegoś innego niż zabawa. Wysyłka 10000 SMS-ów taką metodą będzie trwała 8h. Na dodatek ten "miliard darmowych SMS-ów" jest najczęściej tylko do jednej sieci.

  4. 20 listopada 2009 | #

    Polecam play. Doładowujesz za 5 zł masz 500 smsów w ciągu 5 dni do wszystkich sieci. Taniej nie znajdziesz i nie do wszystkich sieci...

  5. Play Fresh
    20 listopada 2009 | #

    Play już ukróciło swoją ofertę. Jak doładowuje za 50 zł to dostaje 2000 SMSów do wszystkich (wcześniej było 5k), niemniej jednak wciąż to pozostaje najlepsza opcja, ew. dogadanie się z jamiś operatorem.

  6. 21 listopada 2009 | #

    Tego typu rozwiązania przydają się do alarmowania nas o różnych zdarzeniach w systemie: http://thecamels.org/2009/09/13/powiadomienia-smsowe-o-statusie-serwera/

  7. 22 listopada 2009 | #

    @Grzegorz: Tak to prawda, po prostu lepiłem z tego co miałem. Zamiast telefonu lepiej użyć modemu, z którym Gammu też się komunikuje i tym samym przepustowość się zwiększa.

    Nie napisałem jeszcze jednej istotnej rzeczy, a mianowicie grupa odbiorców komunikacji przez SMS-a, jest stosunkowo niewielka. Spodziewana liczba wysłanych wiadomości w ciągu miesiąca, to może około 100.

    Po przemyśleniu sprawy doszedłem do wniosku, że lepiej oprzeć to o gotowe i bardziej stabilne rozwiązania oferowane przez firmy wyspecjalizowane w temacie. Oprócz kombinowania i dogadywania się z operatorem na korzystną liczbę SMS-ów do wszystkich sieci, pojawiają się niuanse związane z energią elektryczną, a właściwie z jej tymczasowym zanikiem, czy ze stabilnością połączenia z internetem.

Napisz komentarz