与本地影子交互 - Amazon IoT Greengrass
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

与本地影子交互

使用影子 IPC 服务与设备上的本地影子交互。您选择与之交互的设备可以是您的核心设备或连接的客户端设备。

要使用这些 IPC 操作,请将影子管理器组件作为依赖关系包含在自定义组件中。然后,您可以在自定义组件中使用 IPC 操作,通过影子管理器与设备上的本地影子交互。要使自定义组件能够对本地影子状态的变化做出反应,您还可以使用发布/订阅 IPC 服务来订阅影子事件。有关使用发布/订阅服务的更多信息,请参阅 发布/订阅本地消息

注意

要使核心设备能够与客户端设备影子交互,您还必须配置和部署 MQTT 网桥组件。有关更多信息,请参阅启用影子管理器以与客户端设备通信

最低 SDK 版本

下表列出了与本地阴影交互时必须使用的最低版本 Amazon IoT Device SDK。

授权

要在自定义组件中使用影子 IPC 服务,必须定义允许您的组件与影子交互的授权策略。有关定义授权策略的信息,请参阅授权组件执行 IPC 操作

影子交互授权策略具有以下属性。

IPC 服务标识符:aws.greengrass.ShadowManager

操作 描述 资源

aws.greengrass#GetThingShadow

允许组件检索事物的影子。

以下字符串之一:

  • $aws/things/thingName/shadow/,允许访问经典设备影子。

  • $aws/things/thingName/shadow/name/shadowName,允许访问已命名的影子。

  • *,允许访问所有影子。

aws.greengrass#UpdateThingShadow

允许组件更新事物的影子。

以下字符串之一:

  • $aws/things/thingName/shadow/,允许访问经典设备影子。

  • $aws/things/thingName/shadow/name/shadowName,允许访问已命名的影子。

  • *,允许访问所有影子。

aws.greengrass#DeleteThingShadow

允许组件删除事物的影子。

以下字符串之一:

  • $aws/things/thingName/shadow/,允许访问经典设备影子。

  • $aws/things/thingName/shadow/name/shadowName,允许访问已命名的影子。

  • *,允许访问所有影子。

aws.greengrass#ListNamedShadowsForThing

允许组件为事物检索已命名影子列表。

允许访问事物以列出其影子的事物名称字符串。

* 以允许访问所有事物。

IPC 服务标识符:aws.greengrass.ipc.pubsub

操作 描述 资源

aws.greengrass#SubscribeToTopic

允许组件订阅您指定主题的消息。

以下主题字符串之一:

  • shadowTopicPrefix/get/accepted

  • shadowTopicPrefix/get/rejected

  • shadowTopicPrefix/delete/accepted

  • shadowTopicPrefix/delete/rejected

  • shadowTopicPrefix/update/accepted

  • shadowTopicPrefix/update/delta

  • shadowTopicPrefix/update/rejected

主题前缀 shadowTopicPrefix 的值取决于影子类型:

  • 经典影子:$aws/things/thingName/shadow

  • 已命名的影子:$aws/things/thingName/shadow/name/shadowName

* 以允许访问所有主题。

Greengrass Nucleus v2.6.0 及更高版本中,您可以订阅包含 MQTT 主题通配符(#+)的主题。此主题字符串支持 MQTT 主题通配符作为文字字符。例如,如果组件的授权策略授予访问 test/topic/# 的权限,则该组件可以订阅 test/topic/#,但无法订阅 test/topic/filter

本地影子授权策略中的配方变量

如果您使用 Greengrass Nucleus 的 v2.6.0 或更高版本,并且将 Greengrass Nucleus 的 interpolateComponentConfiguration 配置选项设置为 true,则可以在授权策略中使用 {iot:thingName} 配方变量。此功能允许您为一组核心设备配置单个授权策略,其中每个核心设备只能访问自己的影子。例如,您可以允许组件访问以下适用于影子 IPC 操作的资源。

$aws/things/{iot:thingName}/shadow/

授权策略示例

您可以参考以下授权策略示例,帮助您为组件配置授权策略。

例 示例:允许一组核心设备与本地影子交互
重要

此示例使用了 Greengrass Nucleus 组件的 v2.6.0 及更高版本中可用的功能。Greengrass Nucleus v2.6.0 在组件配置中添加了对大多数配方变量(例如 {iot:thingName})的支持。要启用此功能,请将 Greengrass Nucles 的 interpolateComponentConfiguration 配置选项设置为 true有关适用于所有版本 Greengrass Nucleus 的示例,请参阅单个核心设备的授权策略示例

以下示例授权策略允许组件 com.example.MyShadowInteractionComponent 与经典设备影子以及运行该组件的核心设备的已命名影子 myNamedShadow 进行交互。此策略还允许此组件接收这些影子的本地主题消息。

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/{iot:thingName}/shadow", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "{iot:thingName}" ] } }, "aws.greengrass.ipc.pubsub": { "com.example.MyShadowInteractionComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/{iot:thingName}/shadow/get/accepted", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/{iot:thingName}/shadow - $aws/things/{iot:thingName}/shadow/name/myNamedShadow 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - '{iot:thingName}' aws.greengrass.ipc.pubsub: 'com.example.MyShadowInteractionComponent:pubsub:1': policyDescription: 'Allows access to shadow pubsub topics' operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/{iot:thingName}/shadow/get/accepted - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted
例 示例:允许一组核心设备与客户端设备影子交互
重要

此功能需要 Greengrass Nucleus v2.6.0 或更高版本、影子管理器 v2.2.0 或更高版本以及 MQTT 网桥器 v2.2.0 或更高版本。您必须配置 MQTT 网桥器才能使影子管理器能够与客户端设备通信

以下示例授权策略允许组件 com.example.MyShadowInteractionComponent 与名称以 MyClientDevice 开头的客户端设备的所有设备影子进行交互。

注意

要使核心设备能够与客户端设备影子交互,您还必须配置和部署 MQTT 网桥组件。有关更多信息,请参阅启用影子管理器以与客户端设备通信

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/MyClientDevice*/shadow", "$aws/things/MyClientDevice*/shadow/name/*" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "MyClientDevice*" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/MyClientDevice*/shadow - $aws/things/MyClientDevice*/shadow/name/* 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - MyClientDevice*
例 示例:允许单个核心设备与本地影子交互

以下示例授权策略允许组件 com.example.MyShadowInteractionComponent 与设备 MyThingName 的经典设备影子和已命名影子 myNamedShadow 进行交互。此策略还允许此组件接收这些影子的本地主题消息。

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/MyThingName/shadow", "$aws/things/MyThingName/shadow/name/myNamedShadow" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "MyThingName" ] } }, "aws.greengrass.ipc.pubsub": { "com.example.MyShadowInteractionComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/MyThingName/shadow/get/accepted", "$aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/MyThingName/shadow - $aws/things/MyThingName/shadow/name/myNamedShadow 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - MyThingName aws.greengrass.ipc.pubsub: 'com.example.MyShadowInteractionComponent:pubsub:1': policyDescription: 'Allows access to shadow pubsub topics' operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/MyThingName/shadow/get/accepted - $aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted
例 示例:允许一组核心设备对本地影子状态变化做出反应
重要

此示例使用了 Greengrass Nucleus 组件的 v2.6.0 及更高版本中可用的功能。Greengrass Nucleus v2.6.0 在组件配置中添加了对大多数配方变量(例如 {iot:thingName})的支持。要启用此功能,请将 Greengrass Nucles 的 interpolateComponentConfiguration 配置选项设置为 true有关适用于所有版本 Greengrass Nucleus 的示例,请参阅单个核心设备的授权策略示例

以下示例访问控制策略允许自定义 com.example.MyShadowReactiveComponent 在运行该组件的每台核心设备上接收有关经典设备影子和已命名影子 myNamedShadow/update/delta 主题消息。

JSON
{ "accessControl": { "aws.greengrass.ipc.pubsub": { "com.example.MyShadowReactiveComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/{iot:thingName}/shadow/update/delta", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta" ] } } } }
YAML
accessControl: aws.greengrass.ipc.pubsub: "com.example.MyShadowReactiveComponent:pubsub:1": policyDescription: Allows access to shadow pubsub topics operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/{iot:thingName}/shadow/update/delta - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta
例 示例:允许单个核心设备对本地影子状态变化做出反应

以下示例访问控制策略允许自定义 com.example.MyShadowReactiveComponent 接收有关设备 MyThingName 的经典设备影子和已命名影子 myNamedShadow/update/delta 主题消息。

JSON
{ "accessControl": { "aws.greengrass.ipc.pubsub": { "com.example.MyShadowReactiveComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/MyThingName/shadow/update/delta", "$aws/things/MyThingName/shadow/name/myNamedShadow/update/delta" ] } } } }
YAML
accessControl: aws.greengrass.ipc.pubsub: "com.example.MyShadowReactiveComponent:pubsub:1": policyDescription: Allows access to shadow pubsub topics operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/MyThingName/shadow/update/delta - $aws/things/MyThingName/shadow/name/myNamedShadow/update/delta

GetThingShadow

获取指定事物的影子。

请求

此操作的请求包含以下参数:

thingName (Python: thing_name)

事物的名称。

类型:string

shadowName (Python: shadow_name)

影子的名称。要指定事物的经典影子,请将此参数设置为空字符串 ("")。

警告

Amazon IoT Greengrass 服务使用 AWSManagedGreengrassV2Deployment 命名的影子来管理针对单个核心设备的部署。这个已命名影子保留给 Amazon IoT Greengrass 服务使用。请勿更新或删除该已命名影子。

类型:string

响应

此操作的响应包含以下信息:

payload

响应状态文档为 blob。

类型:包含以下信息的 object

state

状态信息。

该对象包含以下信息。

desired

请求在设备中更新的状态属性和值。

类型:键/值对 map

reported

设备报告的状态属性和值。

类型:键/值对 map

delta

所需状态和报告的状态属性和值之间的差异。仅当 desiredreported 状态不同时,才会出现此属性。

类型:键/值对 map

metadata

desiredreported 部分中每个属性的时间戳,因此,您可以确定状态的更新时间。

类型:string

timestamp

生成响应时的 Epoch 日期和时间。

类型:integer

clientToken (Python: clientToken)

用于匹配请求和相应响应的令牌。

类型:string

version

本地影子文档版本。

类型:integer

错误

此操作可返回以下错误。

InvalidArgumentsError

本地影子服务无法验证请求参数。如果请求包含格式错误的 JSON 或不支持的字符,则可能会发生这种情况。

ResourceNotFoundError

无法找到请求的本地影子文档。

ServiceError

发生了内部服务错误,或者对 IPC 服务的请求数超过了影子管理器组件中 maxLocalRequestsPerSecondPerThingmaxTotalLocalRequestsRate 配置参数中指定的限制。

UnauthorizedError

该组件的授权策略不包括此操作所需权限。

示例

以下示例演示了如何在自定义组件代码中调用该操作。

Java (IPC client V1)
例 示例:获取事物影子
注意

此示例使用一个 IPCUtils 类来创建与 Amazon IoT Greengrass Core IPC 服务的连接。有关更多信息,请参阅 连接到 Amazon IoT Greengrass Core IPC 服务

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GetThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.model.GetThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.GetThingShadowResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class GetThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); GetThingShadowResponseHandler responseHandler = GetThingShadow.getThingShadow(ipcClient, thingName, shadowName); CompletableFuture<GetThingShadowResponse> futureResponse = responseHandler.getResponse(); try { GetThingShadowResponse response = futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); String shadowPayload = new String(response.getPayload(), StandardCharsets.UTF_8); System.out.printf("Successfully got shadow %s/%s: %s%n", thingName, shadowName, shadowPayload); } catch (TimeoutException e) { System.err.printf("Timeout occurred while getting shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while getting shadow: %s/%s%n", thingName, shadowName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.printf("Unable to find shadow to get: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static GetThingShadowResponseHandler getThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) { GetThingShadowRequest getThingShadowRequest = new GetThingShadowRequest(); getThingShadowRequest.setThingName(thingName); getThingShadowRequest.setShadowName(shadowName); return greengrassCoreIPCClient.getThingShadow(getThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例 示例:获取事物影子
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import GetThingShadowRequest TIMEOUT = 10 def sample_get_thing_shadow_request(thingName, shadowName): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the GetThingShadow request get_thing_shadow_request = GetThingShadowRequest() get_thing_shadow_request.thing_name = thingName get_thing_shadow_request.shadow_name = shadowName # retrieve the GetThingShadow response after sending the request to the IPC server op = ipc_client.new_get_thing_shadow() op.activate(get_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例 示例:获取事物影子
import { GetThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class GetThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleGetThingShadowOperation(this.thingName, this.shadowName); } catch (err) { // parse the error depending on your use cases throw err } } async handleGetThingShadowOperation( thingName: string, shadowName: string ) { const request: GetThingShadowRequest = { thingName: thingName, shadowName: shadowName }; const response = await this.ipcClient.getThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use caseså throw err } } const startScript = new GetThingShadow();

UpdateThingShadow

更新指定事物的影子。如果影子不存在,则会创建一个。

请求

此操作的请求包含以下参数:

thingName (Python: thing_name)

事物的名称。

类型:string

shadowName (Python: shadow_name)

影子的名称。要指定事物的经典影子,请将此参数设置为空字符串 ("")。

警告

Amazon IoT Greengrass 服务使用 AWSManagedGreengrassV2Deployment 命名的影子来管理针对单个核心设备的部署。这个已命名影子保留给 Amazon IoT Greengrass 服务使用。请勿更新或删除该已命名影子。

类型:string

payload

请求状态文档为 blob。

类型:包含以下信息的 object

state

要更新的状态信息。此 IPC 操作仅影响指定字段。

该对象包含以下信息。通常,您将使用 desiredreported 属性,但不能在同一请求中同时使用这两个属性。

desired

请求在设备中更新的状态属性和值。

类型:键/值对 map

reported

设备报告的状态属性和值。

类型:键/值对 map

clientToken (Python: client_token)

(可选)用于匹配请求和客户端令牌的相应响应的令牌。

类型:string

version

(可选)待更新的本地影子文档版本。影子服务只有在指定的版本与其拥有的最新版本一致时才会处理更新。

类型:integer

响应

此操作的响应包含以下信息:

payload

响应状态文档为 blob。

类型:包含以下信息的 object

state

状态信息。

该对象包含以下信息。

desired

请求在设备中更新的状态属性和值。

类型:键/值对 map

reported

设备报告的状态属性和值。

类型:键/值对 map

delta

设备报告的状态属性和值。

类型:键/值对 map

metadata

desiredreported 部分中每个属性的时间戳,因此,您可以确定状态的更新时间。

类型:string

timestamp

生成响应时的 Epoch 日期和时间。

类型:integer

clientToken (Python: client_token)

用于匹配请求和相应响应的令牌。

类型:string

version

更新完成后的本地影子文档的版本。

类型:integer

错误

此操作可返回以下错误。

ConflictError

本地影子服务在更新操作期间遇到了版本冲突。当请求有效载荷中的版本与最新的可用本地影子文档中的版本不匹配时,就会发生这种情况。

InvalidArgumentsError

本地影子服务无法验证请求参数。如果请求包含格式错误的 JSON 或不支持的字符,则可能会发生这种情况。

有效的 payload 具有以下属性:

  • state 节点存在,并且是一个包含 desiredreported 状态信息的对象。

  • desiredreported 节点要么是对象,要么为空。这些对象中至少有一个必须包含有效的状态信息。

  • desiredreported 对象的深度不能超过八个节点。

  • clientToken 值的长度不能超过 64 个字符。

  • version 值必须为 1 或更高。

ServiceError

发生了内部服务错误,或者对 IPC 服务的请求数超过了影子管理器组件中 maxLocalRequestsPerSecondPerThingmaxTotalLocalRequestsRate 配置参数中指定的限制。

UnauthorizedError

该组件的授权策略不包括此操作所需权限。

示例

以下示例演示了如何在自定义组件代码中调用该操作。

Java (IPC client V1)
例 示例:更新事物影子
注意

此示例使用一个 IPCUtils 类来创建与 Amazon IoT Greengrass Core IPC 服务的连接。有关更多信息,请参阅 连接到 Amazon IoT Greengrass Core IPC 服务

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.UpdateThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowResponse; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class UpdateThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; byte[] shadowPayload = args[2].getBytes(StandardCharsets.UTF_8); try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); UpdateThingShadowResponseHandler responseHandler = UpdateThingShadow.updateThingShadow(ipcClient, thingName, shadowName, shadowPayload); CompletableFuture<UpdateThingShadowResponse> futureResponse = responseHandler.getResponse(); try { futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); System.out.printf("Successfully updated shadow: %s/%s%n", thingName, shadowName); } catch (TimeoutException e) { System.err.printf("Timeout occurred while updating shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while updating shadow: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static UpdateThingShadowResponseHandler updateThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName, byte[] shadowPayload) { UpdateThingShadowRequest updateThingShadowRequest = new UpdateThingShadowRequest(); updateThingShadowRequest.setThingName(thingName); updateThingShadowRequest.setShadowName(shadowName); updateThingShadowRequest.setPayload(shadowPayload); return greengrassCoreIPCClient.updateThingShadow(updateThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例 示例:更新事物影子
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import UpdateThingShadowRequest TIMEOUT = 10 def sample_update_thing_shadow_request(thingName, shadowName, payload): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the UpdateThingShadow request update_thing_shadow_request = UpdateThingShadowRequest() update_thing_shadow_request.thing_name = thingName update_thing_shadow_request.shadow_name = shadowName update_thing_shadow_request.payload = payload # retrieve the UpdateThingShadow response after sending the request to the IPC server op = ipc_client.new_update_thing_shadow() op.activate(update_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ConflictError | UnauthorizedError | ServiceError
JavaScript
例 示例:更新事物影子
import { UpdateThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class UpdateThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; private shadowDocumentStr: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.shadowDocumentStr = "<define_your_own_payload>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleUpdateThingShadowOperation( this.thingName, this.shadowName, this.shadowDocumentStr); } catch (err) { // parse the error depending on your use cases throw err } } async handleUpdateThingShadowOperation( thingName: string, shadowName: string, payloadStr: string ) { const request: UpdateThingShadowRequest = { thingName: thingName, shadowName: shadowName, payload: payloadStr } // make the UpdateThingShadow request const response = await this.ipcClient.updateThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new UpdateThingShadow();

DeleteThingShadow

删除指定事物的影子。

从影子管理器 v2.0.4 开始,删除影子会增加版本号。例如,当您在版本 1 中删除影子 MyThingShadow 时,已删除影子的版本为 2。如果您随后使用名称 MyThingShadow 重新创建影子,则该影子的版本为 3。

请求

此操作的请求包含以下参数:

thingName (Python: thing_name)

事物的名称。

类型:string

shadowName (Python: shadow_name)

影子的名称。要指定事物的经典影子,请将此参数设置为空字符串 ("")。

警告

Amazon IoT Greengrass 服务使用 AWSManagedGreengrassV2Deployment 命名的影子来管理针对单个核心设备的部署。这个已命名影子保留给 Amazon IoT Greengrass 服务使用。请勿更新或删除该已命名影子。

类型:string

响应

此操作的响应包含以下信息:

payload

一个空的响应状态文档。

错误

此操作可返回以下错误。

InvalidArgumentsError

本地影子服务无法验证请求参数。如果请求包含格式错误的 JSON 或不支持的字符,则可能会发生这种情况。

ResourceNotFoundError

无法找到请求的本地影子文档。

ServiceError

发生了内部服务错误,或者对 IPC 服务的请求数超过了影子管理器组件中 maxLocalRequestsPerSecondPerThingmaxTotalLocalRequestsRate 配置参数中指定的限制。

UnauthorizedError

该组件的授权策略不包括此操作所需权限。

示例

以下示例演示了如何在自定义组件代码中调用该操作。

Java (IPC client V1)
例 示例:删除事物影子
注意

此示例使用一个 IPCUtils 类来创建与 Amazon IoT Greengrass Core IPC 服务的连接。有关更多信息,请参阅 连接到 Amazon IoT Greengrass Core IPC 服务

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.DeleteThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class DeleteThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); DeleteThingShadowResponseHandler responseHandler = DeleteThingShadow.deleteThingShadow(ipcClient, thingName, shadowName); CompletableFuture<DeleteThingShadowResponse> futureResponse = responseHandler.getResponse(); try { futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); System.out.printf("Successfully deleted shadow: %s/%s%n", thingName, shadowName); } catch (TimeoutException e) { System.err.printf("Timeout occurred while deleting shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while deleting shadow: %s/%s%n", thingName, shadowName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.printf("Unable to find shadow to delete: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static DeleteThingShadowResponseHandler deleteThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) { DeleteThingShadowRequest deleteThingShadowRequest = new DeleteThingShadowRequest(); deleteThingShadowRequest.setThingName(thingName); deleteThingShadowRequest.setShadowName(shadowName); return greengrassCoreIPCClient.deleteThingShadow(deleteThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例 示例:删除事物影子
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import DeleteThingShadowRequest TIMEOUT = 10 def sample_delete_thing_shadow_request(thingName, shadowName): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the DeleteThingShadow request delete_thing_shadow_request = DeleteThingShadowRequest() delete_thing_shadow_request.thing_name = thingName delete_thing_shadow_request.shadow_name = shadowName # retrieve the DeleteThingShadow response after sending the request to the IPC server op = ipc_client.new_delete_thing_shadow() op.activate(delete_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例 示例:删除事物影子
import { DeleteThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class DeleteThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleDeleteThingShadowOperation(this.thingName, this.shadowName) } catch (err) { // parse the error depending on your use cases throw err } } async handleDeleteThingShadowOperation(thingName: string, shadowName: string) { const request: DeleteThingShadowRequest = { thingName: thingName, shadowName: shadowName } // make the DeleteThingShadow request const response = await this.ipcClient.deleteThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new DeleteThingShadow();

ListNamedShadowsForThing

列出指定事物的命名影子。

请求

此操作的请求包含以下参数:

thingName (Python: thing_name)

事物的名称。

类型:string

pageSize (Python: page_size)

(可选)在每个调用中返回的影子名称的数量。

类型:integer

默认值:25

最大值:100

nextToken (Python: next_token)

(可选)用于检索下一组结果的令牌。该值在分页结果中返回,并在返回下一页的调用中使用。

类型:string

响应

此操作的响应包含以下信息:

results

影子名称列表。

类型:array

timestamp

(可选)生成响应的日期和时间。

类型:integer

nextToken (Python: next_token)

(可选)在检索序列中的下一页的分页请求中使用的令牌值。在没有其它要返回的影子名称时,该令牌不存在。

类型:string

注意

如果请求的页面大小与响应中的影子名称数量完全匹配,则出现此令牌;但使用时,它会返回一个空列表。

错误

此操作可返回以下错误。

InvalidArgumentsError

本地影子服务无法验证请求参数。如果请求包含格式错误的 JSON 或不支持的字符,则可能会发生这种情况。

ResourceNotFoundError

无法找到请求的本地影子文档。

ServiceError

发生了内部服务错误,或者对 IPC 服务的请求数超过了影子管理器组件中 maxLocalRequestsPerSecondPerThingmaxTotalLocalRequestsRate 配置参数中指定的限制。

UnauthorizedError

该组件的授权策略不包括此操作所需权限。

示例

以下示例演示了如何在自定义组件代码中调用该操作。

Java (IPC client V1)
例 示例:列出事物的已命名影子
注意

此示例使用一个 IPCUtils 类来创建与 Amazon IoT Greengrass Core IPC 服务的连接。有关更多信息,请参阅 连接到 Amazon IoT Greengrass Core IPC 服务

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.ListNamedShadowsForThingResponseHandler; import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingRequest; import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ListNamedShadowsForThing { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); List<String> namedShadows = new ArrayList<>(); String nextToken = null; try { // Send additional requests until there's no pagination token in the response. do { ListNamedShadowsForThingResponseHandler responseHandler = ListNamedShadowsForThing.listNamedShadowsForThing(ipcClient, thingName, nextToken, 25); CompletableFuture<ListNamedShadowsForThingResponse> futureResponse = responseHandler.getResponse(); ListNamedShadowsForThingResponse response = futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); List<String> responseNamedShadows = response.getResults(); namedShadows.addAll(responseNamedShadows); nextToken = response.getNextToken(); } while (nextToken != null); System.out.printf("Successfully got named shadows for thing %s: %s%n", thingName, String.join(",", namedShadows)); } catch (TimeoutException e) { System.err.println("Timeout occurred while listing named shadows for thing: " + thingName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.println("Unauthorized error while listing named shadows for " + "thing: " + thingName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.println("Unable to find thing to list named shadows: " + thingName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static ListNamedShadowsForThingResponseHandler listNamedShadowsForThing(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String nextToken, int pageSize) { ListNamedShadowsForThingRequest listNamedShadowsForThingRequest = new ListNamedShadowsForThingRequest(); listNamedShadowsForThingRequest.setThingName(thingName); listNamedShadowsForThingRequest.setNextToken(nextToken); listNamedShadowsForThingRequest.setPageSize(pageSize); return greengrassCoreIPCClient.listNamedShadowsForThing(listNamedShadowsForThingRequest, Optional.empty()); } }
Python (IPC client V1)
例 示例:列出事物的已命名影子
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import ListNamedShadowsForThingRequest TIMEOUT = 10 def sample_list_named_shadows_for_thing_request(thingName, nextToken, pageSize): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the ListNamedShadowsForThingRequest request list_named_shadows_for_thing_request = ListNamedShadowsForThingRequest() list_named_shadows_for_thing_request.thing_name = thingName list_named_shadows_for_thing_request.next_token = nextToken list_named_shadows_for_thing_request.page_size = pageSize # retrieve the ListNamedShadowsForThingRequest response after sending the request to the IPC server op = ipc_client.new_list_named_shadows_for_thing() op.activate(list_named_shadows_for_thing_request) fut = op.get_response() list_result = fut.result(TIMEOUT) # additional returned fields timestamp = list_result.timestamp next_token = result.next_token named_shadow_list = list_result.results return named_shadow_list, next_token, timestamp except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例 示例:列出事物的已命名影子
import { ListNamedShadowsForThingRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class listNamedShadowsForThing { private ipcClient: greengrasscoreipc.Client; private thingName: string; private pageSizeStr: string; private nextToken: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.pageSizeStr = "<define_your_own_pageSize>"; this.nextToken = "<define_your_own_token>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleListNamedShadowsForThingOperation(this.thingName, this.nextToken, this.pageSizeStr); } catch (err) { // parse the error depending on your use cases throw err } } async handleListNamedShadowsForThingOperation( thingName: string, nextToken: string, pageSizeStr: string ) { let request: ListNamedShadowsForThingRequest = { thingName: thingName, nextToken: nextToken, }; if (pageSizeStr) { request.pageSize = parseInt(pageSizeStr); } // make the ListNamedShadowsForThing request const response = await this.ipcClient.listNamedShadowsForThing(request); const shadowNames = response.results; } } export async function getIpcClient(){ try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new listNamedShadowsForThing();