diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index c33b5913d62d1c..3bdbd2609551e5 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -42,6 +42,18 @@ RUN useradd -s /bin/bash -u $USER_UID -g $USER_GID -G docker -m $USERNAME
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
RUN chmod 0440 /etc/sudoers.d/$USERNAME
+# Python 3.9 and PIP
+RUN set -x \
+ && sudo apt-get install -y libgirepository1.0-dev \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common \
+ && sudo add-apt-repository universe \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -y python3.9 python3.9-venv python3.9-dev\
+ && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
+ && python3.9 get-pip.py \
+ && sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 \
+ && rm -rf /var/lib/apt/lists/ \
+ && : # last line
+
RUN mkdir -p /var/downloads
RUN cd /var/downloads
RUN curl -JL https://github.com/microsoft/vscode-cpptools/releases/download/0.27.0/cpptools-linux.vsix > extension.zip
diff --git a/.gitmodules b/.gitmodules
index fabee45d3c765c..3db3a2073379b9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -95,3 +95,7 @@
path = third_party/mbed-os-posix-socket/repo
url = https://github.com/ARMmbed/mbed-os-posix-socket.git
branch = main
+[submodule "third_party/pybind11/repo"]
+ path = third_party/pybind11/repo
+ url = ../../pybind/pybind11
+ branch = stable
diff --git a/BUILD.gn b/BUILD.gn
index ee06f5a3240b87..18547278376d1c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -112,6 +112,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
deps += [ "${chip_root}/src/tools/chip-cert" ]
}
if (chip_enable_python_modules) {
+ deps += [ "${chip_root}/src/pybindings/pycontroller" ]
deps += [ "${chip_root}/src/controller/python" ]
}
}
@@ -129,6 +130,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
data_deps = [ "${chip_root}/examples/chip-tool" ]
if (chip_enable_python_modules) {
+ data_deps += [ "${chip_root}/src/pybindings/pycontroller" ]
data_deps += [ "${chip_root}/src/controller/python" ]
}
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 9514db60332582..d6a1377159a8ab 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -356,6 +356,11 @@ config("sanitize_default") {
config("fuzzing_default") {
}
+declare_args() {
+ # Enable Runtime Type Information (RTTI)
+ enable_rtti = false
+}
+
config("no_rtti") {
cflags_cc = [ "-fno-rtti" ]
}
@@ -365,7 +370,11 @@ config("rtti") {
}
config("rtti_default") {
- configs = [ ":no_rtti" ]
+ if (enable_rtti) {
+ configs = [ ":rtti" ]
+ } else {
+ configs = [ ":no_rtti" ]
+ }
}
config("no_exceptions") {
diff --git a/integrations/docker/images/chip-build/Dockerfile b/integrations/docker/images/chip-build/Dockerfile
index 5b5d4b331747a7..f4bcc06e1039f2 100644
--- a/integrations/docker/images/chip-build/Dockerfile
+++ b/integrations/docker/images/chip-build/Dockerfile
@@ -50,13 +50,13 @@ RUN set -x \
ninja-build \
openjdk-8-jdk \
pkg-config \
- python3 \
- python3-dev \
- python3-pip \
- python3-venv \
+ python3.9 \
+ python3.9-dev \
+ python3.9-venv \
rsync \
shellcheck \
strace \
+ sudo \
systemd \
udev \
unzip \
@@ -74,14 +74,17 @@ RUN set -x \
&& exec bash \
&& : # last line
-# Python 2 and PIP
+RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
+# Python 3.9 and PIP
RUN set -x \
- && apt-get update \
+ && sudo apt-get update \
+ && sudo apt-get install -y libgirepository1.0-dev \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common \
&& add-apt-repository universe \
- && DEBIAN_FRONTEND=noninteractive apt-get install -y python python2 \
- && curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py \
- && python2 get-pip.py \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -y python3.9 python3.9-venv python3.9-dev\
+ && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
+ && python3.9 get-pip.py \
+ && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 \
&& rm -rf /var/lib/apt/lists/ \
&& : # last line
diff --git a/scripts/build_python.sh b/scripts/build_python.sh
index e1a29a3ffe64a6..897cc1aba07301 100755
--- a/scripts/build_python.sh
+++ b/scripts/build_python.sh
@@ -39,12 +39,13 @@ OUTPUT_ROOT="$CHIP_ROOT/out/python_lib"
ENVIRONMENT_ROOT="$CHIP_ROOT/out/python_env"
declare chip_detail_logging=false
+declare enable_pybindinds=false
declare chip_mdns
declare clusters=true
help() {
- echo "Usage: $file_name [ options ... ] [ -chip_detail_logging ChipDetailLoggingValue ] [ -chip_mdns ChipMDNSValue ]"
+ echo "Usage: $file_name [ options ... ] [ -chip_detail_logging ChipDetailLoggingValue ] [ -chip_mdns ChipMDNSValue ] [-enable_pybindinds EnableValue]"
echo "General Options:
-h, --help Display this information.
@@ -55,6 +56,7 @@ Input Options:
By default it is minimal.
-c, --clusters_for_ip_commissioning true/false Specify whether to use clusters for IP commissioning.
By default it is true.
+ -p, --enable_pybindinds EnableValue Specify whether to enable pybindings as python controller.
"
}
@@ -78,6 +80,10 @@ while (($#)); do
clusters=$2
shift
;;
+ --enable_pybindinds | -p)
+ enable_pybindinds=$2
+ shift
+ ;;
-*)
help
echo "Unknown Option \"$1\""
@@ -88,25 +94,43 @@ while (($#)); do
done
# Print input values
-echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\""
+echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\", enable_pybindinds = $enable_pybindinds"
# Ensure we have a compilation environment
source "$CHIP_ROOT/scripts/activate.sh"
# Generates ninja files
[[ -n "$chip_mdns" ]] && chip_mdns_arg="chip_mdns=\"$chip_mdns\"" || chip_mdns_arg=""
-gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="chip_detail_logging=$chip_detail_logging chip_use_clusters_for_ip_commissioning=$clusters $chip_mdns_arg"
+
+gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="chip_detail_logging=$chip_detail_logging enable_rtti=$enable_pybindinds chip_use_clusters_for_ip_commissioning=$clusters $chip_mdns_arg"
# Compiles python files
-ninja -C "$OUTPUT_ROOT" python
+# Check pybindings was requested
+if [ $enable_pybindinds == true ]
+then
+ninja -v -C "$OUTPUT_ROOT" pycontroller
+else
+ninja -v -C "$OUTPUT_ROOT" python
+fi
+
+
# Create a virtual environment that has access to the built python tools
virtualenv --clear "$ENVIRONMENT_ROOT"
# Activate the new enviroment to register the python WHL
+
+if [ $enable_pybindinds == true ]
+then
+WHEEL="$OUTPUT_ROOT"/pybindings/pycontroller/pybindings-*.whl
+else
+WHEEL="$OUTPUT_ROOT"/controller/python/chip-*.whl
+fi
+
source "$ENVIRONMENT_ROOT"/bin/activate
"$ENVIRONMENT_ROOT"/bin/python -m pip install --upgrade pip
-"$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir "$OUTPUT_ROOT"/controller/python/chip-*.whl
+"$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir $WHEEL
+
echo ""
echo_green "Compilation completed and WHL package installed in: "
diff --git a/scripts/tools/zap_regen_all.py b/scripts/tools/zap_regen_all.py
index 4bdaca6afe55d4..fb652eab156a1d 100755
--- a/scripts/tools/zap_regen_all.py
+++ b/scripts/tools/zap_regen_all.py
@@ -39,6 +39,7 @@ def getSpecificTemplatesTargets():
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/app/common/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'examples/chip-tool/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/controller/python/templates/templates.json'])
+ targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/pybindings/pycontroller/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/darwin/Framework/CHIP/templates/templates.json'])
targets.append(['src/controller/data_model/controller-clusters.zap', '-t', 'src/controller/java/templates/templates.json'])
return targets
diff --git a/src/pybindings/Bnder_Code_Gen.md b/src/pybindings/Bnder_Code_Gen.md
new file mode 100644
index 00000000000000..0dcc0f9cc9b19b
--- /dev/null
+++ b/src/pybindings/Bnder_Code_Gen.md
@@ -0,0 +1,68 @@
+# Generating PyBind with Binder
+
+## Install Binder
+
+- Installation instructions can be found
+ [here](https://cppbinder.readthedocs.io/en/latest/install.html).
+
+## Binder Command
+
+binder --config `./CHIPDeviceController.config` --suppress-errors --root-module
+PyChip --prefix `connectedhomeip/src/pybindings/pycontroller/GeneratedFiles`
+--flat `all_header.hpp` -- -DCHIP_HAVE_CONFIG_H=1
+-DCHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK=1 -target `x86_64-apple-macos10.15` -x c++
+-std=c++11
+`-I/Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/usr/include/`
+-Iconnectedhomeip/src -Iconnectedhomeip/src/lib
+-Iconnectedhomeip/out/python_lib/gen/include -Iconnectedhomeip/config/standalone
+-Iconnectedhomeip/third_party/pigweed/repo/pw_minimal_cpp_stdlib/public
+-Iconnectedhomeip/third_party/pigweed/repo/pw_polyfill/standard_library_public
+-Iconnectedhomeip/src/include/
+
+- Include paths may vary and `highlighted` text may also vary.
+
+## Binder Output
+
+- Binder will output several files with prefix PyChip and suffix \_#
+- The output will be based on the config and hpp file passed in.
+- Since binder is new to this project, manual conversion is necessary.
+- Example of the output below:
+
+![alt text](https://raw.githubusercontent.com/krypton36/images/master/ss3.png)
+
+## Binder Conversions
+
+- If the file contains everythin you want then the file can be copied over and
+ added.
+- If there is just a class and it can be added to the existing, the class
+ binding can be added.
+
+Example of conversion of Logging:
+
+- Search for the module:
+
+
+
+- Combined these two to a single Logging file
+
+
+ ->
+
+
+- Rename function to bind_PyChip_Logging:
+
+
+
+- Add the logging binding to Main
+
+
+
+ -> -> ->
+
+- Add to BUILD GN file:
+
+
+
+- Lastly Test:
+
+
diff --git a/src/pybindings/pycontroller/BUILD.gn b/src/pybindings/pycontroller/BUILD.gn
new file mode 100644
index 00000000000000..debb877af30ceb
--- /dev/null
+++ b/src/pybindings/pycontroller/BUILD.gn
@@ -0,0 +1,183 @@
+# Copyright (c) 2021 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.
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/python.gni")
+
+import("${chip_root}/build/chip/tools.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${dir_pw_unit_test}/test.gni")
+
+if (current_os == "mac") {
+ import("${build_root}/config/mac/mac_sdk.gni")
+}
+
+config("controller_wno_deprecate") {
+ cflags = [
+ "-Wno-deprecated-declarations",
+ "-Wno-shadow",
+ "-Wno-unused-result",
+ "-Wsign-compare",
+ "-Wunreachable-code",
+ "-Wno-macro-redefined",
+ ]
+}
+
+shared_library("CHIPController") {
+ configs -= [ "//build/config/compiler:exceptions_default" ]
+
+ output_name = "PyChip"
+ output_dir = "${target_out_dir}/pybindings"
+ include_dirs = [ "${chip_root}/third_party/pybind11/repo/include" ]
+ if (current_os == "mac") {
+ include_dirs +=
+ [ "${chip_root}/.environment/cipd/python/include/python3.8" ]
+ } else if (current_os == "linux") {
+ include_dirs += [ "/usr/include/python3.9" ]
+ } else {
+ assert(false, "OS not supprted.")
+ }
+
+ sources = [
+ "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.cpp",
+ "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.h",
+ "ControllerBindings/PyChip_Main.cpp",
+ ]
+
+ public_deps = [
+ ":build_exceptions",
+ "${chip_root}/src/app",
+ "${chip_root}/src/controller/data_model",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/lib/core",
+ "${chip_root}/src/lib/mdns",
+ "${chip_root}/src/lib/support",
+ "${chip_root}/src/platform",
+ "${chip_root}/src/setup_payload",
+ "${chip_root}/src/transport",
+ ]
+ configs += [ ":controller_wno_deprecate" ]
+ ldflags = [ "-frtti" ]
+ if (current_os == "mac") {
+ ldflags += [
+ "-undefined",
+ "dynamic_lookup",
+ ]
+ }
+ if (current_os == "linux") {
+ libs = [ "python3.9" ]
+ }
+}
+pw_python_action("build_exceptions") {
+ script = "create_error_wrapper.py"
+
+ header_file = "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.h"
+ cpp_file = "${root_gen_dir}/include/pybindings/pycontroller/CHIPErrorToExceptionBindings.cpp"
+ outputs = [
+ header_file,
+ cpp_file,
+ ]
+
+ args = [
+ "--output_cpp_file=" + rebase_path(cpp_file, root_build_dir),
+ "--output_header_file=" + rebase_path(header_file, root_build_dir),
+ "--error_header=" +
+ rebase_path("${chip_root}/src/lib/core/CHIPError.h", root_build_dir),
+ "--config_header=" +
+ rebase_path("${chip_root}/src/lib/core/CHIPConfig.h", root_build_dir),
+ ]
+}
+
+pw_python_action("pycontroller") {
+ script = "build-chip-wheel.py"
+
+ _py_manifest_files = [
+ {
+ src_dir = "."
+ sources = [
+ ]
+ },
+ {
+ src_dir = target_out_dir
+ sources = [ "${target_out_dir}/pybindings/PyChip.so" ]
+ },
+ {
+ src_dir = "//"
+ sources = [ "//LICENSE" ]
+ },
+ ]
+
+ _py_manifest_file = "${target_gen_dir}/${target_name}.py_manifest.json"
+
+ inputs = []
+ _py_manifest_files_rebased = []
+ foreach(_manifest_entry, _py_manifest_files) {
+ inputs += _manifest_entry.sources
+ _py_manifest_files_rebased += [
+ {
+ src_dir = rebase_path(_manifest_entry.src_dir,
+ get_path_info(_py_manifest_file, "dir"))
+ sources = rebase_path(_manifest_entry.sources, _manifest_entry.src_dir)
+ },
+ ]
+ }
+
+ _py_manifest = {
+ files = _py_manifest_files_rebased
+ }
+
+ write_file(_py_manifest_file, _py_manifest, "json")
+
+ _dist_dir = "${root_out_dir}/pybindings/pycontroller"
+
+ if (current_cpu == "x64") {
+ cpu_tag = "x86_64"
+ } else if (current_cpu == "arm64") {
+ cpu_tag = "aarch64"
+ } else {
+ cpu_tag = current_cpu
+ }
+
+ if (current_os == "mac") {
+ platform_tag = "macosx_" + string_replace(mac_deployment_target, ".", "_")
+ } else {
+ platform_tag = current_os
+ }
+
+ platform_tag = platform_tag + "_" + cpu_tag
+
+ tags = "cp37-abi3-" + platform_tag
+
+ args = [
+ "--package_name",
+ "pybindings",
+ "--build_number",
+ "0.0",
+ "--build_dir",
+ rebase_path("${target_gen_dir}/${target_name}.py_build", root_build_dir),
+ "--dist_dir",
+ rebase_path(_dist_dir, root_build_dir),
+ "--manifest",
+ rebase_path(_py_manifest_file, root_build_dir),
+ "--plat-name",
+ platform_tag,
+ ]
+
+ public_deps = [ ":CHIPController" ]
+
+ output_name = "pybindings-0.0.dist-info-0.0-${tags}.whl"
+ outputs = [ "${_dist_dir}/$output_name" ]
+}
diff --git a/src/pybindings/pycontroller/ControllerBindings/PyChip_Main.cpp b/src/pybindings/pycontroller/ControllerBindings/PyChip_Main.cpp
new file mode 100644
index 00000000000000..c268cb45526934
--- /dev/null
+++ b/src/pybindings/pycontroller/ControllerBindings/PyChip_Main.cpp
@@ -0,0 +1,36 @@
+#include
+#include