Думаю, что специалистам по корпоративной IP телефонии хорошо известно, что с незапамятных времен у лидера рынка Cisco все производимые телефоны имеют возможность отображать внешние данные. Однако на практике этим никто не пользуется, так как хороших приложений немного, а те что есть – стоят больших денег. Да и возможности телефонов таковы, что приложение с хорошим юзабилити сможет работать только на топовых моделях, которые стоят дороже среднего системного блока.
Мне стало интересно попробовать в работе платформу Google App Engine, чтобы создать небольшой информационный сервис для IP телефонов. Я взял для начала три источника данных: прогноз погоды от сайта GisMeteo, ленту новостей от Яндекса (оба в формате RSS) и официальный сайт Центрального банка РФ, который имеет HTML страницу с курсами валют на заданную дату. Соответственно алгоритм очень прост:
- с помощью интерфейса URL Fetch загружаем необходимую страницу с данными
- парсим ее и извлекаем нужные
- отображаем в текстовом виде (XML я использован только для меню)
Код получился простой и уместился в один файл:
# coding=UTF-8
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.api import urlfetch
import os
from google.appengine.ext.webapp import template
from xml.dom import minidom
import re
WEATHER_URL = 'http://informer.gismeteo.ru/rss/%s.xml'
def render_template(self, templ, template_values={}):
path = os.path.join(os.path.dirname(__file__), 'templates/'+templ)
self.response.out.write(template.render(path, template_values))
def is_ipphone(self):
if re.match('Allegro', self.request.headers.get('User-Agent', '')) == None:
return False
else:
return True
class MainPage(webapp.RequestHandler):
def get(self):
if is_ipphone(self):
self.response.headers['Content-type']='text/xml; charset=utf-8'
render_template(self, 'main.xml')
else:
self.response.headers['Content-type']='text/html; charset=utf-8'
render_template(self, 'main.html')
def parse_rss_data(content):
result = ''
dom = minidom.parseString(content)
for item in dom.getElementsByTagName('item'):
result = result + item.getElementsByTagName('title')[0].firstChild.nodeValue + '\n'
+ item.getElementsByTagName('description')[0].firstChild.nodeValue + '\n\n'
return result
def rss_to_text(self, url):
self.response.headers['Content-type']='text/plain; charset=utf-8'
result = urlfetch.fetch(url)
if result.status_code == 200:
self.response.out.write(parse_rss_data(result.content))
else:
self.redirect('/error.xml')
class GisMeteo(webapp.RequestHandler):
def get(self):
rss_to_text(self, WEATHER_URL % '27612')
class YandexNews(webapp.RequestHandler):
def get(self):
rss_to_text(self, 'http://news.yandex.ru/Russia/index.rss')
class CbRF(webapp.RequestHandler):
def get(self):
self.response.headers['Content-type']='text/plain; charset=windows-1251'
result = urlfetch.fetch('http://www.cbr.ru/currency_base/D_print.asp?date_req')
if result.status_code == 200:
data=re.split('<td align="right" >036</td>', result.content)[1]
for block in re.split('<tr bgcolor="#ffffff">', data):
cells = re.search('<td align="left" > (.*?)</td><td align="right" >(.*?)</td><td> (.*?)</td><td align="right">(.*?)</td>', block)
if cells != None:
self.response.out.write(cells.group(2)+' '+cells.group(3)+' = '+cells.group(4)+'\n')
else:
self.redirect('/error.xml')
class Error(webapp.RequestHandler):
def get(self):
self.response.headers['Content-type]']='text/plain'
self.response.out.write('Произошла ошибка при работе сервиса')
def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/error.xml', Error),
('/yandex_news.xml', YandexNews),
('/meteo.xml', GisMeteo),
('/cbrf.xml', CbRF)
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
Самый интересный момент в коде: проверка при входе на главную страницу, является ли User-Agent IP телефоном или обычным компьютером и соответственно отображение или меню для телефона, или текста с описанием сервиса для человека. Как это выглядит вживую можно посмотреть на сайте сервиса – http://xmlphones.appspot.com. Там же находится описание того, что необходимо прописать в Cisco CallManager для отображения данных на телефонах.
Благодаря Google теперь нет необходимости поднимать такой сервис внутри корпоративной сети, его можно эксплуатировать как общедоступный. Посмотреть другие возможности XML сервисов для IP телефонов Cisco можно здесь.
Перейти к второй части этой темы.