在 Vorto 中使用自定义 javascript 转换解析非固定格式二进制负载

Parsing non-fixed format binary payload with a custom javascript conversion in Vorto

我们现在主要将 Vorto 用作规范化格式,并开始研究使用映射引擎将不同的有效负载格式映射到 Vorto 模型。我或多或少了解如何使用 xpath 和转换函数从 JSON 或二进制负载映射功能块属性。但是,我不清楚如何使用此方法支持解析非固定格式的二进制有效负载。 例如,我们有一个现成的 LoRaWAN 传感器,它以以下格式传输: <length><frame type>[<sensor-id><sensor-value>] 其中长度是总帧长度,传感器 ID(例如温度、湿度、电池等)描述了如何解析传感器值(即长度、数据类型)。在一帧中,这些读数的多个可能以随机顺序出现。

解析这可以很容易地完成,例如 loraserver.io 使用一个小的 javascript 函数迭代所有字节 en returns 解析的属性。同样的方式也适用于 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 是使用的字节数组的第一个元素。

所以函数似乎没有接收字节数组的参数。 该模型配置了 .withXPathStereotype("custom:extractTemperature(data)", "demo"),因此有效负载以与 testMappingBinaryContaining2DataPoints 测试 (.withXPathStereotype("custom:convert(vorto_conversion1:byteArrayToInt(data,0,0,0,2))", "demo")) 相同的方式传递(如 BinaryData)。我现在看到的唯一区别是,在 testMappingBinaryContaining2DataPoints 测试中,byetarray 参数被传递给 Java 函数而不是 javascript 函数。还是我遗漏了什么?

此外,我注意到 javascript 代码中不允许使用 forwhile 等循环关键字。因此,即使我可以访问 javascript 函数中的 bytearray 参数,我现在也看不出如何迭代它。

在 gitter 上我收到了以下回复(连同将讨论移至 SO 的建议)

You are right. We restricted the Javascript function usage to very rudimentary set of language keywords excluding for loops as nasty stuff can be implemented there. What you could do Instead is to register a java function In your own namespace to the mapping engine. That function can hold a byte array. Later this function can be contributed to the mapping engine as a standard function to extract a certain value out for other developers to reuse.

不过我不认为这是解决问题的办法。如上所述,这只是现成的传感器有效负载格式的一个示例,我看不出如何将其泛化到足以作为通用函数包含在映射引擎中。而且我认为不需要在 Java 中实现特定于传感器的转换,因为(作为物联网平台的最终用户想要部署新的传感器类型)开发和部署起来更加复杂而不是一个可以在运行时在映射规范中更改的 javascript 函数。我看到能够在 javascript 中进行简单映射的很多价值,就像这可以在 loraserver.io and Eclipse Ditto.

中完成一样

我认为能够将字节数组传递给 javascript 是第一步。另外我想知道在 javascript 中允许循环的风险到底在哪里?例如 Ditto 在 javascript 沙箱 (see here) 中也有一些限制,但这允许循环并且只能防止无休止的循环和递归。 他们声明如下:

Using Rhino instead of Nashorn, the newer JavaScript engine shipped with Java, has the benefit that sandboxing can be applied in a better way. Sandboxing of different payload scripts is required as Ditto is intended to be run as cloud service where multiple connections to different endpoints are managed for different tenants at the same time. This requires the isolation of each single script to avoid interference with other scripts and to protect the JVM executing the script against harmful code execution.

在 Vorto 中使用 Rhino 是否也可以控制您看到的风险并允许在 Vorto 映射中进行循环构造?

PS: 有足够SO声望点的人可以添加标签eclipse-vorto吗?

我创建了一个问题,要求您在 Java 脚本转换器中支持此功能:https://github.com/eclipse/vorto/issues/2029

如问题中所述,作为当前的解决方法,您可以使用 Java 注册您自己的自定义转换器函数,并在您的映射中重复使用该函数。在这些 java 转换器函数中,您拥有 java 语言的所有转换功能,可以从任意列表中提取正确的 属性。 要了解如何使用 Java 实现您自己的自定义转换器功能,请查看此处:https://github.com/eclipse/vorto/tree/master/mapping-engine#Advanced-Usage

自 Eclipse Vorto 0.12.3 版本发布以来,已针对您的请求提供修复。这样就可以将数组对象传递给 javascript 转换器以及在 javascript 函数中使用循环。你可能想试一试。 请参阅发行说明 https://github.com/eclipse/vorto/blob/master/docs/release-notes.md