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



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

    Думаю, что специалистам по корпоративной 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 можно здесь.

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

    12 Responses to “XML сервисы для IP телефонов”

    1. [...] сервисы, часть вторая Недавно мы рассматривали создание приложения на платформе App Engine, которое [...]

    2. Dury:

      Здравствуйте,

      а не подскажете, как настроить работу XML-приложений на Cisco IP Phone без CCM?

      Спасибо

    3. techworkru:

      Как передаете конфиги телефонам? По tftp?

    4. Oleg-y:

      При попытке http://xmlphones.appspot.com/cbrf.xml
      выдаёт следующее
      Traceback (most recent call last):
      File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 498, in __call__
      handler.get(*groups)
      File "/base/data/home/apps/xmlphones/3.9/main.py", line 143, in get
      cbrf(self)
      File "/base/data/home/apps/xmlphones/3.9/main.py", line 72, in cbrf
      result = urlfetch.fetch(‘http://www.cbr.ru/currency_base/D_print.asp?date_req=’+time.strftime(‘%d.%m.%Y’, time.localtime()))
      File "/base/python_lib/versions/1/google/appengine/api/urlfetch.py", line 273, in fetch
      raise DownloadError(str(e))
      DownloadError: ApplicationError: 5

    5. techworkru:

      Страница с курсами валют иногда глючит, так как в это время не отвечает сервер ЦБ РФ. Видимо тоже кризис сказался…

    6. choka:

      Приветствую,

      Не подскажете и мне, как настроить работу XML-приложений на Cisco IP Phone без CCM?, в частности 7941,
      заранее благодарю за информацию

      dtulegen@mail.ru

    7. Уже ~2 недели как не работают курсы валют, выплевывает IndexError: List Index out of range.

    8. techworkru:

      К сожалению, этот досадный глюк только что был исправен :(

    9. Kirill:

      Отличный дополнительный сервис для цискофонов.
      Но вот незадача: у меня телефончик СР-7940 с СИП прошивкой, а файлов локализации на русском языке для таковых не существует. Можно ли получить ссылочку на XML сервисы для цискофонов на английском языке или в транслите?

    10. DenJS:

      Добрый день!

      Решил воспользоваться вашим сервисом, но увы мои телефоны (7941) вообще не имеют поддержки русского, весь текст отображается квадратиками независимо от выбранной кодировки :( И судя по обсуждениям в сети 7941 с SIP прошивкой, пока не удается нормально русифицировать. В связи с этим вопрос, можно ли добавить к вашим сервисам опцию, чтобы текст выводился в транслите или на Английском?
      Спасибо.

    11. Просто супер!!!

    Leave a Reply