diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 03e3c76c625b7d..88588363d03ad4 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -333,7 +333,7 @@ jobs:
scripts/run_in_build_env.sh 'virtualenv pyenv'
source pyenv/bin/activate
pip3 install -r src/setup_payload/python/requirements.txt
- python3 src/setup_payload/tests/run_python_setup_payload_gen_test.py out/chip-tool
+ python3 src/setup_payload/tests/run_python_setup_payload_test.py out/chip-tool
build_linux_python_lighting_device:
name: Build on Linux (python lighting-app)
diff --git a/.github/workflows/darwin.yaml b/.github/workflows/darwin.yaml
index ad2a513209cc65..ba9c0f1d9f02c3 100644
--- a/.github/workflows/darwin.yaml
+++ b/.github/workflows/darwin.yaml
@@ -97,10 +97,10 @@ jobs:
bootstrap-logs-framework-${{ matrix.options.flavor }}
- name: Build example All Clusters Server
run: |
- scripts/examples/gn_build_example.sh examples/all-clusters-app/linux out/debug chip_config_network_layer_ble=false
+ scripts/examples/gn_build_example.sh examples/all-clusters-app/linux out/debug/all-clusters-app chip_config_network_layer_ble=false
- name: Build example OTA Provider
run: |
- scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false
+ scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug/ota-provider-app chip_config_network_layer_ble=false
- name: Build example OTA Requestor
run: |
scripts/examples/gn_build_example.sh examples/ota-requestor-app/linux out/debug/ota-requestor-app chip_config_network_layer_ble=false non_spec_compliant_ota_action_delay_floor=0
@@ -113,13 +113,8 @@ jobs:
run: |
mkdir -p /tmp/darwin/framework-tests
echo "This is a simple log" > /tmp/darwin/framework-tests/end_user_support_log.txt
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --end_user_support_log /tmp/darwin/framework-tests/end_user_support_log.txt > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --dac_provider ../../../credentials/development/commissioner_dut/struct_cd_origin_pid_vid_correct/test_case_vector.json --product-id 32768 --discriminator 3839 --secured-device-port 5539 --KVS /tmp/chip-all-clusters-app-kvs2 > >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid-err.log >&2) &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --discriminator 101 --passcode 1001 --KVS /tmp/chip-all-clusters-app-kvs101 --secured-device-port 5531 &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --discriminator 102 --passcode 1002 --KVS /tmp/chip-all-clusters-app-kvs102 --secured-device-port 5532 &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --discriminator 103 --passcode 1003 --KVS /tmp/chip-all-clusters-app-kvs103 --secured-device-port 5533 &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --discriminator 104 --passcode 1004 --KVS /tmp/chip-all-clusters-app-kvs104 --secured-device-port 5534 &
- ../../../out/debug/chip-all-clusters-app --interface-id -1 --discriminator 105 --passcode 1005 --KVS /tmp/chip-all-clusters-app-kvs105 --secured-device-port 5535 &
+ ../../../out/debug/all-clusters-app/chip-all-clusters-app --interface-id -1 --end_user_support_log /tmp/darwin/framework-tests/end_user_support_log.txt > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) &
+ ../../../out/debug/all-clusters-app/chip-all-clusters-app --interface-id -1 --dac_provider ../../../credentials/development/commissioner_dut/struct_cd_origin_pid_vid_correct/test_case_vector.json --product-id 32768 --discriminator 3839 --secured-device-port 5539 --KVS /tmp/chip-all-clusters-app-kvs2 > >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid-err.log >&2) &
export TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 4685948fd7bd12..bd5385580b9c22 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -98,7 +98,6 @@ jobs:
--known-failure controller/ExamplePersistentStorage.cpp \
--known-failure controller/ExamplePersistentStorage.h \
--known-failure app/AttributeAccessToken.h \
- --known-failure app/CommandHandler.h \
--known-failure app/CommandHandlerInterface.h \
--known-failure app/CommandResponseSender.h \
--known-failure app/CommandSenderLegacyCallback.h \
diff --git a/.github/workflows/minimal-build.yaml b/.github/workflows/minimal-build.yaml
index 46f1d0b1fce68e..ac11a145c7fa4e 100644
--- a/.github/workflows/minimal-build.yaml
+++ b/.github/workflows/minimal-build.yaml
@@ -26,7 +26,7 @@ concurrency:
cancel-in-progress: true
jobs:
- minimal:
+ minimal-all-clusters:
name: Linux / configure build of all-clusters-app
if: github.actor != 'restyled-io[bot]'
@@ -47,3 +47,25 @@ jobs:
- name: Configure and build All Clusters App
run: |
CC=gcc CXX=g++ scripts/configure --project=examples/all-clusters-app/linux && ./ninja-build
+
+ minimal-network-manager:
+ name: Linux / configure build of network-manager-app
+
+ if: github.actor != 'restyled-io[bot]'
+ runs-on: ubuntu-latest
+
+ container:
+ image: ghcr.io/project-chip/chip-build-minimal:50
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Checkout submodules # but don't bootstrap!
+ uses: ./.github/actions/checkout-submodules
+ with:
+ platform: linux
+
+ - name: Configure and build Network Manager App
+ run: |
+ CC=gcc CXX=g++ scripts/configure --project=examples/network-manager-app/linux && ./ninja-build
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 57bc3971d44ea3..4dc5a4cc48218f 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -189,6 +189,7 @@ jobs:
src/app/zap-templates/zcl/data-model/chip/wake-on-lan-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/washer-controls-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/wifi-network-diagnostics-cluster.xml \
+ src/app/zap-templates/zcl/data-model/chip/wifi-network-management-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/window-covering.xml \
src/app/zap-templates/zcl/data-model/chip/temperature-control-cluster.xml \
src/app/zap-templates/zcl/data-model/chip/matter-devices.xml \
diff --git a/build/chip/linux/BUILD.gn b/build/chip/linux/BUILD.gn
index c86f803a70f3d3..a530d5a611a25e 100644
--- a/build/chip/linux/BUILD.gn
+++ b/build/chip/linux/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Project CHIP Authors
+# Copyright (c) 2020-2024 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -21,4 +21,5 @@ pkg_config("glib") {
"glib-2.0",
"gio-unix-2.0",
]
+ optional = true # Only certain conditionally-compiled modules depend on glib
}
diff --git a/build/config/linux/pkg-config.py b/build/config/linux/pkg-config.py
index 4d6e773a00d666..f44667242de807 100755
--- a/build/config/linux/pkg-config.py
+++ b/build/config/linux/pkg-config.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Copyright (c) 2020 Project CHIP Authors
+# Copyright (c) 2020-2024 Project CHIP Authors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -127,6 +127,7 @@ def RewritePath(path, strip_prefix, sysroot):
def main():
parser = OptionParser()
parser.add_option('-d', '--debug', action='store_true')
+ parser.add_option('-o', '--optional', action='store_true')
parser.add_option('-p', action='store', dest='pkg_config', type='string',
default='pkg-config')
parser.add_option('-v', action='append', dest='strip_out', type='string')
@@ -209,6 +210,10 @@ def main():
try:
flag_string = subprocess.check_output(cmd).decode('utf-8')
except Exception:
+ if options.optional:
+ sys.stderr.write('Ignoring failure to run pkg-config for optional library.\n')
+ print(json.dumps([False])) # Output a GN array indicating missing optional packages
+ return 0
sys.stderr.write('Could not run pkg-config.\n')
return 1
@@ -248,10 +253,10 @@ def main():
else:
cflags.append(flag)
- # Output a GN array, the first one is the cflags, the second are the libs. The
+ # Output a GN array, indicating success and our output lists.
# JSON formatter prints GN compatible lists when everything is a list of
# strings.
- print(json.dumps([includes, cflags, libs, lib_dirs]))
+ print(json.dumps([True, includes, cflags, libs, lib_dirs]))
return 0
diff --git a/build/config/linux/pkg_config.gni b/build/config/linux/pkg_config.gni
index 016defafbc3617..d6892d97fb976f 100644
--- a/build/config/linux/pkg_config.gni
+++ b/build/config/linux/pkg_config.gni
@@ -1,5 +1,5 @@
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Copyright (c) 2020 Project CHIP Authors
+# Copyright (c) 2020-2024 Project CHIP Authors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -43,9 +43,14 @@
#
# You can also use "extra args" to filter out results (see pkg-config.py):
# extra_args = [ "-v, "foo" ]
+#
# To ignore libs and ldflags (only cflags/defines will be set, which is useful
# when doing manual dynamic linking), set:
# ignore_libs = true
+#
+# To allow the build to proceed if (any of) the requested packages are absent, set:
+# optional = true
+# In this case the resulting config object will be empty.
import("//build_overrides/build.gni")
import("${build_root}/config/sysroot.gni")
@@ -109,37 +114,42 @@ template("pkg_config") {
} else {
args = pkg_config_args + invoker.packages
}
+ if (defined(invoker.optional) && invoker.optional) {
+ args += [ "-o" ]
+ }
if (defined(invoker.extra_args)) {
args += invoker.extra_args
}
+ # pkgresult = [present, includes, cflags, libs, lib_dirs]
pkgresult = exec_script(pkg_config_script, args, "value")
- cflags = pkgresult[1]
+ if (pkgresult[0]) {
+ cflags = pkgresult[2]
- foreach(include, pkgresult[0]) {
- cflags += [ "-I$include" ]
- }
+ foreach(include, pkgresult[1]) {
+ cflags += [ "-I$include" ]
+ }
- if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) {
- libs = pkgresult[2]
- lib_dirs = pkgresult[3]
- }
+ if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) {
+ libs = pkgresult[3]
+ lib_dirs = pkgresult[4]
+ }
- # Link libraries statically for OSS-Fuzz fuzzer build
- if (oss_fuzz) {
- libs = []
- ldflags = [ "-Wl,-Bstatic" ]
- foreach(lib, pkgresult[2]) {
- ldflags += [ "-l$lib" ]
+ # Link libraries statically for OSS-Fuzz fuzzer build
+ if (oss_fuzz) {
+ libs = []
+ ldflags = [ "-Wl,-Bstatic" ]
+ foreach(lib, pkgresult[3]) {
+ ldflags += [ "-l$lib" ]
+ }
+ ldflags += [ "-Wl,-Bdynamic" ]
+ lib_dirs = pkgresult[4]
}
- ldflags += [ "-Wl,-Bdynamic" ]
- lib_dirs = pkgresult[3]
- }
- forward_variables_from(invoker,
- [
- "defines",
- "visibility",
- ])
+ forward_variables_from(invoker, [ "defines" ])
+ }
}
+
+ # Always forward visibility
+ forward_variables_from(invoker, [ "visibility" ])
}
diff --git a/credentials/generate-revocation-set.py b/credentials/generate-revocation-set.py
index 534edc15b0f203..bfc5ce560c1f80 100644
--- a/credentials/generate-revocation-set.py
+++ b/credentials/generate-revocation-set.py
@@ -1,7 +1,7 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
-# Copyright (c) 2023 Project CHIP Authors
+# Copyright (c) 2023-2024 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
import base64
import json
+import logging
import subprocess
import sys
from enum import Enum
@@ -30,6 +31,16 @@
import requests
from click_option_group import RequiredMutuallyExclusiveOptionGroup, optgroup
from cryptography import x509
+from cryptography.hazmat.primitives.asymmetric import ec
+
+# Supported log levels, mapping string values required for argument
+# parsing into logging constants
+__LOG_LEVELS__ = {
+ 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'warn': logging.WARN,
+ 'fatal': logging.FATAL,
+}
class RevocationType(Enum):
@@ -44,20 +55,144 @@ class RevocationType(Enum):
TEST_NODE_URL_REST = "https://on.test-net.dcl.csa-iot.org"
-def use_dcld(dcld, production, cmdlist):
- return [dcld] + cmdlist + (['--node', PRODUCTION_NODE_URL] if production else [])
-
-
def extract_single_integer_attribute(subject, oid):
attribute_list = subject.get_attributes_for_oid(oid)
if len(attribute_list) == 1:
- if attribute_list[0].value.isdigit():
- return int(attribute_list[0].value)
+ return int(attribute_list[0].value, 16)
return None
+class DCLDClient:
+ '''
+ A client for interacting with DCLD using either the REST API or command line interface (CLI).
+
+ '''
+
+ def __init__(self, use_rest: bool, dcld_exe: str, production: bool, rest_node_url: str):
+ '''
+ Initialize the client
+
+ use_rest: bool
+ Use RESTful API with HTTPS against `rest_node_url`
+ dcld_exe: str
+ Path to `dcld` executable
+ production: bool
+ Use MainNet DCL URL with dcld executable
+ rest_node_url: str
+ RESTful API URL
+ '''
+
+ self.use_rest = use_rest
+ self.dcld_exe = dcld_exe
+ self.production = production
+ self.rest_node_url = rest_node_url
+
+ def build_dcld_command_line(self, cmdlist: list[str]) -> list[str]:
+ '''
+ Build command line for `dcld` executable.
+
+ Parameters
+ ----------
+ cmdlist: list[str]
+ List of command line arguments to append to some predefined arguments
+
+ Returns
+ -------
+ list[str]
+ The complete command list including the DCLD executable and node option if in production
+ '''
+
+ return [self.dcld_exe] + cmdlist + (['--node', PRODUCTION_NODE_URL] if self.production else [])
+
+ def get_dcld_cmd_output_json(self, cmdlist: list[str]) -> dict:
+ '''
+ Executes a DCLD CLI command and returns the JSON output.
+
+ Parameters
+ ----------
+ cmdlist: list[str]
+ List of command line arguments to append to some predefined arguments
+
+ Returns
+ -------
+ dict
+ The JSON output from the command
+ '''
+
+ # Set the output as JSON
+ subprocess.Popen([self.dcld_exe, 'config', 'output', 'json'])
+
+ cmdpipe = subprocess.Popen(self.build_dcld_command_line(cmdlist),
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ return json.loads(cmdpipe.stdout.read())
+
+ def get_revocation_points(self) -> list[dict]:
+ '''
+ Get revocation points from DCL
+
+ Returns
+ -------
+ list[dict]
+ List of revocation points
+ '''
+
+ if self.use_rest:
+ response = requests.get(f"{self.rest_node_url}/dcl/pki/revocation-points").json()
+ else:
+ response = self.get_dcld_cmd_output_json(['query', 'pki', 'all-revocation-points'])
+
+ return response["PkiRevocationDistributionPoint"]
+
+ def get_paa_cert_for_crl_issuer(self, crl_signer_issuer_name_b64, crl_signer_authority_key_id) -> str:
+ '''
+ Get PAA certificate for CRL issuer
+
+ Parameters
+ ----------
+ crl_signer_issuer_name_b64: str
+ The issuer name of the CRL signer.
+ crl_signer_authority_key_id: str
+ The authority key ID of the CRL signer.
+
+ Returns
+ -------
+ str
+ PAA certificate in PEM format
+ '''
+ if self.use_rest:
+ response = requests.get(
+ f"{self.rest_node_url}/dcl/pki/certificates/{crl_signer_issuer_name_b64}/{crl_signer_authority_key_id}").json()
+ else:
+ response = self.get_dcld_cmd_output_json(
+ ['query', 'pki', 'x509-cert', '-u', crl_signer_issuer_name_b64, '-k', crl_signer_authority_key_id])
+
+ return response["approvedCertificates"]["certs"][0]["pemCert"]
+
+ def get_revocations_points_by_skid(self, issuer_subject_key_id) -> list[dict]:
+ '''
+ Get revocation points by subject key ID
+
+ Parameters
+ ----------
+ issuer_subject_key_id: str
+ Subject key ID
+
+ Returns
+ -------
+ list[dict]
+ List of revocation points
+ '''
+ if self.use_rest:
+ response = requests.get(f"{self.rest_node_url}/dcl/pki/revocation-points/{issuer_subject_key_id}").json()
+ else:
+ response = self.get_dcld_cmd_output_json(['query', 'pki', 'revocation-points',
+ '--issuer-subject-key-id', issuer_subject_key_id])
+
+ return response["pkiRevocationDistributionPointsByIssuerSubjectKeyID"]["points"]
+
+
@click.command()
@click.help_option('-h', '--help')
@optgroup.group('Input data sources', cls=RequiredMutuallyExclusiveOptionGroup)
@@ -66,9 +201,19 @@ def extract_single_integer_attribute(subject, oid):
@optgroup.option('--use-main-net-http', is_flag=True, type=str, help="Use RESTful API with HTTPS against public MainNet observer.")
@optgroup.option('--use-test-net-http', is_flag=True, type=str, help="Use RESTful API with HTTPS against public TestNet observer.")
@optgroup.group('Optional arguments')
-@optgroup.option('--output', default='sample_revocation_set_list.json', type=str, metavar='FILEPATH', help="Output filename (default: sample_revocation_set_list.json)")
-def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_http, output):
- """DCL PAA mirroring tools"""
+@optgroup.option('--output', default='sample_revocation_set_list.json', type=str, metavar='FILEPATH',
+ help="Output filename (default: sample_revocation_set_list.json)")
+@optgroup.option('--log-level', default='INFO', show_default=True, type=click.Choice(__LOG_LEVELS__.keys(),
+ case_sensitive=False), callback=lambda c, p, v: __LOG_LEVELS__[v],
+ help='Determines the verbosity of script output')
+def main(use_main_net_dcld: str, use_test_net_dcld: str, use_main_net_http: bool, use_test_net_http: bool, output: str, log_level: str):
+ """Tool to construct revocation set from DCL"""
+
+ logging.basicConfig(
+ level=log_level,
+ format='%(asctime)s %(name)s %(levelname)-7s %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S'
+ )
production = False
dcld = use_test_net_dcld
@@ -83,28 +228,20 @@ def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_h
rest_node_url = PRODUCTION_NODE_URL_REST if production else TEST_NODE_URL_REST
- # TODO: Extract this to a helper function
- if use_rest:
- revocation_point_list = requests.get(f"{rest_node_url}/dcl/pki/revocation-points").json()["PkiRevocationDistributionPoint"]
- else:
- cmdlist = ['config', 'output', 'json']
- subprocess.Popen([dcld] + cmdlist)
-
- cmdlist = ['query', 'pki', 'all-revocation-points']
-
- cmdpipe = subprocess.Popen(use_dcld(dcld, production, cmdlist), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ dcld_client = DCLDClient(use_rest, dcld, production, rest_node_url)
- revocation_point_list = json.loads(cmdpipe.stdout.read())["PkiRevocationDistributionPoint"]
+ revocation_point_list = dcld_client.get_revocation_points()
revocation_set = []
for revocation_point in revocation_point_list:
# 1. Validate Revocation Type
- if revocation_point["revocationType"] != RevocationType.CRL:
+ if revocation_point["revocationType"] != RevocationType.CRL.value:
+ logging.warning("Revocation Type is not CRL, continue...")
continue
# 2. Parse the certificate
- crl_signer_certificate = x509.load_pem_x509_certificate(revocation_point["crlSignerCertificate"])
+ crl_signer_certificate = x509.load_pem_x509_certificate(bytes(revocation_point["crlSignerCertificate"], 'utf-8'))
vid = revocation_point["vid"]
pid = revocation_point["pid"]
@@ -119,12 +256,15 @@ def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_h
if crl_vid is not None:
if vid != crl_vid:
# TODO: Need to log all situations where a continue is called
+ logging.warning("VID is not CRL VID, continue...")
continue
else:
if crl_vid is None or vid != crl_vid:
+ logging.warning("VID is not CRL VID, continue...")
continue
if crl_pid is not None:
if pid != crl_pid:
+ logging.warning("PID is not CRL PID, continue...")
continue
# 5. Validate the certification path containing CRLSignerCertificate.
@@ -133,99 +273,110 @@ def main(use_main_net_dcld, use_test_net_dcld, use_main_net_http, use_test_net_h
crl_signer_authority_key_id = crl_signer_certificate.extensions.get_extension_for_oid(
x509.OID_AUTHORITY_KEY_IDENTIFIER).value.key_identifier
- paa_certificate = None
+ # Convert CRL Signer AKID to colon separated hex
+ crl_signer_authority_key_id = crl_signer_authority_key_id.hex().upper()
+ crl_signer_authority_key_id = ':'.join([crl_signer_authority_key_id[i:i+2]
+ for i in range(0, len(crl_signer_authority_key_id), 2)])
- # TODO: Extract this to a helper function
- if use_rest:
- response = requests.get(
- f"{rest_node_url}/dcl/pki/certificates/{crl_signer_issuer_name}/{crl_signer_authority_key_id}").json()["approvedCertificates"]["certs"][0]
- paa_certificate = response["pemCert"]
- else:
- cmdlist = ['query', 'pki', 'x509-cert', '-u', crl_signer_issuer_name, '-k', crl_signer_authority_key_id]
- cmdpipe = subprocess.Popen(use_dcld(dcld, production, cmdlist), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- paa_certificate = json.loads(cmdpipe.stdout.read())["approvedCertificates"]["certs"][0]["pemCert"]
+ paa_certificate = dcld_client.get_paa_cert_for_crl_issuer(crl_signer_issuer_name, crl_signer_authority_key_id)
if paa_certificate is None:
+ logging.warning("PAA Certificate not found, continue...")
continue
- paa_certificate_object = x509.load_pem_x509_certificate(paa_certificate)
+ paa_certificate_object = x509.load_pem_x509_certificate(bytes(paa_certificate, 'utf-8'))
+
+ # TODO: use verify_directly_issued_by() method when we upgrade cryptography to v40.0.0
+ # Verify issuer matches with subject
+ if crl_signer_certificate.issuer != paa_certificate_object.subject:
+ logging.warning("CRL Signer Certificate issuer does not match with PAA Certificate subject, continue...")
+ continue
+ # Check crl signers AKID matches with SKID of paa_certificate_object's AKID
+ paa_skid = paa_certificate_object.extensions.get_extension_for_oid(x509.OID_SUBJECT_KEY_IDENTIFIER).value.key_identifier
+ crl_akid = crl_signer_certificate.extensions.get_extension_for_oid(x509.OID_AUTHORITY_KEY_IDENTIFIER).value.key_identifier
+ if paa_skid != crl_akid:
+ logging.warning("CRL Signer's AKID does not match with PAA Certificate SKID, continue...")
+ continue
+
+ # verify if PAA singed the crl signer certificate
try:
- crl_signer_certificate.verify_directly_issued_by(paa_certificate_object)
+ paa_certificate_object.public_key().verify(crl_signer_certificate.signature,
+ crl_signer_certificate.tbs_certificate_bytes,
+ ec.ECDSA(crl_signer_certificate.signature_hash_algorithm))
except Exception:
+ logging.warning("CRL Signer Certificate is not signed by PAA Certificate, continue...")
continue
# 6. Obtain the CRL
- r = requests.get(revocation_point["dataURL"])
- crl_file = x509.load_der_x509_crl(r.content)
+ logging.debug(f"Fetching CRL from {revocation_point['dataURL']}")
+ try:
+ r = requests.get(revocation_point["dataURL"], timeout=5)
+ except Exception:
+ logging.error('Failed to fetch CRL')
+ continue
+
+ try:
+ crl_file = x509.load_der_x509_crl(r.content)
+ except Exception:
+ logging.error('Failed to load CRL')
+ continue
# 7. Perform CRL File Validation
crl_authority_key_id = crl_file.extensions.get_extension_for_oid(x509.OID_AUTHORITY_KEY_IDENTIFIER).value.key_identifier
crl_signer_subject_key_id = crl_signer_certificate.extensions.get_extension_for_oid(
x509.OID_SUBJECT_KEY_IDENTIFIER).value.key_identifier
if crl_authority_key_id != crl_signer_subject_key_id:
+ logging.warning("CRL Authority Key ID is not CRL Signer Subject Key ID, continue...")
continue
issuer_subject_key_id = ''.join('{:02X}'.format(x) for x in crl_authority_key_id)
- same_issuer_points = None
+ # b.
+ same_issuer_points = dcld_client.get_revocations_points_by_skid(issuer_subject_key_id)
+ count_with_matching_vid_issuer_skid = sum(item.get('vid') == vid for item in same_issuer_points)
- # TODO: Extract this to a helper function
- if use_rest:
- response = requests.get(
- f"{rest_node_url}/dcl/pki/revocation-points/{issuer_subject_key_id}").json()["pkiRevocationDistributionPointsByIssuerSubjectKeyID"]
- same_issuer_points = response["points"]
- else:
- cmdlist = ['query', 'pki', 'revocation-points', '--issuer-subject-key-id', issuer_subject_key_id]
- cmdpipe = subprocess.Popen(use_dcld(dcld, production, cmdlist), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- same_issuer_points = json.loads(cmdpipe.stdout.read())[
- "pkiRevocationDistributionPointsByIssuerSubjectKeyID"]["points"]
-
- matching_entries = False
- for same_issuer_point in same_issuer_points:
- if same_issuer_point["vid"] == vid:
- matching_entries = True
- break
-
- if matching_entries:
+ if count_with_matching_vid_issuer_skid > 1:
try:
issuing_distribution_point = crl_file.extensions.get_extension_for_oid(
x509.OID_ISSUING_DISTRIBUTION_POINT).value
except Exception:
+ logging.warning("CRL Issuing Distribution Point not found, continue...")
continue
uri_list = issuing_distribution_point.full_name
if len(uri_list) == 1 and isinstance(uri_list[0], x509.UniformResourceIdentifier):
if uri_list[0].value != revocation_point["dataURL"]:
+ logging.warning("CRL Issuing Distribution Point URI is not CRL URL, continue...")
continue
else:
+ logging.warning("CRL Issuing Distribution Point URI is not CRL URL, continue...")
continue
# 9. Assign CRL File Issuer
certificate_authority_name = base64.b64encode(crl_file.issuer.public_bytes()).decode('utf-8')
+ logging.debug(f"CRL File Issuer: {certificate_authority_name}")
serialnumber_list = []
# 10. Iterate through the Revoked Certificates List
for revoked_cert in crl_file:
+ # a.
try:
revoked_cert_issuer = revoked_cert.extensions.get_extension_for_oid(
x509.CRLEntryExtensionOID.CERTIFICATE_ISSUER).value.get_values_for_type(x509.DirectoryName).value
if revoked_cert_issuer is not None:
if revoked_cert_issuer != certificate_authority_name:
+ logging.warning("CRL Issuer is not CRL File Issuer, continue...")
continue
except Exception:
pass
# b.
- try:
- revoked_cert_authority_key_id = revoked_cert.extensions.get_extension_for_oid(
- x509.OID_AUTHORITY_KEY_IDENTIFIER).value.key_identifier
-
- if revoked_cert_authority_key_id is None or revoked_cert_authority_key_id != crl_signer_subject_key_id:
- continue
- except Exception:
- continue
+ # TODO: Verify that the certificate chain of the entry is linking to the same PAA
+ # that issued the CRLSignerCertificate for this entry, including path through
+ # CRLSignerDelegator if present. If the PAAs under which were issued the certificate
+ # and the CRLSignerCertificate are different, ignore the entry.
# c. and d.
serialnumber_list.append(bytes(str('{:02X}'.format(revoked_cert.serial_number)), 'utf-8').decode('utf-8'))
diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md
index 97f0f76b3b0436..10833e0c0c1ed7 100644
--- a/docs/QUICK_START.md
+++ b/docs/QUICK_START.md
@@ -10,7 +10,7 @@ and platforms.
|
Controller / Admin
| Node
| Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**chip-tool**](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md) (Linux / Mac)
Includes docs for all the cluster commands supported
| **all-clusters-app** [M5Stack](https://github.com/project-chip/connectedhomeip/blob/master/examples/all-clusters-app/esp32/README.md) (ESP)[Linux](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/linux) simulation | Use the command line tool on a laptop to pair with and control an embedded Wi-Fi platform. This demo supports the “all-clusters-app”, so it provides the basic onoff light test and more. |
-| [**chip-device-ctrl.py**](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/README.md) | **all-clusters-app** [M5Stack](https://github.com/project-chip/connectedhomeip/blob/master/examples/all-clusters-app/esp32/README.md) (ESP) [Linux](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/linux) simulation | Same as above, but uses the pychip tool as Controller Node. |
+| [**chip-repl**](https://github.com/project-chip/connectedhomeip/blob/master/src/controller/python/README.md) | **all-clusters-app** [M5Stack](https://github.com/project-chip/connectedhomeip/blob/master/examples/all-clusters-app/esp32/README.md) (ESP) [Linux](https://github.com/project-chip/connectedhomeip/tree/master/examples/all-clusters-app/linux) simulation | Same as above, but uses the Python CHIP REPL as Controller Node. |
## Thread Nodes
diff --git a/docs/guides/python_chip_controller_advanced_usage.md b/docs/guides/python_chip_controller_advanced_usage.md
index c3d3f55ddc5095..2eee5472fdda23 100644
--- a/docs/guides/python_chip_controller_advanced_usage.md
+++ b/docs/guides/python_chip_controller_advanced_usage.md
@@ -7,8 +7,9 @@ tool or Matter accessories on Linux.
-- [Bluetooth LE virtualization on Linux](#bluetooth-le-virtualization-on-linux)
-- [Debugging with gdb](#debugging-with-gdb)
+- [Using Python CHIP Controller advanced features](#using-python-chip-controller-advanced-features)
+ - [Bluetooth LE virtualization on Linux](#bluetooth-le-virtualization-on-linux)
+ - [Debugging with gdb](#debugging-with-gdb)
@@ -62,38 +63,38 @@ interfaces working as Bluetooth LE central and peripheral, respectively.
TX bytes:3488 acl:95 sco:0 commands:110 errors:0
```
-4. Run the Python CHIP Controller with Bluetooth LE adapter defined from a
+4. Run the Python CHIP Controller REPL with Bluetooth LE adapter defined from a
command line:
- For example, add `--bluetooth-adapter=hci2` to use the virtual interface
- `hci2` listed above.
+ For example, add `--ble-adapter=2` to use the virtual interface `hci2`
+ listed above.
```
- chip-device-ctrl --bluetooth-adapter=hci2
+ chip-repl --ble-adapter=2
```
## Debugging with gdb
-You can run the chip-device-ctrl under GDB for debugging, however, since the
-Matter core support library is a dynamic library, you cannot read the symbols
-unless it is fully loaded.
+You can run the chip-repl under GDB for debugging, however, since the Matter SDK
+library is a dynamic library, you cannot read the symbols unless it is fully
+loaded.
The following block is a example debug session using GDB:
```
# GDB cannot run scripts directly
-# so you need to run Python3 with the path of device controller
-# Here, we use the feature from bash to get the path of chip-device-ctrl without typing it.
-$ gdb --args python3 `which chip-device-ctrl`
-GNU gdb (Ubuntu 10.1-2ubuntu2) 10.1.90.20210411-git
-Copyright (C) 2021 Free Software Foundation, Inc.
+# so you need to run Python3 with the path of device controller REPL
+# Here, we use the feature from bash to get the path of chip-repl without typing it.
+$ gdb --args python3 `which chip-repl`
+GNU gdb (GDB) 14.2
+Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
-This GDB was configured as "aarch64-linux-gnu".
+This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
@@ -103,6 +104,12 @@ Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python3...
+
+This GDB supports auto-downloading debuginfo from the following URLs:
+
+Enable debuginfod for this session? (y or [n]) n
+Debuginfod has been disabled.
+To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
(No debugging symbols found in python3)
(gdb)
```
@@ -119,38 +126,68 @@ library, let run the Matter device controller first.
```
(gdb) run
-Starting program: /usr/bin/python3 /home/ubuntu/.local/bin/chip-device-ctrl
+Starting program: /home/sag/projects/project-chip/connectedhomeip/out/venv/bin/python3 /home/sag/projects/project-chip/connectedhomeip/out/venv/bin/chip-repl
[Thread debugging using libthread_db enabled]
-Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
-CHIP:DIS: Init admin pairing table with server storage.
-CHIP:IN: local node id is 0x000000000001b669
-CHIP:DL: MDNS failed to join multicast group on wpan0 for address type IPv4: Inet Error 1016 (0x000003F8): Address not found
-CHIP:ZCL: Using ZAP configuration...
-CHIP:ZCL: deactivate report event
-CHIP:CTL: Getting operational keys
-CHIP:CTL: Generating operational certificate for the controller
-CHIP:CTL: Getting root certificate for the controller from the issuer
-CHIP:CTL: Generating credentials
-CHIP:CTL: Loaded credentials successfully
-CHIP:DL: Platform main loop started.
-Chip Device Controller Shell
+Using host libthread_db library "/usr/lib/libthread_db.so.1".
+Python 3.11.9 (main, Apr 29 2024, 11:59:58) [GCC 13.2.1 20240417]
+Type 'copyright', 'credits' or 'license' for more information
+IPython 8.24.0 -- An enhanced Interactive Python. Type '?' for help.
+[1716395111.775747][364405:364405] CHIP:CTL: Setting attestation nonce to random value
+[1716395111.776196][364405:364405] CHIP:CTL: Setting CSR nonce to random value
+InitBLE 0[1716395111.776809][364405:364405] CHIP:DL: writing settings to file (/tmp/chip_counters.ini-T7hX27)
+[1716395111.776854][364405:364405] CHIP:DL: renamed tmp file to file (/tmp/chip_counters.ini)
+[1716395111.776860][364405:364405] CHIP:DL: NVS set: chip-counters/reboot-count = 9 (0x9)
+[1716395111.777261][364405:364405] CHIP:DL: Got Ethernet interface: eno2
+[1716395111.777555][364405:364405] CHIP:DL: Found the primary Ethernet interface:eno2
+[1716395111.777868][364405:364405] CHIP:DL: Got WiFi interface: wlp7s0
+[1716395111.777877][364405:364405] CHIP:DL: Failed to reset WiFi statistic counts
+────────────────────────────────────────────────────────────────────────────────────────────────────────── Matter REPL ──────────────────────────────────────────────────────────────────────────────────────────────────────────
+
+
+
+ Welcome to the Matter Python REPL!
+
+ For help, please type matterhelp()
+
+ To get more information on a particular object/class, you can pass
+ that into matterhelp() as well.
+
+
+─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+2024-05-22 18:25:11 allenwind PersistentStorage[364405] WARNING Initializing persistent storage from file: /tmp/repl-storage.json
+2024-05-22 18:25:11 allenwind PersistentStorage[364405] WARNING Loading configuration from /tmp/repl-storage.json...
+2024-05-22 18:25:11 allenwind CertificateAuthorityManager[364405] WARNING Loading certificate authorities from storage...
+2024-05-22 18:25:11 allenwind CertificateAuthority[364405] WARNING New CertificateAuthority at index 1
+2024-05-22 18:25:11 allenwind CertificateAuthority[364405] WARNING Loading fabric admins from storage...
+2024-05-22 18:25:11 allenwind FabricAdmin[364405] WARNING New FabricAdmin: FabricId: 0x0000000000000001, VendorId = 0xFFF1
+2024-05-22 18:25:11 allenwind FabricAdmin[364405] WARNING Allocating new controller with CaIndex: 1, FabricId: 0x0000000000000001, NodeId: 0x000000000001B669, CatTags: []
+
+
+The following objects have been created:
+ certificateAuthorityManager: Manages a list of CertificateAuthority instances.
+ caList: The list of CertificateAuthority instances.
+ caList: A specific FabricAdmin object at index m for the nth CertificateAuthority instance.
-chip-device-ctrl >
+
+Default CHIP Device Controller (NodeId: 112233): has been initialized to manage caList[0].adminList[0] (FabricId = 1), and is available as devCtrl
+
+In [1]:
```
-The prompt `chip-device-ctrl >` indicates that the Matter core library is loaded
-by Python, you can browse the symbols in the Matter core library, setting
-breakpoints on functions and many other functions provided by GDB.
+The prompt `In [1]:` indicates that the Matter SDK library has been loaded and
+initialized by the Python Controller REPL, you can browse the symbols in the
+Matter core library, setting breakpoints on functions and many other functions
+provided by GDB.
-You can use `Ctrl-C` to send SIGINT to the controller anytime you want so you
-can set breakpoints.
+You can use `Ctrl-Z` to send `SIGTSTP` to the Python 3 REPL process anytime you
+want so you can set breakpoints (unfortunately Ctrl+C seems to be captured by
+the REPL).
-> (`Ctrl-C` pressed here.)
+In [1]: (`Ctrl-Z` pressed here.)
```
-Thread 1 "python3" received signal SIGINT, Interrupt.
-0x0000fffff7db79ec in __GI___select (nfds=, readfds=0xffffffffe760, writefds=0x0, exceptfds=0x0, timeout=) at ../sysdeps/unix/sysv/linux/select.c:49
-49 ../sysdeps/unix/sysv/linux/select.c: No such file or directory.
+Thread 1 "python3" received signal SIGTSTP, Stopped (user).
+0x00007ffff7650ceb in kill () from /usr/lib/libc.so.6
(gdb)
```
@@ -159,40 +196,27 @@ command in GDB (`b` for short)
```
(gdb) b DeviceCommissioner::PairDevice
-Breakpoint 1 at 0xfffff5b0f6b4 (2 locations)
+Breakpoint 1 at 0x7fffed453943: DeviceCommissioner::PairDevice. (4 locations)
(gdb)
```
-Type `continue` (`c` for short) to continue the device controller, you may need
-another hit of `Enter` to see the prompt.
+Type `signal SIGCONT` to continue the device controller after stopping it with
+signal stop, you may need another hit of `Enter` to see the prompt.
```
-(gdb) c
-Continuing.
-
-chip-device-ctrl >
+(gdb) signal SIGCONT
+Continuing with signal SIGCONT.
+In [1]:
```
Let do pairing over IP to see the effect of the breakpoint we just set.
```
-chip-device-ctrl > connect -ip 192.168.50.5 20202021 1
-Device is assigned with nodeid = 1
-
-Thread 1 "python3" hit Breakpoint 1, 0x0000fffff5b0f6b4 in chip::Controller::DeviceCommissioner::PairDevice(unsigned long, chip::RendezvousParameters&)@plt ()
- from /home/ubuntu/.local/lib/python3.9/site-packages/chip/_ChipDeviceCtrl.so
-(gdb)
-```
-
-The `@plt` symbol means it is a symbol used by dynamic library loader, type `c`
-(for `continue`) and it will break on the real function.
+In [1]: devCtrl.CommissionWithCode("MT:-24J0AFN00KA0648G00", 1234)
-```
-(gdb) c
-Continuing.
-
-Thread 1 "python3" hit Breakpoint 1, chip::Controller::DeviceCommissioner::PairDevice (this=0xd28540, remoteDeviceId=1, params=...) at ../../src/controller/CHIPDeviceController.cpp:827
-827 {
+Thread 5 "python3" hit Breakpoint 1.1, chip::Controller::DeviceCommissioner::PairDevice (this=0x7fffd8003a90, remoteDeviceId=1234, setUpCode=0x7ffff453d490 "MT:-24J0AFN00KA0648G00", params=...,
+ discoveryType=chip::Controller::DiscoveryType::kAll, resolutionData=...) at ../../src/controller/CHIPDeviceController.cpp:646
+646 {
(gdb)
```
@@ -201,46 +225,44 @@ then you can use `bt` (for `backtrace`) to see the backtrace of the call stack.
```
(gdb) bt
-#0 chip::Controller::DeviceCommissioner::PairDevice(unsigned long, chip::RendezvousParameters&) (this=0xd28540, remoteDeviceId=1, params=...)
- at ../../src/controller/CHIPDeviceController.cpp:827
-#1 0x0000fffff5b3095c in pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissioner*, char const*, uint32_t, chip::NodeId)
- (devCtrl=0xd28540, peerAddrStr=0xfffff467ace0 "192.168.50.5", setupPINCode=20202021, nodeid=1) at ../../src/controller/python/ChipDeviceController-ScriptBinding.cpp:234
-#2 0x0000fffff7639148 in () at /lib/aarch64-linux-gnu/libffi.so.8
-#3 0x0000fffff7638750 in () at /lib/aarch64-linux-gnu/libffi.so.8
-#4 0x0000fffff7665a44 in () at /usr/lib/python3.9/lib-dynload/_ctypes.cpython-39-aarch64-linux-gnu.so
-#5 0x0000fffff7664c7c in () at /usr/lib/python3.9/lib-dynload/_ctypes.cpython-39-aarch64-linux-gnu.so
-#6 0x00000000004a54f0 in _PyObject_MakeTpCall ()
-#7 0x000000000049cb10 in _PyEval_EvalFrameDefault ()
-#8 0x0000000000496d1c in ()
-#9 0x00000000004b1eb0 in _PyFunction_Vectorcall ()
-#10 0x0000000000498264 in _PyEval_EvalFrameDefault ()
-#11 0x00000000004b1cb8 in _PyFunction_Vectorcall ()
-#12 0x0000000000498418 in _PyEval_EvalFrameDefault ()
-#13 0x0000000000496d1c in ()
-#14 0x00000000004b1eb0 in _PyFunction_Vectorcall ()
-#15 0x0000000000498418 in _PyEval_EvalFrameDefault ()
-#16 0x00000000004b1cb8 in _PyFunction_Vectorcall ()
-#17 0x00000000004c6bc8 in ()
-#18 0x0000000000498264 in _PyEval_EvalFrameDefault ()
-#19 0x00000000004b1cb8 in _PyFunction_Vectorcall ()
-#20 0x0000000000498418 in _PyEval_EvalFrameDefault ()
-#21 0x00000000004966f8 in ()
-#22 0x00000000004b1f18 in _PyFunction_Vectorcall ()
-#23 0x0000000000498418 in _PyEval_EvalFrameDefault ()
-#24 0x00000000004b1cb8 in _PyFunction_Vectorcall ()
-#25 0x0000000000498264 in _PyEval_EvalFrameDefault ()
-#26 0x00000000004966f8 in ()
-#27 0x0000000000496490 in _PyEval_EvalCodeWithName ()
-#28 0x0000000000595b7c in PyEval_EvalCode ()
-#29 0x00000000005c6a5c in ()
-#30 0x00000000005c0a70 in ()
-#31 0x00000000005c69a8 in ()
-#32 0x00000000005c6148 in PyRun_SimpleFileExFlags ()
-#33 0x00000000005b60bc in Py_RunMain ()
-#34 0x0000000000585a08 in Py_BytesMain ()
-#35 0x0000fffff7d0c9d4 in __libc_start_main (main=
- 0x5858fc <_start+60>, argc=2, argv=0xfffffffff498, init=, fini=, rtld_fini=, stack_end=) at ../csu/libc-start.c:332
-#36 0x00000000005858f8 in _start ()
+(gdb) bt
+#0 chip::Controller::DeviceCommissioner::PairDevice
+ (this=0x7fffd8003a90, remoteDeviceId=1234, setUpCode=0x7fffef2555d0 "MT:-24J0AFN00KA0648G00", params=..., discoveryType=chip::Controller::DiscoveryType::kAll, resolutionData=...)
+ at ../../src/controller/CHIPDeviceController.cpp:646
+#1 0x00007fffed040825 in pychip_DeviceController_ConnectWithCode (devCtrl=0x7fffd8003a90, onboardingPayload=0x7fffef2555d0 "MT:-24J0AFN00KA0648G00", nodeid=1234, discoveryType=2 '\002')
+ at ../../src/controller/python/ChipDeviceController-ScriptBinding.cpp:395
+#2 0x00007ffff6ad5596 in ??? () at /usr/lib/libffi.so.8
+#3 0x00007ffff6ad200e in ??? () at /usr/lib/libffi.so.8
+#4 0x00007ffff6ad4bd3 in ffi_call () at /usr/lib/libffi.so.8
+#5 0x00007ffff6aeaffc in ??? () at /usr/lib/python3.11/lib-dynload/_ctypes.cpython-311-x86_64-linux-gnu.so
+#6 0x00007ffff6aeb4b4 in ??? () at /usr/lib/python3.11/lib-dynload/_ctypes.cpython-311-x86_64-linux-gnu.so
+#7 0x00007ffff794a618 in _PyObject_MakeTpCall () at /usr/lib/libpython3.11.so.1.0
+#8 0x00007ffff78f3d03 in _PyEval_EvalFrameDefault () at /usr/lib/libpython3.11.so.1.0
+#9 0x00007ffff7adef90 in ??? () at /usr/lib/libpython3.11.so.1.0
+#10 0x00007ffff79ebc0b in _PyObject_FastCallDictTstate () at /usr/lib/libpython3.11.so.1.0
+#11 0x00007ffff79ebe02 in _PyObject_Call_Prepend () at /usr/lib/libpython3.11.so.1.0
+#12 0x00007ffff79ec114 in ??? () at /usr/lib/libpython3.11.so.1.0
+#13 0x00007ffff794a618 in _PyObject_MakeTpCall () at /usr/lib/libpython3.11.so.1.0
+#14 0x00007ffff78f3d03 in _PyEval_EvalFrameDefault () at /usr/lib/libpython3.11.so.1.0
+#15 0x00007ffff7adef90 in ??? () at /usr/lib/libpython3.11.so.1.0
+#16 0x00007ffff7955b97 in PyObject_Vectorcall () at /usr/lib/libpython3.11.so.1.0
+#17 0x00007ffff6aea174 in ??? () at /usr/lib/python3.11/lib-dynload/_ctypes.cpython-311-x86_64-linux-gnu.so
+#18 0x00007ffff6aea28c in ??? () at /usr/lib/python3.11/lib-dynload/_ctypes.cpython-311-x86_64-linux-gnu.so
+#19 0x00007ffff6ad5152 in ??? () at /usr/lib/libffi.so.8
+#20 0x00007ffff6ad57b8 in ??? () at /usr/lib/libffi.so.8
+#21 0x00007fffed5de848 in chip::DeviceLayer::Internal::GenericPlatformManagerImpl::_DispatchEvent
+ (this=0x7fffed88dc90 , event=0x7fffe6fffe30) at ../../src/include/platform/internal/GenericPlatformManagerImpl.ipp:304
+#22 0x00007fffed5dd90d in chip::DeviceLayer::PlatformManager::DispatchEvent (this=0x7fffed88dc80 , event=0x7fffe6fffe30) at ../../src/include/platform/PlatformManager.h:503
+#23 0x00007fffed5df45b in chip::DeviceLayer::Internal::GenericPlatformManagerImpl_POSIX::ProcessDeviceEvents
+ (this=0x7fffed88dc90 ) at ../../src/include/platform/internal/GenericPlatformManagerImpl_POSIX.ipp:185
+#24 0x00007fffed5dee64 in chip::DeviceLayer::Internal::GenericPlatformManagerImpl_POSIX::_RunEventLoop (this=0x7fffed88dc90 )
+--Type for more, q to quit, c to continue without paging--
+ at ../../src/include/platform/internal/GenericPlatformManagerImpl_POSIX.ipp:227
+#25 0x00007fffed5dd888 in chip::DeviceLayer::PlatformManager::RunEventLoop (this=0x7fffed88dc80 ) at ../../src/include/platform/PlatformManager.h:403
+#26 0x00007fffed5df3fe in chip::DeviceLayer::Internal::GenericPlatformManagerImpl_POSIX::EventLoopTaskMain (arg=0x7fffed88dc90 )
+ at ../../src/include/platform/internal/GenericPlatformManagerImpl_POSIX.ipp:256
+#27 0x00007ffff76a6ded in ??? () at /usr/lib/libc.so.6
+#28 0x00007ffff772a0dc in ??? () at /usr/lib/libc.so.6
(gdb)
```
diff --git a/docs/guides/python_chip_controller_building.md b/docs/guides/python_chip_controller_building.md
index c940f2c92575e7..8a7acc884ab2fa 100644
--- a/docs/guides/python_chip_controller_building.md
+++ b/docs/guides/python_chip_controller_building.md
@@ -1,25 +1,20 @@
-# Deprecation notice
-
-chip-device-ctrl is no longer maintained and should not be used.
-
-Matter-repl is the current python controller implementation.
-
# Working with Python CHIP Controller
-The Python CHIP Controller is a tool that allows to commission a Matter device
-into the network and to communicate with it using the Zigbee Cluster Library
-(ZCL) messages.
+The Python CHIP controller is a library that allows to create a Matter fabric
+and commission Matter devices with it.
-> The chip-device-ctrl tool will be deprecated, and will be replaced by
-> chip-repl. Continue reading to see how to do the same thing with chip-repl.
+The `chip-repl` is a REPl which sets up a Python CHIP Controller and allows to
+explore the Python CHIP Controller API and communicate with devices from the
+command line.
- [Source files](#source-files)
-- [Building Android CHIPTool](#building-and-installing)
-- [Running the tool](#running-the-tool)
-- [Using Python CHIP Controller for Matter accessory testing](#using-python-chip-controller-for-matter-accessory-testing)
-- [List of commands](#list-of-commands)
+- [Building Python CHIP Controller](#building-and-installing)
+- [Running the CHIP REPL](#running-the-chip-repl)
+- [Using Python CHIP Controller REPL for Matter accessory testing](#using-python-chip-controller-repl-for-matter-accessory-testing)
+- [Example usage of the Python CHIP Controller REPL](#example-usage-of-the-python-chip-controller-repl)
+- [Explore Clusters, Attributes and Commands](#explore-clusters-attributes-and-commands)
@@ -85,35 +80,31 @@ To build and run the Python CHIP controller:
scripts/build_python.sh -m platform -i separate
```
- > Note: To get more details about available build configurations, run the
+ > Note: This builds the Python CHIP Controller along with the CHIP REPL as
+ > Python wheels and installs it into a separate Python virtual environment.
+ > To get more details about available build configurations, run the
> following command: `scripts/build_python.sh --help`
-## Running the tool
+## Running the CHIP REPL
-1. Activate the Python virtual environment:
+1. Activate the Python virtual environment with the Python CHIP Controller
+ installed:
```
source out/python_env/bin/activate
```
-2. Run the Python CHIP controller with root privileges, which is required to
- obtain access to the Bluetooth interface:
-
- ```
- sudo out/python_env/bin/chip-device-ctrl
- ```
-
- You can also select the Bluetooth LE interface using command line argument:
+2. Run the CHIP REPL to explore the API of the Python CHIP controller:
```
- sudo out/python_env/bin/chip-device-ctrl --bluetooth-adapter=hci2
+ chip-repl
```
-## Using Python CHIP Controller for Matter accessory testing
+## Using Python CHIP Controller REPL for Matter accessory testing
This section describes how to use Python CHIP controller to test the Matter
accessory. Below steps depend on the application clusters that you implemented
@@ -135,13 +126,14 @@ require physical trigger, for example pushing a button. Follow the documentation
of the Matter accessory example to learn how Bluetooth LE advertising is enabled
for the given example.
-### Step 3: Discover Matter accessory device over Bluetooth LE
+### Step 3: Discover commissionable Matter accessory device
-An uncommissioned accessory device advertises over Bluetooth LE. Run the
-following command to scan all advertised Matter devices:
+An uncommissioned accessory device advertises over Bluetooth LE or via mDNS if
+already on the network. Run the following command to scan all advertised Matter
+devices:
```
-chip-device-ctrl > ble-scan
+devCtrl.DiscoverCommissionableNodes()
```
### Step 4: Set network pairing credentials
@@ -177,11 +169,12 @@ network interface, such as Thread or Wi-Fi.
datasets directly from the Thread Border Router, you might also use a
different out-of-band method.
-2. Set the previously obtained Active Operational Dataset as a hex-encoded value
- using the following command:
+2. Set the previously obtained Active Operational Dataset as a byte array using
+ the following command:
```
- chip-device-ctrl > set-pairing-thread-credential 0e080000000000010000000300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8
+ thread_dataset = bytes.fromhex("0e080000000000010000000300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8")
+ devCtrl.SetThreadOperationalDataset(thread_dataset)
```
#### Setting Wi-Fi network credentials
@@ -190,11 +183,9 @@ Assuming your Wi-Fi SSID is _TESTSSID_, and your Wi-Fi password is _P455W4RD_,
set the credentials to the controller by executing the following command:
```
-chip-device-ctrl > set-pairing-wifi-credential TESTSSID P455W4RD
+devCtrl.SetWiFiCredentials(, )
```
-**REPL Command**: `devCtrl.SetWiFiCredentials(, )`
-
### Step 5: Commission the Matter accessory device over Bluetooth LE
The controller uses a 12-bit value called **discriminator** to discern between
@@ -222,16 +213,26 @@ with the following assumptions for the Matter accessory device:
- The temporary Node ID is _1234_
```
-chip-device-ctrl > connect -ble 3840 20202021 1234
+devCtrl.ConnectBLE(3840, 20202021, 1234)
```
-**REPL Command:**
-`devCtrl.ConnectBLE(, , )`
-
You can skip the last parameter, the Node ID, in the command. If you skip it,
the controller will assign it randomly. In that case, note down the Node ID,
because it is required later in the configuration process.
+It is also possible to use the QR setup code instead. It typically is shown on
+the terminal of the device as well. For example:
+
+```
+CHIP:SVR: SetupQRCode: [MT:-24J0AFN00KA0648G00]
+```
+
+Use the following command to commission the device with the QR code:
+
+```
+devCtrl.CommissionWithCode("MT:-24J0AFN00KA0648G00", 1234)
+```
+
After connecting the device over Bluetooth LE, the controller will go through
the following stages:
@@ -255,429 +256,155 @@ the following stages:
finished and the Python CHIP controller is now using only the IPv6 traffic
to reach the device.
-### Step 6: Control application ZCL clusters.
+### Step 6: Control application clusters.
For the light bulb example, execute the following command to toggle the LED
state:
```
-chip-device-ctrl > zcl OnOff Toggle 1234 1 0
+await devCtrl.SendCommand(1234, 1, Clusters.OnOff.Commands.Toggle())
```
-**REPL Command:**
-`await devCtrl.SendCommand(1234, 1, Clusters.OnOff.Commands.Toggle())`
-
To change the brightness of the LED, use the following command, with the level
value somewhere between 0 and 255.
```
-chip-device-ctrl > zcl LevelControl MoveToLevel 1234 1 0 level=50
+commandToSend = LevelControl.Commands.MoveToLevel(level=50, transitionTime=Null, optionsMask=0, optionsOverride=0)
+await devCtrl.SendCommand(1234, 1, commandToSend)
```
-**REPL Command:**
-`await devCtrl.SendCommand(1234, 1, LevelControl.Commands.MoveToLevel(level=50, transitionTime=Null, optionsMask=0, optionsOverride=0))`
-
### Step 7: Read basic information out of the accessory.
Every Matter accessory device supports a Basic Information Cluster, which
maintains collection of attributes that a controller can obtain from a device,
-such as the vendor name, the product name, or software version. Use `zclread`
-command to read those values from the device:
+such as the vendor name, the product name, or software version. Use
+`ReadAttribute()` command to read those values from the device:
```
-chip-device-ctrl > zclread BasicInformation VendorName 1234 1 0
-chip-device-ctrl > zclread BasicInformation ProductName 1234 1 0
-chip-device-ctrl > zclread BasicInformation SoftwareVersion 1234 1 0
+attributes = [
+ (0, Clusters.BasicInformation.Attributes.VendorName),
+ (0, Clusters.BasicInformation.Attributes.ProductName),
+ (0, Clusters.BasicInformation.Attributes.SoftwareVersion),
+]
+await devCtrl.ReadAttribute(1234, attributes)
```
-**REPL Command:**
-`await devCtrl.ReadAttribute(1234, [(1, Clusters.BasicInformation.Attributes.VendorName)])`
-
-> Use the `zcl ? BasicInformation` command to list all available commands for
-> Basic Information Cluster.
->
> In REPL, you can type `Clusters.BasicInformation.Attributes.` and then use the
> TAB key.
-## List of commands
-
-### `ble-adapter-print`
+## Example usage of the Python CHIP Controller REPL
-> BLE adapter operations is not yet supported in REPL
+These section covers a few useful commands of the Python CHIP Controller along
+with examples demonstrating how they can be called from the REPL.
-Print the available Bluetooth adapters on device. Takes no arguments:
-
-```
-chip-device-ctrl > ble-adapter-print
-2021-03-04 16:09:40,930 ChipBLEMgr INFO AdapterName: hci0 AdapterAddress: 00:AA:01:00:00:23
-```
+The
+[CHIP Device Controller API documentation offer](https://project-chip.github.io/connectedhomeip-doc/testing/ChipDeviceCtrlAPI.html#chip-chipdevicectrl)
+the full list of available commands.
-### `ble-debug-log`
-
-> BLE adapter operations is not yet supported in REPL
-
-Enable the Bluetooth LE debug logs.
-
-```
-chip-device-ctrl > ble-debug-log 1
-```
-
-### `ble-scan [-t ] [identifier]`
-
-> BLE adapter operations is not yet supported in REPL
-
-Start a scan action to search for valid CHIP devices over Bluetooth LE (for at
-most _timeout_ seconds). Stop when the device is matching the identifier or the
-counter times out.
-
-```
-chip-device-ctrl > ble-scan
-2021-05-29 22:28:05,461 ChipBLEMgr INFO scanning started
-2021-05-29 22:28:07,206 ChipBLEMgr INFO Name = ChipLight
-2021-05-29 22:28:07,206 ChipBLEMgr INFO ID = f016e23d-0d00-35d5-93e7-588acdbc7e54
-2021-05-29 22:28:07,207 ChipBLEMgr INFO RSSI = -79
-2021-05-29 22:28:07,207 ChipBLEMgr INFO Address = E0:4D:84:3C:BB:C3
-2021-05-29 22:28:07,209 ChipBLEMgr INFO Pairing State = 0
-2021-05-29 22:28:07,209 ChipBLEMgr INFO Discriminator = 3840
-2021-05-29 22:28:07,209 ChipBLEMgr INFO Vendor Id = 9050
-2021-05-29 22:28:07,209 ChipBLEMgr INFO Product Id = 20044
-2021-05-29 22:28:07,210 ChipBLEMgr INFO Adv UUID = 0000fff6-0000-1000-8000-00805f9b34fb
-2021-05-29 22:28:07,210 ChipBLEMgr INFO Adv Data = 00000f5a234c4e
-2021-05-29 22:28:07,210 ChipBLEMgr INFO
-2021-05-29 22:28:16,246 ChipBLEMgr INFO scanning stopped
-```
-
-### `set-pairing-thread-credential `
+### `SetThreadOperationalDataset()`
Provides the controller with Thread network credentials that will be used in the
device commissioning procedure to configure the device with a Thread interface.
```
-chip-device-ctrl > set-pairing-thread-credential 0e080000000000010000000300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8
+thread_dataset = bytes.fromhex("0e080000000000010000000300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8")
+devCtrl.SetThreadOperationalDataset(thread_dataset)
```
-**REPL Commands:**
-`devCtrl.SetThreadOperationalDataset(bytes.FromHex("0e080000000000010000000300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8"))`
-
-### `set-pairing-wifi-credential `
+### `SetWiFiCredentials(: str, : str)`
Provides the controller with Wi-Fi network credentials that will be used in the
device commissioning procedure to configure the device with a Wi-Fi interface.
```
-chip-device-ctrl > set-pairing-wifi-credential TESTSSID P455W4RD
+devCtrl.SetWiFiCredentials('TESTSSID', 'P455W4RD')
```
-**REPL Commands:** `devCtrl.SetWiFiCredentials('TESTSSID', 'P455W4RD')`
-
-### `connect -ip []`
-
-Do key exchange and establish a secure session between controller and device
-using IP transport.
-
-The Node ID will be used by controller to distinguish multiple devices. This
-does not match the spec and will be removed later. The nodeid will not be
-persisted by controller / device.
-
-If no nodeid given, a random Node ID will be used.
-
-**REPL Commands:**
-`devCtrl.CommissionIP(b'', , )`
-
-### `connect -ble []`
-
-Do key exchange and establish a secure session between controller and device
-using Bluetooth LE transport.
-
-The Node ID will be used by controller to distinguish multiple devices. This
-does not match the spec and will be removed later. The nodeid will not be
-persisted by controller / device.
-
-If no nodeid given, a random Node ID will be used.
-
-**REPL Commands:**
-`devCtrl.ConnectBLE(, , )`
+### `CommissionWithCode(: str, : int, : DiscoveryType)`
-### `close-session `
+Commission with the given nodeid from the setupPayload. setupPayload may be a QR
+or the manual setup code.
-If case there exists an open session (PASE or CASE) to the device with a given
-Node ID, mark it as expired.
-
-**REPL Commands:** `devCtrl.CloseSession()`
-
-### `discover`
-
-> To be implemented in REPL
-
-Discover available Matter accessory devices:
-
-```
-chip-device-ctrl > discover -all
```
-
-### `resolve `
-
-> To be implemented in REPL
-
-Resolve DNS-SD name corresponding with the given Node ID and update address of
-the node in the device controller:
-
-```
-chip-device-ctrl > resolve 1234
+devCtrl.CommissionWithCode("MT:-24J0AFN00KA0648G00", 1234)
```
-### `setup-payload generate [-v ] [-p ] [-cf ] [-dc ] [-dv ] [-ps ]`
-
-> To be implemented in REPL
+### `SendCommand(: int, : int, Clusters..Commands.())`
-Print the generated Onboarding Payload Contents in human-readable (Manual
-Pairing Code) and machine-readable (QR Code) format:
+Send a Matter command to the device. For example:
+```python
+commandToSend = Clusters.LevelControl.Commands.MoveWithOnOff(moveMode=1, rate=2, optionsMask=0, optionsOverride=0)
+await devCtrl.SendCommand(1234, 1, commandToSend)
```
-chip-device-ctrl > setup-payload generate -v 9050 -p 65279 -cf 0 -dc 2 -dv 2976 -ps 34567890
-Manual pairing code: [26318621095]
-SetupQRCode: [MT:YNJV7VSC00CMVH7SR00]
-```
-
-### `setup-payload parse-manual `
-
-> To be implemented in REPL
-
-Print the commissioning information encoded in the Manual Pairing Code:
-
-```
-chip-device-ctrl > setup-payload parse-manual 34970112332
-Version: 0
-VendorID: 0
-ProductID: 0
-CommissioningFlow: 0
-RendezvousInformation: 0
-Discriminator: 3840
-SetUpPINCode: 20202021
-```
-
-### `setup-payload parse-qr `
-> To be implemented in REPL
-
-Print the commissioning information encoded in the QR Code payload:
+To see available arguments just create a command object without argument:
```
-chip-device-ctrl > setup-payload parse-qr "VP:vendorpayload%MT:W0GU2OTB00KA0648G00"
-Version: 0
-VendorID: 9050
-ProductID: 20043
-CommissioningFlow: 0
-RendezvousInformation: 2 [BLE]
-Discriminator: 3840
-SetUpPINCode: 20202021
+Clusters.LevelControl.Commands.MoveWithOnOff()
```
-### `zcl [arguments]`
-
-Send a ZCL command to the device. For example:
+Shows which arguments are available:
```
-chip-device-ctrl > zcl LevelControl MoveWithOnOff 12344321 1 0 moveMode=1 rate=2
+MoveWithOnOff(
+│ moveMode=0,
+│ rate=Null,
+│ optionsMask=0,
+│ optionsOverride=0
+)
```
-**Format of arguments**
+### `ReadAttribute(: int, [(: int, Clusters..Attributes.)])`
-For any integer and char string (null terminated) types, just use `key=value`,
-for example: `rate=2`, `string=123`, `string_2="123 456"`
-
-For byte string type, use `key=encoding:value`, currently, we support `str` and
-`hex` encoding, the `str` encoding will encode a NULL terminated string. For
-example, `networkId=hex:0123456789abcdef` (for
-`[0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]`), `ssid=str:Test` (for
-`['T', 'e', 's', 't', 0x00]`).
-
-For boolean type, use `key=True` or `key=False`.
-
-**REPL Commands:**
+Read the value of an attribute. For example:
```python
-# await devCtrl.SendCommand(, , Clusters..Commands.())
-# e.g.
-await devCtrl.SendCommand(12344321, 1, Clusters.LevelControl.Commands.MoveWithOnOff(moveMode=1, rate=2, optionsMask=0, optionsOverride=0))
-```
-
-### `zcl ?`
-
-List available clusters:
-
-```
-chip-device-ctrl > zcl ?
-AccountLogin
-ApplicationBasic
-ApplicationLauncher
-AudioOutput
-BarrierControl
-BasicInformation
-Binding
-BridgedDeviceBasicInformation
-ColorControl
-ContentLaunch
-Descriptor
-DoorLock
-EthernetNetworkDiagnostics
-FixedLabel
-GeneralCommissioning
-GeneralDiagnostics
-GroupKeyManagement
-Groups
-Identify
-KeypadInput
-LevelControl
-LowPower
-MediaInput
-MediaPlayback
-NetworkCommissioning
-OnOff
-OperationalCredentials
-PumpConfigurationAndControl
-RelativeHumidityMeasurement
-ScenesManagement
-SoftwareDiagnostics
-Switch
-Channel
-TargetNavigator
-TemperatureMeasurement
-TestCluster
-Thermostat
-TrustedRootCertificates
-WakeOnLan
-WindowCovering
-```
-
-**REPL Commands**
-
-Type `Clusters.` and hit TAB
-
-### `zcl ? `
-
-List available commands in cluster. For example, for _Basic Information_
-cluster:
-
-```
-chip-device-ctrl > zcl ? BasicInformation
-DataModelRevision
-VendorName
-VendorID
-ProductName
-ProductID
-UserLabel
-Location
-HardwareVersion
-HardwareVersionString
-SoftwareVersion
-SoftwareVersionString
-ManufacturingDate
-PartNumber
-ProductURL
-ProductLabel
-SerialNumber
-LocalConfigDisabled
-ClusterRevision
-```
-
-**REPL Commands**
-
-Type `Clusters.(cluster name).Commands.` and hit TAB
-
-### `zclread [arguments]`
-
-Read the value of ZCL attribute. For example:
-
-```
-chip-device-ctrl > zclread BasicInformation VendorName 1234 1 0
-```
-
-**REPL Commands**
-
-```python
-# devCtrl.ReadAttribute(, [(, Clusters..Attributes.)])
-# e.g.
-await devCtrl.ReadAttribute(1234, [(1, Clusters.BasicInformation.Attributes.VendorName)])
-```
-
-### `zclwrite `
-
-Write the value to a ZCL attribute. For example:
-
-```
-chip-device-ctrl > zclwrite TestCluster Int8u 1 1 0 1
-chip-device-ctrl > zclwrite TestCluster Boolean 1 1 0 True
-chip-device-ctrl > zclwrite TestCluster OctetString 1 1 0 str:123123
-chip-device-ctrl > zclwrite TestCluster CharString 1 1 0 233233
+await devCtrl.ReadAttribute(1234, [(0, Clusters.BasicInformation.Attributes.VendorName)])
```
-Note: The format of the value is the same as the format of argument values for
-ZCL cluster commands.
+### `WriteAttribute(: int, [(: int, Clusters..Attributes.(value=))])`
-**REPL Commands**
+Write a value to an attribute. For example:
```python
-# devCtrl.WriteAttribute(, [(, Clusters..Attributes.(value=))])
-# e.g.
-await devCtrl.WriteAttribute(1, [(1, Clusters.UnitTesting.Attributes.Int8u(value=1))])
-await devCtrl.WriteAttribute(1, [(1, Clusters.UnitTesting.Attributes.Boolean(value=True))])
-await devCtrl.WriteAttribute(1, [(1, Clusters.UnitTesting.Attributes.OctetString(value=b'123123\x00'))])
-await devCtrl.WriteAttribute(1, [(1, Clusters.UnitTesting.Attributes.CharString(value='233233'))])
+await devCtrl.WriteAttribute(1234, [(1, Clusters.UnitTesting.Attributes.Int8u(value=1))])
+await devCtrl.WriteAttribute(1234, [(1, Clusters.UnitTesting.Attributes.Boolean(value=True))])
+await devCtrl.WriteAttribute(1234, [(1, Clusters.UnitTesting.Attributes.OctetString(value=b'123123\x00'))])
+await devCtrl.WriteAttribute(1234, [(1, Clusters.UnitTesting.Attributes.CharString(value='233233'))])
```
-### `zclsubscribe `
+### `ReadAttribute(: int, [(: int, Clusters..Attributes.)], reportInterval=(: int, : int))`
-Configure ZCL attribute reporting settings. For example:
-
-```
-chip-device-ctrl > zclsubscribe OccupancySensing Occupancy 1234 1 10 20
-```
-
-**REPL Commands**
+Configure Matter attribute reporting settings. For example:
```python
-# devCtrl.ReadAttribute(, [(, Clusters..Attributes.)], reportInterval=(, ))
-# e.g.
-await devCtrl.ReadAttribute(1, [(1, Clusters.OccupancySensing.Attributes.Occupancy)], reportInterval=(10, 20))
+await devCtrl.ReadAttribute(1234, [(1, Clusters.OccupancySensing.Attributes.Occupancy)], reportInterval=(10, 20))
```
-### `zclsubscribe -shutdown `
-
-Shutdown an existing attribute subscription.
+To shutdown an existing attribute subscription use the `Shutdown()` function on
+the returned subscription object:
-```
-chip-device-ctrl > zclsubscribe -shutdown 0xdeadbeefcafe
+```python
+sub = await devCtrl.ReadAttribute(1234, [(1, Clusters.OccupancySensing.Attributes.Occupancy)], reportInterval=(10, 20))
+sub.Shutdown()
```
-The subscription id can be obtained from previous subscription messages:
+## Explore Clusters, Attributes and Commands
-```
-chip-device-ctrl > zclsubscribe OnOff OnOff 1 1 10 20
-(omitted messages)
-[1633922898.965587][1117858:1117866] CHIP:DMG: SubscribeResponse =
-[1633922898.965599][1117858:1117866] CHIP:DMG: {
-[1633922898.965610][1117858:1117866] CHIP:DMG: SubscriptionId = 0xdeadbeefcafe,
-[1633922898.965622][1117858:1117866] CHIP:DMG: MinIntervalFloorSeconds = 0xa,
-[1633922898.965633][1117858:1117866] CHIP:DMG: MaxIntervalCeilingSeconds = 0x14,
-[1633922898.965644][1117858:1117866] CHIP:DMG: }
-[1633922898.965662][1117858:1117866] CHIP:ZCL: SubscribeResponse:
-[1633922898.965673][1117858:1117866] CHIP:ZCL: SubscriptionId: 0xdeadbeefcafe
-[1633922898.965683][1117858:1117866] CHIP:ZCL: ApplicationIdentifier: 0
-[1633922898.965694][1117858:1117866] CHIP:ZCL: status: EMBER_ZCL_STATUS_SUCCESS (0x00)
-[1633922898.965709][1117858:1117866] CHIP:ZCL: attributeValue: false
-(omitted messages)
-```
+In the Python REPL the Clusters and Attributes are classes. The `Clusters`
+module contains all clusters. Tab completion can be used to explore available
+clusters, attributes and commands.
-The subscription id is `0xdeadbeefcafe` in this case
+For example, to get a list of Clusters, type `Clusters.` and hit tab. Continue
+to hit tab to cycle through the available Clusters. Pressing return will select
+the Cluster.
-**REPL Commands**
+To explore Attributes, use the same technique but with the Attributes sub-class
+of the Clusters class, for example, type `Clusters.(cluster name).Attributes.`
+and hit tab.
-```python
-# SubscriptionTransaction.Shutdown()
-# e.g.
-sub = await devCtrl.ReadAttribute(1, [(1, Clusters.OccupancySensing.Attributes.Occupancy)], reportInterval=(10, 20))
-sub.Shutdown()
-```
+The same is true for Commands, use the Commands sub-class. type
+`Clusters.(cluster name).Commands.` and hit tab.
diff --git a/docs/testing/yaml.md b/docs/testing/yaml.md
index 107c761fbef71e..e7353d09697e30 100644
--- a/docs/testing/yaml.md
+++ b/docs/testing/yaml.md
@@ -279,6 +279,17 @@ function can be use. See
[TestEqualities](https://github.com/project-chip/connectedhomeip/blob/master/src/app/tests/suites/TestEqualities.yaml)
for an example of how to use this pseudo-cluster.
+#### Setting step timeouts
+
+The timeout argument can be used for each individual test step to set the time
+the runner will wait for a test step to complete before reporting a failure.
+
+Note that this timeout is different than the subscription report timeout and the
+subscription report timeout is not currently adjustable in YAML.
+
+There several other options for configuring test steps as shown in the
+[YAML schema](./yaml_schema.md) document.
+
## Running YAML tests
YAML scripts are parsed and run using a python-based runner program that parses
@@ -304,6 +315,24 @@ There are several options for running tests locally. Because the YAML runner
uses python, it is necessary to compile and install the chip python package
before using any YAML runner script.
+First activate the matter environment using either
+
+```
+. ./scripts/bootstrap.sh
+```
+
+or
+
+```
+. ./scripts/activate.sh
+```
+
+bootstrap.sh should be used for for the first setup, activate.sh may be used for
+subsequent setups as it is faster.
+
+Next build the python wheels and create a venv (called `py` here, but any name
+may be used)
+
```
./scripts/build_python.sh -i py
source py/bin/activate
diff --git a/docs/zap_clusters.md b/docs/zap_clusters.md
index eedfb7190e2f27..a11a552bf023a6 100644
--- a/docs/zap_clusters.md
+++ b/docs/zap_clusters.md
@@ -112,6 +112,7 @@ Generally regenerate using one of:
| 1069 | 0x42D | Pm10ConcentrationMeasurement |
| 1070 | 0x42E | TotalVolatileOrganicCompoundsConcentrationMeasurement |
| 1071 | 0x42F | RadonConcentrationMeasurement |
+| 1105 | 0x451 | WiFiNetworkManagement |
| 1283 | 0x503 | WakeOnLan |
| 1284 | 0x504 | Channel |
| 1285 | 0x505 | TargetNavigator |
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
index 59e79389113b79..804d1eae5fbd32 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
@@ -2609,7 +2609,7 @@ cluster BooleanState = 69 {
}
/** This cluster supports remotely monitoring and, where supported, changing the operational state of an Oven. */
-provisional cluster OvenCavityOperationalState = 72 {
+cluster OvenCavityOperationalState = 72 {
revision 1;
enum ErrorStateEnum : enum8 {
@@ -2675,7 +2675,7 @@ provisional cluster OvenCavityOperationalState = 72 {
}
/** Attributes and commands for selecting a mode from a list of supported options. */
-provisional cluster OvenMode = 73 {
+cluster OvenMode = 73 {
revision 1;
enum ModeTag : enum16 {
@@ -3334,7 +3334,7 @@ cluster DishwasherAlarm = 93 {
}
/** Attributes and commands for selecting a mode from a list of supported options. */
-provisional cluster MicrowaveOvenMode = 94 {
+cluster MicrowaveOvenMode = 94 {
revision 1;
enum ModeTag : enum16 {
@@ -3876,7 +3876,7 @@ cluster ValveConfigurationAndControl = 129 {
}
/** This cluster provides a mechanism for querying data about electrical power as measured by the server. */
-provisional cluster ElectricalPowerMeasurement = 144 {
+cluster ElectricalPowerMeasurement = 144 {
revision 1;
enum MeasurementTypeEnum : enum16 {
@@ -3981,7 +3981,7 @@ provisional cluster ElectricalPowerMeasurement = 144 {
}
/** This cluster provides a mechanism for querying data about the electrical energy imported or provided by the server. */
-provisional cluster ElectricalEnergyMeasurement = 145 {
+cluster ElectricalEnergyMeasurement = 145 {
revision 1;
enum MeasurementTypeEnum : enum16 {
@@ -4278,7 +4278,7 @@ provisional cluster DeviceEnergyManagement = 152 {
}
/** Electric Vehicle Supply Equipment (EVSE) is equipment used to charge an Electric Vehicle (EV) or Plug-In Hybrid Electric Vehicle. This cluster provides an interface to the functionality of Electric Vehicle Supply Equipment (EVSE) management. */
-provisional cluster EnergyEvse = 153 {
+cluster EnergyEvse = 153 {
revision 2;
enum EnergyTransferStoppedReasonEnum : enum8 {
@@ -4490,7 +4490,7 @@ provisional cluster EnergyPreference = 155 {
}
/** The Power Topology Cluster provides a mechanism for expressing how power is flowing between endpoints. */
-provisional cluster PowerTopology = 156 {
+cluster PowerTopology = 156 {
revision 1;
bitmap Feature : bitmap32 {
@@ -4511,7 +4511,7 @@ provisional cluster PowerTopology = 156 {
}
/** Attributes and commands for selecting a mode from a list of supported options. */
-provisional cluster EnergyEvseMode = 157 {
+cluster EnergyEvseMode = 157 {
revision 1;
enum ModeTag : enum16 {
diff --git a/examples/android/CHIPTool/app/build.gradle b/examples/android/CHIPTool/app/build.gradle
index 368930259ea66a..4502b7f7a18897 100644
--- a/examples/android/CHIPTool/app/build.gradle
+++ b/examples/android/CHIPTool/app/build.gradle
@@ -43,9 +43,6 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
- packagingOptions {
- exclude 'META-INF/main.kotlin_module'
- }
buildFeatures {
viewBinding = true
diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp
index 3643f5ea1eb02a..a894b5d0150ca6 100644
--- a/examples/bridge-app/linux/main.cpp
+++ b/examples/bridge-app/linux/main.cpp
@@ -899,13 +899,11 @@ void ApplicationInit()
// Setup Mock Devices
Light1.SetReachable(true);
Light2.SetReachable(true);
-
Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
TempSensor1.SetReachable(true);
- TempSensor1.SetReachable(true);
-
+ TempSensor2.SetReachable(true);
TempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged);
TempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged);
@@ -914,7 +912,6 @@ void ApplicationInit()
ActionLight2.SetReachable(true);
ActionLight3.SetReachable(true);
ActionLight4.SetReachable(true);
-
ActionLight1.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
ActionLight2.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
ActionLight3.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
@@ -929,7 +926,6 @@ void ApplicationInit()
ComposedTempSensor2.SetReachable(true);
ComposedPowerSource.SetReachable(true);
ComposedPowerSource.SetBatChargeLevel(58);
-
ComposedTempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged);
ComposedTempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged);
ComposedPowerSource.SetChangeCallback(&HandleDevicePowerSourceStatusChanged);
diff --git a/examples/chef/common/chef-descriptor-namespace.h b/examples/chef/common/chef-descriptor-namespace.h
new file mode 100644
index 00000000000000..e7e8e85df5a551
--- /dev/null
+++ b/examples/chef/common/chef-descriptor-namespace.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2024 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces
+constexpr const uint8_t kNamespaceCommonLevel = 5;
+// Common Number Namespace: 5, tag 0 (Low)
+constexpr const uint8_t kTagCommonLow = 0;
+// Common Number Namespace: 5, tag 1 (Medium)
+constexpr const uint8_t kTagCommonMedium = 1;
+// Common Number Namespace: 5, tag 2 (High)
+constexpr const uint8_t kTagCommonHigh = 2;
+
+constexpr const uint8_t kNamespaceCommonNumber = 7;
+// Common Number Namespace: 7, tag 0 (Zero)
+constexpr const uint8_t kTagCommonZero = 0;
+// Common Number Namespace: 7, tag 1 (One)
+constexpr const uint8_t kTagCommonOne = 1;
+// Common Number Namespace: 7, tag 2 (Two)
+constexpr const uint8_t kTagCommonTwo = 2;
+
+constexpr const uint8_t kNamespacePosition = 8;
+// Common Position Namespace: 8, tag: 0 (Left)
+constexpr const uint8_t kTagPositionLeft = 0;
+// Common Position Namespace: 8, tag: 1 (Right)
+constexpr const uint8_t kTagPositionRight = 1;
+// Common Position Namespace: 8, tag: 2 (Top)
+constexpr const uint8_t kTagPositionTop = 2;
+// Common Position Namespace: 8, tag: 3 (Bottom)
+constexpr const uint8_t kTagPositionBottom = 3;
+// Common Position Namespace: 8, tag: 4 (Middle)
+constexpr const uint8_t kTagPositionMiddle = 4;
+// Common Position Namespace: 8, tag: 5 (Row)
+constexpr const uint8_t kTagPositionRow = 5;
+// Common Position Namespace: 8, tag: 6 (Column)
+constexpr const uint8_t kTagPositionColumn = 6;
diff --git a/examples/chef/common/chef-rpc-actions-worker.cpp b/examples/chef/common/chef-rpc-actions-worker.cpp
new file mode 100644
index 00000000000000..98bba768e7f4d8
--- /dev/null
+++ b/examples/chef/common/chef-rpc-actions-worker.cpp
@@ -0,0 +1,158 @@
+/*
+ *
+ * Copyright (c) 2024 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "chef-rpc-actions-worker.h"
+#include
+#include
+#include
+#include
+#include
+#include