AWS IoT DynamoDB 规则无法读取从 topic() 函数中选择的值

AWS IoT DynamoDB rule not able to read value SELECTed from topic() function

我正在尝试使用规则将数据从 AWS IoT MQTT 主题获取到 DynamoDB。 示例主题是 cooler/cooler42/sensors,示例消息是

{ "waterTemp": 10, "timestamp": 1580370731383 }

我已经这样定义查询,从主题中提取 deviceName(例如 cooler42)并将其插入 JSON:

SELECT *, topic(2) AS deviceName FROM 'cooler/+/sensors'

这似乎确实有效,就好像我将消息重新发布到另一个主题一样我现在看到相同的 JSON 添加了 deviceName

{ "waterTemp": 10, "timestamp": 1580370731383, "deviceName": "cooler42" }

我的理解是所有 3 个字段现在应该可以在我的 DynamoDB 规则中使用,如下所示:

但是我可以从 CloudWatch 中看到该规则因错误而失败 One or more parameter values were invalid: An AttributeValue may not contain an empty string (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException 并且分区键(又名散列键)为空:

{ "ItemRangeKeyValue":"1580370731383", "IsPayloadJSON":"true", "ItemHashKeyField":"deviceName", "Operation":"Insert", "ItemRangeKeyField":"timestamp", "Table":"SensorDataTest2", "ItemHashKeyValue":"" <--- Empty }

我不能使用我刚刚从规则中的主题名称中选择的 deviceName 吗?如果没有,还有其他提取方法吗?

NB 如果我手动将消息发布到已经包含 deviceName 的主题上,那么它确实可以正常工作,但我在一个受限的环境中工作并且不想要额外的有效负载大小。

键值使用无法引用 deviceName 别名的 substitution template (*)。

AWS 文档强调了这一点:

Because an expression in a substitution template is evaluated separately from the "SELECT ..." statement, you cannot reference an alias created using the AS clause. You can reference only information present in the original payload, in addition to supported functions and operators.

您只能参考原始负载中的信息。

由于原始负载中不存在别名,您可以使用 ${topic(2)} 作为分区键值。该函数可以访问主题,尽管这意味着键值与主题名称耦合。

另一种选择是将规则重新发布到负载中包含 deviceName 的另一个主题。处理这个主题的 rule/action 可以写入 DynamoDB。然后此操作将可以访问 deviceName 属性,因为它在重新发布的有效负载中可用。


* 文档暗示键值语法是替换模板。

上面的link表示:

Substitution templates appear in the action parameters within a rule

但是,我还通过使用 encode 函数将操作中可用的整个有效载荷写入 table 来验证函数可用的有效载荷不包括别名。 =28=]

例如使用包含一些别名的规则:

将操作配置为使用 ${encode(*, 'base64')}Sort key value,它将整个负载编码为 base 64 字符串。

当您发布消息时:

此消息写入 DynamoDB 为:

{
  "DateTime": "ewogICJtZXNzYWdlIjogIkhlbGxvIGZyb20gQVdTIElvVCBjb25zb2xlIgp9",
  "Payload": {
    "arrivalTime": 1581082253585,
    "myField": "Hello from AWS IoT console",
    "payload": {
      "message": "Hello from AWS IoT console"
    }
  },
  "Topic": "blt/test"
}

包括别名在内的整个负载都在 Payload 字段中。 但是解码 DateTime 字段中的 base 64 字符串将显示别名不存在于 encode 函数中。

我有一个完整的教程:

CPU Temperature - IoT Project

您可以使用来自 AWS 的 MQTT 库:Notebook

已将遥测数据发送到 AWS IoT 并保存在 DynamoDB 中:

然后运行查询:

SELECT message.reported.* FROM '#'

然后使用 Quick Sight 或 Kibana 创建实时仪表板。整体思路如下: