• Home
  • Учебник по ExtJS
  • О сайте
  •  


    XML сервисы, часть вторая

    Август 28th, 2008

    Недавно мы рассматривали создание приложения на платформе App Engine, которое позволяет IP телефонам Cisco получать информацию о прогнозе погоды, новостях и курсе валют.

    К сожалению, пользователи, которые же в первые дни появились у этого сервиса, обнаружили в нем два существенных недостатка:

    • Мы отображаем только погоду только по Москве, хотя сервис у нас глобальный
    • Существуют проблемы на разных версиях прошивок для телефонов, которые ожидают данные на русском языке в кодировке cp-1251.

    Первый недочет решено было исправить, добавив опциональный параметр city к URL сервиса, равный коду города на сайте ГисМетео, на котором мы берем данные погоды. Таким образом строка для телефонов Питера выглядит как http://xmlphones.appspot.com/?city=26063. Второй аналогично будет называться encode и содержать при необходимости задание кодировки windows-1251.

    Read the rest of this entry »




    XML сервисы для IP телефонов

    Август 9th, 2008

    Думаю, что специалистам по корпоративной 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" >&nbsp;&nbsp;(.*?)</td><td align="right" >(.*?)</td><td>&nbsp;&nbsp;(.*?)</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 можно здесь.

    Перейти к второй части этой темы.