

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 與元件組態互動
<a name="ipc-component-configuration"></a>

元件組態 IPC 服務可讓您執行下列動作：
+ 取得並設定元件組態參數。
+ 訂閱元件組態更新。
+ 在套用核心之前驗證元件組態更新。

**Topics**
+ [最低 SDK 版本](#ipc-component-configuration-sdk-versions)
+ [GetConfiguration](#ipc-operation-getconfiguration)
+ [UpdateConfiguration](#ipc-operation-updateconfiguration)
+ [SubscribeToConfigurationUpdate](#ipc-operation-subscribetoconfigurationupdate)
+ [SubscribeToValidateConfigurationUpdates](#ipc-operation-subscribetovalidateconfigurationupdates)
+ [SendConfigurationValidityReport](#ipc-operation-sendconfigurationvalidityreport)

## 最低 SDK 版本
<a name="ipc-component-configuration-sdk-versions"></a>

下表列出您可以用來與元件組態互動的SDKs最低版本。


| SDK | 最低版本 | 
| --- | --- | 
|  [AWS IoT Greengrass 元件 SDK (C、C\$1\$1、Rust)](https://github.com/aws-greengrass/aws-greengrass-component-sdk)  |  v1.0.0  | 
|  [AWS IoT Device SDK for Java v2](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK for Python v2](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  1.5.3 版  | 
|  [AWS IoT Device SDK 適用於 C\$1\$1 v2](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  1.17.0 版  | 
|  [AWS IoT Device SDK for JavaScript v2](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## GetConfiguration
<a name="ipc-operation-getconfiguration"></a>

取得核心裝置上元件的組態值。您可以指定要取得組態值的金鑰路徑。

### 請求
<a name="ipc-operation-getconfiguration-request"></a>

此操作的請求具有下列參數：

`componentName` (Python：`component_name`)  <a name="ipc-configuration-request-component-name"></a>
（選用） 元件的名稱。  
預設為發出請求的元件名稱。

`keyPath` (Python：`key_path`)  
組態值的金鑰路徑。指定清單，其中每個項目都是組態物件中單一層級的金鑰。例如，指定 `["mqtt", "port"]` 在下列組態`port`中取得 的值。  

```
{
  "mqtt": {
    "port": 443
  }
}
```
若要取得元件的完整組態，請指定空白清單。

### 回應
<a name="ipc-operation-getconfiguration-response"></a>

此操作的回應包含下列資訊：

`componentName` (Python：`component_name`)  <a name="ipc-configuration-response-component-name"></a>
元件的名稱。

`value`  
請求的組態做為 物件。

### 範例
<a name="ipc-operation-getconfiguration-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Rust ]

**Example 範例：取得組態**  

```
use core::mem::MaybeUninit;
use gg_sdk::{Sdk, UnpackedObject};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Get a configuration value at key path ["mqtt", "port"]
    let mut buf = [MaybeUninit::uninit(); 1024];

    let value = sdk
        .get_config(&["mqtt", "port"], None, &mut buf)
        .expect("Failed to get configuration");

    if let UnpackedObject::I64(port) = value.unpack() {
        println!("Configuration value: {port}");
    }
}
```

------
#### [ C ]

**Example 範例：取得組態**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Get a configuration value at key path ["mqtt", "port"]
    uint8_t response_mem[1024];
    GgObject value;

    err = ggipc_get_config(
        GG_BUF_LIST(GG_STR("mqtt"), GG_STR("port")),
        NULL, // component_name (NULL = current component)
        GG_BUF(response_mem),
        &value
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to get configuration.\n");
        exit(-1);
    }

    if (gg_obj_type(value) == GG_TYPE_I64) {
        printf("Configuration value: %" PRId64 "\n", gg_obj_into_i64(value));
    } else if (gg_obj_type(value) == GG_TYPE_BUF) {
        GgBuffer buf = gg_obj_into_buf(value);
        printf("Configuration value: %.*s\n", (int) buf.len, buf.data);
    } else {
        printf("Configuration value is of unexpected type.\n");
    }
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 範例：取得組態**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Get a configuration value at key path ["mqtt", "port"]
    std::array key_path = { gg::Buffer { "mqtt" }, gg::Buffer { "port" } };
    int64_t value = 0;

    error = client.get_config(key_path, std::nullopt, value);
    if (error) {
        std::cerr << "Failed to get configuration.\n";
        exit(-1);
    }

    std::cout << "Configuration value: " << value << "\n";
}
```

------

## UpdateConfiguration
<a name="ipc-operation-updateconfiguration"></a>

更新核心裝置上此元件的組態值。

### 請求
<a name="ipc-operation-updateconfiguration-request"></a>

此操作的請求具有下列參數：

`keyPath` (Python：`key_path`)  
（選用） 要更新的容器節點 ( 物件） 的金鑰路徑。指定清單，其中每個項目都是組態物件中單一層級的金鑰。例如，指定金鑰路徑`["mqtt"]`和合併值`{ "port": 443 }`，以在下列組態`port`中設定 的值。  

```
{
  "mqtt": {
    "port": 443
  }
}
```
金鑰路徑必須在組態中指定容器節點 （物件）。如果節點不存在於元件的組態中，此操作會建立節點，並將其值設定為 中的物件`valueToMerge`。  
預設為組態物件的根。

`timestamp`  
目前的 Unix epoch 時間，以毫秒為單位。此操作使用此時間戳記來解析金鑰的並行更新。如果元件組態中的金鑰的時間戳記大於請求中的時間戳記，則請求會失敗。

`valueToMerge` (Python：`value_to_merge`)  
要在您在 中指定的位置合併的組態物件`keyPath`。如需詳細資訊，請參閱[更新元件組態](update-component-configurations.md)。

### 回應
<a name="ipc-operation-updateconfiguration-response"></a>

此操作不會在其回應中提供任何資訊。

### 範例
<a name="ipc-operation-updateconfiguration-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Rust ]

**Example 範例：更新組態**  

```
use gg_sdk::Sdk;

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Update configuration value at key path ["mqtt", "port"] to 443
    sdk.update_config(&["mqtt", "port"], None, 443)
        .expect("Failed to update configuration");

    println!("Successfully updated configuration.");
}
```

------
#### [ C ]

**Example 範例：更新組態**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Update configuration value at key path ["mqtt", "port"] to 443
    err = ggipc_update_config(
        GG_BUF_LIST(GG_STR("mqtt"), GG_STR("port")),
        NULL, // timestamp (NULL = current time)
        gg_obj_i64(443)
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to update configuration.\n");
        exit(-1);
    }

    printf("Successfully updated configuration.\n");
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 範例：更新組態**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Update configuration value at key path ["mqtt", "port"] to 443
    std::array key_path = { gg::Buffer { "mqtt" }, gg::Buffer { "port" } };

    error = client.update_config(key_path, 443);
    if (error) {
        std::cerr << "Failed to update configuration.\n";
        exit(-1);
    }

    std::cout << "Successfully updated configuration.\n";
}
```

------

## SubscribeToConfigurationUpdate
<a name="ipc-operation-subscribetoconfigurationupdate"></a>

訂閱以在元件的組態更新時接收通知。當您訂閱金鑰時，當該金鑰的任何子項更新時，您會收到通知。

<a name="ipc-subscribe-operation-note"></a>此操作是您訂閱事件訊息串流的訂閱操作。若要使用此操作，請使用處理事件訊息、錯誤和串流關閉的函數來定義串流回應處理常式。如需詳細資訊，請參閱[訂閱 IPC 事件串流](interprocess-communication.md#ipc-subscribe-operations)。

**事件訊息類型：** `ConfigurationUpdateEvents`

### 請求
<a name="ipc-operation-subscribetoconfigurationupdate-request"></a>

此操作的請求具有下列參數：

`componentName` (Python：`component_name`)  <a name="ipc-configuration-request-component-name"></a>
（選用） 元件的名稱。  
預設為發出請求的元件名稱。

`keyPath` (Python：`key_path`)  
要訂閱之組態值的金鑰路徑。指定清單，其中每個項目都是組態物件中單一層級的金鑰。例如，指定 `["mqtt", "port"]` 在下列組態`port`中取得 的值。  

```
{
  "mqtt": {
    "port": 443
  }
}
```
若要訂閱元件組態中所有值的更新，請指定空白清單。

### 回應
<a name="ipc-operation-subscribetoconfigurationupdate-response"></a>

此操作的回應包含下列資訊：

`messages`  
通知訊息的串流。此物件 `ConfigurationUpdateEvents`包含下列資訊：    
`configurationUpdateEvent` (Python：`configuration_update_event`)  
組態更新事件。此物件 `ConfigurationUpdateEvent`包含下列資訊：    
`componentName` (Python：`component_name`)  <a name="ipc-configuration-response-component-name"></a>
元件的名稱。  
`keyPath` (Python：`key_path`)  
已更新之組態值的金鑰路徑。

### 範例
<a name="ipc-operation-subscribetoconfigurationupdate-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Rust ]

**Example 範例：訂閱組態更新**  

```
use gg_sdk::Sdk;
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Subscribe to configuration updates for key path ["mqtt"]
    let callback = |component_name: &str, key_path: &[&str]| {
        println!(
            "Received configuration update for component: {component_name}"
        );
        println!("Key path: {key_path:?}");
    };

    let _sub = sdk
        .subscribe_to_configuration_update(None, &["mqtt"], &callback)
        .expect("Failed to subscribe to configuration updates");

    println!("Successfully subscribed to configuration updates.");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

------
#### [ C ]

**Example 範例：訂閱組態更新**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx,
    GgBuffer component_name,
    GgList key_path,
    GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    printf(
        "Received configuration update for component: %.*s\n",
        (int) component_name.len,
        component_name.data
    );

    printf("Key path: [");
    for (size_t i = 0; i < key_path.len; i++) {
        if (i > 0) {
            printf(", ");
        }
        GgObject *obj = &key_path.items[i];
        if (gg_obj_type(*obj) == GG_TYPE_BUF) {
            GgBuffer key = gg_obj_into_buf(*obj);
            printf("\"%.*s\"", (int) key.len, key.data);
        }
    }
    printf("]\n");
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Subscribe to configuration updates for key path ["mqtt"]
    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_configuration_update(
        NULL, // component_name (NULL = current component)
        GG_BUF_LIST(GG_STR("mqtt")),
        on_subscription_response,
        NULL,
        &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to subscribe to configuration updates.\n");
        exit(-1);
    }

    printf("Successfully subscribed to configuration updates.\n");

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the stream.
    ggipc_close_subscription(handle);
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 範例：訂閱組態更新**  

```
#include <gg/ipc/client.hpp>
#include <unistd.h>
#include <iostream>

class ResponseHandler : public gg::ipc::ConfigurationUpdateCallback {
    void operator()(
        std::string_view component_name,
        gg::List key_path,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        std::cout << "Received configuration update for component: "
                  << component_name << "\n";
        std::cout << "Key path: [";
        for (size_t i = 0; i < key_path.size(); i++) {
            if (i > 0) {
                std::cout << ", ";
            }
            std::cout << "\"" << get<gg::Buffer>(key_path[i]) << "\"";
        }
        std::cout << "]\n";
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Subscribe to configuration updates for key path ["mqtt"]
    std::array key_path = { gg::Buffer { "mqtt" } };

    static ResponseHandler handler;
    error = client.subscribe_to_configuration_update(
        key_path, std::nullopt, handler
    );
    if (error) {
        std::cerr << "Failed to subscribe to configuration updates.\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to configuration updates.\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

------

## SubscribeToValidateConfigurationUpdates
<a name="ipc-operation-subscribetovalidateconfigurationupdates"></a>

訂閱以在此元件的組態更新之前接收通知。這可讓元件驗證其自身組態的更新。使用 [SendConfigurationValidityReport](#ipc-operation-sendconfigurationvalidityreport)操作來告知核心組態是否有效。

**重要**  
本機部署不會通知更新元件。

<a name="ipc-subscribe-operation-note"></a>此操作是您訂閱事件訊息串流的訂閱操作。若要使用此操作，請使用處理事件訊息、錯誤和串流關閉的函數來定義串流回應處理常式。如需詳細資訊，請參閱[訂閱 IPC 事件串流](interprocess-communication.md#ipc-subscribe-operations)。

**事件訊息類型：** `ValidateConfigurationUpdateEvents`

### 請求
<a name="ipc-operation-subscribetovalidateconfigurationupdates-request"></a>

此操作的請求沒有任何參數。

### 回應
<a name="ipc-operation-subscribetovalidateconfigurationupdates-response"></a>

此操作的回應包含下列資訊：

`messages`  
通知訊息的串流。此物件 `ValidateConfigurationUpdateEvents`包含下列資訊：    
`validateConfigurationUpdateEvent` (Python：`validate_configuration_update_event`)  
組態更新事件。此物件 `ValidateConfigurationUpdateEvent`包含下列資訊：    
`deploymentId` (Python：`deployment_id`)  
更新元件的 AWS IoT Greengrass 部署 ID。  
`configuration`  
包含新組態的物件。

## SendConfigurationValidityReport
<a name="ipc-operation-sendconfigurationvalidityreport"></a>

告知核心此元件的組態更新是否有效。如果您告訴核心新組態無效，則部署會失敗。使用 [SubscribeToValidateConfigurationUpdates](#ipc-operation-subscribetovalidateconfigurationupdates)操作來訂閱以驗證組態更新。

如果元件未回應驗證組態更新通知，則 nucleus 會等待您在部署的組態驗證政策中指定的時間量。逾時之後，核會繼續進行部署。預設元件驗證逾時為 20 秒。如需詳細資訊，請參閱 [建立部署](create-deployments.md)和您可以在呼叫 [CreateDeployment](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_CreateDeployment.html) 操作時提供的 [DeploymentConfigurationValidationPolicy](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_DeploymentConfigurationValidationPolicy.html) 物件。

### 請求
<a name="ipc-operation-sendconfigurationvalidityreport-request"></a>

此操作的請求具有下列參數：

`configurationValidityReport` (Python：`configuration_validity_report`)  
告知核心組態更新是否有效的報告。此物件 `ConfigurationValidityReport`包含下列資訊：    
`status`  
有效性狀態。此列舉 `ConfigurationValidityStatus`具有下列值：  
+ `ACCEPTED` – 組態有效，且 核可以套用到此元件。
+ `REJECTED` – 組態無效且部署失敗。  
`deploymentId` (Python：`deployment_id`)  
請求組態更新的 AWS IoT Greengrass 部署 ID。  
`message`  
（選用） 報告組態為何無效的訊息。

### 回應
<a name="ipc-operation-sendconfigurationvalidityreport-response"></a>

此操作不會在其回應中提供任何資訊。