本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
在本節中,您會在 Python 中開發 Hello World 元件,當核心裝置的電池電量低於部署元件時設定的閾值時,該元件會延遲更新。在此元件中,您會在 AWS IoT Device SDK v2 for Python 中使用程序間通訊 (IPC) 介面。您可以使用 SubscribeToComponentUpdates IPC 操作,在核心裝置收到部署時接收通知。然後,您可以使用 DeferComponentUpdate IPC 操作,根據裝置的電池電量延遲或確認更新。
開發延遲更新的 Hello World 元件
-
在開發電腦上,為元件原始碼建立資料夾。
mkdir com.example.BatteryAwareHelloWorld cd com.example.BatteryAwareHelloWorld
-
使用文字編輯器來建立名為 的檔案
gdk-config.json
。GDK CLI 會從名為 的 GDK CLI 組態檔案讀取gdk-config.json
,以建置和發佈元件。此組態檔案存在於元件資料夾的根目錄中。例如,在以 Linux 為基礎的系統上,您可以執行下列命令來使用 GNU nano 來建立 檔案。
nano gdk-config.json
將下列 JSON 複製到 檔案。
-
以您的名稱取代
Amazon
。 -
將
us-west-2
取代為核心裝置運作 AWS 區域 所在的 。GDK CLI 會在此發佈元件 AWS 區域。 -
將
greengrass-component-artifacts
取代為要使用的 S3 儲存貯體字首。當您使用 GDK CLI 發佈元件時,GDK CLI 會使用下列格式,將元件的成品上傳至 S3 儲存貯體,其名稱是從此值 AWS 區域、 和您的 AWS 帳戶 ID 形成:
。bucketPrefix
-region
-accountId
例如,如果您指定
greengrass-component-artifacts
和us-west-2
,且 AWS 帳戶 ID 為123456789012
,則 GDK CLI 會使用名為 的 S3 儲存貯體greengrass-component-artifacts-us-west-2-123456789012
。
{ "component": { "com.example.BatteryAwareHelloWorld": { "author": "
Amazon
", "version": "NEXT_PATCH", "build": { "build_system" : "zip" }, "publish": { "region": "us-west-2
", "bucket": "greengrass-component-artifacts
" } } }, "gdk_version": "1.0.0" }組態檔案會指定下列項目:
-
當 GDK CLI 將 Greengrass 元件發佈至雲端服務時要使用的 AWS IoT Greengrass 版本。
NEXT_PATCH
指定在 AWS IoT Greengrass 雲端服務中可用的最新版本之後選擇下一個修補程式版本。如果元件尚未在 AWS IoT Greengrass 雲端服務中擁有版本,GDK CLI 會使用1.0.0
。 -
元件的建置系統。當您使用
zip
建置系統時,GDK CLI 會將元件的來源封裝到 ZIP 檔案中,該檔案會成為元件的單一成品。 -
GDK CLI 發佈 Greengrass 元件 AWS 區域 的 。
-
GDK CLI 上傳元件成品的 S3 儲存貯體字首。
-
-
使用文字編輯器,在名為 的檔案中建立元件原始碼
main.py
。例如,在以 Linux 為基礎的系統上,您可以執行下列命令來使用 GNU nano 來建立 檔案。
nano main.py
將下列 Python 程式碼複製到 檔案。
import json import os import sys import time import traceback from pathlib import Path from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2 HELLO_WORLD_PRINT_INTERVAL = 15 # Seconds DEFER_COMPONENT_UPDATE_INTERVAL = 30 * 1000 # Milliseconds class BatteryAwareHelloWorldPrinter(): def __init__(self, ipc_client: GreengrassCoreIPCClientV2, battery_file_path: Path, battery_threshold: float): self.battery_file_path = battery_file_path self.battery_threshold = battery_threshold self.ipc_client = ipc_client self.subscription_operation = None def on_component_update_event(self, event): try: if event.pre_update_event is not None: if self.is_battery_below_threshold(): self.defer_update(event.pre_update_event.deployment_id) print('Deferred update for deployment %s' % event.pre_update_event.deployment_id) else: self.acknowledge_update( event.pre_update_event.deployment_id) print('Acknowledged update for deployment %s' % event.pre_update_event.deployment_id) elif event.post_update_event is not None: print('Applied update for deployment') except: traceback.print_exc() def subscribe_to_component_updates(self): if self.subscription_operation == None: # SubscribeToComponentUpdates returns a tuple with the response and the operation. _, self.subscription_operation = self.ipc_client.subscribe_to_component_updates( on_stream_event=self.on_component_update_event) def close_subscription(self): if self.subscription_operation is not None: self.subscription_operation.close() self.subscription_operation = None def defer_update(self, deployment_id): self.ipc_client.defer_component_update( deployment_id=deployment_id, recheck_after_ms=DEFER_COMPONENT_UPDATE_INTERVAL) def acknowledge_update(self, deployment_id): # Specify recheck_after_ms=0 to acknowledge a component update. self.ipc_client.defer_component_update( deployment_id=deployment_id, recheck_after_ms=0) def is_battery_below_threshold(self): return self.get_battery_level() < self.battery_threshold def get_battery_level(self): # Read the battery level from the virtual battery level file. with self.battery_file_path.open('r') as f: data = json.load(f) return float(data['battery_level']) def print_message(self): message = 'Hello, World!' if self.is_battery_below_threshold(): message += ' Battery level (%d) is below threshold (%d), so the component will defer updates' % ( self.get_battery_level(), self.battery_threshold) else: message += ' Battery level (%d) is above threshold (%d), so the component will acknowledge updates' % ( self.get_battery_level(), self.battery_threshold) print(message) def main(): # Read the battery threshold and virtual battery file path from command-line args. args = sys.argv[1:] battery_threshold = float(args[0]) battery_file_path = Path(args[1]) print('Reading battery level from %s and deferring updates when below %d' % ( str(battery_file_path), battery_threshold)) try: # Create an IPC client and a Hello World printer that defers component updates. ipc_client = GreengrassCoreIPCClientV2() hello_world_printer = BatteryAwareHelloWorldPrinter( ipc_client, battery_file_path, battery_threshold) hello_world_printer.subscribe_to_component_updates() try: # Keep the main thread alive, or the process will exit. while True: hello_world_printer.print_message() time.sleep(HELLO_WORLD_PRINT_INTERVAL) except InterruptedError: print('Subscription interrupted') hello_world_printer.close_subscription() except Exception: print('Exception occurred', file=sys.stderr) traceback.print_exc() exit(1) if __name__ == '__main__': main()
此 Python 應用程式會執行下列動作:
-
從您稍後將在核心裝置上建立的虛擬電池電量檔案讀取核心裝置的電池電量。此虛擬電池電量檔案會模擬真正的電池,因此您可以在沒有電池的核心裝置上完成此教學課程。
-
讀取電池閾值的命令列引數,以及虛擬電池電量檔案的路徑。元件配方會根據組態參數設定這些命令列引數,因此您可以在部署元件時自訂這些值。
-
使用 vV2中的 IPC 用戶端 V2 與 AWS IoT Greengrass Core 軟體通訊。 AWS IoT Device SDK
與原始 IPC 用戶端相比,IPC 用戶端 V2 可減少您在自訂元件中使用 IPC 所需的程式碼量。 -
訂閱以使用 SubscribeToComponentUpdates IPC 操作更新通知。 AWS IoT Greengrass 核心軟體會在每次部署前後傳送通知。元件每次收到通知時都會呼叫下列函數。如果通知適用於即將進行的部署,元件會檢查電池電量是否低於閾值。如果電池電量低於閾值,元件會使用 DeferComponentUpdate IPC 操作延遲更新 30 秒。否則,如果電池電量未低於閾值,元件會確認更新,因此可以繼續更新。
def on_component_update_event(self, event): try: if event.pre_update_event is not None: if self.is_battery_below_threshold(): self.defer_update(event.pre_update_event.deployment_id) print('Deferred update for deployment %s' % event.pre_update_event.deployment_id) else: self.acknowledge_update( event.pre_update_event.deployment_id) print('Acknowledged update for deployment %s' % event.pre_update_event.deployment_id) elif event.post_update_event is not None: print('Applied update for deployment') except: traceback.print_exc()
注意
AWS IoT Greengrass 核心軟體不會傳送本機部署的更新通知,因此您可以使用 AWS IoT Greengrass 雲端服務來部署此元件來進行測試。
-
-
使用文字編輯器,在名為
recipe.json
或 的檔案中建立元件配方recipe.yaml
。元件配方定義元件的中繼資料、預設組態參數和平台特定的生命週期指令碼。例如,在以 Linux 為基礎的系統上,您可以執行下列命令來使用 GNU nano 來建立 檔案。
nano recipe.json
將下列 JSON 複製到 檔案。
{ "RecipeFormatVersion": "2020-01-25", "ComponentName": "COMPONENT_NAME", "ComponentVersion": "COMPONENT_VERSION", "ComponentDescription": "This Hello World component defers updates when the battery level is below a threshold.", "ComponentPublisher": "COMPONENT_AUTHOR", "ComponentConfiguration": { "DefaultConfiguration": { "BatteryThreshold": 50, "LinuxBatteryFilePath": "/home/ggc_user/virtual_battery.json", "WindowsBatteryFilePath": "C:\\Users\\ggc_user\\virtual_battery.json" } }, "Manifests": [ { "Platform": { "os": "linux" }, "Lifecycle": { "install": "python3 -m pip install --user awsiotsdk --upgrade", "Run": "python3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py \"{configuration:/BatteryThreshold}\" \"{configuration:/LinuxBatteryFilePath}\"" }, "Artifacts": [ { "Uri": "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip", "Unarchive": "ZIP" } ] }, { "Platform": { "os": "windows" }, "Lifecycle": { "install": "py -3 -m pip install --user awsiotsdk --upgrade", "Run": "py -3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py \"{configuration:/BatteryThreshold}\" \"{configuration:/WindowsBatteryFilePath}\"" }, "Artifacts": [ { "Uri": "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip", "Unarchive": "ZIP" } ] } ] }
此配方會指定下列項目:
-
電池閾值的預設組態參數、Linux 核心裝置上的虛擬電池檔案路徑,以及 Windows 核心裝置上的虛擬電池檔案路徑。
-
安裝 AWS IoT Device SDK 最新版本 v2 for Python 的
install
生命週期。 -
在 中執行 Python 應用程式的
run
生命週期main.py
。 -
預留位置,例如
COMPONENT_NAME
和COMPONENT_VERSION
,其中 GDK CLI 會在建置元件配方時取代資訊。
如需元件配方的詳細資訊,請參閱AWS IoT Greengrass 元件配方參考。