Platform 13.3.7 · Python Device SDK 3.1.0 · API Reference
從零開始理解並使用完整 API
本手冊只描述目前正式支援的 Client API。內容從名詞、資料流、第一次啟用、後續驗證與錯誤處理開始,再逐一說明每個方法的參數、網路行為、持久化影響、重試原則、成功判斷與排錯方式。
第一次接 SDK,先懂這三件事
DeviceLicenseClient
它是應用程式的授權入口,保存公開部署設定、管理 registration.json、呼叫 TPM,並驗證 Gateway 回應簽章。建立 Client 本身不會立刻修改 Server。
LicenseState
它是某次註冊或驗證的結果快照,包含有效性、Entitlement、Usage 與到期資訊。它不會自行更新。長時間程式必須由自己的 Timer、scheduler 或工作 checkpoint 主動呼叫 session.check()/validate。
本機操作與 Server 操作
has、require、Log 與 Model helper 多半只在本機執行;註冊、驗證、Usage、Heartbeat、Component 與 Process Seat 會連線或修改 Server。
`.env`、Process Environment 與 env(name, default)
SDK 本身不要求 `.env`。Admin 完整範例 ZIP 會隨附 `.env.example`;先複製成與 `.py` 同目錄的 `.env`。範例提供標準函式庫 Loader,自動讀取設定;這只建立目前 Python Process 的設定,不會連線或修改 Server。
env("KEYGEN_GATEWAY_URL")必填;缺少或空白時停止並提示。不是自動向 Server 查 URL。env("ABC", "123")讀 ABC;沒有值時回傳字串 123。不會永久建立 ABC,也不會自動轉成整數。int(env("SECONDS", "300"))先讀字串,再由 int 轉成整數。env 本身永遠回傳文字。KEYGEN_ENV_FILE選擇另一個設定檔路徑;一般使用者不需設定。它不是 Server 的 `.env`。優先序是 OS/IDE/Service Manager Environment → `.env` → default。Client `.env` 只能放公開部署值與非敏感選項;License Key 與所有 Server Secret 都必須排除。
每個 Server API 呼叫都必須使用目前 API Revision
SDK 3.1.0 會自動送出 X-Keygen-Device-API-Version: 2026-07-27。缺少或不同時,Gateway 在授權業務邏輯前回傳 HTTP 426,SDK 轉成 ClientCompatibilityError。這不是 License 無效,也不能靠等待修復。
Session 不會自己定時重驗:Heartbeat 與完整驗證的執行模型
licensed_session() 不會在背景自動做完整 License 重驗。它只在啟用 Machine Heartbeat 或 Process Seat 時建立背景 heartbeat thread。你的程式仍要主動呼叫 session.check()。
machine_heartbeat=True進入 Session 時同步首次 ping,之後一條 daemon thread 自動 ping。前景定期 session.check(),接收背景失敗。process_seat=True同步取得 Seat,之後另一條 daemon thread 自動 ping;正常離開時釋放。Session 外的背景工作必須先停止再離開 context。revalidate_interval_seconds=300只是 session.check() 的到期門檻,沒有 Timer、沒有驗證 thread。例如 GUI worker 每 15 秒 check;達 300 秒的 check 才完整連線重驗。session.check(force_validate=True)在目前呼叫執行緒立即執行完整 HTTPS + TPM 驗證。放在匯出、燒錄、產檔、分析等高價值操作前,GUI 使用 worker。ManagedHeartbeat.check()只讀背景 thread 保存的 state/error,不會自己送 ping。每 5~30 秒或主要 checkpoint 呼叫,不要 busy loop。我需要自己寫 for 迴圈嗎?
不需要為了 Session 建立無延遲迴圈。GUI 用 QTimer/Tk after,服務用 scheduler,既有工作迴圈則加入 Event.wait 或合理間隔的 checkpoint。
背景錯誤會自動跳到主執行緒嗎?
不會。Heartbeat thread 保存錯誤;下一次 session.check() 或 lease.check() 才會在你的流程中拋 HeartbeatError。
SDK 新手最容易混淆的 12 個名詞
先分清楚每個物件負責的問題,才能選對 API,並避免把本機清除、Server 解綁、功能權限與計次混在一起。
Gateway URL
Client 對外連線的 HTTPS 根網址。SDK 自行附加 /device/v1/*。
Product ID
Server 上產品的完整 UUID,不是 Account ID、Policy ID 或短碼。
Product Namespace
同一產品固定使用的本機隔離名稱,參與 registration 路徑與 TPM Key Name。
License Key
第一次啟用時輸入的憑證,不保存到 registration.json,也不能寫入 Log。
Device Registration
Server 記錄的裝置公開身分與 TPM Public Key 關聯,不包含可匯出的私鑰。
TPM Key
Windows TPM 內不可匯出的 P-256 私鑰,用來簽署一次性 Challenge。
Machine
Server 上的裝置席位。清除本機資料不會釋放 Machine,必須由管理員處理。
LicenseState
一次驗證的結果快照,包含 valid、code、到期、Entitlement 與 Usage。
Entitlement
功能代碼,例如 HDL_EXPORT。整體 License 有效後,功能入口仍要 require。
Usage
成功完成受限工作的次數,不等於 Machine、Process 或 Check-in。
Heartbeat / Check-in
Heartbeat 維持 Machine 或 Process 活性;Check-in 更新 License 定期回報。
ValidationScope
要求 Server 額外比對 Release、Checksum、User、Entitlement 或 Component 的條件。
10 分鐘最小整合流程
- 步驟 1
向管理員取得 Gateway URL、Product UUID、固定 Namespace、Gateway Public Key、Key ID 與 SDK Wheel。License Key 只在第一次啟用輸入。
- 步驟 2
建立 ClientConfig;不要把 /device/v1 手動接到 URL,也不要把任何 Server Secret 放入 Client。
- 步驟 3
用 requires_license_key 決定是否提示輸入 License Key,再呼叫 ensure_registered。
- 步驟 4
取得 LicenseState 後先 require_valid,再在真正功能入口 require 對應 Entitlement。
- 步驟 5
重新啟動確認日常驗證只使用 Device ID、一次性 Challenge 與 TPM Signature,不要求保存 License Key。
- 步驟 6
最後才依商業規則加入 Usage、Heartbeat、Process Seat、User 或 Component。
import getpass
from keygen_device_sdk import ClientConfig, DeviceLicenseClient, LicenseSDKError
client = DeviceLicenseClient(ClientConfig(
gateway_base_url="https://license.example.com",
product_id="YOUR-PRODUCT-UUID",
product_namespace="com.example.product",
gateway_signing_public_key_b64="GATEWAY-PUBLIC-KEY",
gateway_signing_key_id="gateway-v1",
))
first_key = getpass.getpass("License key: ").strip() if client.requires_license_key else None
try:
state = client.ensure_registered(first_key)
state.require_valid()
state.require("HDL_EXPORT")
run_protected_feature()
except LicenseSDKError as exc:
block_protected_feature(str(exc))
三條必須看懂的完整生命週期
整合測試至少要覆蓋第一次啟用、日常啟動與真正執行高價值功能。任何授權或信任鏈錯誤都必須阻擋受保護操作。
第一次啟用
- requires_license_key=True。
- 使用者輸入 License Key。
- SDK 建立 TPM Key 並取得 Challenge。
- TPM 簽章,Gateway 驗證 License、Product 與 Policy。
- Server 建立 Device Registration/Machine,本機保存 registration。
- Client 驗證 LicenseState 與 Entitlement 後開放功能。
日常啟動
- 讀取 registration 並檢查 TPM Key。
- Gateway 發出新的單次 Challenge。
- TPM 使用原私鑰簽章。
- Gateway 回傳簽章保護的最新 LicenseState。
- Client 驗證 Gateway Signature、到期、撤銷、Usage 與 Scope。
- 失敗時鎖定受保護功能。
高價值功能入口
- 取得最新 state 或 session.check()。
- require_valid()。
- require(FEATURE_CODE)。
- 執行產檔、匯出、燒錄或分析。
- 成功後才增加 Usage。
- 保存安全化 request_id、code 與結果。
ClientConfig 核心欄位
以下欄位不是憑證,但必須正確且固定。Admin Token、License-scoped Token、Gateway Private Key 與資料庫密碼永遠不能放入 Client。
gateway_base_url公開 HTTPS Gateway 根網址;SDK 自行呼叫 /device/v1/*。手動接 /device/v1、使用 HTTP、讓一般使用者任意改網址。product_id管理端 Product 的完整 UUID。填 Account ID、Policy ID、短碼或截斷 UUID。product_namespace同一產品所有版本固定共用的本機命名空間。每次發版更換 Namespace,或不同產品共用同一值。gateway_signing_public_key_b64驗證 Gateway 回應簽章的 Ed25519 信任根。把 Product ID 當公鑰、忽略簽章錯誤、從不可信設定載入。state_directoryregistration.json 與本機狀態保存位置。放暫存、網路共享、唯讀或會被清理的位置。validation_scope只有 Policy 要求額外 Scope 時才填。把 Platform/SDK 版本填入 version,或用不可信 username 當 user_id。從需求反推 API
先描述要完成的事情,再選方法。名稱相近的註冊、驗證、Machine、Process、Usage 與本機重置不可混用。
requires_license_key + ensure_registered()每次都呼叫 register()validate_or_raise()validate() 後忘記檢查 state.validrequire() / require_all()只限制 UI 按鈕licensed_session() + session.check()忽略背景錯誤increment_usage(1)工作開始前扣量或盲目重送process_seat()使用 Machine 上限代替machine_heartbeat()把停止 Heartbeat 當成解除 Machinelocal_identity_info() 後受控 reset直接刪除所有 TPM Keyconnection_log_text() 與具體例外except Exception: pass依工作流程閱讀完整 API
標準應用通常只需要初始化、首次啟用、驗證授權與一種執行中管理方式,不需要從第一個方法讀到最後。
建議的錯誤處理骨架
from keygen_device_sdk import (
ClientCompatibilityError,
GatewayError,
LicenseSDKError,
)
try:
state = client.ensure_registered(first_key)
state.require("HDL_EXPORT")
except ClientCompatibilityError as exc:
disable_protected_features()
show_upgrade_required(
current_api=exc.provided_api_version or "missing",
required_api=exc.required_api_version,
required_sdk=exc.required_sdk_version,
)
except GatewayError as exc:
show_gateway_error(
code=exc.code,
status_code=exc.status_code,
retry_after_seconds=exc.retry_after_seconds,
message=str(exc),
)
except LicenseSDKError as exc:
show_license_error(str(exc))
搜尋與篩選
可用 API 名稱、用途、參數、回傳型別、例外或常見誤用搜尋;分類後仍會保留工作流程章節。
Workflow 01
1. 建立 Client 與準備輸入
先建立固定的 ClientConfig,再準備檔案 checksum、Machine metrics 或 Component fingerprint。這一組不會建立 License 或修改 Server 狀態。
- 1
建立 ClientConfig
- 2
建立 DeviceLicenseClient
- 3
需要時準備 Scope 或硬體識別資料
輔助工具build_component_fingerprint將穩定的硬體或邏輯識別值做具命名空間的 SHA-256 雜湊,避免把原始序號送到 Server。
build_component_fingerprint(value: str, *, namespace: str = '', prefix: str = 'component-sha256') -> str白話解釋:將穩定的硬體或邏輯識別值做具命名空間的 SHA-256 雜湊,避免把原始序號送到 Server。
參數怎麼填
value: str必填要轉換或建立 fingerprint 的原始穩定值;不可傳空字串。
namespace: str = ''可選識別值的固定命名空間,用來避免不同種類資料碰撞。同一產品與元件類型應長期保持一致。
prefix: str = 'component-sha256'可選輸出 fingerprint 的可讀前綴;只用於辨識格式,不是秘密。
Machine Component 需要穩定 fingerprint,但不希望保存原始序號時。
- 先確認輸入值或檔案是你真正要綁定的穩定資料。
- 只計算雜湊、fingerprint 或本機資源資訊。
- 不會建立 License、Machine、Device Registration 或扣除 Usage。
格式為 <prefix>:<sha256> 的字串。
- ValueError:value 為空。
- namespace 應固定且與元件種類相關。
- 同一 namespace 與 value 會得到同一結果。
同步、本機計算
不會建立背景執行緒。
- 在目前呼叫執行緒計算 checksum、fingerprint 或讀取系統資訊。
- 決定何時呼叫並保存結果。
- 對檔案 I/O 錯誤提供可理解訊息。
- 建立 ClientConfig 前、準備 ValidationScope 或同步 Component 前。
計算大型檔案 checksum 可能阻塞;GUI 應在 worker thread 執行。
準備可信輸入。 → 呼叫 helper。 → 把結果交給後續驗證或 Component API。
不連線。只讀取本機值、檔案或系統資訊。
不修改 Server;可能只在記憶體產生 checksum、fingerprint 或 metrics。
輸入檔案暫時被占用時可在確認路徑正確後重試;輸入值錯誤則應先修正,不要無限重試。
確認結果格式符合方法文件,並以同一輸入重算得到相同結果。
把錯誤描述成『本機資料無法讀取』並顯示安全化路徑,不要輸出敏感原始序號。
- 確認檔案存在且目前帳號可讀。
- 確認 fingerprint 輸入是長期穩定值,而不是時間、暫存路徑或隨機值。
- 把會變動的路徑、時間或暫存值當成永久 fingerprint。
- 把 Platform/SDK 版本誤當成檔案 checksum。
fingerprint = build_component_fingerprint(serial, namespace='fpga-board')
輔助工具calculate_file_checksum以串流方式計算檔案雜湊,可放入 ValidationScope.checksum。
calculate_file_checksum(path: str | Path, algorithm: str = 'sha512') -> str白話解釋:以串流方式計算檔案雜湊,可放入 ValidationScope.checksum。
參數怎麼填
path: str | Path必填本機檔案或目錄路徑。使用 Path 物件可避免 Windows 路徑跳脫問題。
algorithm: str = 'sha512'可選雜湊演算法名稱。除非管理員另有規定,沿用預設值即可。
Policy 要求 checksum scope,或應用程式需要確認受保護 Artifact 時。
- 先確認輸入值或檔案是你真正要綁定的穩定資料。
- 只計算雜湊、fingerprint 或本機資源資訊。
- 不會建立 License、Machine、Device Registration 或扣除 Usage。
十六進位雜湊字串。
- FileNotFoundError/OSError:檔案不可讀。
- ValueError:演算法不支援。
- 不要把 Platform 版本代替 checksum。
同步、本機計算
不會建立背景執行緒。
- 在目前呼叫執行緒計算 checksum、fingerprint 或讀取系統資訊。
- 決定何時呼叫並保存結果。
- 對檔案 I/O 錯誤提供可理解訊息。
- 建立 ClientConfig 前、準備 ValidationScope 或同步 Component 前。
計算大型檔案 checksum 可能阻塞;GUI 應在 worker thread 執行。
準備可信輸入。 → 呼叫 helper。 → 把結果交給後續驗證或 Component API。
不連線。只讀取本機值、檔案或系統資訊。
不修改 Server;可能只在記憶體產生 checksum、fingerprint 或 metrics。
輸入檔案暫時被占用時可在確認路徑正確後重試;輸入值錯誤則應先修正,不要無限重試。
確認結果格式符合方法文件,並以同一輸入重算得到相同結果。
把錯誤描述成『本機資料無法讀取』並顯示安全化路徑,不要輸出敏感原始序號。
- 確認檔案存在且目前帳號可讀。
- 確認 fingerprint 輸入是長期穩定值,而不是時間、暫存路徑或隨機值。
- 把會變動的路徑、時間或暫存值當成永久 fingerprint。
- 把 Platform/SDK 版本誤當成檔案 checksum。
checksum = calculate_file_checksum(Path(sys.executable))
輔助工具collect_machine_metrics讀取 CPU core、實體記憶體與系統磁碟容量,不依賴 psutil。
collect_machine_metrics() -> MachineMetrics白話解釋:讀取 CPU core、實體記憶體與系統磁碟容量,不依賴 psutil。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
要預覽或自行提供 Machine Profile 資源資訊時。
- 先確認輸入值或檔案是你真正要綁定的穩定資料。
- 只計算雜湊、fingerprint 或本機資源資訊。
- 不會建立 License、Machine、Device Registration 或扣除 Usage。
MachineMetrics。
- 通常不拋例外;不可讀欄位會回 0。
- ClientConfig.auto_collect_machine_metrics=True 時 SDK 會自動收集。
同步、本機計算
不會建立背景執行緒。
- 在目前呼叫執行緒計算 checksum、fingerprint 或讀取系統資訊。
- 決定何時呼叫並保存結果。
- 對檔案 I/O 錯誤提供可理解訊息。
- 建立 ClientConfig 前、準備 ValidationScope 或同步 Component 前。
計算大型檔案 checksum 可能阻塞;GUI 應在 worker thread 執行。
準備可信輸入。 → 呼叫 helper。 → 把結果交給後續驗證或 Component API。
不連線。只讀取本機值、檔案或系統資訊。
不修改 Server;可能只在記憶體產生 checksum、fingerprint 或 metrics。
輸入檔案暫時被占用時可在確認路徑正確後重試;輸入值錯誤則應先修正,不要無限重試。
確認結果格式符合方法文件,並以同一輸入重算得到相同結果。
把錯誤描述成『本機資料無法讀取』並顯示安全化路徑,不要輸出敏感原始序號。
- 確認檔案存在且目前帳號可讀。
- 確認 fingerprint 輸入是長期穩定值,而不是時間、暫存路徑或隨機值。
- 把會變動的路徑、時間或暫存值當成永久 fingerprint。
- 把 Platform/SDK 版本誤當成檔案 checksum。
metrics = collect_machine_metrics()
初始化DeviceLicenseClient建立 TPM-backed Client,驗證 HTTPS、Gateway Public Key、Heartbeat 與 Connection Log 設定。
DeviceLicenseClient(config: ClientConfig)白話解釋:建立 TPM-backed Client,驗證 HTTPS、Gateway Public Key、Heartbeat 與 Connection Log 設定。
參數怎麼填
config: ClientConfig必填已建立的 ClientConfig。裡面放公開 Gateway URL、Product UUID、固定 Namespace 與 Gateway 公鑰;不可放 Admin Token、License Token 或私鑰。
每個 Product/Namespace 建立一個長生命週期 Client instance。
- 先向管理員取得 Gateway URL、Product UUID、固定 Product Namespace、Gateway Public Key 與 Key ID。
- 確認 Windows TPM 可用,並決定 registration.json 與 Connection Log 的保存位置。
- 只在記憶體建立 Client 設定與物件。
- 直到呼叫註冊、驗證、Heartbeat、Usage 或其他線上方法前,不會修改 Server。
DeviceLicenseClient。
- ValueError:URL、Public Key、Clock Skew 或 Heartbeat 設定不合法。
- TPMUnavailableError:實際存取 TPM 時。
- 同一 Product 的 product_namespace 必須長期固定。
- 不要把 Admin Token、License Token 或 Gateway Private Key 放入 ClientConfig。
同步、本機、立即回傳
不會建立背景執行緒。
- 只驗證設定並建立 Python 物件。
- 在應用程式啟動時建立一個長生命週期 Client。
- 自行保存 Client reference;不要每個按鈕事件都重新建立。
- 應用程式啟動或依賴注入初始化階段。
不做網路 I/O,通常只花極短時間;參數不合法時立即拋 ValueError。
建立 ClientConfig。 → 建立 DeviceLicenseClient。 → 後續由其他 API 使用同一 Client。
不連線。只在目前 Python 程序中建立設定與 Client 物件。
不寫入 Server;通常也不建立 registration.json。
建立失敗通常是參數問題,修正設定後直接重建 Client,不需要網路重試。
Client 物件成功建立,而且公開設定、Namespace 與 Gateway 公鑰和管理員提供值一致。
設定錯誤時顯示『授權元件設定不完整,請聯絡管理員』,不要要求一般使用者猜 UUID 或公鑰。
- 逐字比對 Product UUID、Namespace、Gateway URL 與 Key ID。
- 確認 URL 只包含 HTTPS 根網址,沒有手動附加 /device/v1。
- 把 /device/v1 手動接到 Gateway URL 後面。
- 把 Admin Token、License Token 或 Gateway Private Key 放進 Client。
- 每個版本更換 product_namespace,造成同一產品被視為不同本機身分。
try:
client = DeviceLicenseClient(config)
except ValueError as exc:
raise SystemExit(f'Invalid ClientConfig: {exc}') from exc
Workflow 02
2. 首次啟用與本機身分
標準流程從 requires_license_key 判斷是否需要 Key,再以 ensure_registered 完成首次註冊或後續驗證。本機修復 API 只處理 registration.json 與 TPM Key,不會解除 Server Machine。
- 1
判斷是否首次執行
- 2
首次輸入 License Key
- 3
建立 TPM Device Registration
- 4
異常時受控修復本機身分
本機身分狀態DeviceLicenseClient.is_activated快速判斷本機是否存在註冊資料。
client.is_activated -> bool白話解釋:快速判斷本機是否存在註冊資料。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
UI 要決定是否顯示首次 License Key 輸入欄時。
- ClientConfig 的 Product ID 與 Namespace 必須和建立 registration.json 時一致。
- 主要讀取 registration.json、TPM Key 與目前 fingerprint。
- 除非方法文件明確說明,這一類方法不會向 Server 重新驗證 License。
bool。
- 無特定 SDK 例外。
- 只代表本機有 registration.json,不代表 License 現在仍有效。
同步、本機狀態讀取
不會建立背景執行緒。
- 讀取 registration.json、TPM Key metadata 或本機 fingerprint。
- 把結果當成診斷或流程分支,不要當成最新 License 驗證。
- 應用程式啟動時決定是否要求 License Key。
- 支援頁面或修復流程開始前。
大多快速完成;實際存取 TPM 的方法可能短暫阻塞。
讀取本機狀態。 → 判斷是否健康。 → 需要最新授權時再呼叫線上驗證。
主要不連線;讀取 registration.json、TPM Key 與本機 fingerprint。
唯讀方法不修改本機或 Server。
本機檔案暫時鎖定可短暫重試;內容損壞、Namespace 不一致或 TPM Key 遺失時不要自動反覆重試。
檢查回傳的 healthy、problem_code、device_id、machine_id 與 key_name 是否符合目前 Product。
顯示『本機授權身分需要修復』與 problem_code;不要直接提示使用者刪除所有 TPM Key。
- 先確認程式使用正確的 state_directory 與 product_namespace。
- 使用 local_identity_info() 取得 recovery_hint,再決定是否需要管理員協助。
- 看到 is_activated=True 就當成 License 目前有效。
- 手動修改 registration.json。
- 把其他產品的 TPM Key 當成目前產品的 Key。
if client.is_activated: print('registered locally')
本機身分狀態DeviceLicenseClient.requires_license_key判斷目前流程是否需要首次 License Key。
client.requires_license_key -> bool白話解釋:判斷目前流程是否需要首次 License Key。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
啟動流程要安全地只在第一次詢問 Key。
- ClientConfig 的 Product ID 與 Namespace 必須和建立 registration.json 時一致。
- 主要讀取 registration.json、TPM Key 與目前 fingerprint。
- 除非方法文件明確說明,這一類方法不會向 Server 重新驗證 License。
bool。
- 無特定 SDK 例外。
- 不要把 License Key 寫死在程式中。
同步、本機狀態讀取
不會建立背景執行緒。
- 讀取 registration.json、TPM Key metadata 或本機 fingerprint。
- 把結果當成診斷或流程分支,不要當成最新 License 驗證。
- 應用程式啟動時決定是否要求 License Key。
- 支援頁面或修復流程開始前。
大多快速完成;實際存取 TPM 的方法可能短暫阻塞。
讀取本機狀態。 → 判斷是否健康。 → 需要最新授權時再呼叫線上驗證。
主要不連線;讀取 registration.json、TPM Key 與本機 fingerprint。
唯讀方法不修改本機或 Server。
本機檔案暫時鎖定可短暫重試;內容損壞、Namespace 不一致或 TPM Key 遺失時不要自動反覆重試。
檢查回傳的 healthy、problem_code、device_id、machine_id 與 key_name 是否符合目前 Product。
顯示『本機授權身分需要修復』與 problem_code;不要直接提示使用者刪除所有 TPM Key。
- 先確認程式使用正確的 state_directory 與 product_namespace。
- 使用 local_identity_info() 取得 recovery_hint,再決定是否需要管理員協助。
- 看到 is_activated=True 就當成 License 目前有效。
- 手動修改 registration.json。
- 把其他產品的 TPM Key 當成目前產品的 Key。
import getpass
key = getpass.getpass('License key: ') if client.requires_license_key else None
本機身分狀態DeviceLicenseClient.activation_path取得 registration.json 路徑。
client.activation_path() -> Path白話解釋:取得 registration.json 路徑。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
支援頁面要顯示本機身分檔位置時。
- ClientConfig 的 Product ID 與 Namespace 必須和建立 registration.json 時一致。
- 主要讀取 registration.json、TPM Key 與目前 fingerprint。
- 除非方法文件明確說明,這一類方法不會向 Server 重新驗證 License。
Path。
- 無特定 SDK 例外。
- 不要手動編輯該 JSON。
同步、本機狀態讀取
不會建立背景執行緒。
- 讀取 registration.json、TPM Key metadata 或本機 fingerprint。
- 把結果當成診斷或流程分支,不要當成最新 License 驗證。
- 應用程式啟動時決定是否要求 License Key。
- 支援頁面或修復流程開始前。
大多快速完成;實際存取 TPM 的方法可能短暫阻塞。
讀取本機狀態。 → 判斷是否健康。 → 需要最新授權時再呼叫線上驗證。
主要不連線;讀取 registration.json、TPM Key 與本機 fingerprint。
唯讀方法不修改本機或 Server。
本機檔案暫時鎖定可短暫重試;內容損壞、Namespace 不一致或 TPM Key 遺失時不要自動反覆重試。
檢查回傳的 healthy、problem_code、device_id、machine_id 與 key_name 是否符合目前 Product。
顯示『本機授權身分需要修復』與 problem_code;不要直接提示使用者刪除所有 TPM Key。
- 先確認程式使用正確的 state_directory 與 product_namespace。
- 使用 local_identity_info() 取得 recovery_hint,再決定是否需要管理員協助。
- 看到 is_activated=True 就當成 License 目前有效。
- 手動修改 registration.json。
- 把其他產品的 TPM Key 當成目前產品的 Key。
print(client.activation_path())
本機身分狀態DeviceLicenseClient.registration讀取已保存的 Device Registration。
client.registration() -> DeviceRegistration | None白話解釋:讀取已保存的 Device Registration。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
只需要查看 device_id、machine_id、license_id、fingerprint 時。
- ClientConfig 的 Product ID 與 Namespace 必須和建立 registration.json 時一致。
- 主要讀取 registration.json、TPM Key 與目前 fingerprint。
- 除非方法文件明確說明,這一類方法不會向 Server 重新驗證 License。
DeviceRegistration 或 None。
- LocalIdentityError:內容損壞或 Product 不一致時可能由後續一致性檢查發現。
- 不會做線上驗證。
同步、本機狀態讀取
不會建立背景執行緒。
- 讀取 registration.json、TPM Key metadata 或本機 fingerprint。
- 把結果當成診斷或流程分支,不要當成最新 License 驗證。
- 應用程式啟動時決定是否要求 License Key。
- 支援頁面或修復流程開始前。
大多快速完成;實際存取 TPM 的方法可能短暫阻塞。
讀取本機狀態。 → 判斷是否健康。 → 需要最新授權時再呼叫線上驗證。
主要不連線;讀取 registration.json、TPM Key 與本機 fingerprint。
唯讀方法不修改本機或 Server。
本機檔案暫時鎖定可短暫重試;內容損壞、Namespace 不一致或 TPM Key 遺失時不要自動反覆重試。
檢查回傳的 healthy、problem_code、device_id、machine_id 與 key_name 是否符合目前 Product。
顯示『本機授權身分需要修復』與 problem_code;不要直接提示使用者刪除所有 TPM Key。
- 先確認程式使用正確的 state_directory 與 product_namespace。
- 使用 local_identity_info() 取得 recovery_hint,再決定是否需要管理員協助。
- 看到 is_activated=True 就當成 License 目前有效。
- 手動修改 registration.json。
- 把其他產品的 TPM Key 當成目前產品的 Key。
registration = client.registration()
本機身分狀態DeviceLicenseClient.local_identity_info同時檢查 registration.json、TPM Key 與 fingerprint 是否一致。
client.local_identity_info() -> LocalIdentityInfo白話解釋:同時檢查 registration.json、TPM Key 與 fingerprint 是否一致。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
啟動前診斷、重置確認或支援工具。
- ClientConfig 的 Product ID 與 Namespace 必須和建立 registration.json 時一致。
- 主要讀取 registration.json、TPM Key 與目前 fingerprint。
- 除非方法文件明確說明,這一類方法不會向 Server 重新驗證 License。
LocalIdentityInfo。
- TPMUnavailableError/TPMOperationError。
- healthy=False 時不要直接忽略問題。
同步、本機狀態讀取
不會建立背景執行緒。
- 讀取 registration.json、TPM Key metadata 或本機 fingerprint。
- 把結果當成診斷或流程分支,不要當成最新 License 驗證。
- 應用程式啟動時決定是否要求 License Key。
- 支援頁面或修復流程開始前。
大多快速完成;實際存取 TPM 的方法可能短暫阻塞。
讀取本機狀態。 → 判斷是否健康。 → 需要最新授權時再呼叫線上驗證。
主要不連線;讀取 registration.json、TPM Key 與本機 fingerprint。
唯讀方法不修改本機或 Server。
本機檔案暫時鎖定可短暫重試;內容損壞、Namespace 不一致或 TPM Key 遺失時不要自動反覆重試。
檢查回傳的 healthy、problem_code、device_id、machine_id 與 key_name 是否符合目前 Product。
顯示『本機授權身分需要修復』與 problem_code;不要直接提示使用者刪除所有 TPM Key。
- 先確認程式使用正確的 state_directory 與 product_namespace。
- 使用 local_identity_info() 取得 recovery_hint,再決定是否需要管理員協助。
- 看到 is_activated=True 就當成 License 目前有效。
- 手動修改 registration.json。
- 把其他產品的 TPM Key 當成目前產品的 Key。
info = client.local_identity_info(); print(info.problem_code or 'healthy')
首次啟用DeviceLicenseClient.register使用 License Key 完成第一次 TPM Device Registration 與 Machine activation。
client.register(license_key: str, *, scope=None) -> LicenseState白話解釋:使用 License Key 完成第一次 TPM Device Registration 與 Machine activation。
參數怎麼填
license_key: str必填管理員簽發的 License Key。只在第一次註冊或受控恢復時輸入,不要寫死在程式、設定檔、Log 或安裝包。
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
明確只做首次註冊時;一般應優先使用 ensure_registered()。
- 第一次執行才準備 License Key。
- 確認 Gateway URL、Product UUID、Namespace 與 Gateway Public Key 都是管理員提供的正式值。
- 確認裝置 TPM 可建立不可匯出 P-256 Key。
- Client 建立 TPM Key,對一次性 Challenge 簽章。
- Gateway 驗證後建立 Device Registration,並依 Policy 建立或關聯 Machine。
- 成功後只保存公開 registration 資料,不保存 License Key。
已驗證的 LicenseState。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- LicenseKeyRequiredError
- LocalIdentityError
- TPMUnavailableError/TPMOperationError
- GatewaySignatureError
- GatewayError
- LicenseInvalidError
- License Key 只在此請求使用,不寫入 registration.json。
同步網路交易
不會建立背景執行緒。
- 在同一呼叫中完成 Challenge、TPM 簽章、Gateway 驗證與註冊。
- 只在必要時安全取得 License Key。
- 在 worker thread/啟動畫面執行,捕捉所有授權例外。
- 成功後才開放受保護功能。
- 首次啟用。
- ensure_registered() 用於每次啟動的一次註冊或驗證。
會阻塞到 HTTPS 回應或 timeout_seconds;GUI 不應在主執行緒直接呼叫。
準備 Client 與可能的 License Key。 → 同步呼叫。 → 檢查 LicenseState/Entitlement。 → 繼續啟動或 fail closed。
會透過 HTTPS Gateway 執行 Challenge、TPM proof、License 驗證與首次註冊。
成功時會建立或關聯 Server-side Device Registration/Machine,並在本機保存不含 License Key 的 registration.json。
只有明確的暫時性網路錯誤適合有限次退避重試。收到 License 無效、Machine 上限、簽章失敗或 TPM 錯誤時不可盲目重送。
成功必須同時滿足:回傳 LicenseState.valid=True、本機 registration 存在、Gateway 回應簽章已驗證。
第一次啟用失敗時顯示可行動原因,例如 Key 無效、裝置上限、TPM 不可用或網路中斷;不要把所有錯誤都顯示成『伺服器錯誤』。
- 查看 connection.log 中最後一個成功事件與下一個失敗事件。
- 確認 License Key 只在本次輸入,沒有被寫入設定檔或 Log。
- TPM 錯誤先保留現場,不要先刪除 Key。
- 每次啟動都要求 License Key。
- 註冊失敗後直接刪除 TPM Key,沒有先看 problem_code 與 recovery_hint。
- 把首次註冊和管理員解除 Machine 席位混為一談。
try:
state = client.register(first_key)
except LicenseSDKError as exc:
handle_license_error(exc)
首次啟用DeviceLicenseClient.activateregister() 的使用者友善別名。
client.activate(license_key: str, *, scope=None) -> LicenseState白話解釋:register() 的使用者友善別名。
參數怎麼填
license_key: str必填管理員簽發的 License Key。只在第一次註冊或受控恢復時輸入,不要寫死在程式、設定檔、Log 或安裝包。
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
程式語意偏向『啟用』而非『註冊』時。
- 第一次執行才準備 License Key。
- 確認 Gateway URL、Product UUID、Namespace 與 Gateway Public Key 都是管理員提供的正式值。
- 確認裝置 TPM 可建立不可匯出 P-256 Key。
- Client 建立 TPM Key,對一次性 Challenge 簽章。
- Gateway 驗證後建立 Device Registration,並依 Policy 建立或關聯 Machine。
- 成功後只保存公開 registration 資料,不保存 License Key。
LicenseState。
- 與 register() 相同。
- 不會在已註冊狀態下自動切換 License。
同步網路交易
不會建立背景執行緒。
- 在同一呼叫中完成 Challenge、TPM 簽章、Gateway 驗證與註冊。
- 只在必要時安全取得 License Key。
- 在 worker thread/啟動畫面執行,捕捉所有授權例外。
- 成功後才開放受保護功能。
- 首次啟用。
- ensure_registered() 用於每次啟動的一次註冊或驗證。
會阻塞到 HTTPS 回應或 timeout_seconds;GUI 不應在主執行緒直接呼叫。
準備 Client 與可能的 License Key。 → 同步呼叫。 → 檢查 LicenseState/Entitlement。 → 繼續啟動或 fail closed。
會透過 HTTPS Gateway 執行 Challenge、TPM proof、License 驗證與首次註冊。
成功時會建立或關聯 Server-side Device Registration/Machine,並在本機保存不含 License Key 的 registration.json。
只有明確的暫時性網路錯誤適合有限次退避重試。收到 License 無效、Machine 上限、簽章失敗或 TPM 錯誤時不可盲目重送。
成功必須同時滿足:回傳 LicenseState.valid=True、本機 registration 存在、Gateway 回應簽章已驗證。
第一次啟用失敗時顯示可行動原因,例如 Key 無效、裝置上限、TPM 不可用或網路中斷;不要把所有錯誤都顯示成『伺服器錯誤』。
- 查看 connection.log 中最後一個成功事件與下一個失敗事件。
- 確認 License Key 只在本次輸入,沒有被寫入設定檔或 Log。
- TPM 錯誤先保留現場,不要先刪除 Key。
- 每次啟動都要求 License Key。
- 註冊失敗後直接刪除 TPM Key,沒有先看 problem_code 與 recovery_hint。
- 把首次註冊和管理員解除 Machine 席位混為一談。
state = client.activate(first_key)
首次啟用DeviceLicenseClient.ensure_registered首次執行自動註冊,之後自動使用 TPM proof 做線上驗證。
client.ensure_registered(license_key=None, *, scope=None, recover_local_identity=False) -> LicenseState白話解釋:首次執行自動註冊,之後自動使用 TPM proof 做線上驗證。
參數怎麼填
license_key=None可選管理員簽發的 License Key。只在第一次註冊或受控恢復時輸入,不要寫死在程式、設定檔、Log 或安裝包。
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
recover_local_identity=False可選是否允許 SDK 在本機身分不一致時自動重建。正式環境預設 False,避免未經確認刪除本機識別資料。
絕大多數應用程式的標準啟動入口。
- 第一次執行才準備 License Key。
- 確認 Gateway URL、Product UUID、Namespace 與 Gateway Public Key 都是管理員提供的正式值。
- 確認裝置 TPM 可建立不可匯出 P-256 Key。
- Client 建立 TPM Key,對一次性 Challenge 簽章。
- Gateway 驗證後建立 Device Registration,並依 Policy 建立或關聯 Machine。
- 成功後只保存公開 registration 資料,不保存 License Key。
有效的 LicenseState。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- LicenseKeyRequiredError
- LocalIdentityError
- LicenseInvalidError
- FeatureNotLicensedError(若後續 require)
- GatewayError
- GatewaySignatureError
- TPMUnavailableError/TPMOperationError
- recover_local_identity=True 只有在你接受自動重建本機身分時才使用。
同步網路交易
不會建立背景執行緒。
- 在同一呼叫中完成 Challenge、TPM 簽章、Gateway 驗證與註冊。
- 只在必要時安全取得 License Key。
- 在 worker thread/啟動畫面執行,捕捉所有授權例外。
- 成功後才開放受保護功能。
- 首次啟用。
- ensure_registered() 用於每次啟動的一次註冊或驗證。
會阻塞到 HTTPS 回應或 timeout_seconds;GUI 不應在主執行緒直接呼叫。
準備 Client 與可能的 License Key。 → 同步呼叫。 → 檢查 LicenseState/Entitlement。 → 繼續啟動或 fail closed。
本機未註冊時執行首次啟用;已有健康本機身分時執行 TPM Challenge 線上驗證。
首次成功會建立 Server Device Registration/Machine 與本機 registration.json;後續驗證只更新授權狀態。
只對明確暫時性網路錯誤有限重試。recover_local_identity=False 時,身分不一致必須先顯示診斷,不可偷偷重建。
state.valid=True、registration() 可讀、local_identity_info().healthy=True,且重新啟動時 requires_license_key=False。
第一次使用顯示 License Key 輸入;日常啟動只顯示驗證進度。遇到本機身分問題時顯示 problem_code 與管理員處置。
- 先檢查 requires_license_key,再決定是否要求輸入 Key。
- 確認 License Key 沒有保存到 registration.json。
- 測試第一次、第二次啟動與本機資料損壞三條路徑。
- 每次啟動都要求 License Key。
- 註冊失敗後直接刪除 TPM Key,沒有先看 problem_code 與 recovery_hint。
- 把首次註冊和管理員解除 Machine 席位混為一談。
try:
state = client.ensure_registered(first_key)
state.require_valid()
except LicenseSDKError as exc:
show_license_error(exc)
本機身分維護高影響DeviceLicenseClient.clear_local_registration只刪除本機 registration.json。
client.clear_local_registration() -> bool白話解釋:只刪除本機 registration.json。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
你確定要讓下次執行重新註冊,但暫時保留 TPM Key 時。
- 先呼叫 local_identity_info(),顯示將處理的 Product Namespace、registration 路徑與 TPM Key Name。
- 要求使用者二次確認,並確認仍有 License Key 或管理員協助可重新啟用。
- 只修改目前電腦的本機狀態。
- 不會撤銷 License、不會釋放 Machine 席位,也不會刪除 Server-side Machine。
是否刪除。
- OSError
- 不會解除 Server Machine。
同步、本機高影響維護
不會建立背景執行緒。
- 只操作目前 Product Namespace 的 registration.json 或 TPM Key。
- 先顯示診斷與完整 Key Name。
- 要求二次確認。
- 自行處理重新啟用與 Server Machine 管理。
- 明確的支援/換機流程中。
- 不可作為一般啟動時自動修復。
TPM 刪除可能短暫阻塞;不做網路 I/O,除 recover/switch 另行連線。
診斷。 → 確認。 → 執行本機維護。 → 重新檢查。 → 需要時重新註冊。
不連線。只操作目前電腦的 registration.json 或指定 TPM Key。
可能永久刪除本機註冊檔或不可匯出的 TPM Key;不修改任何 Server License/Machine。
刪除操作不應自動重試。失敗時保留現場,記錄安全化錯誤,讓使用者或管理員決定下一步。
重新呼叫 local_identity_info(),確認預期檔案或 Key 已移除,而且其他 Product Namespace 未受影響。
先明確警告『只清除本機,不會釋放 Server Machine』,並要求二次確認完整 Key Name。
- 先備妥重新啟用需要的 License Key 或管理員協助。
- expected_key_name 必須來自 local_identity_info()。
- 不可列舉後批次刪除不相關 TPM Key。
- 把本機 reset 當成換機或解除綁定流程。
- expected_key_name 留空或使用猜測值。
- 遇到任何錯誤就直接刪除所有 TPM Key。
try:
removed = client.clear_local_registration()
except OSError as exc:
show_local_cleanup_error(exc)
本機身分維護高影響DeviceLicenseClient.delete_device_tpm_key刪除指定且名稱完全吻合的本機 TPM Key。
client.delete_device_tpm_key(*, expected_key_name: str) -> bool白話解釋:刪除指定且名稱完全吻合的本機 TPM Key。
參數怎麼填
expected_key_name: str必填預期刪除的 TPM Key 完整名稱。SDK 會比對後才刪除,避免誤刪其他產品的 Key。
受控修復或完整本機重置。
- 先呼叫 local_identity_info(),顯示將處理的 Product Namespace、registration 路徑與 TPM Key Name。
- 要求使用者二次確認,並確認仍有 License Key 或管理員協助可重新啟用。
- 只修改目前電腦的本機狀態。
- 不會撤銷 License、不會釋放 Machine 席位,也不會刪除 Server-side Machine。
Key 是否存在並成功刪除。
- ValueError:expected_key_name 不符。
- TPMOperationError
- 不可復原;不影響 Server Machine。
同步、本機高影響維護
不會建立背景執行緒。
- 只操作目前 Product Namespace 的 registration.json 或 TPM Key。
- 先顯示診斷與完整 Key Name。
- 要求二次確認。
- 自行處理重新啟用與 Server Machine 管理。
- 明確的支援/換機流程中。
- 不可作為一般啟動時自動修復。
TPM 刪除可能短暫阻塞;不做網路 I/O,除 recover/switch 另行連線。
診斷。 → 確認。 → 執行本機維護。 → 重新檢查。 → 需要時重新註冊。
不連線。只操作目前電腦的 registration.json 或指定 TPM Key。
可能永久刪除本機註冊檔或不可匯出的 TPM Key;不修改任何 Server License/Machine。
刪除操作不應自動重試。失敗時保留現場,記錄安全化錯誤,讓使用者或管理員決定下一步。
重新呼叫 local_identity_info(),確認預期檔案或 Key 已移除,而且其他 Product Namespace 未受影響。
先明確警告『只清除本機,不會釋放 Server Machine』,並要求二次確認完整 Key Name。
- 先備妥重新啟用需要的 License Key 或管理員協助。
- expected_key_name 必須來自 local_identity_info()。
- 不可列舉後批次刪除不相關 TPM Key。
- 把本機 reset 當成換機或解除綁定流程。
- expected_key_name 留空或使用猜測值。
- 遇到任何錯誤就直接刪除所有 TPM Key。
try:
client.delete_device_tpm_key(expected_key_name=info.key_name)
except TPMOperationError as exc:
show_tpm_error(exc)
本機身分維護高影響DeviceLicenseClient.reset_local_identity安全地清除目前 Product Namespace 的本機註冊與/或 TPM Key。
client.reset_local_identity(*, expected_key_name: str, delete_registration=True, delete_tpm_key=True) -> LocalIdentityResetResult白話解釋:安全地清除目前 Product Namespace 的本機註冊與/或 TPM Key。
參數怎麼填
expected_key_name: str必填預期刪除的 TPM Key 完整名稱。SDK 會比對後才刪除,避免誤刪其他產品的 Key。
delete_registration=True可選是否刪除 registration.json。只影響本機,不會解除 Server-side Machine。
delete_tpm_key=True可選是否刪除目前產品的 TPM Key。不可復原,執行前應顯示 Key Name 並二次確認。
換 License、修復本機不一致或正式移除應用程式資料時。
- 先呼叫 local_identity_info(),顯示將處理的 Product Namespace、registration 路徑與 TPM Key Name。
- 要求使用者二次確認,並確認仍有 License Key 或管理員協助可重新啟用。
- 只修改目前電腦的本機狀態。
- 不會撤銷 License、不會釋放 Machine 席位,也不會刪除 Server-side Machine。
LocalIdentityResetResult。
- ValueError
- TPMOperationError
- OSError
- Client 無法藉此解除 Server Machine。
同步、本機高影響維護
不會建立背景執行緒。
- 只操作目前 Product Namespace 的 registration.json 或 TPM Key。
- 先顯示診斷與完整 Key Name。
- 要求二次確認。
- 自行處理重新啟用與 Server Machine 管理。
- 明確的支援/換機流程中。
- 不可作為一般啟動時自動修復。
TPM 刪除可能短暫阻塞;不做網路 I/O,除 recover/switch 另行連線。
診斷。 → 確認。 → 執行本機維護。 → 重新檢查。 → 需要時重新註冊。
不連線。依選項刪除本機 registration.json 與指定 TPM Key。
刪除本機身分資料且不可從 Client 復原;Server Machine、License 與席位完全不變。
不可自動重試。任何失敗都應停止後續刪除並重新檢查 local_identity_info()。
確認 LocalIdentityResetResult 的每個欄位,並重新檢查預期 registration/Key 狀態。
確認對話框必須顯示 Product Namespace、完整 Key Name,以及『不會釋放 Server Machine』。
- expected_key_name 只能使用 local_identity_info() 回傳值。
- 管理員需先完成換機或 Machine 回收流程。
- 重置後第一次啟動需要有效 License Key。
- 把本機 reset 當成換機或解除綁定流程。
- expected_key_name 留空或使用猜測值。
- 遇到任何錯誤就直接刪除所有 TPM Key。
try:
result = client.reset_local_identity(expected_key_name=info.key_name)
except LicenseSDKError as exc:
show_reset_error(exc)
本機身分維護高影響DeviceLicenseClient.recover_local_identity在本機註冊遺失/不一致時,使用 License Key 重建註冊。
client.recover_local_identity(license_key: str, *, delete_tpm_key=False, scope=None) -> LicenseState白話解釋:在本機註冊遺失/不一致時,使用 License Key 重建註冊。
參數怎麼填
license_key: str必填管理員簽發的 License Key。只在第一次註冊或受控恢復時輸入,不要寫死在程式、設定檔、Log 或安裝包。
delete_tpm_key=False可選是否刪除目前產品的 TPM Key。不可復原,執行前應顯示 Key Name 並二次確認。
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
REGISTRATION_INVALID 或本機資料受損,且使用者仍有合法 License Key 時。
- 先呼叫 local_identity_info() 取得 problem_code、registration 路徑與 TPM Key Name。
- 使用者必須持有合法 License Key,且已理解這不會釋放舊的 Server Machine。
- delete_tpm_key=True 前必須二次確認,因為會建立全新 TPM 身分。
- 依選項清理損壞的本機 registration 或 TPM Key。
- 使用 License Key 重新執行 Gateway Challenge、TPM proof 與 Device Registration。
- 成功後保存新的 registration 並回傳最新 LicenseState。
新的 LicenseState。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- LicenseKeyRequiredError
- LocalIdentityError
- TPMOperationError
- GatewayError
- LicenseInvalidError
- delete_tpm_key=True 會建立全新 TPM 身分,需審慎使用。
同步、本機高影響維護
不會建立背景執行緒。
- 只操作目前 Product Namespace 的 registration.json 或 TPM Key。
- 先顯示診斷與完整 Key Name。
- 要求二次確認。
- 自行處理重新啟用與 Server Machine 管理。
- 明確的支援/換機流程中。
- 不可作為一般啟動時自動修復。
TPM 刪除可能短暫阻塞;不做網路 I/O,除 recover/switch 另行連線。
診斷。 → 確認。 → 執行本機維護。 → 重新檢查。 → 需要時重新註冊。
會先檢查/清理本機身分,再透過 HTTPS Gateway 使用 License Key 完成新的 Challenge、TPM proof 與註冊。
可能刪除本機 registration 或 TPM Key,並在成功時建立新的本機 registration;Server 端可能建立新的 Device Registration/Machine 關聯。
只對明確暫時性網路錯誤有限重試。若結果不確定,先檢查 local_identity_info() 與 registration(),不要再次刪除 TPM Key。
回傳 state.valid=True、local_identity_info().healthy=True,且 registration 的 Product/Machine/Device ID 與回傳一致。
顯示『本機授權身分修復』進度,清楚區分本機清理、重新註冊與 Server 拒絕原因。
- 先保存 problem_code 與 recovery_hint。
- delete_tpm_key=True 時確認 Key Name 與重新啟用風險。
- 修復後重新啟動一次,確認日常 TPM Challenge 流程。
- 在沒有診斷 problem_code 前直接重建。
- 把修復流程當成管理員換機/釋放 Machine。
- 網路不確定時反覆輸入 License Key 並重送。
try:
state = client.recover_local_identity(key)
except LocalIdentityError as exc:
show_recovery_hint(exc)
本機身分維護高影響DeviceLicenseClient.switch_license清除本機註冊並以另一張 License 重新註冊。
client.switch_license(new_license_key: str, *, delete_tpm_key=False, scope=None) -> LicenseState白話解釋:清除本機註冊並以另一張 License 重新註冊。
參數怎麼填
new_license_key: str必填要切換或重新建立身分時使用的新 License Key;必須先完成管理端流程與使用者確認。
delete_tpm_key=False可選是否刪除目前產品的 TPM Key。不可復原,執行前應顯示 Key Name 並二次確認。
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
使用者明確選擇切換 License。
- 先由管理員完成舊 License/Machine 的處置規則。
- 使用者明確確認新 License Key 與是否保留目前 TPM Key。
- 保存未完成工作,因為切換失敗時受保護功能必須保持鎖定。
- 清除目前 Product Namespace 的本機 registration。
- 使用新 License Key 重新連線註冊;依 delete_tpm_key 決定是否建立新的 TPM 身分。
- 不會自動撤銷舊 License 或刪除舊 Server Machine。
新 LicenseState。
- LicenseSDKError
- 不會解除舊 Server Machine;舊 Machine 由管理員處理。
同步、本機高影響維護
不會建立背景執行緒。
- 只操作目前 Product Namespace 的 registration.json 或 TPM Key。
- 先顯示診斷與完整 Key Name。
- 要求二次確認。
- 自行處理重新啟用與 Server Machine 管理。
- 明確的支援/換機流程中。
- 不可作為一般啟動時自動修復。
TPM 刪除可能短暫阻塞;不做網路 I/O,除 recover/switch 另行連線。
診斷。 → 確認。 → 執行本機維護。 → 重新檢查。 → 需要時重新註冊。
會清理目前 Product Namespace 的本機註冊,接著透過 HTTPS Gateway 使用新 License Key 重新註冊。
本機 registration 會被替換;依選項可能替換 TPM Key。Server 端會建立或關聯新 License 的 Device Registration/Machine,但不會自動處理舊 Machine。
切換屬高影響交易,不應自動重試。結果不確定時先檢查 registration() 與新 LicenseState,再由使用者決定。
新 state.valid=True、registration.license_id 指向新 License,且本機身分健康。
確認畫面要說明舊 Server Machine 仍由管理員處理;切換失敗時維持受保護功能鎖定。
- 先確認新 License Key 與 Product 相符。
- 確認是否需要保留原 TPM Key。
- 切換後重新驗證 Entitlement、Usage 與 Machine 上限。
- 用 switch_license() 取代管理員的 Server Machine 回收。
- 在 UI 沒有二次確認時直接切換。
- 切換失敗後仍沿用舊 LicenseState 執行功能。
try:
state = client.switch_license(new_key)
except LicenseSDKError as exc:
show_switch_error(exc)
Workflow 03
3. 驗證、Entitlement 與受保護功能
先取得最新 LicenseState,再以 require 或 require_all 在真正執行功能前做 fail-closed 授權判斷。長時間程式優先使用 licensed_session。
- 1
線上驗證
- 2
檢查 License 狀態
- 3
要求 Entitlement
- 4
執行受保護功能
- 5
由呼叫端在安全檢查點執行 session.check()
線上驗證DeviceLicenseClient.validate對既有 Device Registration 發送一次性 Challenge 並取得最新 License 狀態。
client.validate(*, scope=None) -> LicenseState白話解釋:對既有 Device Registration 發送一次性 Challenge 並取得最新 License 狀態。
參數怎麼填
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
需要自行檢查 state.valid/state.code 而不想立刻拋 LicenseInvalidError 時。
- 本機必須已有健康的 Device Registration 與 TPM Key。
- 網路可連到 HTTPS Gateway,且 Client 固定正確 Gateway Public Key。
- Gateway 發出一次性 Challenge,Client 使用 TPM 簽章證明是原裝置。
- 回傳最新 License 狀態、Entitlement、Usage 與 Policy 相關欄位;不會自動執行你的功能。
LicenseState,可能 valid=False。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- LocalIdentityError
- GatewayError
- GatewaySignatureError
- TPMUnavailableError/TPMOperationError
- 不會因 valid=False 自動拋 LicenseInvalidError。
同步網路驗證
不會建立背景執行緒。
- 每次呼叫都建立新的 Challenge 並完成 TPM proof。
- 決定驗證頻率與重試策略。
- 將 License 拒絕與暫時網路錯誤分開處理。
- 在高價值操作前取得足夠新的狀態。
- 程式啟動。
- 高價值操作前。
- 長時間執行中的明確檢查點。
會阻塞到網路完成或 timeout_seconds;GUI 應移到 worker thread。
呼叫驗證。 → 驗證 Gateway 簽章。 → 檢查 valid/例外。 → 檢查 Entitlement。
透過 Gateway Challenge 與 TPM proof 取得最新 LicenseState。
不建立新 Machine;回傳 valid=False 也不自動拋 LicenseInvalidError。
暫時性網路錯誤可有限重試;valid=False 不應重試來規避 Server 決策。
必須由呼叫端明確檢查 state.valid、state.code 與 state.detail。
依 state.code 顯示過期、撤銷、額度、Scope 或裝置問題;不要只顯示『驗證失敗』。
- 最常見錯誤是忘記檢查 state.valid。
- 高價值功能更適合 validate_or_raise() 或 validate() 後立即 require_valid()。
- 忽略 GatewaySignatureError 後繼續執行。
- 只在程式啟動時驗證一次,長時間工作不重新確認。
- 使用 validate() 卻忘記檢查 state.valid。
state = client.validate();
if not state.valid: show_denied(state.code, state.detail)
線上驗證DeviceLicenseClient.validate_or_raise執行線上驗證,無效時直接拋 LicenseInvalidError。
client.validate_or_raise(*, scope=None) -> LicenseState白話解釋:執行線上驗證,無效時直接拋 LicenseInvalidError。
參數怎麼填
scope=None可選ValidationScope 或 None。只有 Policy 確實要求 version、checksum、user_id、entitlement 或 component scope 時才填。
功能入口、CLI 或不想手動判斷 valid 時。
- 本機必須已有健康的 Device Registration 與 TPM Key。
- 網路可連到 HTTPS Gateway,且 Client 固定正確 Gateway Public Key。
- Gateway 發出一次性 Challenge,Client 使用 TPM 簽章證明是原裝置。
- 回傳最新 License 狀態、Entitlement、Usage 與 Policy 相關欄位;不會自動執行你的功能。
有效的 LicenseState。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- LicenseInvalidError
- LocalIdentityError
- GatewayError
- GatewaySignatureError
- TPMUnavailableError/TPMOperationError
- 可從回傳 state.uses/max_uses 查看目前使用量。
同步網路驗證
不會建立背景執行緒。
- 每次呼叫都建立新的 Challenge 並完成 TPM proof。
- 決定驗證頻率與重試策略。
- 將 License 拒絕與暫時網路錯誤分開處理。
- 在高價值操作前取得足夠新的狀態。
- 程式啟動。
- 高價值操作前。
- 長時間執行中的明確檢查點。
會阻塞到網路完成或 timeout_seconds;GUI 應移到 worker thread。
呼叫驗證。 → 驗證 Gateway 簽章。 → 檢查 valid/例外。 → 檢查 Entitlement。
會透過 HTTPS Gateway 取得一次性 Challenge,並使用 TPM 簽章證明目前裝置身分。
一般不建立新 Machine;會讀取最新 License、Entitlement、Usage、Heartbeat 或 Scope 結果。
網路逾時可使用有限次指數退避。簽章錯誤、License 無效、Scope 不符或 TPM proof 失敗必須立即停止受保護功能。
確認回傳簽章已驗證,再依 validate() 的 state.valid 或 validate_or_raise() 是否成功判斷。
區分『暫時無法連線』與『授權已拒絕』;兩者都要阻擋高價值功能,但使用者處置不同。
- 確認系統時間、DNS、TLS 憑證與 Gateway URL。
- 若 state.valid=False,讀取 code 與 detail,而不是只看布林值。
- GatewaySignatureError 一律視為信任鏈失敗。
- 忽略 GatewaySignatureError 後繼續執行。
- 只在程式啟動時驗證一次,長時間工作不重新確認。
- 使用 validate() 卻忘記檢查 state.valid。
try:
state = client.validate_or_raise()
except LicenseInvalidError as exc:
disable_protected_features(exc)
功能授權LicenseState.require_valid確認 LicenseState.valid,否則拋 LicenseInvalidError。
state.require_valid() -> LicenseState白話解釋:確認 LicenseState.valid,否則拋 LicenseInvalidError。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
validate() 後要以例外方式阻擋流程。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
同一個 LicenseState。
- LicenseInvalidError
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
state.require_valid()
功能授權LicenseState.has判斷單一 Entitlement 是否存在。
state.has(feature_code: str) -> bool白話解釋:判斷單一 Entitlement 是否存在。
參數怎麼填
feature_code: str必填單一 Entitlement Code,必須與管理端建立的代碼完全一致,通常使用程式常數。
只需要控制 UI 顯示,不立即拒絕流程時。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
bool。
- 無特定 SDK 例外。
- 真正執行功能前仍建議 require()。
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
if state.has('HDL_EXPORT'): enable_export_button()
功能授權LicenseState.has_all判斷所有 Entitlement 是否都存在。
state.has_all(*feature_codes: str) -> bool白話解釋:判斷所有 Entitlement 是否都存在。
參數怎麼填
*feature_codes: str必填一個或多個 Entitlement Code。使用 *args 傳入,例如 require_all('PRO', 'HDL_EXPORT')。
一個功能需要多個權限條件時。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
bool。
- 無特定 SDK 例外。
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
if state.has_all('PRO', 'HDL_EXPORT'): ...
功能授權LicenseState.has_any判斷任一 Entitlement 是否存在。
state.has_any(*feature_codes: str) -> bool白話解釋:判斷任一 Entitlement 是否存在。
參數怎麼填
*feature_codes: str必填一個或多個 Entitlement Code。使用 *args 傳入,例如 require_all('PRO', 'HDL_EXPORT')。
多種方案任一可開啟同一功能時。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
bool。
- 無特定 SDK 例外。
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
if state.has_any('PRO', 'ENTERPRISE'): ...
功能授權LicenseState.require確認 License 有效且包含指定 Entitlement。
state.require(feature_code: str) -> LicenseState白話解釋:確認 License 有效且包含指定 Entitlement。
參數怎麼填
feature_code: str必填單一 Entitlement Code,必須與管理端建立的代碼完全一致,通常使用程式常數。
每個受保護功能真正開始前。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
同一個 LicenseState。
- LicenseInvalidError
- FeatureNotLicensedError
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
try:
state.require('HDL_EXPORT')
except FeatureNotLicensedError:
show_upgrade_message()
功能授權LicenseState.require_all確認 License 有效且同時包含全部指定 Entitlement。
state.require_all(*feature_codes: str) -> LicenseState白話解釋:確認 License 有效且同時包含全部指定 Entitlement。
參數怎麼填
*feature_codes: str必填一個或多個 Entitlement Code。使用 *args 傳入,例如 require_all('PRO', 'HDL_EXPORT')。
高階功能需要多個功能碼時。
- 先從 ensure_registered()、validate() 或 validate_or_raise() 取得最新 LicenseState。
- Entitlement Code 必須與管理端建立的代碼完全一致。
- 只根據目前 LicenseState 做有效性與功能權限判斷。
- require 系列在不符合時拋例外,讓程式在功能入口 fail closed。
同一個 LicenseState。
- LicenseInvalidError
- FeatureNotLicensedError
同步、本機記憶體判斷
不會建立背景執行緒。
- 只檢查目前 LicenseState 物件。
- 確保 LicenseState 足夠新。
- 在每個真正受保護的核心函式入口再次 require。
- UI 顯示時可用 has*。
- 真正執行功能前使用 require*。
不做網路 I/O,立即回傳或拋授權例外。
先取得最新 state。 → 執行 has/require。 → 允許或拒絕功能。
不連線。只檢查目前記憶體中的 LicenseState。
不修改本機或 Server。
不需要重試;若狀態過舊,先重新呼叫 validate_or_raise() 或 session.check() 取得新狀態。
require 系列沒有拋例外,或 has/has_all/has_any 回傳符合預期。
對無權限功能顯示清楚的功能名稱與聯絡方式,不要顯示內部 Token、Policy JSON 或完整 Server 回應。
- 確認 Entitlement Code 大小寫與管理端完全一致。
- 確認真正的核心操作函式也執行 require,而不只限制按鈕。
- 只把按鈕設為 disabled,核心函式沒有再次 require。
- 把 has() 的 UI 判斷當成最終安全邊界。
- 硬編碼不存在或拼錯的 Entitlement Code。
state.require_all('PRO', 'HDL_EXPORT')
整合 SessionDeviceLicenseClient.licensed_session建立一個由呼叫端控制檢查時機的 context manager:進入時同步完成註冊/驗證與可選資源取得,只有 Heartbeat 會在背景執行;完整 License 重驗必須在呼叫 session.check() 時才發生。
client.licensed_session(license_key=None, *, required_entitlements=(), machine_heartbeat=False, process_seat=False, process_pid='', process_metadata=None, recover_local_identity=False, check_in_on_start=False, usage_increment_on_success=0, revalidate_interval_seconds=0)白話解釋:建立一個由呼叫端控制檢查時機的 context manager:進入時同步完成註冊/驗證與可選資源取得,只有 Heartbeat 會在背景執行;完整 License 重驗必須在呼叫 session.check() 時才發生。
參數怎麼填
license_key=None可選管理員簽發的 License Key。只在第一次註冊或受控恢復時輸入,不要寫死在程式、設定檔、Log 或安裝包。
required_entitlements=()可選Session 進入時與每次真正重新驗證時都必須具備的 Entitlement Code tuple。單純 session.check() 若尚未到 revalidate 間隔,只檢查 Heartbeat 健康,不會向 Server 重新讀取 Entitlement。
machine_heartbeat=False可選是否在進入 licensed_session() 時啟動一條 Machine Heartbeat 背景執行緒。它只送 Machine Heartbeat,不會在背景做完整 License revalidation;只有 Policy 要求 Machine Heartbeat 時才啟用。
process_seat=False可選是否在進入 licensed_session() 時同步取得 Process Seat,並啟動另一條 Process Heartbeat 背景執行緒。用於 maxProcesses,不等於 Machine 席位。
process_pid=''可選建立 Session 時指定的 Process ID;未填時通常由 SDK 使用目前程序。
process_metadata=None可選附加在 Process Seat 的非秘密資訊,例如 application 與 version,便於管理端辨識。
recover_local_identity=False可選是否允許 SDK 在本機身分不一致時自動重建。正式環境預設 False,避免未經確認刪除本機識別資料。
check_in_on_start=False可選是否只在進入 licensed_session() 時同步執行一次 License Check-in。它不是週期排程器;Policy 要求後續定期 Check-in 時,應用程式仍要依 next_check_in 自行安排呼叫。
usage_increment_on_success=0可選with 區塊沒有拋例外並正常離開時,只執行一次 Usage increment。它不會在每次 session.check() 或每個功能呼叫後自動扣次。
revalidate_interval_seconds=0可選session.check() 判斷是否需要重新線上驗證的最短間隔。這個值不會建立 Timer 或背景驗證執行緒;只有呼叫端再次執行 session.check() 時才會判斷是否到期。
GUI、CLI 與長時間自動化程式的推薦高階入口。
- 先決定程式是否真的需要 Machine Heartbeat、Process Seat、Check-in 或 Usage。
- 決定由 GUI Timer、工作迴圈或高價值操作入口在何時呼叫 session.check()。
- 理解 revalidate_interval_seconds 只是 session.check() 的到期門檻,不是背景排程。
- 進入 context 時同步完成 ensure_registered()、Entitlement Gate,以及選用的一次 Check-in/Seat 取得。
- machine_heartbeat=True 或 process_seat=True 才會建立背景 Heartbeat 執行緒;背景執行緒不會自動做完整 License 驗證。
- session.check() 由呼叫端主動執行:先檢查背景 Heartbeat 是否已失敗,再視 force_validate 或到期門檻同步重新驗證。
- 離開 Session 時停止背景 Heartbeat並釋放 Process Seat;不會解除 Server Machine。
LicenseSession context manager。
- 所有 Activation/Heartbeat/Process/Usage 相關例外。
- usage_increment_on_success 只在 with 區塊無例外時執行;若 increment 失敗,離開 context 時仍會拋錯。
先建立 context manager;真正工作在進入 with 時同步執行
machine_heartbeat=True 時建立一條 Machine Heartbeat daemon thread;process_seat=True 時再建立一條 Process Heartbeat daemon thread。revalidate_interval_seconds 絕不會建立背景驗證 thread。
- with 進入時:ensure_registered()、required_entitlements、可選的一次 Check-in、可選 Machine Heartbeat start、可選 Process Seat acquire/start。
- with 期間:只有已啟用的 Heartbeat 在背景自動 ping。
- with 正常離開:可選 Usage increment 一次,然後停止 threads 並釋放 Process Seat。
- 在 GUI Timer、工作迴圈 checkpoint 或高價值操作入口呼叫 session.check()。
- 需要立即取得撤銷/到期/Entitlement 變化時使用 force_validate=True。
- 處理所有例外並 fail closed。
- 不需要寫一個只為 Session 而存在的緊密 for 迴圈。
- GUI 可用既有 QTimer/after/scheduler,每 10~30 秒觸發 worker check。
- 高價值操作前強制驗證一次。
進入與離開可能同步連線;session.check() 到期或 force 時同步連線。UI 主 thread 需移交 worker。
建立 context。 → 進入時同步註冊/驗證。 → 背景只維持 Heartbeat。 → 呼叫端主動 check。 → 正常離開處理 Usage/Seat/thread。
進入 context 時會同步連線註冊/驗證;只有啟用 Machine/Process Heartbeat 時才有背景網路執行緒。完整 License revalidation 不會自動排程,必須由呼叫端執行 session.check()。
可能建立/維持/釋放 Process Seat,更新 Heartbeat、執行一次啟動 Check-in,或在正常離開時增加一次 Usage;不會自動解除 Server Machine。
Heartbeat 執行緒會依設定短暫重試;完整 License 驗證沒有隱藏重試迴圈。呼叫端應以明確 Timer/工作檢查點呼叫 session.check(),並對暫時網路錯誤採有限退避。
Session 進入成功;應用程式安排的每個 session.check() 都通過;高價值操作前的強制驗證通過;退出後 Process Seat 已釋放。
長時間程式應在狀態失效時鎖定受保護功能,保留未完成工作,並顯示重新連線或聯絡管理員的步驟。
- 確認應用程式確實有 Timer、工作迴圈或操作入口會呼叫 session.check()。
- 確認 revalidate_interval_seconds 是門檻而不是排程器。
- 確認 GUI 主執行緒沒有被同步網路呼叫長時間阻塞。
- 檢查背景 Heartbeat 的 last_error 與 consecutive_failures。
- 以為 revalidate_interval_seconds 會自己建立 Timer,因此從不呼叫 session.check()。
- 在無 sleep 的緊密 for 迴圈中一直呼叫 session.check(force_validate=True),造成網路與 UI 負載。
- 在 GUI 主執行緒直接做可能阻塞到 timeout_seconds 的強制驗證。
- 程式發生授權錯誤後仍繼續執行受保護工作。
try:
with client.licensed_session(first_key, required_entitlements=('EXPORT',), usage_increment_on_success=1) as session:
session.check(force_validate=True)
staged = build_to_staging()
publish(staged)
except LicenseSDKError as exc:
discard(staged)
show_license_error(exc)
整合 SessionLicenseSession.refresh立即在目前呼叫執行緒同步完成一次 TPM-authenticated 線上驗證,更新 Session State 與 required_entitlements;不會建立背景工作。
session.refresh() -> LicenseState白話解釋:立即在目前呼叫執行緒同步完成一次 TPM-authenticated 線上驗證,更新 Session State 與 required_entitlements;不會建立背景工作。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
程式運行中要立即取得撤銷、到期或 Entitlement 變化。
- 先決定程式是否真的需要 Machine Heartbeat、Process Seat、Check-in 或 Usage。
- 決定由 GUI Timer、工作迴圈或高價值操作入口在何時呼叫 session.check()。
- 理解 revalidate_interval_seconds 只是 session.check() 的到期門檻,不是背景排程。
- 進入 context 時同步完成 ensure_registered()、Entitlement Gate,以及選用的一次 Check-in/Seat 取得。
- machine_heartbeat=True 或 process_seat=True 才會建立背景 Heartbeat 執行緒;背景執行緒不會自動做完整 License 驗證。
- session.check() 由呼叫端主動執行:先檢查背景 Heartbeat 是否已失敗,再視 force_validate 或到期門檻同步重新驗證。
- 離開 Session 時停止背景 Heartbeat並釋放 Process Seat;不會解除 Server Machine。
LicenseState。
- LicenseSDKError
同步、立即完整線上驗證
不建立背景執行緒。
- 呼叫 validate_or_raise()。
- 重新要求 required_entitlements。
- 更新 session.state 與上次驗證時間。
- 在 worker thread 執行。
- 捕捉並處理授權與網路例外。
- 管理端狀態剛變更後。
- 高價值操作前需要最新狀態時。
- 除錯時明確驗證。
一定做網路與 TPM 操作,最多阻塞到 timeout_seconds。
同步驗證。 → Entitlement Gate。 → 更新 state。 → 返回 LicenseState。
進入 context 時會同步連線註冊/驗證;只有啟用 Machine/Process Heartbeat 時才有背景網路執行緒。完整 License revalidation 不會自動排程,必須由呼叫端執行 session.check()。
可能建立/維持/釋放 Process Seat,更新 Heartbeat、執行一次啟動 Check-in,或在正常離開時增加一次 Usage;不會自動解除 Server Machine。
Heartbeat 執行緒會依設定短暫重試;完整 License 驗證沒有隱藏重試迴圈。呼叫端應以明確 Timer/工作檢查點呼叫 session.check(),並對暫時網路錯誤採有限退避。
Session 進入成功;應用程式安排的每個 session.check() 都通過;高價值操作前的強制驗證通過;退出後 Process Seat 已釋放。
長時間程式應在狀態失效時鎖定受保護功能,保留未完成工作,並顯示重新連線或聯絡管理員的步驟。
- 確認應用程式確實有 Timer、工作迴圈或操作入口會呼叫 session.check()。
- 確認 revalidate_interval_seconds 是門檻而不是排程器。
- 確認 GUI 主執行緒沒有被同步網路呼叫長時間阻塞。
- 檢查背景 Heartbeat 的 last_error 與 consecutive_failures。
- 以為 revalidate_interval_seconds 會自己建立 Timer,因此從不呼叫 session.check()。
- 在無 sleep 的緊密 for 迴圈中一直呼叫 session.check(force_validate=True),造成網路與 UI 負載。
- 在 GUI 主執行緒直接做可能阻塞到 timeout_seconds 的強制驗證。
- 程式發生授權錯誤後仍繼續執行受保護工作。
try:
state = session.refresh()
except LicenseSDKError:
lock_protected_ui()
整合 SessionLicenseSession.check由你的程式主動呼叫的同步檢查點:先讀取背景 Heartbeat/Process Seat 健康狀態,再於 force_validate=True 或重驗門檻已到時進行一次完整線上驗證。它不會自行循環,也不會建立背景驗證執行緒。
session.check(*, force_validate=False) -> LicenseSession白話解釋:由你的程式主動呼叫的同步檢查點:先讀取背景 Heartbeat/Process Seat 健康狀態,再於 force_validate=True 或重驗門檻已到時進行一次完整線上驗證。它不會自行循環,也不會建立背景驗證執行緒。
參數怎麼填
force_validate=False可選True 時,這一次 session.check() 會同步進行完整 Gateway + TPM 線上驗證,並可能阻塞到 timeout_seconds;False 時只有在 revalidate 間隔已到才會連線。
每次高價值操作前與主事件迴圈安全點。
- 先決定程式是否真的需要 Machine Heartbeat、Process Seat、Check-in 或 Usage。
- 決定由 GUI Timer、工作迴圈或高價值操作入口在何時呼叫 session.check()。
- 理解 revalidate_interval_seconds 只是 session.check() 的到期門檻,不是背景排程。
- 進入 context 時同步完成 ensure_registered()、Entitlement Gate,以及選用的一次 Check-in/Seat 取得。
- machine_heartbeat=True 或 process_seat=True 才會建立背景 Heartbeat 執行緒;背景執行緒不會自動做完整 License 驗證。
- session.check() 由呼叫端主動執行:先檢查背景 Heartbeat 是否已失敗,再視 force_validate 或到期門檻同步重新驗證。
- 離開 Session 時停止背景 Heartbeat並釋放 Process Seat;不會解除 Server Machine。
自身。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- HeartbeatError
- ProcessSeatUnavailableError
- LicenseInvalidError
- FeatureNotLicensedError
- GatewayError
同步、由呼叫端主動觸發的一次檢查
不建立任何新執行緒;也不啟動迴圈。它只讀取既有 Heartbeat manager 的狀態,必要時在目前執行緒做一次完整驗證。
- 先呼叫 machine_lease.check()/process_lease.check(),只檢查背景 thread 已保存的錯誤。
- force_validate=True 時立即 refresh()。
- force_validate=False 且距離上次驗證已達 revalidate_interval_seconds 時才 refresh()。
- 若 interval=0 且 force_validate=False,永遠不會因時間自動連線重驗。
- 自行安排呼叫頻率。
- 捕捉 HeartbeatError 與 LicenseSDKError。
- 需要高價值即時性時明確 force_validate=True。
- GUI:Timer/worker 每 10~30 秒 check(False),操作前 check(True)。
- CLI:每個主要步驟前。
- 服務:現有 scheduler 或工作迴圈 checkpoint。
純健康檢查通常立即完成;到期或 force 時會阻塞到完整 HTTPS + TPM 驗證完成或 timeout。
呼叫 check。 → 讀背景健康。 → 判斷是否到期。 → 必要時同步 refresh。 → 成功返回同一 Session 或拋例外。
進入 context 時會同步連線註冊/驗證;只有啟用 Machine/Process Heartbeat 時才有背景網路執行緒。完整 License revalidation 不會自動排程,必須由呼叫端執行 session.check()。
可能建立/維持/釋放 Process Seat,更新 Heartbeat、執行一次啟動 Check-in,或在正常離開時增加一次 Usage;不會自動解除 Server Machine。
Heartbeat 執行緒會依設定短暫重試;完整 License 驗證沒有隱藏重試迴圈。呼叫端應以明確 Timer/工作檢查點呼叫 session.check(),並對暫時網路錯誤採有限退避。
Session 進入成功;應用程式安排的每個 session.check() 都通過;高價值操作前的強制驗證通過;退出後 Process Seat 已釋放。
長時間程式應在狀態失效時鎖定受保護功能,保留未完成工作,並顯示重新連線或聯絡管理員的步驟。
- 確認應用程式確實有 Timer、工作迴圈或操作入口會呼叫 session.check()。
- 確認 revalidate_interval_seconds 是門檻而不是排程器。
- 確認 GUI 主執行緒沒有被同步網路呼叫長時間阻塞。
- 檢查背景 Heartbeat 的 last_error 與 consecutive_failures。
- 以為 revalidate_interval_seconds 會自己建立 Timer,因此從不呼叫 session.check()。
- 在無 sleep 的緊密 for 迴圈中一直呼叫 session.check(force_validate=True),造成網路與 UI 負載。
- 在 GUI 主執行緒直接做可能阻塞到 timeout_seconds 的強制驗證。
- 程式發生授權錯誤後仍繼續執行受保護工作。
try:
session.check(force_validate=True)
except LicenseSDKError as exc:
block_operation(exc)
整合 SessionLicenseSession.process取得目前 Process Seat。
session.process -> ProcessSeat | None白話解釋:取得目前 Process Seat。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
Session 啟用 process_seat=True 時顯示或記錄。
- 先決定程式是否真的需要 Machine Heartbeat、Process Seat、Check-in 或 Usage。
- 決定由 GUI Timer、工作迴圈或高價值操作入口在何時呼叫 session.check()。
- 理解 revalidate_interval_seconds 只是 session.check() 的到期門檻,不是背景排程。
- 進入 context 時同步完成 ensure_registered()、Entitlement Gate,以及選用的一次 Check-in/Seat 取得。
- machine_heartbeat=True 或 process_seat=True 才會建立背景 Heartbeat 執行緒;背景執行緒不會自動做完整 License 驗證。
- session.check() 由呼叫端主動執行:先檢查背景 Heartbeat 是否已失敗,再視 force_validate 或到期門檻同步重新驗證。
- 離開 Session 時停止背景 Heartbeat並釋放 Process Seat;不會解除 Server Machine。
ProcessSeat 或 None。
- 無特定 SDK 例外。
同步、本機屬性讀取
不建立背景執行緒。
- 回傳 Process manager 最近一次保存的 ProcessSeat。
- 只用於顯示/診斷;授權健康仍要 session.check()。
- 需要顯示 process_id、next_heartbeat 或 metadata 時。
立即完成,不做網路。
讀取屬性。 → 得到 snapshot 或 None。
進入 context 時會同步連線註冊/驗證;只有啟用 Machine/Process Heartbeat 時才有背景網路執行緒。完整 License revalidation 不會自動排程,必須由呼叫端執行 session.check()。
可能建立/維持/釋放 Process Seat,更新 Heartbeat、執行一次啟動 Check-in,或在正常離開時增加一次 Usage;不會自動解除 Server Machine。
Heartbeat 執行緒會依設定短暫重試;完整 License 驗證沒有隱藏重試迴圈。呼叫端應以明確 Timer/工作檢查點呼叫 session.check(),並對暫時網路錯誤採有限退避。
Session 進入成功;應用程式安排的每個 session.check() 都通過;高價值操作前的強制驗證通過;退出後 Process Seat 已釋放。
長時間程式應在狀態失效時鎖定受保護功能,保留未完成工作,並顯示重新連線或聯絡管理員的步驟。
- 確認應用程式確實有 Timer、工作迴圈或操作入口會呼叫 session.check()。
- 確認 revalidate_interval_seconds 是門檻而不是排程器。
- 確認 GUI 主執行緒沒有被同步網路呼叫長時間阻塞。
- 檢查背景 Heartbeat 的 last_error 與 consecutive_failures。
- 以為 revalidate_interval_seconds 會自己建立 Timer,因此從不呼叫 session.check()。
- 在無 sleep 的緊密 for 迴圈中一直呼叫 session.check(force_validate=True),造成網路與 UI 負載。
- 在 GUI 主執行緒直接做可能阻塞到 timeout_seconds 的強制驗證。
- 程式發生授權錯誤後仍繼續執行受保護工作。
print(session.process.process_id if session.process else 'none')
整合 SessionLicenseSession.machine_heartbeat取得目前 Machine Heartbeat State。
session.machine_heartbeat -> MachineHeartbeat | None白話解釋:取得目前 Machine Heartbeat State。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
Session 啟用 machine_heartbeat=True 時。
- 先決定程式是否真的需要 Machine Heartbeat、Process Seat、Check-in 或 Usage。
- 決定由 GUI Timer、工作迴圈或高價值操作入口在何時呼叫 session.check()。
- 理解 revalidate_interval_seconds 只是 session.check() 的到期門檻,不是背景排程。
- 進入 context 時同步完成 ensure_registered()、Entitlement Gate,以及選用的一次 Check-in/Seat 取得。
- machine_heartbeat=True 或 process_seat=True 才會建立背景 Heartbeat 執行緒;背景執行緒不會自動做完整 License 驗證。
- session.check() 由呼叫端主動執行:先檢查背景 Heartbeat 是否已失敗,再視 force_validate 或到期門檻同步重新驗證。
- 離開 Session 時停止背景 Heartbeat並釋放 Process Seat;不會解除 Server Machine。
MachineHeartbeat 或 None。
- 無特定 SDK 例外。
同步、本機屬性讀取
不建立背景執行緒。
- 回傳 Machine manager 最近一次保存的 MachineHeartbeat。
- 只用於顯示/診斷;授權健康仍要 session.check()。
- 需要顯示 last/next heartbeat 時。
立即完成,不做網路。
讀取屬性。 → 得到 snapshot 或 None。
進入 context 時會同步連線註冊/驗證;只有啟用 Machine/Process Heartbeat 時才有背景網路執行緒。完整 License revalidation 不會自動排程,必須由呼叫端執行 session.check()。
可能建立/維持/釋放 Process Seat,更新 Heartbeat、執行一次啟動 Check-in,或在正常離開時增加一次 Usage;不會自動解除 Server Machine。
Heartbeat 執行緒會依設定短暫重試;完整 License 驗證沒有隱藏重試迴圈。呼叫端應以明確 Timer/工作檢查點呼叫 session.check(),並對暫時網路錯誤採有限退避。
Session 進入成功;應用程式安排的每個 session.check() 都通過;高價值操作前的強制驗證通過;退出後 Process Seat 已釋放。
長時間程式應在狀態失效時鎖定受保護功能,保留未完成工作,並顯示重新連線或聯絡管理員的步驟。
- 確認應用程式確實有 Timer、工作迴圈或操作入口會呼叫 session.check()。
- 確認 revalidate_interval_seconds 是門檻而不是排程器。
- 確認 GUI 主執行緒沒有被同步網路呼叫長時間阻塞。
- 檢查背景 Heartbeat 的 last_error 與 consecutive_failures。
- 以為 revalidate_interval_seconds 會自己建立 Timer,因此從不呼叫 session.check()。
- 在無 sleep 的緊密 for 迴圈中一直呼叫 session.check(force_validate=True),造成網路與 UI 負載。
- 在 GUI 主執行緒直接做可能阻塞到 timeout_seconds 的強制驗證。
- 程式發生授權錯誤後仍繼續執行受保護工作。
print(session.machine_heartbeat)
Workflow 04
4. Usage 計次與 Check-in
Usage 是受限功能的消耗量,不等同整張 License 是否有效。產生檔案時應先寫入 staging,Server 接受 increment 後才正式交付。
- 1
完成或暫存受限工作
- 2
向 Server 增加正整數 Usage
- 3
成功後交付成果
- 4
必要時執行 License Check-in
計次與 Check-in高影響DeviceLicenseClient.increment_usage以 Server 原子操作增加正整數 Usage。
client.increment_usage(amount: int = 1) -> UsageState白話解釋:以 Server 原子操作增加正整數 Usage。
參數怎麼填
amount: int = 1可選要增加的使用量,必須是正整數。通常一次成功工作傳 1。
成功完成一次或一批計次工作後。
- 先明確定義何謂一次成功工作。
- 在增加 Usage 前先驗證 License 與必要 Entitlement。
- 確認失敗、取消與重試不會被重複計次。
- increment_usage 會永久增加 Server 上的使用量。
- check_in_license 只更新 License Check-in 時間,不等於 Machine/Process Heartbeat。
UsageState,包含 uses 與 max_uses。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- TypeError:bool、float、str 等非 int。
- ValueError:amount < 1。
- GatewayError:包含額度已滿或 Server 拒絕。
- LicenseInvalidError
- License 到達 maxUses 不一定失效;後續 increment 會被拒絕。
- 結果應先寫入 staging,increment 成功後才 publish。
同步網路狀態變更
不會建立背景執行緒。
- 一次呼叫只執行一次 Usage increment 或 Check-in。
- 自行決定成功邊界與防重策略。
- 若 Policy 要週期 Check-in,依 next_check_in 自行排程;SDK 不會建立 Check-in Timer。
- Usage:工作成功且成果尚未正式交付時。
- Check-in:啟動時或應用程式排程的到期前。
會阻塞到網路完成或 timeout_seconds。結果不確定時不可盲目重送 Usage。
驗證授權。 → 完成或暫存工作。 → 同步提交狀態變更。 → 確認成功後交付成果。
會連線並對目前 License 增加指定正整數 Usage。
成功後永久增加 Server uses;通常不可由 Client 回滾。
網路中斷造成結果不確定時,先查詢最新 state.uses 或以業務 operation ID 防重,不可直接重送。
比較呼叫前後 uses,確認增加量和預期一致,且成果已成功產生。
顯示『已使用 X / Y 次』;不確定結果要顯示待確認,不要讓使用者再次按下造成重複扣量。
- 只在工作成功後計次。
- 建立防連點與重複提交保護。
- 測試網路在 Server 接受後中斷的情境。
- 工作一開始就先扣 Usage。
- 網路逾時後盲目重送,造成同一工作重複扣量。
- 把 Usage 額度當成 Machine activation。
try:
usage = client.increment_usage(3)
publish_staged_result()
except GatewayError as exc:
discard_staged_result()
show_usage_denied(exc)
計次與 Check-inDeviceLicenseClient.check_in_license執行 License Check-in,更新 last/next check-in。
client.check_in_license() -> CheckInState白話解釋:執行 License Check-in,更新 last/next check-in。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
Policy requireCheckIn 或程式需要主動回報時。
- 先明確定義何謂一次成功工作。
- 在增加 Usage 前先驗證 License 與必要 Entitlement。
- 確認失敗、取消與重試不會被重複計次。
- increment_usage 會永久增加 Server 上的使用量。
- check_in_license 只更新 License Check-in 時間,不等於 Machine/Process Heartbeat。
CheckInState。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError
- LicenseInvalidError
- Check-in 不等於 Machine/Process Heartbeat。
同步、單次 License Check-in
不建立背景執行緒或定時器。
- 只更新一次 last_check_in/next_check_in。
- 若 Policy 要求持續 Check-in,讀取 next_check_in 並用應用程式既有 scheduler 自行安排下一次。
- 程式啟動。
- next_check_in 到期前。
會阻塞到網路完成或 timeout_seconds。
同步 Check-in。 → 保存 next_check_in。 → 自行排程後續呼叫。
會透過 HTTPS Gateway 修改 Usage 或 Check-in 狀態。
increment_usage 會永久增加使用量;check_in_license 會更新最後/下次 Check-in 時間。
Usage 遇到不確定結果時不可直接重送,應使用業務 operation ID 或查詢最新狀態避免重複扣量。Check-in 暫時失敗可有限次重試。
確認回傳 uses、max_uses、last_check_in 或 next_check_in 已更新,而且業務成果與計次順序符合設計。
額度已滿時顯示目前用量與聯絡管理員方式;網路不確定時顯示『結果待確認』,不要假裝計次成功。
- 把計次放在工作成功邊界,而不是按下按鈕時。
- 檢查重試流程是否可能對同一工作重複扣量。
- 確認 Check-in、Machine Heartbeat 與 Process Heartbeat 沒有混用。
- 工作一開始就先扣 Usage。
- 網路逾時後盲目重送,造成同一工作重複扣量。
- 把 Usage 額度當成 Machine activation。
try:
checkin = client.check_in_license()
except LicenseSDKError as exc:
show_checkin_error(exc)
Workflow 05
5. Machine、Component、Process 與 Heartbeat
這些 API 管理執行中的 Machine Profile、Component matching、Machine Heartbeat 與並行 Process 席位。Process 席位可由 Client 取得與釋放;Server Machine 生命週期由管理員處理。
- 1
同步裝置資料
- 2
啟動 Heartbeat
- 3
需要時取得 Process 席位
- 4
在安全點檢查背景狀態
- 5
結束時釋放 Process 席位
Machine ComponentsDeviceLicenseClient.list_machine_components列出目前 TPM-proven Machine 的 Components。
client.list_machine_components() -> tuple[MachineComponent, ...]白話解釋:列出目前 TPM-proven Machine 的 Components。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
查看已註冊 FPGA、板卡或邏輯元件。
- 先為每個 Component 選擇穩定 name 與 fingerprint 規則。
- 確認 fingerprint 不包含不必要的明文序號。
- 建立、更新、刪除或同步目前 TPM-proven Machine 的 Component。
- remove_missing=True 可能刪除未出現在本次完整清單中的既有元件。
MachineComponent tuple。
- LicenseSDKError
同步網路讀寫
不會建立背景執行緒。
- 一次呼叫完成一次 Component list/add/update/remove/sync。
- 提供穩定 fingerprint。
- 對 sync/remove 建立二次確認與結果核對。
- 首次啟用後建立硬體快照。
- 硬體更換經確認後。
- 驗證前需要同步元件時。
會阻塞到網路完成或 timeout_seconds;大量元件同步應在 worker thread。
收集並正規化識別值。 → 建立雜湊 fingerprint。 → 同步。 → 重新 list 核對。
會透過 HTTPS Gateway讀取或修改目前 Machine 的 Component 清單。
新增、更新、移除或同步 Component 會修改 Server 狀態;remove_missing=True 可能批次刪除。
讀取可以有限重試;新增/移除/同步遇到不確定結果時先重新列出 Components,再決定下一步。
重新讀取 Component 清單,確認 name、fingerprint 與 metadata 和預期一致。
指出哪個元件無法綁定或同步;不要向使用者顯示未雜湊的硬體序號。
- 確認 fingerprint 規則固定且可重現。
- 使用 remove_missing=True 前,確認傳入的是完整快照。
- 確認 Policy 的 component scope 需求。
- 使用會隨開機改變的值當 fingerprint。
- 傳入部分清單卻啟用 remove_missing=True。
- 誤以為 Component matching 可以取代 TPM Machine 身分。
try:
items = client.list_machine_components()
except LicenseSDKError as exc:
show_component_error(exc)
Machine ComponentsDeviceLicenseClient.add_machine_component新增一個 Component 到目前 Machine。
client.add_machine_component(component: MachineComponentSpec) -> MachineComponent白話解釋:新增一個 Component 到目前 Machine。
參數怎麼填
component: MachineComponentSpec必填既有 MachineComponent 物件或識別資料;只允許操作目前 TPM-proven Machine 的元件。
首次綁定可更換硬體或邏輯模組時。
- 先為每個 Component 選擇穩定 name 與 fingerprint 規則。
- 確認 fingerprint 不包含不必要的明文序號。
- 建立、更新、刪除或同步目前 TPM-proven Machine 的 Component。
- remove_missing=True 可能刪除未出現在本次完整清單中的既有元件。
MachineComponent。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ValueError
- GatewayError
- LicenseInvalidError
- fingerprint 建議先用 build_component_fingerprint()。
同步網路讀寫
不會建立背景執行緒。
- 一次呼叫完成一次 Component list/add/update/remove/sync。
- 提供穩定 fingerprint。
- 對 sync/remove 建立二次確認與結果核對。
- 首次啟用後建立硬體快照。
- 硬體更換經確認後。
- 驗證前需要同步元件時。
會阻塞到網路完成或 timeout_seconds;大量元件同步應在 worker thread。
收集並正規化識別值。 → 建立雜湊 fingerprint。 → 同步。 → 重新 list 核對。
會透過 HTTPS Gateway讀取或修改目前 Machine 的 Component 清單。
新增、更新、移除或同步 Component 會修改 Server 狀態;remove_missing=True 可能批次刪除。
讀取可以有限重試;新增/移除/同步遇到不確定結果時先重新列出 Components,再決定下一步。
重新讀取 Component 清單,確認 name、fingerprint 與 metadata 和預期一致。
指出哪個元件無法綁定或同步;不要向使用者顯示未雜湊的硬體序號。
- 確認 fingerprint 規則固定且可重現。
- 使用 remove_missing=True 前,確認傳入的是完整快照。
- 確認 Policy 的 component scope 需求。
- 使用會隨開機改變的值當 fingerprint。
- 傳入部分清單卻啟用 remove_missing=True。
- 誤以為 Component matching 可以取代 TPM Machine 身分。
component = client.add_machine_component(spec)
Machine ComponentsDeviceLicenseClient.update_machine_component更新 Component 的可變名稱或 Metadata。
client.update_machine_component(component, *, name=None, metadata=None) -> MachineComponent白話解釋:更新 Component 的可變名稱或 Metadata。
參數怎麼填
component必填既有 MachineComponent 物件或識別資料;只允許操作目前 TPM-proven Machine 的元件。
name=None可選顯示名稱。它不是安全識別主鍵,真正綁定仍依 Machine/Component fingerprint。
metadata=None可選附加的 JSON-compatible dict。只放非秘密、可序列化、對營運或診斷有用的資料。
顯示名稱或非識別屬性改變時。
- 先為每個 Component 選擇穩定 name 與 fingerprint 規則。
- 確認 fingerprint 不包含不必要的明文序號。
- 建立、更新、刪除或同步目前 TPM-proven Machine 的 Component。
- remove_missing=True 可能刪除未出現在本次完整清單中的既有元件。
更新後 MachineComponent。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ValueError
- GatewayError
- fingerprint 不在此方法變更。
同步網路讀寫
不會建立背景執行緒。
- 一次呼叫完成一次 Component list/add/update/remove/sync。
- 提供穩定 fingerprint。
- 對 sync/remove 建立二次確認與結果核對。
- 首次啟用後建立硬體快照。
- 硬體更換經確認後。
- 驗證前需要同步元件時。
會阻塞到網路完成或 timeout_seconds;大量元件同步應在 worker thread。
收集並正規化識別值。 → 建立雜湊 fingerprint。 → 同步。 → 重新 list 核對。
會透過 HTTPS Gateway讀取或修改目前 Machine 的 Component 清單。
新增、更新、移除或同步 Component 會修改 Server 狀態;remove_missing=True 可能批次刪除。
讀取可以有限重試;新增/移除/同步遇到不確定結果時先重新列出 Components,再決定下一步。
重新讀取 Component 清單,確認 name、fingerprint 與 metadata 和預期一致。
指出哪個元件無法綁定或同步;不要向使用者顯示未雜湊的硬體序號。
- 確認 fingerprint 規則固定且可重現。
- 使用 remove_missing=True 前,確認傳入的是完整快照。
- 確認 Policy 的 component scope 需求。
- 使用會隨開機改變的值當 fingerprint。
- 傳入部分清單卻啟用 remove_missing=True。
- 誤以為 Component matching 可以取代 TPM Machine 身分。
updated = client.update_machine_component(item, name='Main FPGA')
Machine Components高影響DeviceLicenseClient.remove_machine_component從目前 Machine 移除指定 Component。
client.remove_machine_component(component) -> bool白話解釋:從目前 Machine 移除指定 Component。
參數怎麼填
component必填既有 MachineComponent 物件或識別資料;只允許操作目前 TPM-proven Machine 的元件。
元件已不再屬於裝置且 Policy 允許時。
- 先為每個 Component 選擇穩定 name 與 fingerprint 規則。
- 確認 fingerprint 不包含不必要的明文序號。
- 建立、更新、刪除或同步目前 TPM-proven Machine 的 Component。
- remove_missing=True 可能刪除未出現在本次完整清單中的既有元件。
True。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError
- LicenseInvalidError
- 可能影響要求 component scope 的驗證。
同步網路讀寫
不會建立背景執行緒。
- 一次呼叫完成一次 Component list/add/update/remove/sync。
- 提供穩定 fingerprint。
- 對 sync/remove 建立二次確認與結果核對。
- 首次啟用後建立硬體快照。
- 硬體更換經確認後。
- 驗證前需要同步元件時。
會阻塞到網路完成或 timeout_seconds;大量元件同步應在 worker thread。
收集並正規化識別值。 → 建立雜湊 fingerprint。 → 同步。 → 重新 list 核對。
會透過 HTTPS Gateway讀取或修改目前 Machine 的 Component 清單。
新增、更新、移除或同步 Component 會修改 Server 狀態;remove_missing=True 可能批次刪除。
讀取可以有限重試;新增/移除/同步遇到不確定結果時先重新列出 Components,再決定下一步。
重新讀取 Component 清單,確認 name、fingerprint 與 metadata 和預期一致。
指出哪個元件無法綁定或同步;不要向使用者顯示未雜湊的硬體序號。
- 確認 fingerprint 規則固定且可重現。
- 使用 remove_missing=True 前,確認傳入的是完整快照。
- 確認 Policy 的 component scope 需求。
- 使用會隨開機改變的值當 fingerprint。
- 傳入部分清單卻啟用 remove_missing=True。
- 誤以為 Component matching 可以取代 TPM Machine 身分。
try:
client.remove_machine_component(item)
except LicenseSDKError as exc:
show_component_error(exc)
Machine Components高影響DeviceLicenseClient.sync_machine_components將 Server Components 對齊到期望清單。
client.sync_machine_components(components, *, remove_missing=False) -> tuple[MachineComponent, ...]白話解釋:將 Server Components 對齊到期望清單。
參數怎麼填
components必填MachineComponentSpec 集合。每個項目至少需要穩定 name 與 fingerprint。
remove_missing=False可選同步時是否刪除 Server 上未出現在本次清單的 Component。啟用前要確認清單是完整快照。
啟動時同步多個板卡/FPGA 元件。
- 先為每個 Component 選擇穩定 name 與 fingerprint 規則。
- 確認 fingerprint 不包含不必要的明文序號。
- 建立、更新、刪除或同步目前 TPM-proven Machine 的 Component。
- remove_missing=True 可能刪除未出現在本次完整清單中的既有元件。
同步後 Component tuple。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ValueError
- GatewayError
- remove_missing=True 會刪除不在清單中的元件。
同步網路讀寫
不會建立背景執行緒。
- 一次呼叫完成一次 Component list/add/update/remove/sync。
- 提供穩定 fingerprint。
- 對 sync/remove 建立二次確認與結果核對。
- 首次啟用後建立硬體快照。
- 硬體更換經確認後。
- 驗證前需要同步元件時。
會阻塞到網路完成或 timeout_seconds;大量元件同步應在 worker thread。
收集並正規化識別值。 → 建立雜湊 fingerprint。 → 同步。 → 重新 list 核對。
會連線並將目前 Machine 的 Component 清單對齊指定完整清單。
會新增或更新 Components;remove_missing=True 時也會刪除未出現在輸入清單的項目。
結果不確定時先 list_machine_components() 比對,不可立刻再次以 remove_missing=True 重送。
重新列出 Components,逐項比對 fingerprint、name、metadata 與數量。
在確認頁清楚列出將新增、更新與刪除的元件數;刪除模式必須二次確認。
- 只把完整硬體快照傳給 remove_missing=True。
- 先在測試 Machine 驗證 fingerprint 規則。
- 避免把未偵測到的暫時狀態當成元件已拆除。
- 使用會隨開機改變的值當 fingerprint。
- 傳入部分清單卻啟用 remove_missing=True。
- 誤以為 Component matching 可以取代 TPM Machine 身分。
try:
synced = client.sync_machine_components(specs, remove_missing=False)
except LicenseSDKError as exc:
show_component_error(exc)
Machine 與 HeartbeatDeviceLicenseClient.get_machine_profile讀取目前 Machine 的安全可見屬性與 Heartbeat 狀態。
client.get_machine_profile() -> MachineProfile白話解釋:讀取目前 Machine 的安全可見屬性與 Heartbeat 狀態。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
顯示裝置資訊或確認 Server 記錄。
- 本機必須先完成 TPM Device Registration。
- 只操作 SDK 目前 registration 對應的 Machine,不接受任意 Machine ID。
- 讀取或更新目前 Machine 的管理資料與資源資訊。
- Heartbeat 只更新目前 Machine 活性,不會解除或刪除 Machine。
MachineProfile。
- LicenseSDKError
同步網路操作;Heartbeat manager 工廠除外
一般方法不建立執行緒;machine_heartbeat() 只建立 manager,必須 start()/with 才啟動背景執行緒。
- 單次讀取、更新或 ping 只做一次請求。
- 自行決定何時更新 Profile 或做單次 ping。
- 需要持續 Heartbeat 時使用 manager 並定期 check()。
- Profile:啟用後或資訊變更時。
- 單次 ping:診斷。
- 持續 Heartbeat:長時間 Floating Machine 生命週期。
單次網路方法會阻塞;manager.start() 的第一次 ping 也同步阻塞。
確認已註冊。 → 呼叫單次方法或建立 manager。 → 需要背景維持時 start。 → 主流程定期 check。 → 結束時 stop。
會透過 HTTPS Gateway讀取或更新目前 TPM-proven Machine。
Profile 更新與 Heartbeat 會修改 Server 上目前 Machine 的管理資料或活性時間;不會解除 Machine。
讀取可對暫時網路錯誤有限重試;更新操作要先確認是否已成功,避免重複覆寫或產生誤判。
確認回傳 machine_id 等於本機 registration 的 Machine,且更新欄位或 Heartbeat 時間符合預期。
Machine 操作失敗時說明是資料更新、Heartbeat 還是授權拒絕;不要引導使用者刪除 registration 來釋放席位。
- 比對 local registration 的 machine_id。
- 確認 Hostname、IP 只是管理資料,不是安全身分。
- Floating Policy 下確認 Heartbeat 間隔與 cull 規則。
- 把 Hostname 或 IP 當成安全身分。
- 正常退出程式時自動解除 Server Machine。
- 使用 Client SDK 管理其他電腦的 Machine。
profile = client.get_machine_profile()
Machine 與 HeartbeatDeviceLicenseClient.update_machine_profile更新目前 TPM-proven Machine 的安全屬性,不能指定任意 Machine ID。
client.update_machine_profile(*, name=None, ip=None, hostname=None, platform_name=None, metadata=None, cores=None, memory_bytes=None, disk_bytes=None, refresh_local_system_info=False) -> MachineProfile白話解釋:更新目前 TPM-proven Machine 的安全屬性,不能指定任意 Machine ID。
參數怎麼填
name=None可選顯示名稱。它不是安全識別主鍵,真正綁定仍依 Machine/Component fingerprint。
ip=None可選目前裝置 IP 字串;可能會改變,只適合管理與診斷。
hostname=None可選目前裝置 Hostname;屬於管理資訊,不應拿來取代 TPM 身分。
platform_name=None可選作業系統或平台描述,例如 Windows 11;不是 Product Namespace。
metadata=None可選附加的 JSON-compatible dict。只放非秘密、可序列化、對營運或診斷有用的資料。
cores=None可選CPU core 數量。通常由 SDK 自動收集,只有客製流程才手動指定。
memory_bytes=None可選實體記憶體容量,單位是 bytes,不是 GiB。
disk_bytes=None可選系統磁碟容量,單位是 bytes,不是 GiB。
refresh_local_system_info=False可選是否重新讀取本機 Hostname、Platform 與資源資訊後再更新 Server。
裝置名稱、Metadata 或硬體資源資訊更新時。
- 本機必須先完成 TPM Device Registration。
- 只操作 SDK 目前 registration 對應的 Machine,不接受任意 Machine ID。
- 讀取或更新目前 Machine 的管理資料與資源資訊。
- Heartbeat 只更新目前 Machine 活性,不會解除或刪除 Machine。
MachineProfile。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ValueError
- GatewayError
- refresh_local_system_info=True 可自動收集本機資訊。
同步網路操作;Heartbeat manager 工廠除外
一般方法不建立執行緒;machine_heartbeat() 只建立 manager,必須 start()/with 才啟動背景執行緒。
- 單次讀取、更新或 ping 只做一次請求。
- 自行決定何時更新 Profile 或做單次 ping。
- 需要持續 Heartbeat 時使用 manager 並定期 check()。
- Profile:啟用後或資訊變更時。
- 單次 ping:診斷。
- 持續 Heartbeat:長時間 Floating Machine 生命週期。
單次網路方法會阻塞;manager.start() 的第一次 ping 也同步阻塞。
確認已註冊。 → 呼叫單次方法或建立 manager。 → 需要背景維持時 start。 → 主流程定期 check。 → 結束時 stop。
會透過 HTTPS Gateway讀取或更新目前 TPM-proven Machine。
Profile 更新與 Heartbeat 會修改 Server 上目前 Machine 的管理資料或活性時間;不會解除 Machine。
讀取可對暫時網路錯誤有限重試;更新操作要先確認是否已成功,避免重複覆寫或產生誤判。
確認回傳 machine_id 等於本機 registration 的 Machine,且更新欄位或 Heartbeat 時間符合預期。
Machine 操作失敗時說明是資料更新、Heartbeat 還是授權拒絕;不要引導使用者刪除 registration 來釋放席位。
- 比對 local registration 的 machine_id。
- 確認 Hostname、IP 只是管理資料,不是安全身分。
- Floating Policy 下確認 Heartbeat 間隔與 cull 規則。
- 把 Hostname 或 IP 當成安全身分。
- 正常退出程式時自動解除 Server Machine。
- 使用 Client SDK 管理其他電腦的 Machine。
profile = client.update_machine_profile(refresh_local_system_info=True)
Machine 與 HeartbeatDeviceLicenseClient.ping_machine立即送一次 Machine Heartbeat。
client.ping_machine() -> MachineHeartbeat白話解釋:立即送一次 Machine Heartbeat。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
測試 Heartbeat 或自行排程時。
- 本機必須先完成 TPM Device Registration。
- 只操作 SDK 目前 registration 對應的 Machine,不接受任意 Machine ID。
- 讀取或更新目前 Machine 的管理資料與資源資訊。
- Heartbeat 只更新目前 Machine 活性,不會解除或刪除 Machine。
MachineHeartbeat。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError
- LicenseInvalidError
同步網路操作;Heartbeat manager 工廠除外
一般方法不建立執行緒;machine_heartbeat() 只建立 manager,必須 start()/with 才啟動背景執行緒。
- 單次讀取、更新或 ping 只做一次請求。
- 自行決定何時更新 Profile 或做單次 ping。
- 需要持續 Heartbeat 時使用 manager 並定期 check()。
- Profile:啟用後或資訊變更時。
- 單次 ping:診斷。
- 持續 Heartbeat:長時間 Floating Machine 生命週期。
單次網路方法會阻塞;manager.start() 的第一次 ping 也同步阻塞。
確認已註冊。 → 呼叫單次方法或建立 manager。 → 需要背景維持時 start。 → 主流程定期 check。 → 結束時 stop。
會透過 HTTPS Gateway讀取或更新目前 TPM-proven Machine。
Profile 更新與 Heartbeat 會修改 Server 上目前 Machine 的管理資料或活性時間;不會解除 Machine。
讀取可對暫時網路錯誤有限重試;更新操作要先確認是否已成功,避免重複覆寫或產生誤判。
確認回傳 machine_id 等於本機 registration 的 Machine,且更新欄位或 Heartbeat 時間符合預期。
Machine 操作失敗時說明是資料更新、Heartbeat 還是授權拒絕;不要引導使用者刪除 registration 來釋放席位。
- 比對 local registration 的 machine_id。
- 確認 Hostname、IP 只是管理資料,不是安全身分。
- Floating Policy 下確認 Heartbeat 間隔與 cull 規則。
- 把 Hostname 或 IP 當成安全身分。
- 正常退出程式時自動解除 Server Machine。
- 使用 Client SDK 管理其他電腦的 Machine。
heartbeat = client.ping_machine()
Machine 與 HeartbeatDeviceLicenseClient.machine_heartbeat建立背景 Machine Heartbeat 管理器。
client.machine_heartbeat(*, interval_seconds=None) -> ManagedHeartbeat[MachineHeartbeat]白話解釋:建立背景 Machine Heartbeat 管理器。
參數怎麼填
interval_seconds=None可選Heartbeat 間隔秒數。沿用 Server/SDK 建議值,過短會增加負載,過長會延遲失效偵測。
Floating Machine 或 Policy requireHeartbeat 的長時間程式。
- 本機必須先完成 TPM Device Registration。
- 只操作 SDK 目前 registration 對應的 Machine,不接受任意 Machine ID。
- 讀取或更新目前 Machine 的管理資料與資源資訊。
- Heartbeat 只更新目前 Machine 活性,不會解除或刪除 Machine。
ManagedHeartbeat。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- HeartbeatError
- GatewayError
- 停止 Heartbeat 不等於解除 Server Machine。
只建立 ManagedHeartbeat 物件;start()/with 時才連線
呼叫 machine_heartbeat() 本身不建立 thread;manager.start() 或進入 with 後建立一條 daemon thread。
- 建立含有 start/ping/interval 規則的 manager。
- 使用 with 或明確 start。
- 定期 manager.check()。
- 結束時 stop。
- 長時間 Floating Machine 應用的外層生命週期。
工廠呼叫立即回傳;start() 的首次 ping 會同步阻塞。
建立 manager。 → start/with。 → 背景 ping。 → 主流程 check。 → stop;不解除 Machine。
會透過 HTTPS Gateway讀取或更新目前 TPM-proven Machine。
Profile 更新與 Heartbeat 會修改 Server 上目前 Machine 的管理資料或活性時間;不會解除 Machine。
讀取可對暫時網路錯誤有限重試;更新操作要先確認是否已成功,避免重複覆寫或產生誤判。
確認回傳 machine_id 等於本機 registration 的 Machine,且更新欄位或 Heartbeat 時間符合預期。
Machine 操作失敗時說明是資料更新、Heartbeat 還是授權拒絕;不要引導使用者刪除 registration 來釋放席位。
- 比對 local registration 的 machine_id。
- 確認 Hostname、IP 只是管理資料,不是安全身分。
- Floating Policy 下確認 Heartbeat 間隔與 cull 規則。
- 把 Hostname 或 IP 當成安全身分。
- 正常退出程式時自動解除 Server Machine。
- 使用 Client SDK 管理其他電腦的 Machine。
try:
with client.machine_heartbeat() as lease:
run_app()
lease.check()
except HeartbeatError as exc:
pause_protected_work(exc)
並行 Process 席位DeviceLicenseClient.acquire_process_seat取得一個並行 Process Seat。
client.acquire_process_seat(*, pid='', metadata=None) -> ProcessSeat白話解釋:取得一個並行 Process Seat。
參數怎麼填
pid=''可選Process ID。通常使用目前程式 os.getpid(),不要隨意重複其他執行中的 PID。
metadata=None可選附加的 JSON-compatible dict。只放非秘密、可序列化、對營運或診斷有用的資料。
Policy 使用 maxProcesses,且你自行管理生命週期時。
- Policy 必須設定 maxProcesses 或要求 Process 管理。
- 每個真正執行中的程式實例使用自己的 PID/Seat。
- 建立 Process Seat 後,Client 必須依 interval 維持 Heartbeat。
- 正常結束時可以釋放 Process Seat;這不會解除 Machine。
ProcessSeat。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ProcessSeatUnavailableError
- GatewayError
- LicenseInvalidError
- 一般建議使用 process_seat() context manager。
同步網路操作;Process manager 工廠除外
一般方法不建立執行緒;process_seat() 只建立 manager,必須 start()/with 才取得 Seat 並啟動背景 Heartbeat。
- acquire/ping/release 各只執行一次。
- 每個真實程序管理自己的 Seat。
- 使用 manager 時定期 check() 並在結束時 stop/離開 with。
- 應用程式/工作程序開始時取得。
- 長時間執行期間維持。
- 正常結束時釋放。
單次網路方法與 manager.start() 會阻塞到網路完成或 timeout_seconds。
取得 Seat。 → 背景維持或自行 ping。 → 主流程檢查錯誤。 → 正常結束釋放。
會透過 HTTPS Gateway 建立、維持、列出或釋放 Process Seat。
建立與釋放 Seat 會修改 Server 的並行程序狀態;Heartbeat 更新 Seat 活性。
建立 Seat 收到不確定結果時先列出目前 Process;釋放失敗可在安全關閉流程中有限重試,但不可阻止程式退出。
確認回傳 Seat 的 PID、process_id、heartbeat 與目前程序一致;結束時確認 release 結果。
席位不足時顯示並行上限與稍後重試建議;不要把它描述成 Machine 啟用失敗。
- 每個真實程序使用自己的 PID。
- 確認崩潰後的 Seat 回收依 Server cull 規則。
- 不要讓多個程序共用同一個 ProcessSeat 物件。
- 多個程序共用同一個 Seat。
- 程式崩潰後假設 Seat 一定立即消失。
- 把 Process Seat 當成 Windows 使用者數。
try:
seat = client.acquire_process_seat(metadata={'app': 'FSM Studio'})
except ProcessSeatUnavailableError:
show_no_seat()
並行 Process 席位DeviceLicenseClient.ping_process_seat更新既有 Process Seat Heartbeat。
client.ping_process_seat(process) -> ProcessSeat白話解釋:更新既有 Process Seat Heartbeat。
參數怎麼填
process必填已取得的 ProcessSeat。release 或 heartbeat 時應傳回同一個 Seat。
自行管理 Seat 心跳時。
- Policy 必須設定 maxProcesses 或要求 Process 管理。
- 每個真正執行中的程式實例使用自己的 PID/Seat。
- 建立 Process Seat 後,Client 必須依 interval 維持 Heartbeat。
- 正常結束時可以釋放 Process Seat;這不會解除 Machine。
更新後 ProcessSeat。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError
- LicenseInvalidError
同步網路操作;Process manager 工廠除外
一般方法不建立執行緒;process_seat() 只建立 manager,必須 start()/with 才取得 Seat 並啟動背景 Heartbeat。
- acquire/ping/release 各只執行一次。
- 每個真實程序管理自己的 Seat。
- 使用 manager 時定期 check() 並在結束時 stop/離開 with。
- 應用程式/工作程序開始時取得。
- 長時間執行期間維持。
- 正常結束時釋放。
單次網路方法與 manager.start() 會阻塞到網路完成或 timeout_seconds。
取得 Seat。 → 背景維持或自行 ping。 → 主流程檢查錯誤。 → 正常結束釋放。
會透過 HTTPS Gateway 建立、維持、列出或釋放 Process Seat。
建立與釋放 Seat 會修改 Server 的並行程序狀態;Heartbeat 更新 Seat 活性。
建立 Seat 收到不確定結果時先列出目前 Process;釋放失敗可在安全關閉流程中有限重試,但不可阻止程式退出。
確認回傳 Seat 的 PID、process_id、heartbeat 與目前程序一致;結束時確認 release 結果。
席位不足時顯示並行上限與稍後重試建議;不要把它描述成 Machine 啟用失敗。
- 每個真實程序使用自己的 PID。
- 確認崩潰後的 Seat 回收依 Server cull 規則。
- 不要讓多個程序共用同一個 ProcessSeat 物件。
- 多個程序共用同一個 Seat。
- 程式崩潰後假設 Seat 一定立即消失。
- 把 Process Seat 當成 Windows 使用者數。
seat = client.ping_process_seat(seat)
並行 Process 席位DeviceLicenseClient.release_process_seat正常釋放短期 Process Seat。
client.release_process_seat(process) -> bool白話解釋:正常釋放短期 Process Seat。
參數怎麼填
process必填已取得的 ProcessSeat。release 或 heartbeat 時應傳回同一個 Seat。
程式退出或受保護工作結束時。
- Policy 必須設定 maxProcesses 或要求 Process 管理。
- 每個真正執行中的程式實例使用自己的 PID/Seat。
- 建立 Process Seat 後,Client 必須依 interval 維持 Heartbeat。
- 正常結束時可以釋放 Process Seat;這不會解除 Machine。
True。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError
- Process release 允許;這與 Machine deactivation 不同。
同步網路操作;Process manager 工廠除外
一般方法不建立執行緒;process_seat() 只建立 manager,必須 start()/with 才取得 Seat 並啟動背景 Heartbeat。
- acquire/ping/release 各只執行一次。
- 每個真實程序管理自己的 Seat。
- 使用 manager 時定期 check() 並在結束時 stop/離開 with。
- 應用程式/工作程序開始時取得。
- 長時間執行期間維持。
- 正常結束時釋放。
單次網路方法與 manager.start() 會阻塞到網路完成或 timeout_seconds。
取得 Seat。 → 背景維持或自行 ping。 → 主流程檢查錯誤。 → 正常結束釋放。
會透過 HTTPS Gateway 建立、維持、列出或釋放 Process Seat。
建立與釋放 Seat 會修改 Server 的並行程序狀態;Heartbeat 更新 Seat 活性。
建立 Seat 收到不確定結果時先列出目前 Process;釋放失敗可在安全關閉流程中有限重試,但不可阻止程式退出。
確認回傳 Seat 的 PID、process_id、heartbeat 與目前程序一致;結束時確認 release 結果。
席位不足時顯示並行上限與稍後重試建議;不要把它描述成 Machine 啟用失敗。
- 每個真實程序使用自己的 PID。
- 確認崩潰後的 Seat 回收依 Server cull 規則。
- 不要讓多個程序共用同一個 ProcessSeat 物件。
- 多個程序共用同一個 Seat。
- 程式崩潰後假設 Seat 一定立即消失。
- 把 Process Seat 當成 Windows 使用者數。
try:
client.release_process_seat(seat)
except GatewayError as exc:
log_release_failure(exc)
並行 Process 席位DeviceLicenseClient.process_seat建立自動取得、Heartbeat、釋放 Process Seat 的 context manager。
client.process_seat(*, pid='', metadata=None, interval_seconds=None) -> ManagedHeartbeat[ProcessSeat]白話解釋:建立自動取得、Heartbeat、釋放 Process Seat 的 context manager。
參數怎麼填
pid=''可選Process ID。通常使用目前程式 os.getpid(),不要隨意重複其他執行中的 PID。
metadata=None可選附加的 JSON-compatible dict。只放非秘密、可序列化、對營運或診斷有用的資料。
interval_seconds=None可選Heartbeat 間隔秒數。沿用 Server/SDK 建議值,過短會增加負載,過長會延遲失效偵測。
大多數 Concurrent Process 場景。
- Policy 必須設定 maxProcesses 或要求 Process 管理。
- 每個真正執行中的程式實例使用自己的 PID/Seat。
- 建立 Process Seat 後,Client 必須依 interval 維持 Heartbeat。
- 正常結束時可以釋放 Process Seat;這不會解除 Machine。
ManagedHeartbeat[ProcessSeat]。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ProcessSeatUnavailableError
- HeartbeatError
- GatewayError
只建立 ManagedHeartbeat 物件;start()/with 時才取得 Seat 並連線
呼叫 process_seat() 本身不建立 thread;manager.start() 或進入 with 後建立一條 daemon thread。
- 建立含 acquire/ping/release 規則的 manager。
- 使用 with 或明確 start。
- 定期 manager.check()。
- 正常結束 stop/release。
- 需要 maxProcesses 控制的程序生命週期外層。
工廠呼叫立即回傳;start() 取得 Seat 時同步阻塞。
建立 manager。 → start 時 acquire。 → 背景 ping。 → 主流程 check。 → stop 時 release。
會透過 HTTPS Gateway 建立、維持、列出或釋放 Process Seat。
建立與釋放 Seat 會修改 Server 的並行程序狀態;Heartbeat 更新 Seat 活性。
建立 Seat 收到不確定結果時先列出目前 Process;釋放失敗可在安全關閉流程中有限重試,但不可阻止程式退出。
確認回傳 Seat 的 PID、process_id、heartbeat 與目前程序一致;結束時確認 release 結果。
席位不足時顯示並行上限與稍後重試建議;不要把它描述成 Machine 啟用失敗。
- 每個真實程序使用自己的 PID。
- 確認崩潰後的 Seat 回收依 Server cull 規則。
- 不要讓多個程序共用同一個 ProcessSeat 物件。
- 多個程序共用同一個 Seat。
- 程式崩潰後假設 Seat 一定立即消失。
- 把 Process Seat 當成 Windows 使用者數。
try:
with client.process_seat() as lease:
run_protected_process()
lease.check()
except ProcessSeatUnavailableError:
show_no_seat()
背景 HeartbeatManagedHeartbeat.start取得 Server resource 並啟動背景 Heartbeat。
lease.start() -> ManagedHeartbeat白話解釋:取得 Server resource 並啟動背景 Heartbeat。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
沒有使用 with 語法而要手動管理時。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
自身。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- ProcessSeatUnavailableError/GatewayError
同步啟動 + 一條 daemon Heartbeat thread
會建立一條名為 keygen-<name>-heartbeat 的 daemon thread;同一 manager 重複 start 不會再建立第二條。
- 先同步呼叫 start callback 取得初始 MachineHeartbeat 或 ProcessSeat。
- 再啟動背景 loop,依 interval 自動 ping。
- 捕捉初始取得失敗。
- 在主流程安排 check()。
- 生命週期結束時 stop()。
- 進入長時間工作前呼叫一次,或直接使用 with manager。
初始網路取得會同步阻塞;背景 thread 啟動後 start() 返回 manager。
同步取得初始 state。 → 啟動 thread。 → 返回 manager。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
lease = client.process_seat().start()
背景 HeartbeatManagedHeartbeat.check只檢查背景執行緒已記錄的最新狀態與連續失敗;它本身不送出新的 Heartbeat。超過門檻時在呼叫端拋 HeartbeatError。
lease.check() -> state白話解釋:只檢查背景執行緒已記錄的最新狀態與連續失敗;它本身不送出新的 Heartbeat。超過門檻時在呼叫端拋 HeartbeatError。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
長時間程式的安全點或高價值操作前。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
最新 MachineHeartbeat 或 ProcessSeat。
- HeartbeatError
同步、本機讀取背景結果
不建立執行緒,也不主動送 Heartbeat。
- 若連續失敗未達門檻,回傳最近 state。
- 達門檻時把保存的 last_error 包成 HeartbeatError 拋給呼叫端。
- 在應用程式自己的 Timer/checkpoint 呼叫。
- HeartbeatError 後停止受保護操作。
- 每 5~30 秒或每個主要工作階段;不需要無延遲 for 迴圈。
通常立即完成,因為不做網路 I/O。
讀取 failure counters。 → 必要時拋錯。 → 否則回傳最近 state。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
try:
current = lease.check()
except HeartbeatError:
stop_protected_work()
背景 HeartbeatManagedHeartbeat.stop停止背景 Heartbeat;Process lease 預設會 release,Machine lease 不會 deactivation。
lease.stop(*, release=None) -> None白話解釋:停止背景 Heartbeat;Process lease 預設會 release,Machine lease 不會 deactivation。
參數怎麼填
release=None可選停止管理器時是否釋放 Process Seat。Machine Heartbeat 停止不代表解除 Machine。
手動生命週期結束。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
None。
- ClientCompatibilityError:HTTP 426,Client API Revision 缺少或與 Server 不相符。
- GatewayError:Process release 失敗時。
同步停止背景 thread;Process manager 可能再做一次網路 release
不建立新 thread;設定 stop event 並等待現有 thread 最多 5 秒。
- 停止後續 ping。
- 依 release_on_exit/release 參數決定是否呼叫 release callback。
- 在 finally、關閉事件或離開 with 時保證呼叫。
- 不要把 Machine stop 誤認為 deactivation。
- 應用程式正常關閉。
- 工作取消。
- 授權失效後清理。
join 最多等待 5 秒;Process release 可能再阻塞到網路 timeout。
設定 stop。 → join thread。 → 可選 release。 → 返回。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
lease.stop()
背景 HeartbeatManagedHeartbeat.state取得最近一次 Heartbeat State。
lease.state -> state白話解釋:取得最近一次 Heartbeat State。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
顯示目前 Seat/Heartbeat 狀態。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
泛型 state。
- RuntimeError:尚未 start。
背景 Heartbeat 生命週期管理
start()/with 會建立一條 daemon thread;每一個 manager 各有一條。check() 不建立新執行緒。
- 背景 thread 依 Server/SDK 間隔送 Heartbeat。
- 短暫失敗會按 retry_interval_seconds 重試,達門檻後停止 thread 並保存 last_error。
- 必須呼叫 start() 或使用 with。
- 必須在 Timer/工作檢查點呼叫 check(),否則背景失敗不會自動拋到主流程。
- 結束時 stop()。
- GUI:每 5~30 秒由 Timer 觸發一次本機 check;不要每次都 force network。
- CLI/worker:每個主要階段或迴圈 checkpoint。
start() 會同步做第一次網路操作;check() 通常立即完成;stop() 最多等待背景 thread 結束並可能同步 release Process Seat。
建立 manager。 → start/進入 with。 → 背景 thread 自動 ping。 → 呼叫端定期 check。 → stop/離開 with。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
print(lease.state)
背景 HeartbeatManagedHeartbeat.last_error讀取最近一次背景錯誤。
lease.last_error -> BaseException | None白話解釋:讀取最近一次背景錯誤。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
UI 要顯示警告但尚未達連續失敗門檻。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
例外或 None。
- 無特定 SDK 例外。
背景 Heartbeat 生命週期管理
start()/with 會建立一條 daemon thread;每一個 manager 各有一條。check() 不建立新執行緒。
- 背景 thread 依 Server/SDK 間隔送 Heartbeat。
- 短暫失敗會按 retry_interval_seconds 重試,達門檻後停止 thread 並保存 last_error。
- 必須呼叫 start() 或使用 with。
- 必須在 Timer/工作檢查點呼叫 check(),否則背景失敗不會自動拋到主流程。
- 結束時 stop()。
- GUI:每 5~30 秒由 Timer 觸發一次本機 check;不要每次都 force network。
- CLI/worker:每個主要階段或迴圈 checkpoint。
start() 會同步做第一次網路操作;check() 通常立即完成;stop() 最多等待背景 thread 結束並可能同步 release Process Seat。
建立 manager。 → start/進入 with。 → 背景 thread 自動 ping。 → 呼叫端定期 check。 → stop/離開 with。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
if lease.last_error: show_warning(lease.last_error)
背景 HeartbeatManagedHeartbeat.consecutive_failures取得目前連續 Heartbeat 失敗次數。
lease.consecutive_failures -> int白話解釋:取得目前連續 Heartbeat 失敗次數。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
監控與診斷。
- 先取得有效 Machine 或 Process 資源。
- 設定可接受的連續失敗次數與重試間隔。
- 背景執行緒週期呼叫 Heartbeat。
- 當連續失敗超過門檻時,check() 會把錯誤帶回主流程。
int。
- 無特定 SDK 例外。
背景 Heartbeat 生命週期管理
start()/with 會建立一條 daemon thread;每一個 manager 各有一條。check() 不建立新執行緒。
- 背景 thread 依 Server/SDK 間隔送 Heartbeat。
- 短暫失敗會按 retry_interval_seconds 重試,達門檻後停止 thread 並保存 last_error。
- 必須呼叫 start() 或使用 with。
- 必須在 Timer/工作檢查點呼叫 check(),否則背景失敗不會自動拋到主流程。
- 結束時 stop()。
- GUI:每 5~30 秒由 Timer 觸發一次本機 check;不要每次都 force network。
- CLI/worker:每個主要階段或迴圈 checkpoint。
start() 會同步做第一次網路操作;check() 通常立即完成;stop() 最多等待背景 thread 結束並可能同步 release Process Seat。
建立 manager。 → start/進入 with。 → 背景 thread 自動 ping。 → 呼叫端定期 check。 → stop/離開 with。
start() 先同步取得/更新一次 Server resource,之後背景執行緒依間隔呼叫 Machine 或 Process Heartbeat;check() 本身通常只讀取本機記錄的背景狀態。
持續更新 Server 活性時間;停止 manager 只停止後續 Heartbeat。Process manager 可在停止時釋放 Seat,Machine manager 不會解除 Machine。
背景執行緒依設定處理暫時失敗;主流程必須呼叫 check() 才會收到超過門檻的 HeartbeatError。不要用無 sleep 的緊密迴圈輪詢。
start() 成功、last_error 為 None、consecutive_failures 為 0,且應用程式安排的 check() 沒有拋例外。
連續失敗時將程式切換為受限模式,顯示網路或授權狀態,不要讓背景錯誤只留在 Log。
- 確認 interval 與 failure threshold。
- 確認程式結束時 stop() 或離開 with。
- 確認 UI Timer/工作迴圈會定期呼叫 check()。
- 確認 Machine 與 Process manager 的 release 語意不同。
- 只啟動背景管理器,主程式從不呼叫 check()。
- 停止 Machine Heartbeat 時誤以為會刪除 Machine。
print(lease.consecutive_failures)
Workflow 06
6. 診斷、Connection Log 與資料模型
當整合失敗時先讀取 LocalIdentityInfo 與 Connection Log。Model helper 適合 GUI 顯示、測試或支援工具,不應取代線上驗證。
- 1
取得診斷路徑
- 2
讀取最近事件
- 3
顯示安全化錯誤資訊
- 4
需要時匯出支援資料
診斷與支援DeviceLicenseClient.connection_log_path取得目前 Connection Log 檔案位置。
client.connection_log_path -> Path白話解釋:取得目前 Connection Log 檔案位置。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
要顯示支援資訊或讓使用者找到診斷檔時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
Path。
- 無特定 SDK 例外。
- Log 已做敏感資料遮罩,但仍應視為內部支援資料。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
print(client.connection_log_path)
診斷與支援DeviceLicenseClient.enable_connection_log執行期間啟用或重新設定 Connection Log。
client.enable_connection_log(path=None, *, level=None) -> Path白話解釋:執行期間啟用或重新設定 Connection Log。
參數怎麼填
path=None可選本機檔案或目錄路徑。使用 Path 物件可避免 Windows 路徑跳脫問題。
level=None可選Connection Log 等級,例如 INFO。正式環境通常不建議長期使用過度詳細的 DEBUG。
需要把診斷輸出到自訂位置或提高/降低記錄等級時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
實際 Log Path。
- OSError:目錄不可寫。
- 正式環境通常使用 INFO。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
path = client.enable_connection_log(level='INFO')
診斷與支援DeviceLicenseClient.disable_connection_log停止後續 Connection Log 寫入。
client.disable_connection_log() -> None白話解釋:停止後續 Connection Log 寫入。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
測試或極度受限環境不希望留下診斷檔時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
None。
- 無特定 SDK 例外。
- 停用後排錯能力會降低。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
client.disable_connection_log()
診斷與支援DeviceLicenseClient.read_connection_log讀取最近的結構化 Log Entry。
client.read_connection_log(*, limit: int = 200) -> list[ConnectionLogEntry]白話解釋:讀取最近的結構化 Log Entry。
參數怎麼填
limit: int = 200可選最多讀取幾筆最近紀錄。數字越大,UI 顯示與讀檔成本越高。
GUI 要呈現最近連線事件時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
ConnectionLogEntry list。
- ValueError:limit 不合理時可能由內部約束拒絕。
- 適合 UI,不需自行解析 JSONL。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
for item in client.read_connection_log(limit=50): print(item.format_line())
診斷與支援DeviceLicenseClient.connection_log_text將最近 Log 轉成可貼給支援人員的文字。
client.connection_log_text(*, limit: int = 200) -> str白話解釋:將最近 Log 轉成可貼給支援人員的文字。
參數怎麼填
limit: int = 200可選最多讀取幾筆最近紀錄。數字越大,UI 顯示與讀檔成本越高。
CLI 或支援對話框需要複製文字時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
多行字串。
- 無特定 SDK 例外。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
print(client.connection_log_text(limit=50))
診斷與支援DeviceLicenseClient.clear_connection_log刪除目前 Connection Log。
client.clear_connection_log() -> bool白話解釋:刪除目前 Connection Log。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
完成支援或依資料保留政策清除本機紀錄時。
- 確認 Log 目錄可寫,並遵守公司資料保留政策。
- 讀取、格式化、啟用、停用或清除已遮罩的 Connection Log。
- 不會重新驗證 License,也不會修改 Server 資源。
是否實際刪除。
- OSError:檔案被鎖定或權限不足。
- 不影響 registration.json 或 TPM Key。
同步、本機 Log I/O
不會建立背景執行緒。
- 只讀寫已遮罩的本機 Connection Log。
- 決定保留時間與顯示方式。
- 交付支援前再次檢查自訂 metadata。
- 發生問題後、支援畫面、受控清除時。
讀寫大型 Log 可能短暫阻塞;limit 應保持合理。
啟用。 → 重現。 → 讀取/格式化。 → 提供支援。 → 依政策清理。
不連線。只讀寫本機已遮罩的 Connection Log。
可能建立、追加、停止或清除本機 Log;不修改 License 或 Server。
讀檔/寫檔權限錯誤可在修正路徑後重試;不要無限制增加 Log 詳細度或保留時間。
確認 Log Path 可寫、每行可解析,且內容沒有 License Key、Token、Private Key 或完整 credential。
提供『複製診斷資訊』功能並提醒使用者先檢查敏感資料;不要要求上傳整個應用程式資料目錄。
- 先找最後一個成功事件,再看下一個失敗事件。
- 保留 request_id、endpoint、status 與 error code。
- 完成支援後依資料政策清理 Log。
- 完全停用 Log 後才開始排錯。
- 把 Log 視為可公開資料。
- 只貼錯誤畫面,不保留 request_id、code 與重現步驟。
removed = client.clear_connection_log()
資料轉換ValidationScope.to_payload將非空 Scope 欄位轉成 Gateway request payload。
scope.to_payload() -> dict[str, object]白話解釋:將非空 Scope 欄位轉成 Gateway request payload。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
測試或診斷 Scope 內容;一般呼叫由 SDK 自動完成。
- 先確認輸入 dict 或模型來自可信 SDK 回傳或已驗證資料。
- 只將資料模型轉換為 dict、文字或其他本機格式。
- 不會因為呼叫 to_payload() 就完成 Server 驗證。
dict。
- 無特定 SDK 例外。
- 不要把輸出視為已驗證資料。
同步、本機資料轉換
不會建立背景執行緒。
- 只轉換目前記憶體中的資料。
- 驗證輸入來源與型別。
- 不要將轉換結果誤認為 Server 已接受。
- 測試、診斷、序列化或自訂 UI。
立即完成,不做網路 I/O。
準備可信模型/dict。 → 轉換。 → 由後續 API 或 UI 使用。
不連線。只在本機轉換資料模型。
不修改本機持久狀態或 Server。
不需要網路重試;輸入資料不合法時應修正來源。
轉換後欄位、型別與原模型一致,並通過應用程式自己的 schema 驗證。
資料格式錯誤時顯示可理解欄位名稱,不要輸出整份可能含內部資訊的 payload。
- 確認模型來自可信 SDK 回傳。
- 不要把 to_payload() 當成已完成 Server 驗證。
- 把模型資料當成即時狀態。
- 直接信任外部 JSON 後建立模型。
payload = ValidationScope(user_id=user_id).to_payload()
資料轉換MachineComponentSpec.to_payload驗證 name/fingerprint 並轉成 Gateway payload。
component_spec.to_payload() -> dict[str, object]白話解釋:驗證 name/fingerprint 並轉成 Gateway payload。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
建立 Component 前做本機檢查或測試。
- 先確認輸入 dict 或模型來自可信 SDK 回傳或已驗證資料。
- 只將資料模型轉換為 dict、文字或其他本機格式。
- 不會因為呼叫 to_payload() 就完成 Server 驗證。
dict。
- ValueError:name 或 fingerprint 為空。
同步、本機資料轉換
不會建立背景執行緒。
- 只轉換目前記憶體中的資料。
- 驗證輸入來源與型別。
- 不要將轉換結果誤認為 Server 已接受。
- 測試、診斷、序列化或自訂 UI。
立即完成,不做網路 I/O。
準備可信模型/dict。 → 轉換。 → 由後續 API 或 UI 使用。
不連線。只在本機轉換資料模型。
不修改本機持久狀態或 Server。
不需要網路重試;輸入資料不合法時應修正來源。
轉換後欄位、型別與原模型一致,並通過應用程式自己的 schema 驗證。
資料格式錯誤時顯示可理解欄位名稱,不要輸出整份可能含內部資訊的 payload。
- 確認模型來自可信 SDK 回傳。
- 不要把 to_payload() 當成已完成 Server 驗證。
- 把模型資料當成即時狀態。
- 直接信任外部 JSON 後建立模型。
try:
payload = spec.to_payload()
except ValueError as exc:
show_invalid_component(exc)
資料轉換ConnectionLogEntry.format_line將結構化 Connection Log Entry 格式化成單行支援文字。
entry.format_line() -> str白話解釋:將結構化 Connection Log Entry 格式化成單行支援文字。
依簽章直接讀取屬性,或使用空括號呼叫;不要自行傳入額外值。
CLI、GUI Log Viewer 或複製給支援人員。
- 先確認輸入 dict 或模型來自可信 SDK 回傳或已驗證資料。
- 只將資料模型轉換為 dict、文字或其他本機格式。
- 不會因為呼叫 to_payload() 就完成 Server 驗證。
str。
- 無特定 SDK 例外。
同步、本機資料轉換
不會建立背景執行緒。
- 只轉換目前記憶體中的資料。
- 驗證輸入來源與型別。
- 不要將轉換結果誤認為 Server 已接受。
- 測試、診斷、序列化或自訂 UI。
立即完成,不做網路 I/O。
準備可信模型/dict。 → 轉換。 → 由後續 API 或 UI 使用。
不連線。只在本機轉換資料模型。
不修改本機持久狀態或 Server。
不需要網路重試;輸入資料不合法時應修正來源。
轉換後欄位、型別與原模型一致,並通過應用程式自己的 schema 驗證。
資料格式錯誤時顯示可理解欄位名稱,不要輸出整份可能含內部資訊的 payload。
- 確認模型來自可信 SDK 回傳。
- 不要把 to_payload() 當成已完成 Server 驗證。
- 把模型資料當成即時狀態。
- 直接信任外部 JSON 後建立模型。
print(entry.format_line())
資料轉換ConnectionLogEntry.from_dict從已保存的 JSON-compatible dict 重建 Log Entry。
ConnectionLogEntry.from_dict(payload: dict) -> ConnectionLogEntry白話解釋:從已保存的 JSON-compatible dict 重建 Log Entry。
參數怎麼填
payload: dict必填JSON-compatible dict。通常用於資料模型重建、測試或診斷,不應直接信任外部輸入。
測試、匯入診斷紀錄或自訂 Log Viewer。
- 先確認輸入 dict 或模型來自可信 SDK 回傳或已驗證資料。
- 只將資料模型轉換為 dict、文字或其他本機格式。
- 不會因為呼叫 to_payload() 就完成 Server 驗證。
ConnectionLogEntry。
- ValueError/TypeError:欄位無法轉型。
同步、本機資料轉換
不會建立背景執行緒。
- 只轉換目前記憶體中的資料。
- 驗證輸入來源與型別。
- 不要將轉換結果誤認為 Server 已接受。
- 測試、診斷、序列化或自訂 UI。
立即完成,不做網路 I/O。
準備可信模型/dict。 → 轉換。 → 由後續 API 或 UI 使用。
不連線。只在本機轉換資料模型。
不修改本機持久狀態或 Server。
不需要網路重試;輸入資料不合法時應修正來源。
轉換後欄位、型別與原模型一致,並通過應用程式自己的 schema 驗證。
資料格式錯誤時顯示可理解欄位名稱,不要輸出整份可能含內部資訊的 payload。
- 確認模型來自可信 SDK 回傳。
- 不要把 to_payload() 當成已完成 Server 驗證。
- 把模型資料當成即時狀態。
- 直接信任外部 JSON 後建立模型。
try:
entry = ConnectionLogEntry.from_dict(payload)
except (ValueError, TypeError) as exc:
show_bad_log_entry(exc)
找不到符合條件的 API。
回傳資料模型
Model 只代表資料,不會自行重新連線或重新驗證。
ClientConfig
建立 DeviceLicenseClient 的不可變設定。
欄位gateway_base_urlproduct_idproduct_namespacegateway_signing_public_key_b64gateway_signing_key_idtimeout_secondsverify_tlstrust_envmax_clock_skew_secondsstate_directoryvalidation_scopeapplication_pathchecksum_algorithmauto_collect_machine_metricsmachine_componentsdefault_heartbeat_ratioheartbeat_max_consecutive_failuresheartbeat_retry_interval_secondsconnection_log_*ValidationScope
額外要求 Server 驗證的 Policy/Version/Checksum/User/Entitlement/Component Scope。
欄位policy_idversionchecksumuser_identitlementscomponentsto_payload()LicenseState
一次註冊或驗證的授權結果。
欄位validcodedetaildevice_idlicense_idmachine_idfingerprintentitlementslicense_dataassurancenamestatusexpiryusesmax_usesrequire_heartbeatrequire_check_innext_check_inmetadatarequire_valid()has()has_all()has_any()require()require_all()DeviceRegistration
本機 registration.json 的公開識別資料。
欄位device_idmachine_idlicense_idfingerprintassuranceLocalIdentityInfo
TPM Key 與 registration.json 一致性診斷。
欄位key_namekey_providerkey_existsregistration_pathregistration_existsregistrationcurrent_fingerprintregistration_matches_keyproblem_codeproblem_detailhealthyLocalIdentityResetResult
本機重置結果。
欄位key_nameregistration_pathregistration_removedtpm_key_existedtpm_key_deletedMachineMetrics
本機資源量。
欄位coresmemory_bytesdisk_bytesMachineComponentSpec
要新增/同步的 Component 定義。
欄位namefingerprintmetadatato_payload()MachineComponent
Server 回傳的 Component。
欄位component_idnamefingerprintmachine_idmetadatarawMachineProfile
目前 Machine Profile 與 Heartbeat 欄位。
欄位machine_idfingerprintnameiphostnameplatformcoresmemory_bytesdisk_bytesmetadatarequire_heartbeatheartbeat_statuslast_heartbeatnext_heartbeatrawMachineHeartbeat
Machine Heartbeat 結果。
欄位machine_idstatusheartbeat_durationlast_heartbeatnext_heartbeatrawProcessSeat
並行 Process Seat。
欄位process_idpidstatusinterval_secondslast_heartbeatnext_heartbeatmachine_idlicense_idmetadatarawUsageState
Usage increment 後的最新計數。
欄位license_idusesmax_usesrawCheckInState
License Check-in 結果。
欄位license_idlast_check_innext_check_inrawConnectionLogEntry
已遮罩的結構化診斷事件。
欄位timestampleveleventmessagerequest_idoperationmethodpathstatus_codeelapsed_msdetailsformat_line()from_dict()例外處理決策表
LicenseSDKError所有 SDK 例外的基底。最外層可用它做統一 fallback,但高價值流程應優先捕捉更具體例外。ClientCompatibilityErrorHTTP 426。Client 缺少 X-Keygen-Device-API-Version,或送出的 API Revision 與 Server 的精確契約不相等。它是 GatewayError 的子類別,可讀取 provided_api_version、required_api_version、client_sdk_version、required_sdk_version、platform_version 與 documentation_path。這不是 License 無效。立即停止授權操作與受保護功能,顯示需要更新 Client/SDK,安裝管理員提供的目前 Wheel 後重新測試。retry_after_seconds 固定為 0;等待、無限重試或只偽造 Header 都不能修復不相容。GatewayErrorGateway HTTP、Keygen API、流量防護、API 相容性或 Server 拒絕。可讀取 status_code、code 與 retry_after_seconds。426 代表 Client API 不相容;429 代表暫時超過請求或並行門檻;503 代表 Gateway 暫時無法承接或處於 Emergency;403/IP_DENIED 代表來源位址被拒絕。這些狀態都不是 License 無效結論。先依具體子類別、status_code 與 code 分流。426 不重試並更新 SDK;429 僅對可安全重試的讀取/驗證操作等待 max(1, retry_after_seconds) 後重試;503 應退避並 fail closed;403 應停止重試並聯絡管理員。Usage、建立資源等可能改變 Server 狀態的操作,除非已有 idempotency 設計,不要盲目自動重送。GatewaySignatureErrorGateway 回應簽章缺失、Key ID 不符、時間窗無效或 Ed25519 驗證失敗。立即拒絕結果;不要自動忽略或降級。LicenseInvalidErrorLicense revoked、suspended、expired、scope mismatch 或其他 validation failure。停止受保護功能,顯示 code/detail。FeatureNotLicensedError缺少要求的 Entitlement。停用特定功能,不必把整個程式視為崩潰。LicenseKeyRequiredError首次註冊或 recovery 需要 License Key。安全地提示使用者輸入,不要從 Log 或設定檔取 Key。LocalIdentityErrorregistration.json、Product、TPM Key 或 fingerprint 不一致。顯示 recovery_hint,讓使用者選擇 recover 或受控 reset。ProcessSeatUnavailableErrormaxProcesses 已滿或 Process Seat 無法取得。顯示席位不足,稍後重試或聯絡管理員。HeartbeatError背景 Heartbeat 連續失敗超過門檻。暫停高價值工作並嘗試恢復連線。TPMUnavailableErrorWindows TPM Provider 不存在或不可用。檢查 TPM、Windows 版本、Provider 與執行帳號。TPMOperationErrorTPM Key 建立、簽章、讀取或刪除失敗。保留錯誤碼,避免盲目刪除其他 Key。