Мониторинг CO2 и работа с USB на scala

Озадачился мониторингом CO2 в помещениях. Сначала смотрел на отдельные датчики, думая собрать на коленке и rPi, но потом нашёл дешёвый сборный комплект Masterkit MT8057. Он настолько отличный, что с удовольствием его рекламирую.

В результате у меня получился драйвер к MT8057 на scala и stand alone утилита, ниже в посте поделюсь некоторыми заметками к этой реализации.

Драйвер MT8057

Для MT8057 есть opensource реализация утилиты для съёма параметров от Олега Булатова написанная на C – co2mon. co2mon вариант хороший и рабочий, поддерживает и OS X, и Linux. Наверное, я бы справился докрутить туда выгрузку данных в InfluxDB, куда я собирался сложить все метрики, но решил пописать своих велосипедов, попрактиковаться в низкоуровневых штуках на scala и вспомнить работу с USB.

В первый подход взял хороший и зрелый проект usb4java, но оказалось, что с поддержкой OS X там беда. Требуются извращения типа выгрузки-загрузки kext'ов, которые у меня ещё и не завелись с первого раза.

Во второй подход взял hid4java, этот продукт хоть и анонсируется, как годный к production использованию, ещё достаточно сырой. Шаг влево, шаг вправо и ловишь jvm crash где-то в кишках интеграции с C-шной библиотекой. Написан через JNA, внутри лежат скомпилированные библиотеки для Linux x86_64, Linux ARM, OS X и ещё нескольких платформ. На OS X работает без всяких танцев с kext'ами. Из проблем – API не очень удобный, хуки вызываются из каких попало тредов, у меня это обходится с помощью обёртки с потокобезопасной очередью. Часть методов работает как бы правильно, возвращает правильные Java объекты, но при попытке что-то вызвать у этого объекта получаешь ошибку или crash, так что пришлось добавить костыль.

HID это отдельный класс USB устройств, поэтому не всегда будет выбор между этими библиотеками, в частности usb4java (а вернее libusb) ничего про HID не знает и знать не собирается.

Scala для работы с байтами

В scala всё просто и удобно. Массивы java типа byte[] в Scala превращаются в Array[Byte]. Вооружившись в добавок scala.collection.JavaConversions можно писать привычный scala код.

Внутри драйвера есть зубодробительный код с распаковкой данных от MT8057 и всё это неплохо легло в scala код, местами даже функциональный.

Результат

На выходе у меня получился драйвер MT8057 и декодер к HID пакетам с данными. В отдельный артефакт я их не выделял, но при необходимости это можно сделать.

Про драйвер можно ничего не знать и использовать готовую утилиту ambient7-mt8057-agent которая из зависимостей требует только jre 1.6+ и пока умеет выводить данные в stdout/stderr (для записи в текстовый лог) или работать в интерактивном режиме с ANSI цветами в консоле. На подходе ещё возможность писать в InfluxDB. Готовый jar можно скачать в github.

Про InfluxDB, если удастся с ним подружиться, расскажу отдельно.