Целью статьи является демонстрация возможностей Python for s60 для работы с смс сообщениями и базами данных. Чтобы было интересней, разберем на реальном примере, создадим приложение, которое будет читать новые сообщения смартфона, парсить их, сохранять в свою базу данных номера телефонов с логинами и паролями, и постить твиты, пришедшие с этих номеров.
Для чего это еще может пригодиться? В наше время смс сервисы используются достаточно широко. Способов их реализации достаточно много. У меня недавно возникла необходимость реализовать сервис, при котором клиенты могли бы посылать смс сообщением номер заказа и в ответ приходил бы его статус. Задача решилась так: за 500 руб., на барахолке был куплен старенький Nokia 7610 в разваливающемся состоянии, у которого не работала половина кнопок, были проблемы со звуком и т. д. Туда была вставлена сим карта от местного оператора с безлимитным смс пакетом. Теперь этот аппарат будет играть роль сервера, который будет работать в режиме 24/7, с бесперебойным источником питания (аккамулятор), и не будет знать проблем с охлаждением :)
Тут все просто. Есть модуль inbox, которые позволяет нам работать с сообщениями в нашем телефоне. У этого модуля одноименный класс Inbox, которые позволяет прочесть сообщение, отправителя и время. У каждого сообщения есть свой ID. Список ID всех сообщений можно получить функцией sms_messages(). Но нам более интересна функция bind, которой мы указываем функцию, которая будет вызываться сразу же, как только нам поступит новое сообщение.
Выглядеть это будет вот так:
Хотелось бы упомянуть об особенности адреса в сообщении. Если нам пришло сообщение, номер отправителя которого есть в записной книжке телефона, то в address нам вернет имя, а не номер. Если же абонента и записной книжке нет, то мы получим строку с номером.
Через python есть возможность работать с нативной базой данных symbian — dbms, которая представляет собой реляционную базу данных, и поддерживает sql синтаксис. Мне доводилось работать 600-800 тысячами записей на относительно старом смартфоне nokia 3230, который достатоно неплохо справлялся с таким объемом данных.
Есть 2 модуля для работы с базами данных e32db, который работает непосредственно с базой данных и e32dbm, который является надстройкой над e32db и реализует интерфейс базы данных ключ-значение. Не смотря на то, что в данном случае мы будем использовать e32dbm, я хотел бы показать, как работать с e32db. Те, кто пишет на питоне, наверняка привыкли к DB API 2, поэтому принципы работы с этой базой покажутся немного странными.
У e32db есть 2 класса. Один для записи в базу, другой для чтения.
Создание базы данных, создание таблиц и их наполнение выглядит так:
Не забываете, что путь к базе и запросы должны быть в юникоде.
С чтение из базы данных немного посложнее.
Для работы приложения, нам хватит e32dbm, работать с которой проще простого:
Возьмем за основу наш код, который получает смс сообщения. Добавим в начало следующие строки:
Осталось написать функцию, которая будет парсить сообщения. Для того, чтобы абонент мог работать с этим гейтом, его номер нужно ассоциировать с аккаунтом на твиттере. Давайте не будем перебирать все возможные варианты авторизации и спорить о безопасности, а просто введем две команды: add login password и delete. Первая команда, посланная на телефон будет добавлять в базу данных логин и пароль, ассоциированные с номером телефона, а вторая удалять. Соответственно, после такой авторизации, пользователь сможет просто писать на номер гейта смс, которые будут уходить на твиттер.
и в функцию incoming_callback добавляем строчку:
И осталось реализовать добавление твита, как мы это делали в этом топике.
Теперь наш гейт готов. По желанию, его можно упаковать в sis и подпилить напильником в плане обработки ошибок.
Исходики, берем здесь, а готовый sis здесь
Свежих вам идей!
Для чего это еще может пригодиться? В наше время смс сервисы используются достаточно широко. Способов их реализации достаточно много. У меня недавно возникла необходимость реализовать сервис, при котором клиенты могли бы посылать смс сообщением номер заказа и в ответ приходил бы его статус. Задача решилась так: за 500 руб., на барахолке был куплен старенький Nokia 7610 в разваливающемся состоянии, у которого не работала половина кнопок, были проблемы со звуком и т. д. Туда была вставлена сим карта от местного оператора с безлимитным смс пакетом. Теперь этот аппарат будет играть роль сервера, который будет работать в режиме 24/7, с бесперебойным источником питания (аккамулятор), и не будет знать проблем с охлаждением :)
Работа с смс сообщениями
Тут все просто. Есть модуль inbox, которые позволяет нам работать с сообщениями в нашем телефоне. У этого модуля одноименный класс Inbox, которые позволяет прочесть сообщение, отправителя и время. У каждого сообщения есть свой ID. Список ID всех сообщений можно получить функцией sms_messages(). Но нам более интересна функция bind, которой мы указываем функцию, которая будет вызываться сразу же, как только нам поступит новое сообщение.
Выглядеть это будет вот так:
- #coding:utf-8
- import e32
- from appuifw import app
- import inbox
- class Main:
- def incoming_callback(self,id):
- print 'incoming message'
- # делаем небольшую паузу, чтоб не было конфликтов
- # с приложением "Сообщения"
- e32.ao_sleep(1)
- # создаем новый экземпляр класса Inbox, так как в старом
- # не будут видны вновь поступившие сообщения
- messages=inbox.Inbox()
- # получаем содержание сообщения и адрес, откуда оно пришло
- print messages.content(id)
- print messages.address(id)
- # и удаляем его, чтоб оно нам не мешалось
- messages.delete(id)
- def __init__(self):
- # создаем экземпляр класса inbox и биндим к входящим функцию
- self.inb=inbox.Inbox()
- self.inb.bind(self.incoming_callback)
- print 'Start'
- lock=e32.Ao_lock()
- app.exit_key_handler=lock.signal
- a=Main()
- lock.wait()
Хотелось бы упомянуть об особенности адреса в сообщении. Если нам пришло сообщение, номер отправителя которого есть в записной книжке телефона, то в address нам вернет имя, а не номер. Если же абонента и записной книжке нет, то мы получим строку с номером.
Работа с базой данных
Через python есть возможность работать с нативной базой данных symbian — dbms, которая представляет собой реляционную базу данных, и поддерживает sql синтаксис. Мне доводилось работать 600-800 тысячами записей на относительно старом смартфоне nokia 3230, который достатоно неплохо справлялся с таким объемом данных.
Есть 2 модуля для работы с базами данных e32db, который работает непосредственно с базой данных и e32dbm, который является надстройкой над e32db и реализует интерфейс базы данных ключ-значение. Не смотря на то, что в данном случае мы будем использовать e32dbm, я хотел бы показать, как работать с e32db. Те, кто пишет на питоне, наверняка привыкли к DB API 2, поэтому принципы работы с этой базой покажутся немного странными.
У e32db есть 2 класса. Один для записи в базу, другой для чтения.
Создание базы данных, создание таблиц и их наполнение выглядит так:
- import e32db
- db_path=u'e:\\data\\python\\test.db'
- db=e32db.Dbms()
- db.create(db_path)
- db.open(db_path)
- db.execute(u'CREATE TABLE users (number CHAR(12), login LONG VARCHAR, password LONG VARCHAR)')
- db.execute(u"""INSERT INTO users VALUES('+79xxxxxxxxx','kAIST','password')""")
Не забываете, что путь к базе и запросы должны быть в юникоде.
С чтение из базы данных немного посложнее.
- db_view=e32db.Db_view()
- # делаем запрос, указывая уже открытую базу данных
- db_view.prepare(db,u'SELECT * from users')
- # проходимся по всем строкам
- for x in xrange(db_view.count_line()):
- # подготавлием новую строку к выдаче
- db_view.get_line()
- # и смотрим, что у нас в колонках
- # странно, но нумерация начиниается с 1 а не с 0
- print db_view.col(1),db_view.col(2)
- # переходим на следующую строку
- db_view.next_line()
Для работы приложения, нам хватит e32dbm, работать с которой проще простого:
- import e32dbm
- db=e32dbm.open(u'e:\\data\\python\\test','c')
- db['first']='hello'
- db['second']='second key'
- db.sync()
- db.close()
Перейдем непосредственно к нашей задаче
Возьмем за основу наш код, который получает смс сообщения. Добавим в начало следующие строки:
- import e32dbm
- db=e32dbm.open(u'e:\\mydb','c')
Осталось написать функцию, которая будет парсить сообщения. Для того, чтобы абонент мог работать с этим гейтом, его номер нужно ассоциировать с аккаунтом на твиттере. Давайте не будем перебирать все возможные варианты авторизации и спорить о безопасности, а просто введем две команды: add login password и delete. Первая команда, посланная на телефон будет добавлять в базу данных логин и пароль, ассоциированные с номером телефона, а вторая удалять. Соответственно, после такой авторизации, пользователь сможет просто писать на номер гейта смс, которые будут уходить на твиттер.
- def parse(self,content,address):
- if content.startswith('add'):
- print 'Add:',address
- db[address]=repr(content.split()[1:3])
- db.sync()
- elif content.startswith('delete'):
- if address in db.keys():
- print 'Delete:',adress
- del db[address]
- db.sync()
- else:
- if address in db.keys():
- print 'Send:',address
- self.send_twit(db[address],content)
и в функцию incoming_callback добавляем строчку:
self.parse(messages.content(id),str(hash(messages.address(id))))
И осталось реализовать добавление твита, как мы это делали в этом топике.
def send_twit(self,tw,content):
login,password=eval(tw)
api = tweepy.API.new('basic', login, password)
api.update_status(content)
Теперь наш гейт готов. По желанию, его можно упаковать в sis и подпилить напильником в плане обработки ошибок.
Исходики, берем здесь, а готовый sis здесь
Свежих вам идей!