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

Modbus-RTU 协议适配器 连接器

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

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

此连接器具有以下版本。

版本

ARN

3

arn:aws-cn:greengrass:区域::/connectors/ModbusRTUProtocolAdapter/versions/3

2

arn:aws-cn:greengrass:区域::/connectors/ModbusRTUProtocolAdapter/versions/2

1

arn:aws:greengrass:区域::/connectors/ModbusRTUProtocolAdapter/versions/1

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

要求

此连接器具有以下要求:

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

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

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

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

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

Versions 1 - 2
  • AWS IoT Greengrass Core 软件 v1.7 or later。

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

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

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

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

连接器参数

此连接器支持以下参数:

ModbusSerialPort-ResourceId

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

注意

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

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

必需:true

类型:string

有效模式:.+

ModbusSerialPort

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

在 AWS IoT 控制台中显示名称:Modbus 串行端口资源的源路径

必需:true

类型:string

有效模式:.+

创建连接器示例 (AWS CLI)

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

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

该连接器中的 Lambda 函数具有很长的生命周期。

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

注意

部署 Modbus-RTU 协议适配器 连接器后,您可以使用 AWS IoT Things Graph 协调组中设备之间的交互。有关更多信息,请参阅 AWS 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 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 函数。

注意

连接器入门(控制台)连接器入门 (CLI) 主题包含详细步骤,说明如何配置和部署示例 Twilio 通知连接器。

 

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

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

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

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

  3. 配置 Greengrass 组。

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

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

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

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

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

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

  4. 部署组。

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

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

Ejemplo

以下是 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 核心软件许可协议发布。

Changelog

下表描述了连接器每个版本中所做的更改。

版本

更改

3

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

2

用于 AWS 区域支持的已更新连接器 ARN。

改进了错误日志记录。

1

首次发布。

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

另请参阅