Modbus-RTU 协议适配器连接器 - Amazon IoT Greengrass
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

Amazon IoT Greengrass Version 1 2023 年 6 月 30 日进入延长寿命阶段。有关更多信息,请参阅 Amazon IoT Greengrass V1 维护策略。在此日期之后,将 Amazon IoT Greengrass V1 不会发布提供功能、增强功能、错误修复或安全补丁的更新。在上面运行的设备 Amazon IoT Greengrass V1 不会中断,将继续运行并连接到云端。我们强烈建议您迁移到 Amazon IoT Greengrass Version 2,这样可以添加重要的新功能支持其他平台

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Modbus-RTU 协议适配器连接器

Modbus-RTU 协议适配器连接器从 Amazon IoT Greengrass 组中的 Modbus RTU 设备轮询信息。

此连接器从用户定义的 Lambda 函数接收 Modbus RTU 请求的参数。它发送相应的请求,然后从目标设备发布响应作为 MQTT 消息。

此连接器具有以下版本。

版本

ARN

3

arn:aws:greengrass:region::/connectors/ModbusRTUProtocolAdapter/versions/3

2

arn:aws:greengrass:region::/connectors/ModbusRTUProtocolAdapter/versions/2

1

arn:aws:greengrass:region::/connectors/ModbusRTUProtocolAdapter/versions/1

有关版本更改的信息,请参阅更改日志

要求

此连接器具有以下要求:

Version 3
  • Amazon IoT Greengrass Core 软件 v1.9.3 版或更高版本。

  • Python 版本 3.7 或 3.8 已安装在核心设备上,并已添加到 PATH 环境变量中。

    注意

    要使用 Python 3.8,请运行以下命令来创建从默认 Python 3.7 安装文件夹到已安装的 Python 3.8 二进制文件的符号链接。

    sudo ln -s path-to-python-3.8/python3.8 /usr/bin/python3.7

    这会将设备配置为满足 Amazon IoT Greengrass 的 Python 要求。

  • Amazon IoT Greengrass 核心与 Modbus 设备之间的物理连接。核心必须通过串行端口(例如 USB 端口)以物理方式连接到 Modbus RTU 网络。

  • Greengrass 组中一个指向物理 Modbus 串行端口的本地设备资源

  • 用户定义的 Lambda 函数,可向此连接器发送 Modbus RTU 请求参数。请求参数必须符合预期模式,并包含 Modbus RTU 网络上的目标设备的 ID 和地址。有关更多信息,请参阅输入数据

Versions 1 - 2
  • Amazon IoT Greengrass Core 软件 v1.7 版或更高版本。

  • Python 版本 2.7 已安装在核心设备上,并已添加到 PATH 环境变量中。

  • Amazon IoT Greengrass 核心与 Modbus 设备之间的物理连接。核心必须通过串行端口(例如 USB 端口)以物理方式连接到 Modbus RTU 网络。

  • Greengrass 组中一个指向物理 Modbus 串行端口的本地设备资源

  • 用户定义的 Lambda 函数,可向此连接器发送 Modbus RTU 请求参数。请求参数必须符合预期模式,并包含 Modbus RTU 网络上的目标设备的 ID 和地址。有关更多信息,请参阅输入数据

连接器参数

此连接器支持以下参数:

ModbusSerialPort-ResourceId

表示物理 Modbus 串行端口的本地设备资源的 ID。

注意

连接器被授予对该资源的读写访问权限。

Amazon IoT 控制台中的显示名称:Modbus 串行端口资源

必需:true

类型:string

有效模式:.+

ModbusSerialPort

设备上的物理 Modbus 串行端口的绝对路径。这是为 Modbus 本地设备资源指定的源路径。

Amazon IoT 控制台中的显示名称:Modbus 串口资源的源路径

必需:true

类型:string

有效模式:.+

创建连接器示例 (Amazon CLI)

以下 CLI 命令创建一个 ConnectorDefinition,其初始版本包含 Modbus-RTU 协议适配器连接器。

aws greengrass create-connector-definition --name MyGreengrassConnectors --initial-version '{ "Connectors": [ { "Id": "MyModbusRTUProtocolAdapterConnector", "ConnectorArn": "arn:aws:greengrass:region::/connectors/ModbusRTUProtocolAdapter/versions/3", "Parameters": { "ModbusSerialPort-ResourceId": "MyLocalModbusSerialPort", "ModbusSerialPort": "/path-to-port" } } ] }'
注意

此连接器中的 Lambda 函数的生命周期很长

在 Amazon IoT Greengrass 控制台中,您可以从组的连接器页面添加连接器。有关更多信息,请参阅Greengrass 连接器入门(控制台)

注意

部署 Modbus-RTU 协议适配器连接器后,您可以使用 Amazon IoT Things Graph 协调组中设备之间的交互。有关更多信息,请参阅 Amazon IoT Things Graph 用户指南中的 Modbus

输入数据

此连接器从用户定义的 Lambda 函数接受关于 MQTT 主题的 Modbus RTU 请求参数。输入消息必须采用 JSON 格式。

订阅中的主题筛选条件

modbus/adapter/request

消息属性

请求消息因其所表示的 Modbus RTU 请求类型而异。所有请求都需要具有以下属性:

  • request 对象中:

    • operation. 要执行的操作的名称。例如,指定 "operation": "ReadCoilsRequest" 可读取线圈。该值必须是 Unicode 字符串。有关支持的操作,请参阅 Modbus RTU 请求和响应

    • device. 请求的目标设备。该值必须介于 0 - 247 之间。

  • id 属性。请求的 ID。该值用于重复数据删除,并在所有响应(包括错误响应)的 id 属性中按原样返回。该值必须是 Unicode 字符串。

注意

如果请求包含地址字段,您必须将值指定为整数。例如,"address": 1

要包含在请求中的其他参数取决于操作。需要除 CRC 之外的所有请求参数,且分别进行处理。有关示例,请参阅 示例请求和响应

示例输入:读取线圈请求
{ "request": { "operation": "ReadCoilsRequest", "device": 1, "address": 1, "count": 1 }, "id": "TestRequest" }

输出数据

此连接器发布对传入 Modbus RTU 请求的响应。

订阅中的主题筛选条件

modbus/adapter/response

消息属性

响应消息的格式因相应的请求和响应状态而异。有关示例,请参阅 示例请求和响应

注意

写入操作的响应只不过是对请求的回显。尽管对于写入响应不会返回有意义的信息,但最好还是检查一下响应的状态。

每个响应均包括以下属性:

  • response 对象中:

    • status. 请求的状态。状态可以是以下值之一:

      • Success. 请求有效,已发送至 Modbus RTU 网络并返回响应。

      • Exception. 请求有效,已发送至 Modbus RTU 网络并返回异常响应。有关更多信息,请参阅响应状态:异常

      • No Response. 请求无效,并且连接器在通过 Modbus RTU 网络发送请求之前捕获到错误。有关更多信息,请参阅响应状态:无响应

    • device. 请求发送到的设备。

    • operation. 发送的请求类型。

    • payload. 返回的响应内容。如果 statusNo Response,则该对象只包含一个 error 属性及错误描述(例如 "error": "[Input/Output] No Response received from the remote unit")。

  • id 属性。用于重复数据删除的请求的 ID。

示例输出:成功
{ "response" : { "status" : "success", "device": 1, "operation": "ReadCoilsRequest", "payload": { "function_code": 1, "bits": [1] } }, "id" : "TestRequest" }
示例输出:失败
{ "response" : { "status" : "fail", "error_message": "Internal Error", "error": "Exception", "device": 1, "operation": "ReadCoilsRequest", "payload": { "function_code": 129, "exception_code": 2 } }, "id" : "TestRequest" }

有关更多示例,请参阅 示例请求和响应

Modbus RTU 请求和响应

此连接器接受 Modbus RTU 请求参数作为输入数据,并发布响应作为输出数据

支持以下常见操作。

请求中的操作名称 响应中的函数代码
ReadCoilsRequest 01
ReadDiscreteInputsRequest 02
ReadHoldingRegistersRequest 03
ReadInputRegistersRequest 04
WriteSingleCoilRequest 05
WriteSingleRegisterRequest 06
WriteMultipleCoilsRequest 15
WriteMultipleRegistersRequest 16
MaskWriteRegisterRequest 22
ReadWriteMultipleRegistersRequest 23

以下是受支持操作的示例请求和响应。

读取线圈

请求示例:

{ "request": { "operation": "ReadCoilsRequest", "device": 1, "address": 1, "count": 1 }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "ReadCoilsRequest", "payload": { "function_code": 1, "bits": [1] } }, "id" : "TestRequest" }
读取离散输入

请求示例:

{ "request": { "operation": "ReadDiscreteInputsRequest", "device": 1, "address": 1, "count": 1 }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "ReadDiscreteInputsRequest", "payload": { "function_code": 2, "bits": [1] } }, "id" : "TestRequest" }
读取保持寄存器

请求示例:

{ "request": { "operation": "ReadHoldingRegistersRequest", "device": 1, "address": 1, "count": 1 }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "ReadHoldingRegistersRequest", "payload": { "function_code": 3, "registers": [20,30] } }, "id" : "TestRequest" }
读取输入寄存器

请求示例:

{ "request": { "operation": "ReadInputRegistersRequest", "device": 1, "address": 1, "value": 1 }, "id": "TestRequest" }
写入单线圈

请求示例:

{ "request": { "operation": "WriteSingleCoilRequest", "device": 1, "address": 1, "value": 1 }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "WriteSingleCoilRequest", "payload": { "function_code": 5, "address": 1, "value": true } }, "id" : "TestRequest"
写入单寄存器

请求示例:

{ "request": { "operation": "WriteSingleRegisterRequest", "device": 1, "address": 1, "value": 1 }, "id": "TestRequest" }
写入多线圈

请求示例:

{ "request": { "operation": "WriteMultipleCoilsRequest", "device": 1, "address": 1, "values": [1,0,0,1] }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "WriteMultipleCoilsRequest", "payload": { "function_code": 15, "address": 1, "count": 4 } }, "id" : "TestRequest" }
写入多寄存器

请求示例:

{ "request": { "operation": "WriteMultipleRegistersRequest", "device": 1, "address": 1, "values": [20,30,10] }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "WriteMultipleRegistersRequest", "payload": { "function_code": 23, "address": 1, "count": 3 } }, "id" : "TestRequest" }
屏蔽写入寄存器

请求示例:

{ "request": { "operation": "MaskWriteRegisterRequest", "device": 1, "address": 1, "and_mask": 175, "or_mask": 1 }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "MaskWriteRegisterRequest", "payload": { "function_code": 22, "and_mask": 0, "or_mask": 8 } }, "id" : "TestRequest" }
读取写入多寄存器

请求示例:

{ "request": { "operation": "ReadWriteMultipleRegistersRequest", "device": 1, "read_address": 1, "read_count": 2, "write_address": 3, "write_registers": [20,30,40] }, "id": "TestRequest" }

响应示例:

{ "response": { "status": "success", "device": 1, "operation": "ReadWriteMultipleRegistersRequest", "payload": { "function_code": 23, "registers": [10,20,10,20] } }, "id" : "TestRequest" }
注意

此响应中返回的寄存器是读取的寄存器。

当请求格式有效但请求未成功完成时,可能会发生异常。在此情况下,响应将包含以下信息:

  • status 设置为 Exception

  • function_code 等于请求的函数代码 + 128。

  • exception_code 包含异常代码。有关更多信息,请参阅 Modbus 异常代码。

示例:

{ "response" : { "status" : "fail", "error_message": "Internal Error", "error": "Exception", "device": 1, "operation": "ReadCoilsRequest", "payload": { "function_code": 129, "exception_code": 2 } }, "id" : "TestRequest" }

该连接器对 Modbus 请求执行验证检查。例如,它会检查无效格式和缺失字段。如果验证失败,则连接器不会发送请求。而是会返回一个包含以下信息的响应:

  • status 设置为 No Response

  • error 包含错误的原因。

  • error_message 包含错误消息。

示例:

{ "response" : { "status" : "fail", "error_message": "Invalid address field. Expected <type 'int'>, got <type 'str'>", "error": "No Response", "device": 1, "operation": "ReadCoilsRequest", "payload": { "error": "Invalid address field. Expected <type 'int'>, got <type 'str'>" } }, "id" : "TestRequest" }

如果请求目标是不存在的设备,或者 Modbus RTU 网络不起作用,您可能会获得采用“无响应”格式的 ModbusIOException

{ "response" : { "status" : "fail", "error_message": "[Input/Output] No Response received from the remote unit", "error": "No Response", "device": 1, "operation": "ReadCoilsRequest", "payload": { "error": "[Input/Output] No Response received from the remote unit" } }, "id" : "TestRequest" }

用法示例

使用以下概括步骤设置可用于尝试连接器的示例 Python 3.7 Lambda 函数。

注意
  1. 确保满足连接器的要求

  2. 创建并发布将输入数据发送到连接器的 Lambda 函数。

    示例代码保存为 PY 文件。下载并解压适用于 Python 的 Amazon IoT Greengrass Core 软件开发工具包。然后,创建一个 zip 包,其中在根级别包含 PY 文件和 greengrasssdk 文件夹。此 zip 包是您上传到 Amazon Lambda 的部署包。

    创建 Python 3.7 Lambda 函数后,请发布函数版本并创建别名。

  3. 配置 Greengrass 组。

    1. 通过别名来添加 Lambda 函数(推荐)。将 Lambda 生命周期配置为长时间生存(或在 CLI 中设置为 "Pinned": true)。

    2. 添加所需的本地设备资源并授予对 Lambda 函数的读/写访问权限。

    3. 添加连接器并配置其参数

    4. 添加允许连接器接收输入数据并针对支持的主题筛选条件发送输出数据的订阅。

      • 将 Lambda 函数设置为源,将连接器设置为目标,并使用支持的输入主题筛选条件。

      • 将连接器设置为源,将 Amazon IoT Core 设置为目标,并使用支持的输出主题筛选条件。您可以使用此订阅查看 Amazon IoT 控制台中的状态消息。

  4. 部署组。

  5. 在 Amazon IoT 控制台中,在测试页面上,订阅输出数据主题以查看连接器中的状态消息。示例 Lambda 函数是长时间生存的,并且在部署组后立即开始发送消息。

    完成测试后,您可以将 Lambda 生命周期设置为按需(或在 CLI 中设置为 "Pinned": false)并部署组。这会阻止函数发送消息。

示例

以下示例 Lambda 函数向连接器发送一条输入消息。

import greengrasssdk import json TOPIC_REQUEST = 'modbus/adapter/request' # Creating a greengrass core sdk client iot_client = greengrasssdk.client('iot-data') def create_read_coils_request(): request = { "request": { "operation": "ReadCoilsRequest", "device": 1, "address": 1, "count": 1 }, "id": "TestRequest" } return request def publish_basic_request(): iot_client.publish(payload=json.dumps(create_read_coils_request()), topic=TOPIC_REQUEST) publish_basic_request() def lambda_handler(event, context): return

许可证

Modbus-RTU 协议适配器连接器包含以下第三方软件/许可:

该连接器在 Greengrass Core 软件许可协议下发布。

更改日志

下表介绍每个版本连接器的更改。

版本

更改

3

已将 Lambda 运行时升级到 Python 3.7,这会更改运行时要求。

2

更新了连接器 ARN 以获得 Amazon Web Services 区域 支持。

改进了错误日志记录。

1

首次发布。

Greengrass 组在一个时间上只能包含一个版本的连接器。有关升级连接器版本的信息,请参阅升级连接器版本

另请参阅