Разбор двоичной полезной нагрузки нефиксированного формата с пользовательским преобразованием javascript в Vorto

Сейчас мы используем Vorto в основном как нормализованный формат и начинаем изучать использование механизма сопоставления для сопоставления различных форматов полезной нагрузки с моделью Vorto. Я более или менее понимаю, как сопоставить свойства функционального блока из JSON или двоичной полезной нагрузки с помощью xpath и функций преобразования. Однако я не понимаю, как с помощью этого метода поддерживать синтаксический анализ двоичной полезной нагрузки нефиксированного формата. Например, у нас есть готовый датчик LoRaWAN, который передает в следующем формате:<length><frame type>[<sensor-id><sensor-value>]где длина - это общая длина кадра, а идентификатор датчика (например, температура, влажность, батарея и т. д.) описывает, как анализировать значение датчика (то есть длина, тип данных). В одном кадре могут присутствовать несколько таких показаний в случайном порядке.

Разбор этого может быть легко выполнен, например, в loraserver.io, используя небольшую функцию javascript, которая выполняет итерацию по всем байтам и возвращает проанализированные свойства. То же самое будет работать в движке отображения полезной нагрузки Ditto afaik. Однако в настоящее время я не понимаю, как сделать что-то подобное в маппинге Vorto. Конечно, это всего лишь один конкретный пример датчика, но на рынке существует больше примеров с использованием аналогичного формата динамической полезной нагрузки. Я знаю, что уже есть открытая проблема (№ 1535) для улучшения документации, но уже было бы полезно узнать, возможен ли такой гибкий синтаксический анализ с использованием сопоставления DSL.

Я попытался передать необработанную полезную нагрузку как массив байтов в функцию javascript. Чтобы проверить это, я продублировалorg.eclipse.vorto.mapping.engine.converter.binary.BinaryMappingTest#testMappingBinaryContaining2DataPoints и адаптировали модель для использования пользовательской функции javascript, подобной этой

    evaluator.addScriptFunction(new ScriptClassFunction("extractTemperature",
"function extractTemperature(value) { " +
        " print(\"parameter of type \" + typeof value + \", value = \" + value);" +
        " print(value[1]);" +
        "}"));

Результатом этой функции будет

parameter of type number, value = 1
undefined

Где значение 1 - это первый элемент используемого байтового массива.

Таким образом, функция не получает параметр как bytarray. Модель настроена с.withXPathStereotype("custom:extractTemperature(data)", "demo") поэтому полезная нагрузка передается (как BinaryData) так же, как и в testMappingBinaryContaining2DataPoints контрольная работа (.withXPathStereotype("custom:convert(vorto_conversion1:byteArrayToInt(data,0,0,0,2))", "demo")). Единственная разница, которую я сейчас вижу, это то, что вtestMappingBinaryContaining2DataPointstest заключается в том, что параметр byetarray передается функции Java вместо функции javascript. Или я что-то упускаю?

Также я заметил, что ключевые слова цикла, такие как for а также whileне допускаются в коде javascript. Поэтому, даже если я могу получить доступ к параметру bytearray в функции javascript, я пока не вижу способа, как перебрать это.

На gitter я получил следующий ответ (вместе с предложением перенести обсуждение в SO)

Вы правы. Мы ограничили использование функции Javascript очень элементарным набором ключевых слов языка, за исключением циклов for, поскольку там могут быть реализованы неприятные вещи. Вместо этого вы могли бы зарегистрировать java-функцию в вашем собственном пространстве имен для механизма сопоставления. Эта функция может содержать байтовый массив. Позже эта функция может быть добавлена ​​в механизм сопоставления как стандартная функция для извлечения определенного значения для повторного использования другими разработчиками.

Однако я не думаю, что это решение проблемы. Как упоминалось выше, это всего лишь один пример стандартного формата полезной нагрузки датчика, и я не понимаю, как его можно достаточно обобщить для включения в качестве общей функции в механизм сопоставления. И я не думаю, что необходимо реализовать преобразование конкретного датчика в Java, поскольку (как конечный пользователь платформы IoT, желающий развернуть новый тип датчика) его сложнее разработать и развернуть, чем небольшой javascript функция, которую можно изменить во время выполнения в спецификации сопоставления. Я вижу большую ценность в возможности выполнять простые сопоставления в javascript, точно так же, как это можно сделать, например, в loraserver.io и Eclipse Ditto.

Я думаю, что возможность передать массив байтов в javascript - это первый шаг. Также мне интересно, где именно риск допустить циклы в javascript? Например, Ditto также имеет некоторые ограничения в песочнице javascript (см. Здесь), но это разрешает циклы и предотвращает только бесконечные циклы и рекурсию. Они заявляют следующее:

Использование Rhino вместо Nashorn, нового движка JavaScript, поставляемого с Java, дает преимущество в том, что песочница может применяться более эффективно. Требуется изолирование различных сценариев полезной нагрузки, поскольку Ditto предназначен для работы в качестве облачной службы, где для разных клиентов одновременно управляются несколько подключений к разным конечным точкам. Это требует изоляции каждого отдельного сценария, чтобы избежать помех другим сценариям и защитить JVM, выполняющую сценарий, от выполнения вредоносного кода.

Может ли использование Rhino в Vorto также позволить контролировать риски, которые вы видите, и разрешить создание цикла в отображении Vorto?

PS: может ли кто-нибудь с достаточным количеством очков репутации SO добавить тег eclipse-vorto пожалуйста?

2 ответа

Решение

Я создал проблему для вашего запроса на поддержку этого в конвертерах Javascript: https://github.com/eclipse/vorto/issues/2029

Как указано в проблеме, в качестве текущего обходного пути вы можете зарегистрировать свою собственную функцию преобразователя с помощью Java и повторно использовать эту функцию в своих сопоставлениях. В этих функциях java-конвертера у вас есть все возможности языка java для преобразования для извлечения нужного свойства из произвольного списка. Чтобы узнать, как реализовать свою собственную функцию конвертера с помощью Java, взгляните здесь: https://github.com/eclipse/vorto/tree/master/mapping-engine

Начиная с выпуска Eclipse Vorto 0.12.3, доступно исправление для вашего запроса. С его помощью можно передавать объект массива в конвертер javascript, а также использовать для циклов внутри функций javascript. Вы можете попробовать. См. Примечания к выпуску https://github.com/eclipse/vorto/blob/master/docs/release-notes.md

Другие вопросы по тегам