Преамбула
В конце 2013 года наша компания переехала в новый офис в одну из башен комплекса Москва-Сити. В наследство от прошлого арендатора помещения нам достались потолочные часы, предназначенные для отображения времени в различных часовых поясах. Судя по всему, арендатор был завязан с финансовым или банковским сектором.
Сначала мы пытались перенастроить часы (подправить время и сменить отображаемые города), но не смогли этого сделать – на потолке висела монолитная алюминиевая коробка без каких-либо органов управления. В последствие часы были обесточены и остались висеть без признаков жизни. Спустя два года загорелись идеей воскресить часы и использовать их как нечто большее.
Идентификация устройства
Первой проблемой на пути была необходимость идентификации устройства — ни модели часов, ни их производителя мы не знали. Никаких опознавательных знаков, наклеек и гравировок на корпусе устройства найти не удалось. Документация к устройству также отсутствовала.
В этот момент мы пришли к выводу, что для идентификации устройства необходимо вскрытие коробки, начиная с боков. Головки болтов были повреждены ещё при первой попытке вскрытия два года назад. Один из болтов так и не удалось выкрутить – пришлось ломать уголок панели. Благо она выполнена из мягкого алюминия, так что удалось нанести минимальный визуальный и структурный урон конструкции.
Отломанный уголок
Внутри оказалась паутина из проводов и россыпь управляющих плат. На одной из них мы смогли высмотреть название производителя часов Wharton, на сайте которого по визуальным признакам был определён наш экземпляр.
Внутренности часов
На сайте производителя раздел поддержки потребителей ограничена контактными данными организации, штаб-квартира которой расположена в Великобритании. После десяти минут разговоров по телефону со второй линией поддержки нам выслали инструкцию к часам, где была в подробностях описана процедура настройки часов с помощью пульта дистанционного управления. Пульт ДУ арендаторы нам не оставили.
После очередных десяти минут разговора со службой поддержки нам прислали фирменную утилиту, предназначенную для настройки часов, выставления часовых поясов, установки подписи над секциями, а также для синхронизации времени. Программа связывается с часами через обычный COM-порт, который был любезно спрятан монтажниками под фальш-потолком над часами. Для нашего экземпляра программа отработала «на ура».
В процессе изучения внутренностей часов был замечен набор джамперов на управляющей плате каждой секции. Поигравшись с утилитой и джамперами, мы выяснили, что они управляют внутренним номером секции, что позволяет отображать одну и ту же информацию и время на разных секциях. Эта возможность является актуальной для нашего двустороннего образца – время и текст дублируются с обеих сторон.
Программа управления часами
Пора перейти к занимательной части упражнения: разбору алгоритма работы настроечной программы с целью написать собственной управляющей программы. К этой задаче можно подойти несколькими способами. Сначала мы рассматривали вариант дизассемблирования официальной утилиты. После нескольких попыток понять ассемблерный код решили пойти по пути реверс-инжиниринга протокола передачи данных: изучить и понять данные, которые передаются по COM-кабелю.
Для изучения команд, передающихся по COM-порту, мы использовали программу HDD Software Device Monitoring Studio. Программа цепляется к установленному в системе COM-порту, не нарушая режима его работы, снимает передаваемые на порту данные и автоматически разбивает на пакеты данных на основании задержек между передачами. С запущенной студией мы сняли трафик от программы настройки на часы:
Для целей проекта смена временной зоны не требуется, потому детально была изучена только первая часть запроса. Методом проб и ошибок удалось разобрать структуру первой части запроса более детально:
Начало и конец команды – постоянные значения для всех команд. В таблице ASCII эти коды соответствуют символам «начало текста» и «конец текста». Код табло имеет смысл, если несколько табло подключены цепочкой между собой. В нашем случае табло всего одно, потому для нас по смыслу значение является константой. Кодов команд существует несколько («установить текст», «установить часовой пояс», «синхронизировать время»), для нашего проекта используется только «0x83
– установить текст». Для номера секции используется значение по формуле: 0x80 + номер_секции – 1
.
Для текста секции используется правило перекодировки: 0x80 | ord(символ)
. Часы поддерживают небольшой набор символов для отображения: цифры, символы латиницы строчные и прописные, пробел, спецсимволы и знаки препинания. Кириллица в систему не зашита. Длина текста ограничена десятью символами и является постоянной. Если длина отображаемой строки менее десяти символов, то необходимо «добить» строку до полной длины пробелами. При отображении текста на часах пробелы в начале и конце строки игнорируются, а сам текст при визуализации центрируется. Если код символа не поддерживается, то на дисплее отображается символ «!».
Проверочный разряд присутствует в конце каждой команды. Для интересующей нас команды формула расчёта проверочного разряда: посимвольный XOR для текста и номера секции (уже закодированного). Для полученного значения старший и младший октеты записываются в отдельные байты контрольного разряда сообщения. Визуальный пример:
Проверка корректности алгоритма выполняли через proof-of-concept скрипт, написанный на PHP, который пишет напрямую в COM-порт соответствующие команды. С помощью этого скрипта мы уточнили минимально допустимые задержки между командами, в частности удалось минимизировать задержку между командами с одной секунды (стандарт в программе от поставщика) до 300 мсек, а также проверили поддерживаемый часами алфавит.
Доступ к часам по сети
Взаимодействие с программой часов была только одной частью проблемы, хотя и самой сложной. Для обеспечения успешности проекта требовалось иметь возможность посылать на часы управляющие команды через сеть. В конце концов, мы не могли оставить тестовый ноутбук подключённым к часам 24x7.
Для реализации сетевого подключения было решено составить простую программу на C#, которая открывает TCP-порт и ждёт подключения извне. При получении команды по сети программа выполняет следующие операции:
- устанавливает блокировку (для исключения параллельной работы с часами);
- открывает локальный COM-порт, на котором «висят» часы;
- отсылает команду;
- закрывает порт;
- ждёт предварительно настроенное время (как установлено выше – 300 мсек);
- снимает блокировку;
- отсылает подтверждение выполнения команды.
Изначально была мысль предоставить прямое подключение к COM-порту по сети (т.е. реализовать tcp2com-решение). Такой подход мог позволить посылать любые команды на часы и экспериментировать с устройством. Но в итоге от этой идеи отказались в пользу реализации сервисной программы, которая реализует в себе всю логику кодирования и управления часами.
Составленная программа реализует XML интерфейс, принимает запросы через стандартный для C# HttpListener
. Формат сообщений по сети предполагает указание секции для настройки и отображаемый текст:
<setTextXML>
<section>[section number]</section>
<text>[section text]</text>
</setTextXML>
Написанная программа была установлена на Windows-сервер, запертый в техническом помещении офиса. Так как сервер находится на некотором удалении, мы протащили 10 метров CAT5-провода под фальш-потолком от часов до подсобного помещения. Кабель CAT5 использовался в качестве сигнального COM-кабеля (использовалось всего две жилы). Имелись переживания, что десять метров провода для часов – это слишком много, но, к счастью, связь отработала без проблем. Сам Windows-сервер подключён к внутренней сети компании и имеет статический адрес. Простое тестирование из браузера во внутренней сети подтвердило наличие связи и корректной работы как программы, так и связи с часами.
Отображение полезной информации
Часы подключены и теперь доступны по сети в качестве вебсервиса. Пришло время выводить полезную информацию!
Для интеграции с внешними источниками данных взяли развёрнутую в нашем офисе корпоративную шину SAP Process Integration 7.4. На момент запуска проекта в эксплуатацию мы взяли три источника данных:
- Центробанк России;
- Гидрометцентр России;
- Яндекс.Пробки.
Система SAP PI занимается опросом по расписанию внешних источников, преобразованием данных и последующей передачей результата на часы.
Для Центробанка мы забираем раз в час последние опубликованные данные о курсе евро и долларов США. Для Гидрометцентра раз в 15 минут мы забираем информацию с метеостанции, расположенной в районе станции метро Киевская – ближайшая метеостанция в открытом доступе к нашему офису. Из числа доступных атрибутов мы отображаем только температуру и относительную влажность воздуха. Для сервиса Яндекс.Пробки происходит обновление каждые 15 минут и отображается текущее состояние загруженности дорог для Москвы в целом.
А теперь – фотофиниш!
Автор: platinumice