OTT: видео сервисы на экранах Panasonic ТВ

This post is also available in: Английский

Panasonic Viera Connect

Крупнейшие производители телевизоров в последние годы активно осваивают возможности предоставления услуг через интернет, и компания Panasonic не стала в этом отношении исключением. Свое видение концепции умного телевидения специалисты японской компании воплотили в технологии Viera Connect.

Из пресс-релиза Panasonic:

VIERA Connect — это сетевая ТВ-платформа Panasonic, которая обеспечивает владельцам телевизоров HD, проигрывателей Blu-ray и домашних кинотеатров с поддержкой VIERA Connect, доступ к самому разнообразному контенту: от новостей до социальных сетей и онлайн-игр.

В этой статье мы хотим поделиться опытом разработки приложений для платформы Viera Connect.

Настройка среды разработки

Прежде всего, нам нужно было настроить среду разработки. Начнём с того, что Panasonic не предоставляет эмулятор для разработки приложений. Это значит, что для того, чтобы начать разрабатывать приложение, необходим сам телевизор Panasonic с поддержкой технологии Viera Connect. Также потребуется сервер, на котором будет располагаться бэкенд приложения. Хост, на котором будет развернут бэкенд, должен либо иметь IP адрес 192.168.0.100, либо доменное имя localserver.vieraconnect.com. Мы выбрали второй вариант, так как он позволяет сделать процесс разработки более гибким. Мы развернули на локальной машине одного из разработчиков хост localserver.vieraconnect.com и DNS сервер bind9. Далее, в настройках сетевого подключения телевизора мы прописали адрес нашего локального DNS.

Hello, World!

Следующим шагом стала попытка запустить тестовое приложение. При старте приложения телевизор посылает запрос по адресу localserver.vieraconnect.com/sdkapp/main.js. В документации написано, что это основной файл, с которого начинается работа приложения. В нём мы и поместили код нашего «Hello, world!». Убедившись, что среда разработки настроена, мы запустили тестовые приложения, входящие в состав SDK Panasonic. Изучение рабочего кода помогло заполнить пробелы, которые остались после прочтения документации, написанной суховато и представляет собой перечисление элементов языка со списками параметров и функций с краткими пояснениями.

Организация приложения

Любое приложение Panasonic Viera Connect состоит из стейджей или экранов. Вышеупомянутый файл main.js — главный стейдж, точка входа в приложение. Обычно стейджи содержат графические элементы пользовательского интерфейса и код для взаимодействия с пользователем. В нашем случае мы несколько отошли от этой концепции и использовали стейдж main.js для подключения всех необходимых библиотек с дальнейшим перенаправлением пользователя на главную страницу приложения.

Еще одним важным понятием является концепция packages. Это рекомендованный Panasonic способ организации кода приложения. Сам package может включать объявление переменных, объектов и функций, которые после подключения package становятся видимыми глобально, то есть на любом стейдже. Код одного package также будет доступен внутри другого. Заканчиваться код package должен инструкцией provide(), которая делает package доступным для использования в приложении. Packages полезно использовать для создания глобальных объектов типа navigation, userInput, userAuthentication и т.д.

Организация параллельной работы нескольких членов команды.

Отсутствие в SDK эмулятора сильно усложняет разработку, так как несколько разработчиков должны совместно использовать один телевизор. При этом возникает необходимость постоянно перенастраивать телевизор на работу с версией приложения того или иного разработчика. Процедура изменения адреса DNS-сервера в настройках сетевого подключения занимает примерно 30 секунд, следовательно, делать это часто слишком накладно. Можно настроить телевизор на работу с конкретным сервером и использовать систему управления версиями для выливки кода. Однако при этом коммиты будут настолько частыми, что накладные расходы очень быстро превысят разумные пределы. Из этой ситуации наша команда вышла не самым изящным, но довольно простым способом. Мы настроили телевизор на работу с бэкендом, который хостился на компьютере одного из членов команды, сделали папку проекта доступной по samba, а остальные разработчики примонтировали ее как удалённую файловую систему. Это позволило повысить оперативность разработки, хотя и наложило ограничения на одновременный доступ к конкретным файлам.

Разработка приложения

Cистема навигации

При разработке приложения для телевизора Panasonic Viera наша команда столкнулась с большим количеством интересных задач. Одной из наиболее сложных из них стала разработка системы навигации. Стоит отметить, что отладка больших объёмов кода на устройствах Panasonic Viera Connect сильно затрудняется отсутствием средств тестирования. Подробнее об этом будет написано позже. В связи с этим сначала мы разработали прототип навигационной системы, который работал в браузере. Только после того, как были написаны основные классы, сформировавшие ядро системы, разработка была перенесена на реальное устройство.

Мы начали с того, что разработали 3 основных класса:

  • NavigationStage
  • NavigationArea
  • NavigationNode

NavigationStage содержит общие методы для передвижения курсора по стейджам и навигации между стейджами. NavigationArea — это класс навигационной области, объединяющей навигационные элементы NavigationNodes. Области могут иметь соседние области сверху, снизу, справа и слева. Это справедливо и для навигационных элементов. Навигационные элементы виртуальны, но хранят ссылку на элемент на стейдже, визуальное отображение которого мы можем менять в зависимости от того, находится элемент в фокусе или нет.

Интерфейсы NavigationArea и NavigationNode содержат схожие методы: executeSelect и executeLeave. Они вызываются, когда область или элемент получают или теряют фокус. Помимо этого объекты NavigationNode также имеют метод executeEnter, который вызывается для элемента, находящегося в фокусе, когда пользователь нажимает кнопку OK на пульте дистанционного управления.

Все навигационные области ведут себя одинаково. При первоначальной постановке курсора в навигационную область для нее активируется навигационный элемент по умолчанию. Если пользователь переводит курсор в другую область, мы запоминаем индекс последнего активного навигационного элемента. Это делается для того, чтобы, когда курсор вернётся назад, мы смогли бы активировать элемент, с которого был осуществлён переход.

Приведём пример. Допустим, пользователь зашёл в раздел «Кино» и выбрал в левом меню подкатегорию «Детективы». Если он нажмёт на пульте дистанционного управления стрелку вправо, то курсор переместится на первый элемент в списке фильмов. Допустим теперь, что далее пользователь нажмёт стрелку влево, чтобы вернуться в список категорий. Курсор снова окажется на подкатегории «Детективы».

В самом начале разработки все навигационные элементы и области также вели себя одинаково. Первоначально это были текстовые надписи, которые меняли цвет в зависимости от положения фокуса и это поведение было прописано в самом классе NavigationNode. Когда мы сверстали сетку фильмов, встала необходимость создавать более сложные навигационные элементы, которые состояли бы из произвольного набора графических элементов и текста. Поэтому мы вынесли поведение навигационного элемента в отдельный класс типа strategy, объект которого передавали в конструктор навигационного элемента. Этот подход работал идеально, но не долго. Дело в том, что пока мы создавали навигационные области, все элементы в которых были одинаковыми, например меню с текстовыми пунктами или сетку из обложек фильмов, все было нормально. Затем возникла необходимость создавать навигационные области, состоящие из произвольных элементов, а при работе над клавиатурой для поиска нам потребовалось не только назначать стратегию поведения для каждого элемента но и передавать ей дополнительные параметры поведения. Приведу пример. Пусть необходимо создать клавиатуру для ввода поискового запроса. На клавиатуре есть 4 типа кнопок, которые отличаются стратегиями поведения:

  • CharButtonStrategy
  • CursorMoveButtonStrategy
  • BackspaceButtonStrategy
  • SwitchLayoutButtonStrtegy

Каждая кнопка со стратегией CharButtonStrategy получает массив настроек, в котором содержится, в частности, код символа, который будет добавлен к поисковой строке при нажатии на эту кнопку. SwitchLayoutButtonStrategy принимает массив, содержащий ID клавиатуры, на которую необходимо переключиться, регистр букв и т.д.

Этот подход мы также использовали в дальнейшем при создании всплывающих окон — кнопки «да» и «нет» получают в конструкторе различные стратегии поведения, которые, в свою очередь, инициализируются собственными параметрами.

Прокручивающиеся контейнеры

Ещё одной крупной задачей стала реализация прокручивающихся элементов интерфейса — скроллеров.

Когда мы проектировали скроллеры, было принято решение написать библиотеку, которая бы позволяла любой элемент типа container превращать в прокручиваемую область, причём шаг прокрутки должен был вычисляться автоматически. Мы сделали одно допущение и исходили из того, что в нашем интерфейсе прокручивались только контейнеры, внутри которых находились навигационные элементы. Примером такого контейнера является меню подкатегорий.

Поэтому событие прокрутки контейнера совместили с перемещением фокуса от одного навигационного элемента внутри контейнера к другому. Для доступа к событиям перемещения по элементам мы используем описанную выше систему навигации. Так как при создании навигационной области мы задаем взаимное расположение элементов в ней, то при перемещении фокуса с первого элемента меню ко второму, расположенному под первым, мы всегда имеем возможность вычислить расстояние, на которое должен быть прокручен скроллер. Так была реализована первая версия скроллера. В процессе разработки стало понятно, что скроллер должен прокручиваться не всегда. Например, в описанном выше примере с переходом от первого элемента меню ко второму прокручивать скроллер нет смысла потому, что на экране все ещё много видимых элементов меню. Когда же наступает момент, когда необходимо включить прокрутку? Мы приняли решение прокручивать скроллер только в случае, если элемент, на который осуществляется переход, располагается на небольшом расстоянии от центра скроллера. Следующим шагом была введена проверка на то, что границы прямоугольника, окружающего прокручиваемый контент, всегда должны располагаться вне границ скроллера.

Стоит отметить, что все элементы на стейдже позиционируются относительно полярной системы координат с нулевыми координатами в центре экрана. Эту интересную особенность необходимо учитывать при проектировании.

Отладка кода

Panasonic не предоставляет никаких встроенных средств отладки. Это означает, что стейдж, использующий функционал, который вы сейчас отлаживаете, — либо запускается, либо падает всё приложение и далее Вам предстоит постепенно откатывать код до рабочей версии, чтобы локализовать и исправить ошибку. Можно немного упростить эту задачу. В документации для разработчиков Panasonic рекомендует написать функцию, позволяющую выводить отладочные сообщения. Суть в том, что при помощи объекта http_request во время выполнения кода можно отправлять асинхронные запросы в backend вашего приложения и логировать их. Мы писали сообщения в файл, который затем открывали при помощи команды tail debug.log -f . Нужно отметить, что при таком подходе не следует рассчитывать, что все отладочные сообщения будут приходить в лог в той последовательности, в которой они встречаются в коде, так как запросы асинхронны. Частично решить проблему удается, последовательно объединяя отладочные сообщения в одну строку, а затем отсылая их на сервер одним запросом. Однако этот подход срабатывает только в случае, если код от первого отладочного сообщения до строки, отсылающей весь лог на сервер, не содержит ошибок, — иначе сообщение просто не будет отправлено.

Итог

Попробуем кратко подытожить сказанное выше. Процесс разработки приложений для платформы Viera Connect нельзя назвать простым. Помимо непосредственного проектирования и написания кода, разработчик должен решить большое количество организационных вопросов, включая настройку среды разработки, а также написание необходимых утилит. Отладка приложения сильно осложняется отсутствием в SDK эмулятора и спецификой работы с устройствами Panasonic.