AWS IoT Greengrass
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

Modbus-RTU 协议适配器

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

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

此连接器具有以下版本。

版本

ARN

2

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

1

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

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

要求

此连接器具有以下要求:

  • AWS IoT Greengrass 核心软件 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。

注意

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

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

必需:true

类型:string

有效模式:.+

ModbusSerialPort

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

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

必需:true

类型:string

有效模式:.+

创建连接器示例 (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/12", "Parameters": { "ModbusSerialDevice-ResourceId": "MyLocalModbusSerialPort", "ModbusSerialDevice": "/path-to-port" } } ] }'

注意

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

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

输入数据

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

主题筛选条件

modbus/adapter/request

消息属性

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

  • request 对象中:

    • operation。要执行的操作,由名称或函数代码指定。例如,要读取线圈,可以指定 ReadCoilsRequest0x01。该值必须是 Unicode 字符串。

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

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

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

示例输入:使用操作名称
{ "request": { "operation": "ReadCoilsRequest", "device": 1, "address": 0x01, "count": 1 }, "id": "TestRequest" }
示例输入:使用函数代码
{ "request": { "operation": 0x01, "device": 1, "address": 0x01, "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": 0x01, "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": 0x01, "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": 0x01, "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": 0x01, "value": 1 }, "id": "TestRequest" }
写入单线圈

请求示例:

{ "request": { "operation": "WriteSingleCoilRequest", "device": 1, "address": 0x01, "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": 0x01, "value": 1 }, "id": "TestRequest" }
写入多线圈

请求示例:

{ "request": { "operation": "WriteMultipleCoilsRequest", "device": 1, "address": 0x01, "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": 0x01, "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": 0x01, "and_mask": 0xaf, "or_mask": 0x01 }, "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": 0x01, "read_count": 2, "write_address": 0x03, "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" }

示例用法

以下是 Lambda 功能将输入消息发送到连接器的示例。

注意

该 Python 功能使用 AWS IoT Greengrass Core 开发工具包 来发布 MQTT 消息。您可以使用以下 pip 命令在核心设备上安装 SDK 的 Python 版本:

pip install greengrasssdk
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": 0x01, "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 function_handler(event, context): return

许可证

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

此连接器按照 Greengrass 核心软件许可协议发布。

Changelog

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

版本

更改

2

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

1

首次发布。

Greengrass 组一次只能包含一个版本的连接器。

另请参阅