├── Sources └── SwiftMatterExamples │ ├── Documentation.docc │ ├── Resources │ │ ├── setup-macOS │ │ │ ├── setup-macOS-00.sh │ │ │ ├── setup-macOS-01.sh │ │ │ └── setup-macOS-02.sh │ │ ├── setup-docker │ │ │ ├── setup-docker-00.sh │ │ │ ├── setup-docker-01.sh │ │ │ ├── setup-docker-02.sh │ │ │ ├── setup-docker-03.sh │ │ │ ├── setup-docker-04.sh │ │ │ └── setup-docker-05.sh │ │ ├── run-example-led-blink │ │ │ ├── run-example-led-blink-00.sh │ │ │ ├── esp32-c6-usb.png │ │ │ ├── run-example-led-blink-hello.png │ │ │ ├── run-example-led-blink-01.sh │ │ │ ├── run-example-led-blink-02.sh │ │ │ ├── run-example-led-blink-03.sh │ │ │ ├── run-example-led-blink-04.sh │ │ │ ├── walkthrough-example-led-blink-00.swift │ │ │ ├── walkthrough-example-led-blink-led-00.swift │ │ │ ├── walkthrough-example-led-blink-01.swift │ │ │ ├── walkthrough-example-led-blink-02.swift │ │ │ ├── walkthrough-example-led-blink-03.swift │ │ │ ├── walkthrough-example-led-blink-04.swift │ │ │ ├── walkthrough-example-led-blink-05.swift │ │ │ └── walkthrough-example-led-blink-led-01.swift │ │ ├── run-example-smart-light │ │ │ ├── run-example-smart-light-00.sh │ │ │ ├── homekit-logo.png │ │ │ ├── pairing │ │ │ │ ├── pairing-00.png │ │ │ │ ├── pairing-01.png │ │ │ │ ├── pairing-02.png │ │ │ │ ├── pairing-03.png │ │ │ │ ├── pairing-04.png │ │ │ │ ├── pairing-05.png │ │ │ │ ├── pairing-06.png │ │ │ │ ├── pairing-07.png │ │ │ │ ├── pairing-08.png │ │ │ │ ├── pairing-09.png │ │ │ │ ├── pairing-10.png │ │ │ │ └── pairing-11.png │ │ │ ├── run-example-smart-light-hello.png │ │ │ ├── run-example-smart-light-01.sh │ │ │ ├── run-example-smart-light-02.sh │ │ │ ├── run-example-smart-light-03.sh │ │ │ ├── run-example-smart-light-04.sh │ │ │ ├── walkthrough-example-smart-light-00.swift │ │ │ ├── walkthrough-example-smart-light-01.swift │ │ │ ├── walkthrough-example-smart-light-02.swift │ │ │ ├── walkthrough-example-smart-light-03.swift │ │ │ ├── walkthrough-example-smart-light-04.swift │ │ │ ├── walkthrough-example-smart-light-04-a.swift │ │ │ ├── walkthrough-example-smart-light-04-b.swift │ │ │ ├── walkthrough-example-smart-light-04-c.swift │ │ │ ├── walkthrough-example-smart-light-05.swift │ │ │ └── walkthrough-example-smart-light-06.swift │ │ ├── symbols │ │ │ ├── cpu.png │ │ │ ├── lightbulb.max.png │ │ │ ├── house.badge.wifi.png │ │ │ ├── arrow.down.circle.png │ │ │ └── lightbulb.led.wide.png │ │ ├── xcode │ │ │ ├── xcode-home.png │ │ │ ├── xcode-logo.png │ │ │ └── xcode-download.png │ │ ├── install-esp-terminal │ │ │ ├── install-esp-terminal-00.sh │ │ │ ├── install-esp-terminal-01.sh │ │ │ ├── install-esp-terminal-02.sh │ │ │ ├── install-esp-terminal-03.sh │ │ │ ├── install-esp-terminal-04.sh │ │ │ ├── install-esp-terminal-05.sh │ │ │ └── install-esp-terminal-06.sh │ │ ├── swift-org-downloads │ │ │ ├── swift-logo.png │ │ │ ├── swift-org-downloads.png │ │ │ ├── swift-org-downloads-main.png │ │ │ └── swift-org-downloads-installer.png │ │ └── install-swift-terminal │ │ │ ├── install-swift-terminal-00.sh │ │ │ ├── install-swift-terminal-01.sh │ │ │ └── install-swift-terminal-02.sh │ ├── Tutorial Table of Contents.tutorial │ └── Tutorials │ │ ├── Setup-Docker.tutorial │ │ ├── Run-Example-LED-Blink.tutorial │ │ ├── Setup-MacOS.tutorial │ │ └── Run-Example-Smart-Light.tutorial │ └── Empty.swift ├── led-blink ├── main │ ├── idf_component.yml │ ├── Main.swift │ ├── BridgingHeader.h │ ├── LED.swift │ └── CMakeLists.txt ├── partitions.csv ├── sdkconfig.defaults ├── CMakeLists.txt └── README.md ├── smart-light ├── main │ ├── idf_component.yml │ ├── linker.lf │ ├── BridgingHeader.h │ ├── Main.swift │ ├── LED.swift │ └── CMakeLists.txt ├── partitions.csv ├── sdkconfig.defaults.esp32c6 ├── Matter │ ├── MatterInterface.cpp │ ├── MatterInterface.h │ ├── Attribute.swift │ ├── Node.swift │ ├── Clusters.swift │ └── Matter.swift ├── sdkconfig.defaults ├── CMakeLists.txt └── README.md ├── empty-template ├── main │ ├── idf_component.yml │ ├── Main.swift │ ├── BridgingHeader.h │ └── CMakeLists.txt ├── partitions.csv ├── sdkconfig.defaults ├── CMakeLists.txt └── README.md ├── .gitignore ├── Package.swift ├── CODEOWNERS ├── .github └── workflows │ ├── lint.yml │ └── build.yml ├── Dockerfile ├── .swift-format ├── README.md └── LICENSE.txt /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-macOS/setup-macOS-00.sh: -------------------------------------------------------------------------------- 1 | # Setup the Swift nightly toolchain 2 | $ export TOOLCHAINS=org.swift.59202406031a 3 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-00.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-00.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-00.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/cpu.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-home.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-logo.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/lightbulb.max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/lightbulb.max.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/xcode/xcode-download.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/house.badge.wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/house.badge.wifi.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/arrow.down.circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/arrow.down.circle.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/lightbulb.led.wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/symbols/lightbulb.led.wide.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-macOS/setup-macOS-01.sh: -------------------------------------------------------------------------------- 1 | # Setup the Swift nightly toolchain 2 | $ export TOOLCHAINS=org.swift.59202406031a 3 | 4 | # Setup the ESP-IDF environment 5 | $ . ~/esp/esp-idf/export.sh 6 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-00.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-logo.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/esp32-c6-usb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/esp32-c6-usb.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-swift-terminal/install-swift-terminal-00.sh: -------------------------------------------------------------------------------- 1 | # Locate the toolchain 2 | $ ls ~/Library/Developer/Toolchains/ 3 | swift-DEVELOPMENT-SNAPSHOT-2024-06-03-a.xctoolchain 4 | swift-latest.xctoolchain 5 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/homekit-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/homekit-logo.png -------------------------------------------------------------------------------- /led-blink/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | espressif/cmake_utilities: 3 | version: 0.* 4 | rules: # will add "optional_component" only when all if clauses are True 5 | - if: "idf_version >=5.0" 6 | - if: "target in [esp32c2]" 7 | -------------------------------------------------------------------------------- /smart-light/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | espressif/cmake_utilities: 3 | version: 0.* 4 | rules: # will add "optional_component" only when all if clauses are True 5 | - if: "idf_version >=5.0" 6 | - if: "target in [esp32c2]" 7 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads.png -------------------------------------------------------------------------------- /empty-template/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | espressif/cmake_utilities: 3 | version: 0.* 4 | rules: # will add "optional_component" only when all if clauses are True 5 | - if: "idf_version >=5.0" 6 | - if: "target in [esp32c2]" 7 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-00.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-01.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-02.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-03.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-04.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-05.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-06.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-07.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-08.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-09.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-10.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/pairing/pairing-11.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads-main.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-hello.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/swift-org-downloads/swift-org-downloads-installer.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftlang/swift-matter-examples/HEAD/Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-hello.png -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-01.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the smart light example 6 | $ cd ~/swift-matter-examples/smart-light 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | dependencies.lock 10 | build/ 11 | managed_components/ 12 | sdkconfig 13 | sdkconfig.old 14 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-01.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Build and tag the docker image 6 | $ cd ~/swift-matter-examples 7 | $ docker build . --tag swift-matter-examples-builder 8 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-macOS/setup-macOS-02.sh: -------------------------------------------------------------------------------- 1 | # Setup the Swift nightly toolchain 2 | $ export TOOLCHAINS=org.swift.59202406031a 3 | 4 | # Setup the ESP-IDF environment 5 | $ . ~/esp/esp-idf/export.sh 6 | 7 | # Setup the ESP-Matter environment 8 | $ . ~/esp/esp-matter/export.sh 9 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-01.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the led blink example 6 | $ cd ~/swift-matter-examples/led-blink 7 | # In docker use "cd /code/led-blink" 8 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.10 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "swift-matter-examples", 7 | products: [ 8 | .library(name: "SwiftMatterExamples", targets: ["SwiftMatterExamples"]) 9 | ], 10 | targets: [ 11 | .target(name: "SwiftMatterExamples") 12 | ]) 13 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-01.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-02.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | # Create an ESP SDK directory 10 | $ mkdir -p ~/esp 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-02.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Build and tag the docker image 6 | $ cd ~/swift-matter-examples 7 | $ docker build . --tag swift-matter-examples-builder 8 | 9 | # Install esptool on macOS and Linux 10 | $ python3 -m pip install esptool --user 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-02.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the led blink example 6 | $ cd ~/swift-matter-examples/led-blink 7 | # In docker use "cd /code/led-blink" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-02.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the smart light example 6 | $ cd ~/swift-matter-examples/smart-light 7 | # In docker use "cd /code/smart-light" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-03.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the led blink example 6 | $ cd ~/swift-matter-examples/led-blink 7 | # In docker use "cd /code/led-blink" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | 12 | # Build the application 13 | $ idf.py build 14 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-03.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the smart light example 6 | $ cd ~/swift-matter-examples/smart-light 7 | # In docker use "cd /code/smart-light" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | 12 | # Build the application 13 | $ idf.py build 14 | 15 | -------------------------------------------------------------------------------- /smart-light/main/linker.lf: -------------------------------------------------------------------------------- 1 | [sections:flash_text_swift] 2 | entries: 3 | .swift_modhash+ 4 | [sections:dram0_swift] 5 | entries: 6 | .got+ 7 | .got.plt+ 8 | [scheme:swift_default] 9 | entries: 10 | flash_text_swift -> flash_text 11 | dram0_swift -> dram0_data 12 | [mapping:swift_default] 13 | archive: * 14 | entries: 15 | * (swift_default); 16 | flash_text_swift -> flash_text SURROUND (swift_text), 17 | dram0_swift -> dram0_data SURROUND (swift_dram0) -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-swift-terminal/install-swift-terminal-01.sh: -------------------------------------------------------------------------------- 1 | # Locate the toolchain 2 | $ ls ~/Library/Developer/Toolchains/ 3 | swift-DEVELOPMENT-SNAPSHOT-2024-06-03-a.xctoolchain 4 | swift-latest.xctoolchain 5 | 6 | # Find the toolchain identifier 7 | $ plutil -extract CFBundleIdentifier raw \ 8 | -o - \ 9 | ~/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-06-03-a.xctoolchain/Info.plist 10 | org.swift.59202406031a 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/run-example-led-blink-04.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the led blink example 6 | $ cd ~/swift-matter-examples/led-blink 7 | # In docker use "cd /code/led-blink" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | 12 | # Build the application 13 | $ idf.py build 14 | 15 | # Flash and monitor the application 16 | $ idf.py flash monitor 17 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/run-example-smart-light-04.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Navigate to the smart light example 6 | $ cd ~/swift-matter-examples/smart-light 7 | # In docker use "cd /code/smart-light" 8 | 9 | # Configure the target microcontroller 10 | $ idf.py set-target esp32c6 11 | 12 | # Build the application 13 | $ idf.py build 14 | 15 | # Flash and monitor the application 16 | $ idf.py flash monitor 17 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-00.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-00.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Empty.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // This file is included so SwiftPM considers the target to be a Swift target. 13 | -------------------------------------------------------------------------------- /empty-template/main/Main.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift!") 15 | } 16 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-03.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | # Create an ESP SDK directory 10 | $ mkdir -p ~/esp 11 | 12 | # Download the ESP-IDF SDK 13 | $ cd ~/esp 14 | $ git clone \ 15 | --branch v5.4.1 \ 16 | --depth 1 \ 17 | --shallow-submodules \ 18 | --recursive https://github.com/espressif/esp-idf.git \ 19 | --jobs 24 20 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-led-00.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | final class LED { 13 | } 14 | -------------------------------------------------------------------------------- /led-blink/partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table 3 | esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted 4 | nvs, data, nvs, 0x10000, 0xC000, 5 | nvs_keys, data, nvs_keys,, 0x1000, encrypted 6 | otadata, data, ota, , 0x2000 7 | phy_init, data, phy, , 0x1000, 8 | ota_0, app, ota_0, 0x20000, 0x1E0000, 9 | ota_1, app, ota_1, 0x200000, 0x1E0000, 10 | fctry, data, nvs, 0x3E0000, 0x6000 11 | coredump, data, coredump,, 64K 12 | -------------------------------------------------------------------------------- /smart-light/partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table 3 | esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted 4 | nvs, data, nvs, 0x10000, 0xC000, 5 | nvs_keys, data, nvs_keys,, 0x1000, encrypted 6 | otadata, data, ota, , 0x2000 7 | phy_init, data, phy, , 0x1000, 8 | ota_0, app, ota_0, 0x20000, 0x1E0000, 9 | ota_1, app, ota_1, 0x200000, 0x1E0000, 10 | fctry, data, nvs, 0x3E0000, 0x6000 11 | coredump, data, coredump,, 64K 12 | -------------------------------------------------------------------------------- /empty-template/partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table 3 | esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted 4 | nvs, data, nvs, 0x10000, 0xC000, 5 | nvs_keys, data, nvs_keys,, 0x1000, encrypted 6 | otadata, data, ota, , 0x2000 7 | phy_init, data, phy, , 0x1000, 8 | ota_0, app, ota_0, 0x20000, 0x1E0000, 9 | ota_1, app, ota_1, 0x200000, 0x1E0000, 10 | fctry, data, nvs, 0x3E0000, 0x6000 11 | coredump, data, coredump,, 64K 12 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-03.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Build and tag the docker image 6 | $ cd ~/swift-matter-examples 7 | $ docker build . --tag swift-matter-examples-builder 8 | 9 | # Install esptool on macOS and Linux 10 | $ python3 -m pip install esptool --user 11 | 12 | # Find your attached microcontroller 13 | # On macOS it usually attaches on /dev/cu.usbserial-10 14 | $ ls /dev/cu.usbserial-* 15 | /dev/cu.usbserial-10 16 | 17 | # On Linux it usually attaches on /dev/ttyUSB0 18 | $ ls /dev/ttyUSB* 19 | /dev/ttyUSB0 20 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-01.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | func main() { 13 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 14 | } 15 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-swift-terminal/install-swift-terminal-02.sh: -------------------------------------------------------------------------------- 1 | # Locate the toolchain 2 | $ ls ~/Library/Developer/Toolchains/ 3 | swift-DEVELOPMENT-SNAPSHOT-2024-06-03-a.xctoolchain 4 | swift-latest.xctoolchain 5 | 6 | # Find the toolchain identifier 7 | $ plutil -extract CFBundleIdentifier raw \ 8 | -o - \ 9 | ~/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2024-06-03-a.xctoolchain/Info.plist 10 | org.swift.59202406031a 11 | 12 | # Test the toolchain 13 | $ TOOLCHAINS=org.swift.59202406031a swift --version 14 | Apple Swift version 6.0-dev (LLVM c7c87ee42989d4b, Swift 0aa0687fe0f4047) 15 | Target: arm64-apple-macosx14.0 16 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-02.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 15 | } 16 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-01.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | } 16 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-04.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | # Create an ESP SDK directory 10 | $ mkdir -p ~/esp 11 | 12 | # Download the ESP-IDF SDK 13 | $ cd ~/esp 14 | $ git clone \ 15 | --branch v5.4.1 \ 16 | --depth 1 \ 17 | --shallow-submodules \ 18 | --recursive https://github.com/espressif/esp-idf.git \ 19 | --jobs 24 20 | 21 | # Install the ESP-IDF SDK 22 | $ cd ~/esp/esp-idf 23 | $ ./install.sh 24 | 25 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-03.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 15 | 16 | let led = LED() 17 | } 18 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-02.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | } 18 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-04.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Build and tag the docker image 6 | $ cd ~/swift-matter-examples 7 | $ docker build . --tag swift-matter-examples-builder 8 | 9 | # Install esptool on macOS and Linux 10 | $ python3 -m pip install esptool --user 11 | 12 | # Find your attached microcontroller 13 | # On macOS it usually attaches on /dev/cu.usbserial-10 14 | $ ls /dev/cu.usbserial-* 15 | /dev/cu.usbserial-10 16 | 17 | # On Linux it usually attaches on /dev/ttyUSB0 18 | $ ls /dev/ttyUSB* 19 | /dev/ttyUSB0 20 | 21 | # Run the serial server 22 | $ esp_rfc2217_server.py -v -p 4000 /dev/cu.usbserial-10 23 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-04.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 15 | 16 | let led = LED() 17 | led.color = .red 18 | led.brightness = 10 19 | } 20 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This file is a list of the people responsible for ensuring that patches for a 2 | # particular part of Swift are reviewed, either by themselves or by someone else. 3 | # They are also the gatekeepers for their part of Swift, with the final word on 4 | # what goes in or not. 5 | # 6 | # The list is sorted by surname and formatted to allow easy grepping and 7 | # beautification by scripts. The fields are: name (N), email (E), web-address 8 | # (W), PGP key ID and fingerprint (P), description (D), and snail-mail address 9 | # (S). 10 | 11 | # N: Kuba Mracek 12 | # E: mracek@apple.com 13 | # D: Everything in swift-embedded-examples not covered by someone else 14 | 15 | ### 16 | 17 | # The following lines are used by GitHub to automatically recommend reviewers. 18 | 19 | * @kubamracek @rauhul @phausler 20 | -------------------------------------------------------------------------------- /led-blink/main/Main.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 15 | 16 | let led = LED() 17 | led.color = .red 18 | led.brightness = 10 19 | 20 | while true { 21 | sleep(1) 22 | led.enabled.toggle() 23 | if led.enabled { 24 | led.color = .hueSaturation(Int.random(in: 0..<360), 100) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-03.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/setup-docker/setup-docker-05.sh: -------------------------------------------------------------------------------- 1 | # Clone the repo 2 | $ cd ~ 3 | $ git clone https://github.com/apple/swift-matter-examples.git 4 | 5 | # Build and tag the docker image 6 | $ cd ~/swift-matter-examples 7 | $ docker build . --tag swift-matter-examples-builder 8 | 9 | # Install esptool on macOS and Linux 10 | $ python3 -m pip install esptool --user 11 | 12 | # Find your attached microcontroller 13 | # On macOS it usually attaches on /dev/cu.usbserial-10 14 | $ ls /dev/cu.usbserial-* 15 | /dev/cu.usbserial-10 16 | 17 | # On Linux it usually attaches on /dev/ttyUSB0 18 | $ ls /dev/ttyUSB* 19 | /dev/ttyUSB0 20 | 21 | # Run the serial server 22 | $ esp_rfc2217_server.py -v -p 4000 /dev/cu.usbserial-10 23 | 24 | # Launch the docker container 25 | $ cd ~/swift-matter-examples 26 | $ docker run -it --cpus 4 --memory 8G -v .:/code:z swift-matter-examples-builder 27 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-05.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | # Create an ESP SDK directory 10 | $ mkdir -p ~/esp 11 | 12 | # Download the ESP-IDF SDK 13 | $ cd ~/esp 14 | $ git clone \ 15 | --branch v5.4.1 \ 16 | --depth 1 \ 17 | --shallow-submodules \ 18 | --recursive https://github.com/espressif/esp-idf.git \ 19 | --jobs 24 20 | 21 | # Install the ESP-IDF SDK 22 | $ cd ~/esp/esp-idf 23 | $ ./install.sh 24 | 25 | # Download the ESP-Matter SDK 26 | $ cd ~/esp 27 | $ git clone \ 28 | --branch release/v1.2 \ 29 | --depth 1 \ 30 | --shallow-submodules \ 31 | --recursive https://github.com/espressif/esp-matter.git \ 32 | --jobs 24 33 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-05.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (LED Blink)") 15 | 16 | let led = LED() 17 | led.color = .red 18 | led.brightness = 10 19 | 20 | while true { 21 | sleep(1) 22 | led.enabled.toggle() 23 | if led.enabled { 24 | led.color = .hueSaturation(Int.random(in: 0..<360), 100) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/install-esp-terminal/install-esp-terminal-06.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Install Homebrew 4 | $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 5 | 6 | # Install CMake, Ninja, and dfu-util 7 | $ brew install cmake ninja dfu-util 8 | 9 | # Create an ESP SDK directory 10 | $ mkdir -p ~/esp 11 | 12 | # Download the ESP-IDF SDK 13 | $ cd ~/esp 14 | $ git clone \ 15 | --branch v5.4.1 \ 16 | --depth 1 \ 17 | --shallow-submodules \ 18 | --recursive https://github.com/espressif/esp-idf.git \ 19 | --jobs 24 20 | 21 | # Install the ESP-IDF SDK 22 | $ cd ~/esp/esp-idf 23 | $ ./install.sh 24 | 25 | # Download the ESP-Matter SDK 26 | $ cd ~/esp 27 | $ git clone \ 28 | --branch release/v1.2 \ 29 | --depth 1 \ 30 | --shallow-submodules \ 31 | --recursive https://github.com/espressif/esp-matter.git \ 32 | --jobs 24 33 | 34 | # Install the ESP-Matter SDK 35 | $ cd ~/esp/esp-matter 36 | $ ./install.sh 37 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-04.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | // TODO... 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-04-a.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | switch event.attribute { 28 | default: 29 | break 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Tutorial Table of Contents.tutorial: -------------------------------------------------------------------------------- 1 | @Tutorials(name: "Swift Matter Examples") { 2 | @Intro(title: "Build a Matter accessory with Embedded Swift") { 3 | Learn how to build a simple Embedded Swift application that implements a Matter smart light accessory. 4 | 5 | Requirements: an ESP32-C6 microcontroller, ESP-IDF SDK, and ESP-Matter SDK. 6 | 7 | @Image(source: "house.badge.wifi.png", alt: "FIXME-ALT") 8 | } 9 | 10 | @Chapter(name: "Setup your environment") { 11 | Download, install, and configure the necessary tools. 12 | 13 | @Image(source: "arrow.down.circle.png", alt: "FIXME-ALT") 14 | 15 | @TutorialReference(tutorial: "doc:Setup-MacOS") 16 | @TutorialReference(tutorial: "doc:Setup-Docker") 17 | } 18 | 19 | @Chapter(name: "Run the examples") { 20 | Build the smart light application and run it on your microcontroller. 21 | 22 | @Image(source: "cpu.png", alt: "FIXME-ALT") 23 | 24 | @TutorialReference(tutorial: "doc:Run-Example-LED-Blink") 25 | @TutorialReference(tutorial: "doc:Run-Example-Smart-Light") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-led-blink/walkthrough-example-led-blink-led-01.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | final class LED { 13 | // Additional API ... 14 | 15 | var brightness: Int = 100 { 16 | didSet { 17 | brightness = max(0, min(100, brightness)) 18 | led_driver_set_brightness(handle, UInt8(brightness)) 19 | } 20 | } 21 | 22 | var color: Color = .hueSaturation(0, 100) { 23 | didSet { 24 | switch color { 25 | case .hueSaturation(let hue, let saturation): 26 | led_driver_set_hue(handle, UInt16(hue)) 27 | led_driver_set_saturation(handle, UInt8(saturation)) 28 | case .temperature(let temperature): 29 | led_driver_set_temperature(handle, UInt32(temperature)) 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-04-b.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | switch event.attribute { 28 | case .onOff: 29 | led.enabled = (event.value == 1) 30 | 31 | case .levelControl: 32 | led.brightness = Int(Float(event.value) / 255.0 * 100.0) 33 | 34 | default: 35 | break 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /smart-light/sdkconfig.defaults.esp32c6: -------------------------------------------------------------------------------- 1 | CONFIG_IDF_TARGET="esp32c6" 2 | 3 | # libsodium 4 | CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y 5 | 6 | # NIMBLE 7 | CONFIG_BT_ENABLED=y 8 | CONFIG_BT_NIMBLE_ENABLED=y 9 | CONFIG_BT_NIMBLE_EXT_ADV=n 10 | CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 11 | CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=y 12 | 13 | # FreeRTOS should use legacy API 14 | CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y 15 | 16 | # Disable lwip ipv6 autoconfig 17 | CONFIG_LWIP_IPV6_AUTOCONFIG=y 18 | 19 | # Use a custom partition table 20 | CONFIG_PARTITION_TABLE_CUSTOM=y 21 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" 22 | 23 | # Use minimal mDNS 24 | CONFIG_USE_MINIMAL_MDNS=y 25 | CONFIG_ENABLE_EXTENDED_DISCOVERY=y 26 | 27 | # Enable OTA Requestor 28 | CONFIG_ENABLE_OTA_REQUESTOR=y 29 | 30 | # Disable AP 31 | CONFIG_ENABLE_WIFI_STATION=y 32 | CONFIG_ENABLE_WIFI_AP=n 33 | 34 | # Button 35 | CONFIG_BUTTON_PERIOD_TIME_MS=20 36 | CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 37 | 38 | # Enable chip shell 39 | CONFIG_ENABLE_CHIP_SHELL=y 40 | 41 | # ESP32-C6-DevKitM-1 Settings 42 | # Buttons 43 | CONFIG_BSP_BUTTONS_NUM=1 44 | CONFIG_BSP_BUTTON_1_TYPE_GPIO=y 45 | CONFIG_BSP_BUTTON_1_GPIO=9 46 | CONFIG_BSP_BUTTON_1_LEVEL=0 47 | # LEDs 48 | CONFIG_BSP_LEDS_NUM=1 49 | CONFIG_BSP_LED_TYPE_RGB=y 50 | CONFIG_BSP_LED_RGB_GPIO=8 51 | CONFIG_BSP_LED_RGB_BACKEND_RMT=y 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: ["main"] 9 | pull_request: 10 | branches: ["main"] 11 | 12 | jobs: 13 | validate_format_config: 14 | name: Validate Format Config 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repo 18 | uses: actions/checkout@v4 19 | 20 | - name: Install apt dependencies 21 | run: sudo apt-get -qq update && sudo apt-get -qq -y install curl 22 | 23 | - name: Compare against swift-mmio swift-format config 24 | run: | 25 | curl -sL https://raw.githubusercontent.com/apple/swift-mmio/refs/heads/main/.swift-format -o .swift-format-mmio 26 | diff .swift-format .swift-format-mmio 27 | 28 | soundness: 29 | name: Soundness 30 | uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main 31 | with: 32 | api_breakage_check_enabled: false # this repo doesn't vend any API 33 | license_header_check_enabled: false # incorrectly flags this github workflow yml file 34 | license_header_check_project_name: "" # bug: https://github.com/swiftlang/github-workflows/issues/76 35 | shell_check_enabled: false # incorrectly flags tutorial content 36 | unacceptable_language_check_enabled: false # incorrectly flags "master" in external branch names 37 | -------------------------------------------------------------------------------- /smart-light/Matter/MatterInterface.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include "BridgingHeader.h" 13 | 14 | esp_err_t esp_matter::attribute::set_callback_shim(callback_t_shim callback) { 15 | return set_callback((callback_t)callback); 16 | } 17 | 18 | esp_matter::cluster_t *esp_matter::cluster::get_shim(esp_matter::endpoint_t *endpoint, unsigned int cluster_id) { 19 | return get(endpoint, (uint32_t)cluster_id); 20 | } 21 | 22 | esp_matter::attribute_t *esp_matter::attribute::get_shim(esp_matter::cluster_t *cluster, unsigned int attribute_id) { 23 | return get(cluster, (uint32_t)attribute_id); 24 | } 25 | 26 | void recomissionFabric() { 27 | if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) { 28 | chip::CommissioningWindowManager & commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager(); 29 | constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(300); 30 | if (!commissionMgr.IsCommissioningWindowOpen()) { 31 | commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /smart-light/Matter/MatterInterface.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // GNU C++ interfaces do not work well with Swift for certain types, so let's use some simple C++ shims. 13 | // For example, uint32_t gets imported as UInt and not CUnsignedLong (as defined in ESP IDF). 14 | namespace esp_matter { 15 | namespace attribute { 16 | typedef esp_err_t (*callback_t_shim)(callback_type_t type, uint16_t endpoint_id, unsigned int cluster_id, 17 | unsigned int attribute_id, esp_matter_attr_val_t *val, void *priv_data); 18 | esp_err_t set_callback_shim(callback_t_shim callback); 19 | } 20 | 21 | namespace cluster { 22 | cluster_t *get_shim(endpoint_t *endpoint, unsigned int cluster_id); 23 | } 24 | 25 | namespace attribute { 26 | attribute_t *get_shim(cluster_t *cluster, unsigned int attribute_id); 27 | } 28 | } 29 | 30 | // Recomissioning causes failures with reference semantics so this is done as a function implemented in C++. 31 | // Ideally this would be done by changing some of the headers in ESP Matter to have proper Swift annotations. 32 | void recomissionFabric(); 33 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-04-c.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | switch event.attribute { 28 | case .onOff: 29 | led.enabled = (event.value == 1) 30 | 31 | case .levelControl: 32 | led.brightness = Int(Float(event.value) / 255.0 * 100.0) 33 | 34 | case .colorControl(.currentHue): 35 | let newHue = Int(Float(event.value) / 255.0 * 360.0) 36 | led.color = .hueSaturation(newHue, led.color.saturation) 37 | 38 | case .colorControl(.currentSaturation): 39 | let newSaturation = Int(Float(event.value) / 255.0 * 100.0) 40 | led.color = .hueSaturation(led.color.hue, newSaturation) 41 | 42 | case .colorControl(.colorTemperatureMireds): 43 | let kelvins = 1_000_000 / event.value 44 | led.color = .temperature(kelvins) 45 | 46 | default: 47 | break 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /led-blink/main/BridgingHeader.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // C standard library 13 | // ================== 14 | 15 | #include 16 | #include 17 | 18 | // ESP IDF 19 | // ======= 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | // ESP Matter 30 | // ========== 31 | 32 | #define CHIP_HAVE_CONFIG_H 1 33 | #define CHIP_USE_ENUM_CLASS_FOR_IM_ENUM 1 34 | #define CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER 35 | 36 | // There seems to be assumption in FabricTable.h that strnlen is implicitly available via some other headers, but that 37 | // turns out to not be the case when importing these headers in Swift. Let's manually declare strnlen as a workaround. 38 | // 39 | // connectedhomeip/src/credentials/FabricTable.h:82:69: error: use of undeclared identifier 'strnlen' 40 | extern "C" size_t strnlen(const char *s, size_t maxlen); 41 | // esp-matter/components/esp_matter/esp_matter_client.h:57:26: error: use of undeclared identifier 'strdup' 42 | extern "C" char *strdup(const char *s1); 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | -------------------------------------------------------------------------------- /empty-template/main/BridgingHeader.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // C standard library 13 | // ================== 14 | 15 | #include 16 | #include 17 | 18 | // ESP IDF 19 | // ======= 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | // ESP Matter 30 | // ========== 31 | 32 | #define CHIP_HAVE_CONFIG_H 1 33 | #define CHIP_USE_ENUM_CLASS_FOR_IM_ENUM 1 34 | #define CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER 35 | 36 | // There seems to be assumption in FabricTable.h that strnlen is implicitly available via some other headers, but that 37 | // turns out to not be the case when importing these headers in Swift. Let's manually declare strnlen as a workaround. 38 | // 39 | // connectedhomeip/src/credentials/FabricTable.h:82:69: error: use of undeclared identifier 'strnlen' 40 | extern "C" size_t strnlen(const char *s, size_t maxlen); 41 | // esp-matter/components/esp_matter/esp_matter_client.h:57:26: error: use of undeclared identifier 'strdup' 42 | extern "C" char *strdup(const char *s1); 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-05.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | switch event.attribute { 28 | case .onOff: 29 | led.enabled = (event.value == 1) 30 | 31 | case .levelControl: 32 | led.brightness = Int(Float(event.value) / 255.0 * 100.0) 33 | 34 | case .colorControl(.currentHue): 35 | let newHue = Int(Float(event.value) / 255.0 * 360.0) 36 | led.color = .hueSaturation(newHue, led.color.saturation) 37 | 38 | case .colorControl(.currentSaturation): 39 | let newSaturation = Int(Float(event.value) / 255.0 * 100.0) 40 | led.color = .hueSaturation(led.color.hue, newSaturation) 41 | 42 | case .colorControl(.colorTemperatureMireds): 43 | let kelvins = 1_000_000 / event.value 44 | led.color = .temperature(kelvins) 45 | 46 | default: 47 | break 48 | } 49 | } 50 | 51 | // (3) Add the endpoint to the node 52 | rootNode.addEndpoint(lightEndpoint) 53 | } 54 | -------------------------------------------------------------------------------- /smart-light/main/BridgingHeader.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // C standard library 13 | // ================== 14 | 15 | #include 16 | #include 17 | 18 | // ESP IDF 19 | // ======= 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | // ESP Matter 30 | // ========== 31 | 32 | #define CHIP_HAVE_CONFIG_H 1 33 | #define CHIP_USE_ENUM_CLASS_FOR_IM_ENUM 1 34 | #define CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER 35 | 36 | // There seems to be assumption in FabricTable.h that strnlen is implicitly available via some other headers, but that 37 | // turns out to not be the case when importing these headers in Swift. Let's manually declare strnlen as a workaround. 38 | // 39 | // connectedhomeip/src/credentials/FabricTable.h:82:69: error: use of undeclared identifier 'strnlen' 40 | extern "C" size_t strnlen(const char *s, size_t maxlen); 41 | // esp-matter/components/esp_matter/esp_matter_client.h:57:26: error: use of undeclared identifier 'strdup' 42 | extern "C" char *strdup(const char *s1); 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | // Swift Matter interface 50 | // ====================== 51 | 52 | #include "../Matter/MatterInterface.h" 53 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Matter Examples 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: ["main"] 9 | pull_request: 10 | branches: ["main"] 11 | schedule: 12 | # Build on Mondays at 9am PST every week 13 | - cron: '0 17 * * 1' 14 | 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | build: 21 | runs-on: ubuntu-latest 22 | container: espressif/esp-matter:latest 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | example: [empty-template, led-blink, smart-light] 28 | swift: [swift-DEVELOPMENT-SNAPSHOT-2025-03-28-a] 29 | 30 | steps: 31 | - name: Checkout repo 32 | uses: actions/checkout@v4 33 | 34 | - name: Install Swift ${{ matrix.swift }} & CMake 35 | run: | 36 | set -vex 37 | 38 | wget -q https://download.swift.org/development/ubuntu2404/${{ matrix.swift }}/${{ matrix.swift }}-ubuntu24.04.tar.gz 39 | tar xzf ${{ matrix.swift }}-ubuntu24.04.tar.gz 40 | export PATH="$PATH:`pwd`/${{ matrix.swift }}-ubuntu24.04/usr/bin/" 41 | swiftc --version 42 | 43 | wget https://github.com/Kitware/CMake/releases/download/v3.30.2/cmake-3.30.2-linux-x86_64.tar.gz 44 | tar xzf cmake-3.30.2-linux-x86_64.tar.gz 45 | export PATH="`pwd`/cmake-3.30.2-linux-x86_64/bin:$PATH" 46 | cmake --version 47 | 48 | echo "PATH=$PATH" >> $GITHUB_ENV 49 | 50 | - name: Build with idf.py 51 | run: | 52 | pwd 53 | cd /opt/espressif/esp-idf 54 | . ./export.sh 55 | cd - 56 | cd /opt/espressif/esp-matter 57 | . ./export.sh 58 | cd - 59 | cd ${{ matrix.example }}/ 60 | idf.py set-target esp32c6 && 61 | idf.py build 62 | -------------------------------------------------------------------------------- /led-blink/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Default to 921600 baud when flashing and monitoring device 2 | CONFIG_ESPTOOLPY_BAUD_921600B=y 3 | CONFIG_ESPTOOLPY_BAUD=921600 4 | CONFIG_ESPTOOLPY_COMPRESSED=y 5 | CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y 6 | CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 7 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 8 | 9 | #enable BT 10 | CONFIG_BT_ENABLED=y 11 | CONFIG_BT_NIMBLE_ENABLED=y 12 | 13 | #disable BT connection reattempt 14 | CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n 15 | 16 | #enable lwip ipv6 autoconfig 17 | CONFIG_LWIP_IPV6_AUTOCONFIG=y 18 | 19 | # Use a custom partition table 20 | CONFIG_PARTITION_TABLE_CUSTOM=y 21 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" 22 | CONFIG_PARTITION_TABLE_OFFSET=0xC000 23 | 24 | # Enable chip shell 25 | CONFIG_ENABLE_CHIP_SHELL=y 26 | 27 | #enable lwIP route hooks 28 | CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y 29 | CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y 30 | 31 | # Button 32 | CONFIG_BUTTON_PERIOD_TIME_MS=20 33 | CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 34 | 35 | # disable softap by default 36 | CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n 37 | 38 | # Disable DS Peripheral 39 | CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n 40 | 41 | # Use compact attribute storage mode 42 | CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y 43 | 44 | # Enable HKDF in mbedtls 45 | CONFIG_MBEDTLS_HKDF_C=y 46 | 47 | # Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) 48 | # unique local addresses for fabrics(MAX_FABRIC), a link local address(1) 49 | CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 50 | 51 | # ESP32-DevKitC Settings 52 | # Buttons 53 | CONFIG_BSP_BUTTONS_NUM=1 54 | CONFIG_BSP_BUTTON_1_TYPE_GPIO=y 55 | CONFIG_BSP_BUTTON_1_GPIO=0 56 | CONFIG_BSP_BUTTON_1_LEVEL=0 57 | # LEDs 58 | CONFIG_BSP_LEDS_NUM=0 59 | 60 | # configurations required for diagnostic logs cluster 61 | # Enable the diagnostic logs transfer over BDX protocol 62 | CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER=y 63 | 64 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y 65 | CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y 66 | -------------------------------------------------------------------------------- /smart-light/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Default to 921600 baud when flashing and monitoring device 2 | CONFIG_ESPTOOLPY_BAUD_921600B=y 3 | CONFIG_ESPTOOLPY_BAUD=921600 4 | CONFIG_ESPTOOLPY_COMPRESSED=y 5 | CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y 6 | CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 7 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 8 | 9 | #enable BT 10 | CONFIG_BT_ENABLED=y 11 | CONFIG_BT_NIMBLE_ENABLED=y 12 | 13 | #disable BT connection reattempt 14 | CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n 15 | 16 | #enable lwip ipv6 autoconfig 17 | CONFIG_LWIP_IPV6_AUTOCONFIG=y 18 | 19 | # Use a custom partition table 20 | CONFIG_PARTITION_TABLE_CUSTOM=y 21 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" 22 | CONFIG_PARTITION_TABLE_OFFSET=0xC000 23 | 24 | # Enable chip shell 25 | CONFIG_ENABLE_CHIP_SHELL=y 26 | 27 | #enable lwIP route hooks 28 | CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y 29 | CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y 30 | 31 | # Button 32 | CONFIG_BUTTON_PERIOD_TIME_MS=20 33 | CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 34 | 35 | # disable softap by default 36 | CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n 37 | 38 | # Disable DS Peripheral 39 | CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n 40 | 41 | # Use compact attribute storage mode 42 | CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y 43 | 44 | # Enable HKDF in mbedtls 45 | CONFIG_MBEDTLS_HKDF_C=y 46 | 47 | # Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) 48 | # unique local addresses for fabrics(MAX_FABRIC), a link local address(1) 49 | CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 50 | 51 | # ESP32-DevKitC Settings 52 | # Buttons 53 | CONFIG_BSP_BUTTONS_NUM=1 54 | CONFIG_BSP_BUTTON_1_TYPE_GPIO=y 55 | CONFIG_BSP_BUTTON_1_GPIO=0 56 | CONFIG_BSP_BUTTON_1_LEVEL=0 57 | # LEDs 58 | CONFIG_BSP_LEDS_NUM=0 59 | 60 | # configurations required for diagnostic logs cluster 61 | # Enable the diagnostic logs transfer over BDX protocol 62 | CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER=y 63 | 64 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y 65 | CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y 66 | -------------------------------------------------------------------------------- /empty-template/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Default to 921600 baud when flashing and monitoring device 2 | CONFIG_ESPTOOLPY_BAUD_921600B=y 3 | CONFIG_ESPTOOLPY_BAUD=921600 4 | CONFIG_ESPTOOLPY_COMPRESSED=y 5 | CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y 6 | CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 7 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 8 | 9 | #enable BT 10 | CONFIG_BT_ENABLED=y 11 | CONFIG_BT_NIMBLE_ENABLED=y 12 | 13 | #disable BT connection reattempt 14 | CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n 15 | 16 | #enable lwip ipv6 autoconfig 17 | CONFIG_LWIP_IPV6_AUTOCONFIG=y 18 | 19 | # Use a custom partition table 20 | CONFIG_PARTITION_TABLE_CUSTOM=y 21 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" 22 | CONFIG_PARTITION_TABLE_OFFSET=0xC000 23 | 24 | # Enable chip shell 25 | CONFIG_ENABLE_CHIP_SHELL=y 26 | 27 | #enable lwIP route hooks 28 | CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y 29 | CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y 30 | 31 | # Button 32 | CONFIG_BUTTON_PERIOD_TIME_MS=20 33 | CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000 34 | 35 | # disable softap by default 36 | CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n 37 | 38 | # Disable DS Peripheral 39 | CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n 40 | 41 | # Use compact attribute storage mode 42 | CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y 43 | 44 | # Enable HKDF in mbedtls 45 | CONFIG_MBEDTLS_HKDF_C=y 46 | 47 | # Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1) 48 | # unique local addresses for fabrics(MAX_FABRIC), a link local address(1) 49 | CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 50 | 51 | # ESP32-DevKitC Settings 52 | # Buttons 53 | CONFIG_BSP_BUTTONS_NUM=1 54 | CONFIG_BSP_BUTTON_1_TYPE_GPIO=y 55 | CONFIG_BSP_BUTTON_1_GPIO=0 56 | CONFIG_BSP_BUTTON_1_LEVEL=0 57 | # LEDs 58 | CONFIG_BSP_LEDS_NUM=0 59 | 60 | # configurations required for diagnostic logs cluster 61 | # Enable the diagnostic logs transfer over BDX protocol 62 | CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER=y 63 | 64 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y 65 | CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y 66 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Resources/run-example-smart-light/walkthrough-example-smart-light-06.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | switch event.attribute { 28 | case .onOff: 29 | led.enabled = (event.value == 1) 30 | 31 | case .levelControl: 32 | led.brightness = Int(Float(event.value) / 255.0 * 100.0) 33 | 34 | case .colorControl(.currentHue): 35 | let newHue = Int(Float(event.value) / 255.0 * 360.0) 36 | led.color = .hueSaturation(newHue, led.color.saturation) 37 | 38 | case .colorControl(.currentSaturation): 39 | let newSaturation = Int(Float(event.value) / 255.0 * 100.0) 40 | led.color = .hueSaturation(led.color.hue, newSaturation) 41 | 42 | case .colorControl(.colorTemperatureMireds): 43 | let kelvins = 1_000_000 / event.value 44 | led.color = .temperature(kelvins) 45 | 46 | default: 47 | break 48 | } 49 | } 50 | 51 | // (3) Add the endpoint to the node 52 | rootNode.addEndpoint(lightEndpoint) 53 | 54 | // (4) Provide the node to a Matter application and start it 55 | let app = Matter.Application() 56 | app.rootNode = rootNode 57 | app.start() 58 | } 59 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Start from the latest Swift nightly main toolchain 2 | FROM swiftlang/swift:nightly-main-jammy 3 | 4 | # The number of submodules fetched at the same time 5 | ARG GIT_CLONE_JOBS=24 6 | 7 | # Install ESP-IDF dependencies 8 | RUN apt-get update \ 9 | && apt-get install --yes --no-install-recommends \ 10 | git wget flex bison gperf python3 python3-pip python3-venv \ 11 | ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 \ 12 | && rm -rf /var/lib/apt/lists/* 13 | 14 | # Install CMake >= 3.29 15 | RUN pip install --upgrade cmake 16 | 17 | # Download ESP-IDF 18 | RUN mkdir -p ~/esp \ 19 | && cd ~/esp \ 20 | && git clone \ 21 | --branch v5.4.1 \ 22 | --depth 1 \ 23 | --shallow-submodules \ 24 | --recursive https://github.com/espressif/esp-idf.git \ 25 | --jobs $GIT_CLONE_JOBS 26 | 27 | # Install ESP-IDF 28 | RUN cd ~/esp/esp-idf \ 29 | && ./install.sh esp32c6 30 | 31 | # Install ESP-Matter dependencies 32 | RUN apt-get update \ 33 | && apt-get install --yes --no-install-recommends \ 34 | git gcc g++ pkg-config libssl-dev libdbus-1-dev \ 35 | libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \ 36 | python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev \ 37 | && rm -rf /var/lib/apt/lists/* 38 | 39 | # Download ESP-Matter 40 | RUN mkdir -p ~/esp \ 41 | && cd ~/esp \ 42 | && git clone \ 43 | --branch release/v1.2 \ 44 | --depth 1 \ 45 | --shallow-submodules \ 46 | --recursive https://github.com/espressif/esp-matter.git \ 47 | --jobs $GIT_CLONE_JOBS 48 | 49 | # Download ESP-Matter 50 | RUN mkdir -p ~/esp \ 51 | && cd ~/esp/esp-matter/connectedhomeip/connectedhomeip \ 52 | && ./scripts/checkout_submodules.py --platform esp32 linux --shallow 53 | 54 | # Install ESP-Matter 55 | RUN cd ~/esp/esp-matter \ 56 | && ./install.sh 57 | 58 | # Setup shell environment 59 | RUN echo '. ~/esp/esp-idf/export.sh > /dev/null' >> ~/.bashrc \ 60 | && echo '. ~/esp/esp-matter/export.sh > /dev/null' >> ~/.bashrc 61 | ENV ESPPORT='rfc2217://host.docker.internal:4000?ign_set_control' 62 | -------------------------------------------------------------------------------- /led-blink/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.29) 4 | 5 | if(NOT DEFINED ENV{ESP_MATTER_PATH}) 6 | message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo") 7 | endif(NOT DEFINED ENV{ESP_MATTER_PATH}) 8 | 9 | if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 10 | if("${IDF_TARGET}" STREQUAL "esp32c6" OR "${IDF_TARGET}" STREQUAL "") 11 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c) 12 | else() 13 | message(FATAL_ERROR "Unsupported IDF_TARGET") 14 | endif() 15 | endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 16 | 17 | set(PROJECT_VER "1.0") 18 | set(PROJECT_VER_NUMBER 1) 19 | 20 | set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH}) 21 | set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip) 22 | 23 | # This should be done before using the IDF_TARGET variable. 24 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 25 | include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake) 26 | 27 | set(EXTRA_COMPONENT_DIRS 28 | "${ESP_MATTER_PATH}/examples/common" 29 | "${MATTER_SDK_PATH}/config/esp32/components" 30 | "${ESP_MATTER_PATH}/components" 31 | "${ESP_MATTER_PATH}/device_hal/device" 32 | ${extra_components_dirs_append}) 33 | 34 | project(light) 35 | 36 | # WARNING: This is just an example for using key for decrypting the encrypted OTA image 37 | # Please do not use it as is. 38 | if(CONFIG_ENABLE_ENCRYPTED_OTA) 39 | target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT) 40 | endif() 41 | 42 | if(CONFIG_IDF_TARGET_ESP32C2) 43 | include(relinker) 44 | endif() 45 | 46 | idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND) 47 | idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND) 48 | # For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various 49 | # flags that depend on -Wformat 50 | idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND) 51 | -------------------------------------------------------------------------------- /empty-template/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.29) 4 | 5 | if(NOT DEFINED ENV{ESP_MATTER_PATH}) 6 | message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo") 7 | endif(NOT DEFINED ENV{ESP_MATTER_PATH}) 8 | 9 | if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 10 | if("${IDF_TARGET}" STREQUAL "esp32c6" OR "${IDF_TARGET}" STREQUAL "") 11 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c) 12 | else() 13 | message(FATAL_ERROR "Unsupported IDF_TARGET") 14 | endif() 15 | endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 16 | 17 | set(PROJECT_VER "1.0") 18 | set(PROJECT_VER_NUMBER 1) 19 | 20 | set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH}) 21 | set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip) 22 | 23 | # This should be done before using the IDF_TARGET variable. 24 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 25 | include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake) 26 | 27 | set(EXTRA_COMPONENT_DIRS 28 | "${ESP_MATTER_PATH}/examples/common" 29 | "${MATTER_SDK_PATH}/config/esp32/components" 30 | "${ESP_MATTER_PATH}/components" 31 | "${ESP_MATTER_PATH}/device_hal/device" 32 | ${extra_components_dirs_append}) 33 | 34 | project(light) 35 | 36 | # WARNING: This is just an example for using key for decrypting the encrypted OTA image 37 | # Please do not use it as is. 38 | if(CONFIG_ENABLE_ENCRYPTED_OTA) 39 | target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT) 40 | endif() 41 | 42 | if(CONFIG_IDF_TARGET_ESP32C2) 43 | include(relinker) 44 | endif() 45 | 46 | idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND) 47 | idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND) 48 | # For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various 49 | # flags that depend on -Wformat 50 | idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND) 51 | -------------------------------------------------------------------------------- /smart-light/main/Main.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | @_cdecl("app_main") 13 | func main() { 14 | print("🏎️ Hello, Embedded Swift! (Smart Light)") 15 | 16 | let led = LED() 17 | 18 | // (1) Create a Matter root node 19 | let rootNode = Matter.Node() 20 | rootNode.identifyHandler = { 21 | print("identify") 22 | } 23 | 24 | // (2) Create a "light" endpoint 25 | let lightEndpoint = Matter.ExtendedColorLight(node: rootNode) 26 | lightEndpoint.eventHandler = { event in 27 | print("lightEndpoint.eventHandler:") 28 | print(event.attribute) 29 | print(event.value) 30 | 31 | switch event.attribute { 32 | case .onOff: 33 | led.enabled = (event.value == 1) 34 | 35 | case .levelControl: 36 | led.brightness = Int(Float(event.value) / 255.0 * 100.0) 37 | 38 | case .colorControl(.currentHue): 39 | let newHue = Int(Float(event.value) / 255.0 * 360.0) 40 | led.color = .hueSaturation(newHue, led.color.saturation) 41 | 42 | case .colorControl(.currentSaturation): 43 | let newSaturation = Int(Float(event.value) / 255.0 * 100.0) 44 | led.color = .hueSaturation(led.color.hue, newSaturation) 45 | 46 | case .colorControl(.colorTemperatureMireds): 47 | let kelvins = 1_000_000 / event.value 48 | led.color = .temperature(kelvins) 49 | 50 | default: 51 | break 52 | } 53 | } 54 | 55 | // (3) Add the endpoint to the node 56 | rootNode.addEndpoint(lightEndpoint) 57 | 58 | // (4) Provide the node to a Matter application and start it 59 | let app = Matter.Application() 60 | app.rootNode = rootNode 61 | app.start() 62 | 63 | // Keep local variables alive. Workaround for issue #10 64 | // https://github.com/apple/swift-matter-examples/issues/10 65 | while true { 66 | sleep(1) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /smart-light/Matter/Attribute.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | protocol MatterAttribute { 13 | var attribute: UnsafeMutablePointer { get } 14 | 15 | init(attribute: UnsafeMutablePointer) 16 | } 17 | 18 | extension MatterAttribute { 19 | var value: esp_matter_attr_val_t { 20 | var val = esp_matter_attr_val_t() 21 | esp_matter.attribute.get_val(attribute, &val) 22 | return val 23 | } 24 | } 25 | 26 | enum MatterAttributeEvent: esp_matter.attribute.callback_type_t.RawValue { 27 | case willSet = 0 28 | case didSet = 1 29 | case read = 2 30 | case write = 3 31 | 32 | var description: StaticString { 33 | switch self { 34 | case .willSet: "willSet" 35 | case .didSet: "didSet" 36 | case .read: "read" 37 | case .write: "write" 38 | } 39 | } 40 | } 41 | 42 | func print(_ e: MatterAttributeEvent) { 43 | print(e.description) 44 | } 45 | 46 | protocol MatterAttributeID: RawRepresentable where RawValue == UInt32 { 47 | associatedtype Attribute: MatterAttribute 48 | } 49 | 50 | extension LevelControl { 51 | struct CurrentLevel: MatterAttribute { 52 | var attribute: UnsafeMutablePointer 53 | } 54 | } 55 | 56 | extension ColorControl { 57 | struct CurrentHue: MatterAttribute { 58 | var attribute: UnsafeMutablePointer 59 | } 60 | 61 | struct CurrentSaturation: MatterAttribute { 62 | var attribute: UnsafeMutablePointer 63 | } 64 | 65 | struct CurrentX: MatterAttribute { 66 | var attribute: UnsafeMutablePointer 67 | } 68 | 69 | struct CurrentY: MatterAttribute { 70 | var attribute: UnsafeMutablePointer 71 | } 72 | 73 | struct ColorTemperatureMireds: MatterAttribute { 74 | var attribute: UnsafeMutablePointer 75 | } 76 | 77 | struct ColorMode: MatterAttribute { 78 | var attribute: UnsafeMutablePointer 79 | } 80 | } 81 | 82 | extension OnOff { 83 | struct OnOffState: MatterAttribute { 84 | var attribute: UnsafeMutablePointer 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /.swift-format: -------------------------------------------------------------------------------- 1 | { 2 | "fileScopedDeclarationPrivacy" : { 3 | "accessLevel" : "private" 4 | }, 5 | "indentation" : { 6 | "spaces" : 2 7 | }, 8 | "indentConditionalCompilationBlocks" : false, 9 | "indentSwitchCaseLabels" : false, 10 | "lineBreakAroundMultilineExpressionChainComponents" : false, 11 | "lineBreakBeforeControlFlowKeywords" : false, 12 | "lineBreakBeforeEachArgument" : false, 13 | "lineBreakBeforeEachGenericRequirement" : false, 14 | "lineLength" : 80, 15 | "maximumBlankLines" : 1, 16 | "multiElementCollectionTrailingCommas" : true, 17 | "noAssignmentInExpressions" : { 18 | "allowedFunctions" : [ 19 | "XCTAssertNoThrow" 20 | ] 21 | }, 22 | "prioritizeKeepingFunctionOutputTogether" : false, 23 | "respectsExistingLineBreaks" : true, 24 | "rules" : { 25 | "AllPublicDeclarationsHaveDocumentation" : false, 26 | "AlwaysUseLiteralForEmptyCollectionInit" : true, 27 | "AlwaysUseLowerCamelCase" : true, 28 | "AmbiguousTrailingClosureOverload" : false, 29 | "BeginDocumentationCommentWithOneLineSummary" : true, 30 | "DoNotUseSemicolons" : true, 31 | "DontRepeatTypeInStaticProperties" : true, 32 | "FileScopedDeclarationPrivacy" : true, 33 | "FullyIndirectEnum" : true, 34 | "GroupNumericLiterals" : true, 35 | "IdentifiersMustBeASCII" : true, 36 | "NeverForceUnwrap" : true, 37 | "NeverUseForceTry" : true, 38 | "NeverUseImplicitlyUnwrappedOptionals" : true, 39 | "NoAccessLevelOnExtensionDeclaration" : true, 40 | "NoAssignmentInExpressions" : true, 41 | "NoBlockComments" : true, 42 | "NoCasesWithOnlyFallthrough" : true, 43 | "NoEmptyTrailingClosureParentheses" : true, 44 | "NoLabelsInCasePatterns" : true, 45 | "NoLeadingUnderscores" : false, 46 | "NoParensAroundConditions" : true, 47 | "NoPlaygroundLiterals" : true, 48 | "NoVoidReturnOnFunctionSignature" : true, 49 | "OmitExplicitReturns" : true, 50 | "OneCasePerLine" : true, 51 | "OneVariableDeclarationPerLine" : true, 52 | "OnlyOneTrailingClosureArgument" : true, 53 | "OrderedImports" : true, 54 | "ReplaceForEachWithForLoop" : true, 55 | "ReturnVoidInsteadOfEmptyTuple" : true, 56 | "TypeNamesShouldBeCapitalized" : true, 57 | "UseEarlyExits" : false, 58 | "UseExplicitNilCheckInConditions" : true, 59 | "UseLetInEveryBoundCaseVariable" : true, 60 | "UseShorthandTypeNames" : true, 61 | "UseSingleLinePropertyGetter" : true, 62 | "UseSynthesizedInitializer" : true, 63 | "UseTripleSlashForDocumentationComments" : true, 64 | "UseWhereClausesInForLoops" : false, 65 | "ValidateDocumentationComments" : true 66 | }, 67 | "spacesBeforeEndOfLineComments": 2, 68 | "spacesAroundRangeFormationOperators" : false, 69 | "tabWidth" : 2, 70 | "version" : 1 71 | } 72 | -------------------------------------------------------------------------------- /smart-light/main/LED.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // Helper object that can be used to control the ESP32C6 on-board LED. Settings 13 | // the `enabled`, `brightness`, `color` properties immediately propagates those 14 | // to the physical LED. 15 | final class LED { 16 | // Whether the LED should be turned on 17 | var enabled: Bool = true { 18 | didSet { 19 | led_driver_set_power(handle, enabled) 20 | } 21 | } 22 | 23 | // Brightness of the LED 24 | var brightness: Int = 100 { 25 | didSet { 26 | brightness = max(0, min(100, brightness)) 27 | led_driver_set_brightness(handle, UInt8(brightness)) 28 | } 29 | } 30 | 31 | // Color of the LED 32 | var color: Color = .hueSaturation(0, 100) { 33 | didSet { 34 | switch color { 35 | case .hueSaturation(let hue, let saturation): 36 | led_driver_set_hue(handle, UInt16(hue)) 37 | led_driver_set_saturation(handle, UInt8(saturation)) 38 | case .temperature(let temperature): 39 | led_driver_set_temperature(handle, UInt32(temperature)) 40 | } 41 | } 42 | } 43 | 44 | // Color, represented as either "hue + saturation", or temperature. 45 | enum Color { 46 | // "Hue + saturation" color representation. Hue range is 0 ..< 360. 47 | // Saturation is 0 ... 100. 48 | case hueSaturation(Int, Int) 49 | 50 | // Temperature color representation in Kelvins (range 600 ... 10000). 51 | case temperature(Int) 52 | 53 | // Hue range is 0 ..< 360. 54 | var hue: Int { 55 | switch self { 56 | case .hueSaturation(let hue, _): return hue 57 | case .temperature: return 0 58 | } 59 | } 60 | 61 | // Saturation is 0 ... 100. 62 | var saturation: Int { 63 | switch self { 64 | case .hueSaturation(_, let saturation): return saturation 65 | case .temperature: return 0 66 | } 67 | } 68 | } 69 | 70 | var handle: led_driver_handle_t 71 | 72 | init() { 73 | var config = led_driver_get_config() 74 | let handle = led_driver_init(&config) 75 | guard let handle else { fatalError("Failed to initialize handle") } 76 | led_driver_set_power(handle, true) 77 | self.handle = handle 78 | } 79 | 80 | } 81 | 82 | extension LED.Color { 83 | static var red: LED.Color { .hueSaturation(0, 100) } 84 | static var blue: LED.Color { .hueSaturation(240, 100) } 85 | } 86 | -------------------------------------------------------------------------------- /led-blink/main/LED.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | // Helper object that can be used to control the ESP32C6 on-board LED. Settings 13 | // the `enabled`, `brightness`, `color` properties immediately propagates those 14 | // to the physical LED. 15 | final class LED { 16 | // Whether the LED should be turned on 17 | var enabled: Bool = true { 18 | didSet { 19 | led_driver_set_power(handle, enabled) 20 | } 21 | } 22 | 23 | // Brightness of the LED 24 | var brightness: Int = 100 { 25 | didSet { 26 | brightness = max(0, min(100, brightness)) 27 | led_driver_set_brightness(handle, UInt8(brightness)) 28 | } 29 | } 30 | 31 | // Color of the LED 32 | var color: Color = .hueSaturation(0, 100) { 33 | didSet { 34 | switch color { 35 | case .hueSaturation(let hue, let saturation): 36 | led_driver_set_hue(handle, UInt16(hue)) 37 | led_driver_set_saturation(handle, UInt8(saturation)) 38 | case .temperature(let temperature): 39 | led_driver_set_temperature(handle, UInt32(temperature)) 40 | } 41 | } 42 | } 43 | 44 | // Color, represented as either "hue + saturation", or temperature. 45 | enum Color { 46 | // "Hue + saturation" color representation. Hue range is 0 ..< 360. 47 | // Saturation is 0 ... 100. 48 | case hueSaturation(Int, Int) 49 | 50 | // Temperature color representation in Kelvins (range 600 ... 10000). 51 | case temperature(Int) 52 | 53 | // Hue range is 0 ..< 360. 54 | var hue: Int { 55 | switch self { 56 | case .hueSaturation(let hue, _): return hue 57 | case .temperature: return 0 58 | } 59 | } 60 | 61 | // Saturation is 0 ... 100. 62 | var saturation: Int { 63 | switch self { 64 | case .hueSaturation(_, let saturation): return saturation 65 | case .temperature: return 0 66 | } 67 | } 68 | } 69 | 70 | var handle: led_driver_handle_t 71 | 72 | init() { 73 | var config = led_driver_get_config() 74 | let handle = led_driver_init(&config) 75 | guard let handle else { fatalError("Failed to initialize handle") } 76 | led_driver_set_power(handle, true) 77 | self.handle = handle 78 | } 79 | 80 | } 81 | 82 | extension LED.Color { 83 | static var green: LED.Color { .hueSaturation(120, 100) } 84 | static var red: LED.Color { .hueSaturation(0, 100) } 85 | static var blue: LED.Color { .hueSaturation(240, 100) } 86 | } 87 | -------------------------------------------------------------------------------- /smart-light/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.29) 4 | 5 | if(NOT DEFINED ENV{ESP_MATTER_PATH}) 6 | message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo") 7 | endif(NOT DEFINED ENV{ESP_MATTER_PATH}) 8 | 9 | if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 10 | if("${IDF_TARGET}" STREQUAL "esp32" OR "${IDF_TARGET}" STREQUAL "") 11 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32_devkit_c) 12 | elseif("${IDF_TARGET}" STREQUAL "esp32c3") 13 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c3_devkit_m) 14 | elseif("${IDF_TARGET}" STREQUAL "esp32c2") 15 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m) 16 | elseif("${IDF_TARGET}" STREQUAL "esp32h2") 17 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32h2_devkit_c) 18 | elseif("${IDF_TARGET}" STREQUAL "esp32s3") 19 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32s3_devkit_c) 20 | elseif("${IDF_TARGET}" STREQUAL "esp32c6") 21 | set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c) 22 | else() 23 | message(FATAL_ERROR "Unsupported IDF_TARGET") 24 | endif() 25 | endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH}) 26 | 27 | set(PROJECT_VER "1.0") 28 | set(PROJECT_VER_NUMBER 1) 29 | 30 | set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH}) 31 | set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip) 32 | 33 | # This should be done before using the IDF_TARGET variable. 34 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 35 | include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake) 36 | 37 | set(EXTRA_COMPONENT_DIRS 38 | "${ESP_MATTER_PATH}/examples/common" 39 | "${MATTER_SDK_PATH}/config/esp32/components" 40 | "${ESP_MATTER_PATH}/components" 41 | "${ESP_MATTER_PATH}/device_hal/device" 42 | ${extra_components_dirs_append}) 43 | 44 | project(light) 45 | 46 | # WARNING: This is just an example for using key for decrypting the encrypted OTA image 47 | # Please do not use it as is. 48 | if(CONFIG_ENABLE_ENCRYPTED_OTA) 49 | target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT) 50 | endif() 51 | 52 | if(CONFIG_IDF_TARGET_ESP32C2) 53 | include(relinker) 54 | endif() 55 | 56 | idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND) 57 | idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND) 58 | # For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various 59 | # flags that depend on -Wformat 60 | idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND) 61 | -------------------------------------------------------------------------------- /led-blink/README.md: -------------------------------------------------------------------------------- 1 | # Embedded Swift Matter Example: Blinking LED template 2 | 3 | This directory contains a template for blinking an LED in Embedded Swift, and it can be built using the ESP IDF, and uploaded to an ESP32C6 development board. 4 | 5 | Breakdown of the files included: 6 | 7 | - **CMakeLists.txt** — Top-level CMake configuration file for the example, similar to the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light), with the minimum CMake version increased to 3.29 as required by Swift. 8 | - **partitions.csv** — Partition table for the firmware. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 9 | - **README.md** — This documentation file. 10 | - **sdkconfig.defaults** — Compile-time settings for the ESP IDF. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 11 | - **main/** — Subdirectory with actual source files to build. 12 | - **main/BridgingHeader.h** — A bridging header that imports C and C++ declarations from ESP IDF and ESP Matter SDKs into Swift. 13 | - **main/CmakeLists.txt** — CMake configuration describing what files to build and how. This includes a lot of Embedded Swift specific logic (e.g. Swift compiler flags). 14 | - **main/idf_component.yml** — Dependency list for the IDF Component Manager. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 15 | - **main/LED.swift** — Implementation of a helper "LED" object in Embedded Swift. 16 | - **main/Main.swift** — Main file with Embedded Swift application source code. 17 | 18 | ## Building and running the example 19 | 20 | For full steps how to build the example code, follow the [Setup Your Environment](https://apple.github.io/swift-matter-examples/tutorials/tutorial-table-of-contents#setup-your-environment) tutorials and the [Explore the LED Blink example](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-led-blink) tutorial. In summary: 21 | 22 | - Ensure your system has all the required software installed and your shell has access to the tools listed in the top-level README file. 23 | - Plug in the ESP32C6 development board via a USB cable. 24 | 25 | 1. Clone the repository and navigate to the `led-blink` example. 26 | ```shell 27 | $ git clone https://github.com/apple/swift-matter-examples.git 28 | $ cd swift-matter-examples/led-blink 29 | ``` 30 | 31 | 2. Configure the build system for your microcontroller. 32 | ```shell 33 | $ idf.py set-target esp32c6 34 | ``` 35 | 36 | 3. Build and deploy the application to your device. 37 | ```shell 38 | $ idf.py build flash monitor 39 | ``` 40 | 41 | 4. Observe that after the firmware starts up, the on-board LED is blinking and changing colors randomly. 42 | 43 | 5. Explore the implementation, see [Understand the code](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-led-blink#Understand-the-code) for a guided walkthrough. 44 | -------------------------------------------------------------------------------- /empty-template/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Register the app as an IDF component 2 | idf_component_register( 3 | SRCS /dev/null # We don't have any C++ sources 4 | PRIV_INCLUDE_DIRS "." 5 | ) 6 | 7 | # Clear the default COMPILE_OPTIONS which include a lot of C/C++ specific compiler flags that the Swift compiler will not accept 8 | get_target_property(var ${COMPONENT_LIB} COMPILE_OPTIONS) 9 | set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_OPTIONS "") 10 | 11 | set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) 12 | target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") 13 | 14 | # Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header). 15 | set(SWIFT_INCLUDES) 16 | foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) 17 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 18 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 19 | endforeach() 20 | foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) 21 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 22 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 23 | endforeach() 24 | 25 | # Swift compiler flags to build in Embedded Swift mode, optimize for size, choose the right ISA, ABI, C++ language standard, etc. 26 | target_compile_options(${COMPONENT_LIB} PUBLIC "$<$:SHELL: 27 | -target riscv32-none-none-eabi 28 | -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library -Osize 29 | -color-diagnostics 30 | -Xcc -DCHIP_HAVE_CONFIG_H 31 | -Xcc -std=c++17 32 | -cxx-interoperability-mode=default 33 | -Xcc -fno-exceptions 34 | -Xcc -fno-rtti 35 | 36 | -Xcc -DESP_PLATFORM 37 | -Xcc -DIDF_VER=\"v5.3-dev-2815-gbe06a6f5ff-dirty\" 38 | -Xcc -DLV_CONF_INCLUDE_SIMPLE 39 | -Xcc -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" 40 | -Xcc -DMD5_ENABLED=1 41 | -Xcc -DSERIAL_FLASHER_BOOT_HOLD_TIME_MS=50 42 | -Xcc -DSERIAL_FLASHER_RESET_HOLD_TIME_MS=100 43 | -Xcc -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE 44 | -Xcc -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ 45 | -Xcc -DUNITY_INCLUDE_CONFIG_H 46 | -Xcc -D_GLIBCXX_HAVE_POSIX_SEMAPHORE 47 | -Xcc -D_GLIBCXX_USE_POSIX_SEMAPHORE 48 | -Xcc -D_POSIX_READER_WRITER_LOCKS 49 | 50 | -pch-output-dir /tmp 51 | -Xfrontend -enable-single-module-llvm-emission 52 | 53 | ${SWIFT_INCLUDES} 54 | 55 | -import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h 56 | >") 57 | 58 | # Enable Swift support in CMake, force Whole Module builds (required by Embedded Swift), and use "CMAKE_Swift_COMPILER_WORKS" to 59 | # skip the trial compilations which don't (yet) correctly work when cross-compiling. 60 | set(CMAKE_Swift_COMPILER_WORKS YES) 61 | set(CMAKE_Swift_COMPILATION_MODE_DEFAULT wholemodule) 62 | set(CMAKE_Swift_COMPILATION_MODE wholemodule) 63 | enable_language(Swift) 64 | 65 | # List of Swift source files to build. 66 | target_sources(${COMPONENT_LIB} 67 | PRIVATE 68 | Main.swift 69 | ) 70 | -------------------------------------------------------------------------------- /led-blink/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Register the app as an IDF component 2 | idf_component_register( 3 | SRCS /dev/null # We don't have any C++ sources 4 | PRIV_INCLUDE_DIRS "." 5 | ) 6 | 7 | # Clear the default COMPILE_OPTIONS which include a lot of C/C++ specific compiler flags that the Swift compiler will not accept 8 | get_target_property(var ${COMPONENT_LIB} COMPILE_OPTIONS) 9 | set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_OPTIONS "") 10 | 11 | set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) 12 | target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") 13 | 14 | # Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header). 15 | set(SWIFT_INCLUDES) 16 | foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) 17 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 18 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 19 | endforeach() 20 | foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) 21 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 22 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 23 | endforeach() 24 | 25 | # Swift compiler flags to build in Embedded Swift mode, optimize for size, choose the right ISA, ABI, C++ language standard, etc. 26 | target_compile_options(${COMPONENT_LIB} PUBLIC "$<$:SHELL: 27 | -target riscv32-none-none-eabi 28 | -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library -Osize 29 | -color-diagnostics 30 | -Xcc -DCHIP_HAVE_CONFIG_H 31 | -Xcc -std=c++17 32 | -cxx-interoperability-mode=default 33 | -Xcc -fno-exceptions 34 | -Xcc -fno-rtti 35 | 36 | -Xcc -DESP_PLATFORM 37 | -Xcc -DIDF_VER=\"v5.3-dev-2815-gbe06a6f5ff-dirty\" 38 | -Xcc -DLV_CONF_INCLUDE_SIMPLE 39 | -Xcc -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" 40 | -Xcc -DMD5_ENABLED=1 41 | -Xcc -DSERIAL_FLASHER_BOOT_HOLD_TIME_MS=50 42 | -Xcc -DSERIAL_FLASHER_RESET_HOLD_TIME_MS=100 43 | -Xcc -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE 44 | -Xcc -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ 45 | -Xcc -DUNITY_INCLUDE_CONFIG_H 46 | -Xcc -D_GLIBCXX_HAVE_POSIX_SEMAPHORE 47 | -Xcc -D_GLIBCXX_USE_POSIX_SEMAPHORE 48 | -Xcc -D_POSIX_READER_WRITER_LOCKS 49 | 50 | -pch-output-dir /tmp 51 | -Xfrontend -enable-single-module-llvm-emission 52 | 53 | ${SWIFT_INCLUDES} 54 | 55 | -import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h 56 | >") 57 | 58 | # Enable Swift support in CMake, force Whole Module builds (required by Embedded Swift), and use "CMAKE_Swift_COMPILER_WORKS" to 59 | # skip the trial compilations which don't (yet) correctly work when cross-compiling. 60 | set(CMAKE_Swift_COMPILER_WORKS YES) 61 | set(CMAKE_Swift_COMPILATION_MODE_DEFAULT wholemodule) 62 | set(CMAKE_Swift_COMPILATION_MODE wholemodule) 63 | enable_language(Swift) 64 | 65 | # List of Swift source files to build. 66 | target_sources(${COMPONENT_LIB} 67 | PRIVATE 68 | LED.swift 69 | Main.swift 70 | ) 71 | -------------------------------------------------------------------------------- /empty-template/README.md: -------------------------------------------------------------------------------- 1 | # Embedded Swift Matter Example: Empty application template 2 | 3 | > [!IMPORTANT] 4 | > We highly recommend following along with the [Explore the LED Blink example](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-led-blink) and [Explore the Smart Light example](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-smart-light) tutorials before using the empty application template. 5 | 6 | This directory contains the simplest empty template to start writing Embedded Swift that can be built using the ESP IDF, and uploaded to an ESP32C6 development board. 7 | 8 | Breakdown of the files included: 9 | 10 | - **CMakeLists.txt** — Top-level CMake configuration file for the example, similar to the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light), with the minimum CMake version increased to 3.29 as required by Swift. 11 | - **partitions.csv** — Partition table for the firmware. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 12 | - **README.md** — This documentation file. 13 | - **sdkconfig.defaults** — Compile-time settings for the ESP IDF. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 14 | - **main/** — Subdirectory with actual source files to build. 15 | - **main/BridgingHeader.h** — A bridging header that imports C and C++ declarations from ESP IDF and ESP Matter SDKs into Swift. 16 | - **main/CmakeLists.txt** — CMake configuration describing what files to build and how. This includes a lot of Embedded Swift specific logic (e.g. Swift compiler flags). 17 | - **main/idf_component.yml** — Dependency list for the IDF Component Manager. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 18 | - **main/Main.swift** — Main file with Embedded Swift source code. 19 | 20 | ## Building and running the example 21 | 22 | For full steps how to build the example code, follow the [Setup Your Environment](https://apple.github.io/swift-embedded/swift-matter-examples/tutorials/tutorial-table-of-contents#setup-your-environment) tutorials and the "Build and Run" section of the [Explore the LED Blink example](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-led-blink) tutorial. In summary: 23 | 24 | - Ensure your system has all the required software installed and your shell has access to the tools listed in the top-level README file. 25 | - Plug in the ESP32C6 development board via a USB cable. 26 | 27 | 1. Clone the repository and navigate to the `empty-template` example. 28 | ```shell 29 | $ git clone https://github.com/apple/swift-matter-examples.git 30 | $ cd swift-matter-examples/empty-template 31 | ``` 32 | 33 | 2. Configure the build system for your microcontroller. 34 | ```shell 35 | $ idf.py set-target esp32c6 36 | ``` 37 | 38 | 3. Build and deploy the application to your device. 39 | ```shell 40 | $ idf.py build flash monitor 41 | ``` 42 | 43 | 4. Observe that in the device logs, the log message from Embedded Swift shows up: 44 | ```shell 45 | 🏎️ Hello, Embedded Swift! 46 | ``` 47 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Tutorials/Setup-Docker.tutorial: -------------------------------------------------------------------------------- 1 | @Tutorial(time: 30) { 2 | @Intro(title: "Get started on a Linux Docker container") { 3 | Install the tools needed to build an ESP Matter accessory in a Docker container. 4 | } 5 | 6 | @Section(title: "Build the Docker image and tools") { 7 | @ContentAndMedia { 8 | > Important: Make sure you have at least 30 GB of free space on your host computer. 9 | } 10 | 11 | @Steps { 12 | @Step { 13 | If you don't have it yet, install Docker by following the [Get Docker](https://docs.docker.com/get-docker/) setup instructions. 14 | } 15 | 16 | @Step { 17 | Clone the swift-matter-examples repository. 18 | 19 | The `Dockerfile` in swift-matter-examples has all of the steps needed for a working build environment, many of which are the same steps described in the tutorial. 20 | 21 | @Code(name: "Setup.shell", file: "setup-docker-00.sh") 22 | } 23 | 24 | @Step { 25 | Use `docker build` to build and tag the image. 26 | 27 | Building the image may take a significant amount of time to download and build all the required dependencies. 28 | 29 | @Code(name: "Setup.shell", file: "setup-docker-01.sh", previousFile: "setup-docker-00.sh") 30 | } 31 | 32 | @Step { 33 | Install `esptool`, see [Using Remote Serial Port](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/tools/idf-docker-image.html#using-remote-serial-port) for installation instructions. 34 | 35 | The `esptool` package contains `esp_rfc2217_server`, a program needed to flash the microcontroller from a docker container. 36 | 37 | @Code(name: "Setup.shell", file: "setup-docker-02.sh", previousFile: "setup-docker-01.sh") 38 | } 39 | } 40 | } 41 | 42 | @Section(title: "Run the container") { 43 | @ContentAndMedia { 44 | Launch the docker container and forward access to your microcontroller to the container. 45 | } 46 | 47 | @Steps { 48 | @Step { 49 | Find your attached microcontroller; the microcontroller should appear as a special file with the format **`/dev/cu.usbserial-...`** on macOS and **`/dev/ttyUSB...`** on Linux. 50 | 51 | Ensure your microcontroller is connected over USB before looking for the device. 52 | 53 | @Code(name: "Setup.shell", file: "setup-docker-03.sh", previousFile: "setup-docker-02.sh") 54 | } 55 | 56 | @Step { 57 | Run `esp_rfc2217_server` on your host machine to proxy the microcontroller serial connection to docker, see [Using Remote Serial Port](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/tools/idf-docker-image.html#using-remote-serial-port) for instructions. 58 | 59 | @Code(name: "Setup.shell", file: "setup-docker-04.sh", previousFile: "setup-docker-03.sh") 60 | } 61 | 62 | @Step { 63 | In a new shell, launch the docker container from the previously built image. 64 | 65 | If you are running Docker on Linux you also need to add `--add-host=host.docker.internal:host-gateway` to the flags. 66 | 67 | > Important: Be sure to run the container from the root directory of swift-matter-examples. 68 | 69 | @Code(name: "Setup.shell", file: "setup-docker-05.sh", previousFile: "setup-docker-04.sh") 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /smart-light/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Register the app as an IDF component 2 | idf_component_register( 3 | SRCS "../Matter/MatterInterface.cpp" 4 | PRIV_INCLUDE_DIRS "." 5 | LDFRAGMENTS "linker.lf" 6 | ) 7 | 8 | # Clear the default COMPILE_OPTIONS which include a lot of C/C++ specific compiler flags that the Swift compiler will not accept 9 | get_target_property(var ${COMPONENT_LIB} COMPILE_OPTIONS) 10 | set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_OPTIONS "") 11 | 12 | set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) 13 | target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") 14 | 15 | # Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header). 16 | set(SWIFT_INCLUDES) 17 | foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) 18 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 19 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 20 | endforeach() 21 | foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) 22 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ") 23 | string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ") 24 | endforeach() 25 | 26 | # Set device-specific march/mabi flags 27 | idf_build_get_property(target IDF_TARGET) 28 | if(${target} STREQUAL "esp32c2" OR ${target} STREQUAL "esp32c3") 29 | set(march_flag "rv32imc_zicsr_zifencei") 30 | set(mabi_flag "ilp32") 31 | elseif(${target} STREQUAL "esp32p4") 32 | set(march_flag "rv32imafc_zicsr_zifencei") 33 | set(mabi_flag "ilp32f") 34 | else() 35 | set(march_flag "rv32imac_zicsr_zifencei") 36 | set(mabi_flag "ilp32") 37 | endif() 38 | 39 | # Swift compiler flags to build in Embedded Swift mode, optimize for size, choose the right ISA, ABI, C++ language standard, etc. 40 | target_compile_options(${COMPONENT_LIB} PUBLIC "$<$:SHELL: 41 | -target riscv32-none-none-eabi 42 | -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library -Osize 43 | -color-diagnostics 44 | -Xcc -DCHIP_HAVE_CONFIG_H 45 | -Xcc -std=c++17 46 | -cxx-interoperability-mode=default 47 | -Xcc -fno-exceptions 48 | -Xcc -fno-rtti 49 | 50 | -Xcc -DESP_PLATFORM 51 | -Xcc -DIDF_VER=\"v5.3-dev-2815-gbe06a6f5ff-dirty\" 52 | -Xcc -DLV_CONF_INCLUDE_SIMPLE 53 | -Xcc -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" 54 | -Xcc -DMD5_ENABLED=1 55 | -Xcc -DSERIAL_FLASHER_BOOT_HOLD_TIME_MS=50 56 | -Xcc -DSERIAL_FLASHER_RESET_HOLD_TIME_MS=100 57 | -Xcc -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE 58 | -Xcc -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ 59 | -Xcc -DUNITY_INCLUDE_CONFIG_H 60 | -Xcc -D_GLIBCXX_HAVE_POSIX_SEMAPHORE 61 | -Xcc -D_GLIBCXX_USE_POSIX_SEMAPHORE 62 | -Xcc -D_POSIX_READER_WRITER_LOCKS 63 | -Xcc -march=${march_flag} 64 | -Xcc -mabi=${mabi_flag} 65 | 66 | -pch-output-dir /tmp 67 | -Xfrontend -enable-single-module-llvm-emission 68 | 69 | ${SWIFT_INCLUDES} 70 | 71 | -import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h 72 | >") 73 | 74 | # Enable Swift support in CMake, force Whole Module builds (required by Embedded Swift), and use "CMAKE_Swift_COMPILER_WORKS" to 75 | # skip the trial compilations which don't (yet) correctly work when cross-compiling. 76 | set(CMAKE_Swift_COMPILER_WORKS YES) 77 | set(CMAKE_Swift_COMPILATION_MODE_DEFAULT wholemodule) 78 | set(CMAKE_Swift_COMPILATION_MODE wholemodule) 79 | enable_language(Swift) 80 | 81 | # List of Swift source files to build. 82 | target_sources(${COMPONENT_LIB} 83 | PRIVATE 84 | Main.swift 85 | LED.swift 86 | ../Matter/Attribute.swift 87 | ../Matter/Clusters.swift 88 | ../Matter/Matter.swift 89 | ../Matter/Node.swift 90 | ) 91 | -------------------------------------------------------------------------------- /smart-light/README.md: -------------------------------------------------------------------------------- 1 | # Embedded Swift Matter Example: Smart Light example 2 | 3 | This directory contains an example implementation of a Matter smart LED light accessory in Embedded Swift, and it can be built using the ESP IDF and ESP Matter SDKs, and uploaded to an ESP32C6 or ESP32C3 development board. 4 | 5 | Breakdown of the files included: 6 | 7 | - **CMakeLists.txt** — Top-level CMake configuration file for the example, similar to the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light), with the minimum CMake version increased to 3.29 as required by Swift. 8 | - **partitions.csv** — Partition table for the firmware. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 9 | - **README.md** — This documentation file. 10 | - **sdkconfig.defaults** — Compile-time settings for the ESP IDF. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 11 | - **main/** — Subdirectory with actual source files to build. 12 | - **main/BridgingHeader.h** — A bridging header that imports C and C++ declarations from ESP IDF and ESP Matter SDKs into Swift. 13 | - **main/CmakeLists.txt** — CMake configuration describing what files to build and how. This includes a lot of Embedded Swift specific logic (e.g. Swift compiler flags). 14 | - **main/idf_component.yml** — Dependency list for the IDF Component Manager. Same as the ["light" example from the ESP Matter SDK](https://github.com/espressif/esp-matter/tree/main/examples/light). 15 | - **main/LED.swift** — Implementation of a helper "LED" object in Embedded Swift. 16 | - **main/Main.swift** — Main file with Embedded Swift application source code. 17 | - **Matter/** — Subdirectory with a simple (incomplete) Matter overlay to bridge C++ Matter APIs into Swift 18 | - **Matter/Attribute.swift** — Low-level overlay code for Matter attributes. 19 | - **Matter/Clusters.swift** — Low-level overlay code for Matter clusters. 20 | - **Matter/Matter.swift** — High-level Matter overlay code. 21 | - **Matter/MatterInterface.cpp** — Helper C++ code for interoperating with Matter C++ APIs. 22 | - **Matter/MatterInterface.h** — Helper C++ code for interoperating with Matter C++ APIs. 23 | - **Matter/Node.swift** — Low-level overlay code for Matter nodes. 24 | 25 | ## Building and running the example 26 | 27 | For full steps how to build the example code, follow the [Setup Your Environment](https://apple.github.io/swift-embedded/swift-matter-examples/tutorials/tutorial-table-of-contents#setup-your-environment) tutorials and the [Explore the Smart Light example](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-smart-light) tutorial. In summary: 28 | 29 | - Ensure your system has all the required software installed and your shell has access to the tools listed in the top-level README file. 30 | - Plug in the ESP32C6/C3 development board via a USB cable. 31 | - Have a set up HomeKit or other Matter-enabled smart home ecosystem. 32 | - For HomeKit, this includes a configured home, a Wi-Fi network which additional devices can join, a [home hub](https://support.apple.com/en-us/102557), and an iOS device for managing the home. 33 | 34 | 1. Clone the repository and navigate to the `smart-light` example. 35 | ```shell 36 | $ git clone https://github.com/apple/swift-matter-examples.git 37 | $ cd swift-matter-examples/smart-light 38 | ``` 39 | 40 | 2. Configure the build system for your microcontroller, this example should also be runnable on `esp32c3`. 41 | ```shell 42 | $ idf.py set-target esp32c6 43 | ``` 44 | 45 | 3. Build and deploy the application to your device. 46 | ```shell 47 | $ idf.py build flash monitor 48 | ``` 49 | 50 | 4. Register the device in your home network. See [Connect-using-Matter](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-smart-light#Connect-using-Matter) for detailed pairing instructions with HomeKit. 51 | 52 | 5. You can now control the smart light. In case of a HomeKit network, the Home app, and Siri can both be used to turn the light on, off, change colors, etc. 53 | 54 | 6. Explore the implementation, see [Understand the code](https://apple.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-smart-light#Understand-the-code) for a guided walkthrough. 55 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Tutorials/Run-Example-LED-Blink.tutorial: -------------------------------------------------------------------------------- 1 | @Tutorial(time: 10) { 2 | @Intro(title: "Explore the LED Blink example") { 3 | Build, run, and understand the LED Blink application. 4 | } 5 | 6 | @Section(title: "Build and Run") { 7 | @ContentAndMedia { 8 | Build the LED Blink application and run it on your microcontroller. 9 | } 10 | 11 | @Steps { 12 | @Step { 13 | Connect your ESP32-C6 microcontroller to your host machine over USB using the USB Type-C connector closest to the RGB LED. 14 | 15 | @Image(source: "esp32-c6-usb.png", alt: "FIXME-ALT.") 16 | } 17 | 18 | @Step { 19 | If you don't have it yet, clone the `swift-matter-examples` repository. 20 | 21 | @Code(name: "Run.shell", file: "run-example-led-blink-00.sh") 22 | } 23 | 24 | @Step { 25 | Navigate to the led-blink example. 26 | 27 | @Code(name: "Run.shell", file: "run-example-led-blink-01.sh", previousFile: "run-example-led-blink-00.sh") 28 | } 29 | 30 | @Step { 31 | Use **idf.py** to configure example for the ESP32-C6 microcontroller. 32 | 33 | @Code(name: "Run.shell", file: "run-example-led-blink-02.sh", previousFile: "run-example-led-blink-01.sh") 34 | } 35 | 36 | @Step { 37 | Use **idf.py** to build the application. 38 | 39 | @Code(name: "Run.shell", file: "run-example-led-blink-03.sh", previousFile: "run-example-led-blink-02.sh") 40 | } 41 | 42 | @Step { 43 | Use **idf.py** to flash the application onto your microcontroller. 44 | 45 | > Important: Use **`Ctrl + ]`** to exit the monitor program. 46 | 47 | @Code(name: "Run.shell", file: "run-example-led-blink-04.sh", previousFile: "run-example-led-blink-03.sh") 48 | } 49 | 50 | @Step { 51 | After flashing completes, you should see the microcontroller begin to blink its LED once per second changing to a random color each time. 52 | 53 | Additionally, you should see `🏎️ Hello, Embedded Swift! (LED Blink)` in the monitor log followed by logs indicating the LED is changing colors. 54 | 55 | @Image(source: "run-example-led-blink-hello.png", alt: "FIXME-ALT.") 56 | } 57 | } 58 | } 59 | 60 | @Section(title: "Understand the code") { 61 | @ContentAndMedia { 62 | Take a brief tour of the code that composes the LED Blink example. 63 | } 64 | 65 | @Steps { 66 | @Step { 67 | We start the application by declaring an **`main`** function with a print statement to show the application has started. 68 | 69 | @Code(name: "Main.swift", file: "walkthrough-example-led-blink-01.swift", previousFile: "walkthrough-example-led-blink-00.swift") 70 | } 71 | 72 | @Step { 73 | We use the **`@_cdecl("app_main")`** attribute to generate a wrapper C symbol which is expected by ESP IDF. 74 | 75 | > Important: Underscored attributes, like `@_cdecl`, are unstable features of the Swift compiler and may change behavior or break between compiler versions. 76 | 77 | @Code(name: "Main.swift", file: "walkthrough-example-led-blink-02.swift", previousFile: "walkthrough-example-led-blink-01.swift") 78 | } 79 | 80 | @Step { 81 | We then declare an **`led`** variable of type **`LED`** to control the hardware RGB LED on the microcontroller. 82 | 83 | @Code(name: "Main.swift", file: "walkthrough-example-led-blink-03.swift", previousFile: "walkthrough-example-led-blink-02.swift") 84 | } 85 | 86 | @Step { 87 | Diverting for a moment, "LED.swift" is a light-weight wrapper around ESP IDF functions. It defines an LED type to provide idiomatic Swift APIs for existing IDF functionality. 88 | 89 | Wrapping existing C APIs is a great way to make your code more readable and wrap potentially unsafe interfaces into safe ones. 90 | 91 | @Code(name: "LED.swift", file: "walkthrough-example-led-blink-led-01.swift", previousFile: "walkthrough-example-led-blink-led-00.swift") 92 | } 93 | 94 | @Step { 95 | Returning to "Main.swift", we next use the API provided by "LED.swift" to set the initial LED color to red and brightness to 10%. 96 | 97 | @Code(name: "Main.swift", file: "walkthrough-example-led-blink-04.swift", previousFile: "walkthrough-example-led-blink-03.swift") 98 | } 99 | 100 | @Step { 101 | Lastly, we create an infinite loop which waits 1 second before switching the led from on to off or vise-versa. Next, if the LED is on, we set LED to a random color. 102 | 103 | This loop creates the blinking behavior we observe on the microcontroller. 104 | 105 | @Code(name: "Main.swift", file: "walkthrough-example-led-blink-05.swift", previousFile: "walkthrough-example-led-blink-04.swift") 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift Matter Examples 2 | 3 | Build a Matter accessory using Embedded Swift 4 | 5 | ## Overview 6 | 7 | 8 | 9 | This repository contains an example simple Embedded Swift application that implements a Matter smart light accessory and can be used from HomeKit. The examples use an ESP32-C6 or ESP32-C3 (RISC-V) microcontroller and build on top of the ESP-IDF and ESP-Matter SDKs. 10 | 11 | > [!NOTE] 12 | > This repository is associated with WWDC24 session 10197: [Go small with Embedded Swift](https://developer.apple.com/wwdc24/10197). 13 | 14 | #### Embedded Swift 15 | 16 | Embedded Swift is a subset of Swift designed for constrained environments, such as embedded devices, kernel code, and other low-level systems. It includes most Swift language features, like generics, value and reference types, optionals, error handling, and more. Embedded Swift introduces the safety and expressivity of Swift to environments usually dominated by C or C++ code. To learn more, see [A Vision for Embedded Swift](https://github.com/swiftlang/swift-evolution/blob/main/visions/embedded-swift.md). 17 | 18 | #### Matter 19 | 20 | Matter is an open standard for building smart home accessories, supported natively by many smart home ecosystems such as HomeKit. For more information about Matter, see the [Matter documentation](https://project-chip.github.io/connectedhomeip-doc/index.html). 21 | 22 | #### Additional Resources 23 | 24 | - [Embedded Swift User Manual](https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md) 25 | - [More Embedded Swift Example Projects](https://github.com/swiftlang/swift-embedded-examples) 26 | - [Swift Forums Embedded Discussion](https://forums.swift.org/c/development/embedded/107) 27 | 28 | ## Getting Started 29 | 30 | ### Documentation 31 | 32 | For comprehensive tutorials with detailed instructions, please refer to the [**project documentation**](https://swiftlang.github.io/swift-matter-examples/tutorials/tutorial-table-of-contents). 33 | 34 | ### Requirements 35 | 36 | Before running the examples, ensure you have the following tools available: 37 | 38 | - Hardware: 39 | - [ESP32-C6-DevKitC-1-N8](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html) 40 | - Software 41 | - [Swift Nightly Toolchain](https://www.swift.org/download) 42 | - [CMake 3.29+](https://cmake.org/download) 43 | - [ESP-IDF v5.4.1](https://docs.espressif.com/projects/esp-idf/en/v5.4.1/esp32c6/get-started/index.html) 44 | - [ESP-Matter SDK 1.2](https://docs.espressif.com/projects/esp-matter/en/latest/esp32c6/introduction.html) 45 | 46 | > [!IMPORTANT] 47 | > The examples are designed for an Espressif C6 Development Kit from both macOS and Linux host systems. Other configurations may work, but have not been tested. 48 | 49 | ### Quick Start Guide 50 | 51 | > [!IMPORTANT] 52 | > We highly recommend following the provided [tutorials](https://swiftlang.github.io/swift-matter-examples/tutorials/tutorial-table-of-contents). 53 | 54 | Ensure your shell has access to the tools listed above, see [Get started on macOS](https://swiftlang.github.io/swift-matter-examples/tutorials/swiftmatterexamples/setup-macos) or [Get started on Linux with Docker](https://swiftlang.github.io/swift-matter-examples/tutorials/swiftmatterexamples/setup-docker) for additional setup instructions. 55 | 56 | 1. Clone the repository and navigate to one of the examples. 57 | ```shell 58 | $ git clone https://github.com/swiftlang/swift-matter-examples.git 59 | $ cd swift-matter-examples/smart-light 60 | ``` 61 | 62 | 2. Configure the build system for your microcontroller, the `smart-light` example should also be runnable on `esp32c3`. 63 | ```shell 64 | $ idf.py set-target esp32c6 65 | ``` 66 | 67 | 3. Build and deploy the application to your device. 68 | ```shell 69 | $ idf.py build flash monitor 70 | ``` 71 | 72 | Explore the implementation, see [Explore the LED Blink example](https://swiftlang.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-led-blink#Understand-the-code) and 73 | [Explore the Smart Light example](https://swiftlang.github.io/swift-matter-examples/tutorials/swiftmatterexamples/run-example-smart-light#Understand-the-code) for guided walkthroughs. 74 | 75 | ## Contributing to Swift Matter Examples 76 | 77 | This repo is intended to demonstrate use of Embedded Swift for different applications, using Matter as an example. PRs demonstrating ways to adapt Swift's language or tooling to this application are welcome. It is not intended to be a full-featured Matter SDK so please do not raise PRs to extend the Matter Swift overlay to new areas. 78 | 79 | ### Code of Conduct 80 | 81 | Like all Swift.org projects, we would like these Embedded Swift example projects to foster a diverse and friendly community. We expect contributors to adhere to the [Swift.org Code of Conduct](https://swift.org/code-of-conduct). 82 | 83 | ### Contact information 84 | 85 | The current code owners of this repository are Kuba Mracek ([@kubamracek](https://github.com/kubamracek)), Rauhul Varma ([@rauhul](https://github.com/rauhul)), and Philippe Hausler (https://github.com/phausler). You can contact them on the Swift forums via the handles [@kubamracek](https://forums.swift.org/u/kubamracek/summary), [@rauhul](https://forums.swift.org/u/rauhul/summary), and [@Philippe_Hausler](https://forums.swift.org/u/philippe_hausler/summary). 86 | 87 | In case of moderation issues, you can also directly contact a member of the [Swift Core Team](https://swift.org/community/#community-structure). 88 | -------------------------------------------------------------------------------- /smart-light/Matter/Node.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | protocol MatterNode { 13 | var node: UnsafeMutablePointer { get } 14 | } 15 | 16 | protocol MatterEndpoint { 17 | var endpoint: UnsafeMutablePointer { get } 18 | } 19 | 20 | protocol MatterConreteEndpoint: MatterEndpoint { 21 | static var deviceTypeId: UInt32 { get } 22 | 23 | init(_ endpoint: UnsafeMutablePointer) 24 | } 25 | 26 | extension MatterEndpoint { 27 | var id: UInt16 { esp_matter.endpoint.get_id(endpoint) } 28 | 29 | func cluster(_ id: ClusterID) -> Cluster { 30 | Cluster(esp_matter.cluster.get_shim(endpoint, id.rawValue)) 31 | } 32 | } 33 | 34 | struct RootNode: MatterNode { 35 | typealias AttributeCallback = ( 36 | MatterAttributeEvent, Endpoint, Cluster, UInt32, 37 | UnsafeMutablePointer? 38 | ) -> Void 39 | typealias IdentifyCallback = ( 40 | esp_matter.identification.callback_type_t, UInt16, UInt8, UInt8 41 | ) -> Void 42 | 43 | final class Context { 44 | var attribute: AttributeCallback 45 | var identify: IdentifyCallback 46 | 47 | init( 48 | attribute: @escaping AttributeCallback, 49 | identify: @escaping IdentifyCallback 50 | ) { 51 | self.attribute = attribute 52 | self.identify = identify 53 | } 54 | } 55 | 56 | var node: UnsafeMutablePointer 57 | let context: Context 58 | 59 | init?( 60 | attribute: @escaping AttributeCallback, identify: @escaping IdentifyCallback 61 | ) { 62 | var nodeConfig = esp_matter.node.config_t() 63 | esp_matter.attribute.set_callback_shim { 64 | type, endpoint, cluster, attribute, value, context in 65 | guard let context else { 66 | return ESP_OK 67 | } 68 | guard let e = Endpoint(id: endpoint) else { return ESP_OK } 69 | guard let c = Cluster(endpoint: e, id: cluster) else { return ESP_OK } 70 | guard let event = MatterAttributeEvent(rawValue: type.rawValue) else { 71 | fatalError("Unknown event type") 72 | } 73 | let ctx = Unmanaged.fromOpaque(context).takeUnretainedValue() 74 | ctx.attribute(event, e, c, attribute, value) 75 | return ESP_OK 76 | } 77 | esp_matter.identification.set_callback { 78 | type, endpoint, effect, variant, context in 79 | guard let context else { fatalError("context must be non-nil") } 80 | Unmanaged.fromOpaque(context).takeUnretainedValue().identify( 81 | type, endpoint, effect, variant) 82 | return ESP_OK 83 | } 84 | guard let node = esp_matter.node.create_raw() else { 85 | return nil 86 | } 87 | 88 | let context = Context(attribute: attribute, identify: identify) 89 | withUnsafeMutablePointer(to: &nodeConfig.root_node) { 90 | // Transfer ownership to the node. This is a leak for now, but we don't expect nodes to be created and destroyed repeatedly. 91 | _ = esp_matter.endpoint.root_node.create( 92 | node, $0, 0x00, Unmanaged.passRetained(context).toOpaque()) 93 | } 94 | self.node = node 95 | self.context = context 96 | } 97 | 98 | var endpoint: Endpoint { 99 | Endpoint(esp_matter.endpoint.get(node, 0)) 100 | } 101 | } 102 | 103 | struct Endpoint: MatterEndpoint { 104 | var endpoint: UnsafeMutablePointer 105 | 106 | init(_ endpoint: UnsafeMutablePointer) { 107 | self.endpoint = endpoint 108 | } 109 | 110 | init?(id: UInt16) { 111 | guard let root = esp_matter.node.get() else { return nil } 112 | guard let endpoint = esp_matter.endpoint.get(root, id) else { return nil } 113 | self.init(endpoint) 114 | } 115 | 116 | func `as`(_ type: T.Type) -> T? { 117 | var count = UInt8(0) 118 | let expected = T.deviceTypeId 119 | let ids = esp_matter.endpoint.get_device_type_ids(endpoint, &count) 120 | for id in UnsafeMutableBufferPointer(start: ids, count: Int(count)) { 121 | if id == expected { 122 | return T(endpoint) 123 | } 124 | } 125 | return nil 126 | } 127 | } 128 | 129 | struct MatterExtendedColorLight: MatterConreteEndpoint { 130 | static var deviceTypeId: UInt32 { 131 | esp_matter.endpoint.extended_color_light.get_device_type_id() 132 | } 133 | 134 | var endpoint: UnsafeMutablePointer 135 | 136 | init( 137 | _ node: RootNode, 138 | configuration: esp_matter.endpoint.extended_color_light.config_t 139 | ) { 140 | var config = configuration 141 | endpoint = esp_matter.endpoint.extended_color_light.create( 142 | node.node, &config, 0x00, Unmanaged.passRetained(node.context).toOpaque()) 143 | } 144 | 145 | init(_ endpoint: UnsafeMutablePointer) { 146 | self.endpoint = endpoint 147 | } 148 | 149 | var levelControl: LevelControl { 150 | cluster(.levelControl) 151 | } 152 | 153 | var colorControl: ColorControl { 154 | cluster(.colorControl) 155 | } 156 | 157 | var onOff: OnOff { 158 | cluster(.onOff) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /smart-light/Matter/Clusters.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | protocol MatterCluster { 13 | var cluster: UnsafeMutablePointer { get } 14 | 15 | init(_ cluster: UnsafeMutablePointer) 16 | } 17 | 18 | extension MatterCluster { 19 | init?(endpoint: some MatterEndpoint, id: UInt32) { 20 | guard let cluster = esp_matter.cluster.get_shim(endpoint.endpoint, id) 21 | else { 22 | return nil 23 | } 24 | self.init(cluster) 25 | } 26 | } 27 | 28 | protocol MatterConcreteCluster: MatterCluster { 29 | static var clusterTypeId: ClusterID { get } 30 | } 31 | 32 | struct ClusterID: RawRepresentable { 33 | var rawValue: UInt32 34 | 35 | static var identify: ClusterID { .init(rawValue: 0x0000_0003) } 36 | static var onOff: ClusterID { .init(rawValue: 0x0000_0006) } 37 | static var levelControl: ClusterID { 38 | .init(rawValue: 0x0000_0008) 39 | } 40 | static var colorControl: ClusterID { 41 | .init(rawValue: 0x0000_0300) 42 | } 43 | } 44 | 45 | struct Cluster: MatterCluster { 46 | var cluster: UnsafeMutablePointer 47 | 48 | init(_ cluster: UnsafeMutablePointer) { 49 | self.cluster = cluster 50 | } 51 | 52 | func `as`(_ type: T.Type) -> T? { 53 | let expected = T.clusterTypeId 54 | let id = esp_matter.cluster.get_id(cluster) 55 | if id == expected.rawValue { 56 | return T(cluster) 57 | } 58 | return nil 59 | } 60 | } 61 | 62 | struct Identify: MatterConcreteCluster { 63 | static var clusterTypeId: ClusterID { .identify } 64 | struct AttributeID: MatterAttributeID { 65 | var rawValue: UInt32 66 | } 67 | 68 | var cluster: UnsafeMutablePointer 69 | 70 | init(_ cluster: UnsafeMutablePointer) { 71 | self.cluster = cluster 72 | } 73 | 74 | func attribute(_ id: AttributeID) 75 | -> Attribute 76 | { 77 | Attribute(attribute: esp_matter.attribute.get_shim(cluster, id.rawValue)) 78 | } 79 | } 80 | 81 | struct OnOff: MatterConcreteCluster { 82 | static var clusterTypeId: ClusterID { .onOff } 83 | struct AttributeID: MatterAttributeID { 84 | var rawValue: UInt32 85 | 86 | static var state: AttributeID { .init(rawValue: 0x0000_0000) } 87 | } 88 | 89 | var cluster: UnsafeMutablePointer 90 | 91 | init(_ cluster: UnsafeMutablePointer) { 92 | self.cluster = cluster 93 | } 94 | 95 | func attribute(_ id: AttributeID) 96 | -> Attribute 97 | { 98 | Attribute(attribute: esp_matter.attribute.get_shim(cluster, id.rawValue)) 99 | } 100 | 101 | var state: OnOffState { attribute(.state) } 102 | } 103 | 104 | struct LevelControl: MatterConcreteCluster { 105 | static var clusterTypeId: ClusterID { .levelControl } 106 | struct AttributeID: MatterAttributeID { 107 | var rawValue: UInt32 108 | 109 | static var currentLevel: AttributeID { 110 | .init(rawValue: 0x0000_0000) 111 | } 112 | } 113 | 114 | var cluster: UnsafeMutablePointer 115 | 116 | init(_ cluster: UnsafeMutablePointer) { 117 | self.cluster = cluster 118 | } 119 | 120 | func attribute(_ id: AttributeID) 121 | -> Attribute 122 | { 123 | Attribute(attribute: esp_matter.attribute.get_shim(cluster, id.rawValue)) 124 | } 125 | 126 | var currentLevel: CurrentLevel { attribute(.currentLevel) } 127 | } 128 | 129 | struct ColorControl: MatterConcreteCluster { 130 | static var clusterTypeId: ClusterID { .colorControl } 131 | struct AttributeID: MatterAttributeID { 132 | var rawValue: UInt32 133 | 134 | static var currentHue: AttributeID { 135 | .init(rawValue: 0x0000_0000) 136 | } 137 | static var currentSaturation: AttributeID { 138 | .init(rawValue: 0x0000_0001) 139 | } 140 | static var currentX: AttributeID { .init(rawValue: 0x0000_0003) } 141 | static var currentY: AttributeID { .init(rawValue: 0x0000_0004) } 142 | static var colorTemperatureMireds: AttributeID { 143 | .init(rawValue: 0x0000_0007) 144 | } 145 | static var colorMode: AttributeID { 146 | .init(rawValue: 0x0000_0008) 147 | } 148 | } 149 | 150 | var cluster: UnsafeMutablePointer 151 | 152 | init(_ cluster: UnsafeMutablePointer) { 153 | self.cluster = cluster 154 | } 155 | 156 | func attribute(_ id: AttributeID) 157 | -> Attribute 158 | { 159 | Attribute(attribute: esp_matter.attribute.get_shim(cluster, id.rawValue)) 160 | } 161 | 162 | var currentHue: CurrentHue { attribute(.currentHue) } 163 | var currentSaturation: CurrentSaturation { attribute(.currentSaturation) } 164 | var currentX: CurrentX { attribute(.currentX) } 165 | var currentY: CurrentY { attribute(.currentY) } 166 | var colorTemperatureMireds: ColorTemperatureMireds { 167 | attribute(.colorTemperatureMireds) 168 | } 169 | var colorMode: ColorMode { attribute(.colorMode) } 170 | 171 | func add( 172 | _ config: esp_matter.cluster.color_control.feature.hue_saturation.config_t 173 | ) { 174 | var cfg = config 175 | esp_matter.cluster.color_control.feature.hue_saturation.add(cluster, &cfg) 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Tutorials/Setup-MacOS.tutorial: -------------------------------------------------------------------------------- 1 | @Tutorial(time: 30) { 2 | @Intro(title: "Get started on macOS") { 3 | Install the tools needed to build an ESP Matter accessory on macOS. 4 | } 5 | 6 | @Section(title: "Install Xcode") { 7 | @ContentAndMedia { 8 | Install Xcode to manage custom Swift toolchains. 9 | 10 | @Image(source: "xcode-logo.png", alt: "FIXME-ALT") 11 | } 12 | 13 | @Steps { 14 | @Step{ 15 | Navigate to [Xcode on the App store](https://apps.apple.com/us/app/xcode/id497799835) and select **Get** to download and install Xcode. 16 | 17 | @Image(source: "xcode-download.png", alt: "FIXME-ALT") 18 | } 19 | 20 | @Step { 21 | (Optional) Visit the [Xcode homepage](https://developer.apple.com/xcode/) to learn more about Xcode. 22 | 23 | @Image(source: "xcode-home.png", alt: "FIXME-ALT") 24 | } 25 | } 26 | } 27 | 28 | @Section(title: "Install the Swift Nightly Toolchain") { 29 | @ContentAndMedia { 30 | Embedded Swift requires a recent nightly version of the Swift toolchain. Learn how to download and install a nightly build of Swift. 31 | 32 | @Image(source: "swift-logo.png", alt: "FIXME-ALT") 33 | } 34 | 35 | @Steps { 36 | @Step { 37 | Navigate to the [Swift.org](https://www.swift.org/download/) downloads page. 38 | 39 | @Image(source: "swift-org-downloads.png", alt: "FIXME-ALT") 40 | } 41 | 42 | @Step { 43 | Scroll to the **Trunk Development (main)** subsection, and select **Xcode Universal** to download the latest Swift nightly toolchain. 44 | 45 | @Image(source: "swift-org-downloads-main.png", alt: "FIXME-ALT") 46 | } 47 | 48 | @Step { 49 | Open and install the downloaded **swift-DEVELOPMENT-SNAPSHOT-202X-XX-XX-a-osx.pkg**. 50 | 51 | Installing this package for **all users** requires administrative privileges and may open a password or Touch ID prompt. 52 | 53 | @Image(source: "swift-org-downloads-installer.png", alt: "FIXME-ALT") 54 | } 55 | 56 | @Step { 57 | Locate the installed toolchain. During the installation process, if you selected **Install for all users**, the toolchain should be installed under **`/Library/Developer/Toolchains`**, if you selected **Install for me only**, check **`~/Library/Developer/Toolchains`** instead. 58 | 59 | Make sure you see an **xctoolchain** file matching the name of the toolchain package in this directory. 60 | 61 | @Code(name: "Setup.shell", file: "install-swift-terminal-00.sh") 62 | } 63 | 64 | @Step { 65 | Find the toolchain's identifier with the **`plutil`** command and record the printed identifier. 66 | 67 | In this example the toolchain has the identifier "org.swift.59202406031a". 68 | 69 | @Code(name: "Setup.shell", file: "install-swift-terminal-01.sh", previousFile: "install-swift-terminal-00.sh") 70 | } 71 | 72 | @Step { 73 | Select the installed toolchain with the **`TOOLCHAINS`** environment variable and verify it works with the **`swift --version`** command. 74 | 75 | You should see a version string like **"Apple Swift version 6.0-dev"**. 76 | 77 | @Code(name: "Setup.shell", file: "install-swift-terminal-02.sh", previousFile: "install-swift-terminal-01.sh") 78 | } 79 | } 80 | } 81 | 82 | @Section(title: "Install ESP-IDF and ESP-Matter SDKs") { 83 | @ContentAndMedia { 84 | Install the tools and SDKs needed to build an ESP32-C6 Matter accessory. 85 | 86 | The steps here should be enough to get started quickly, but for additional detailed instructions see the official [ESP-IDF Setup](https://docs.espressif.com/projects/esp-idf/en/v5.4.1/esp32/get-started/linux-macos-setup.html) and [ESP-Matter Setup](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#esp-matter-setup) documentation. 87 | } 88 | 89 | @Steps { 90 | @Step { 91 | If you don't have it yet, install Homebrew by following the setup instructions on [the Brew homepage](https://brew.sh). 92 | 93 | @Code(name: "Setup.shell", file: "install-esp-terminal-00.sh") 94 | } 95 | 96 | @Step { 97 | Use `brew` to install the ESP SDK dependencies: CMake, Ninja, and dfu-util. 98 | 99 | Note: Building Swift code with CMake requires version 3.29 or later. 100 | 101 | @Code(name: "Setup.shell", file: "install-esp-terminal-01.sh", previousFile: "install-esp-terminal-00.sh") 102 | } 103 | 104 | @Step { 105 | In your home directory, prepare a subdirectory for the ESP SDKs that we need. 106 | 107 | @Code(name: "Setup.shell", file: "install-esp-terminal-02.sh", previousFile: "install-esp-terminal-01.sh") 108 | } 109 | 110 | @Step { 111 | Clone the ESP-IDF repository version v5.4.1 from GitHub. 112 | 113 | Note this SDK is quite large (~500 MB for a shallow clone) and may take significant time to download depending on your internet connection. 114 | 115 | @Code(name: "Setup.shell", file: "install-esp-terminal-03.sh", previousFile: "install-esp-terminal-02.sh") 116 | } 117 | 118 | @Step { 119 | Run the ESP-IDF install script. 120 | 121 | This will download additional tools and python packages needed to build for the ESP32 microcontrollers. 122 | 123 | @Code(name: "Setup.shell", file: "install-esp-terminal-04.sh", previousFile: "install-esp-terminal-03.sh") 124 | } 125 | 126 | @Step { 127 | Clone the ESP Matter repository version 1.2 from GitHub. 128 | 129 | Note this SDK is extremely large (~13 GB for a shallow clone) and may take significant time to download depending on your internet connection. 130 | 131 | @Code(name: "Setup.shell", file: "install-esp-terminal-05.sh", previousFile: "install-esp-terminal-04.sh") 132 | } 133 | 134 | @Step { 135 | Run the ESP Matter install script. 136 | 137 | This will download and build additional tools and python packages needed to build a Matter accessory for the ESP32 microcontrollers. 138 | 139 | @Code(name: "Setup.shell", file: "install-esp-terminal-06.sh", previousFile: "install-esp-terminal-05.sh") 140 | } 141 | } 142 | } 143 | 144 | @Section(title: "Setup your shell environment") { 145 | @ContentAndMedia { 146 | Configure your shell to find the installed tools. 147 | 148 | The following commands can be either be run once per shell session or be placed your `~/.zshrc` file. 149 | } 150 | 151 | @Steps { 152 | @Step { 153 | Set the `TOOLCHAINS` environment variable to use the installed Swift nightly toolchain. 154 | 155 | @Code(name: "Setup.shell", file: "setup-macOS-00.sh") 156 | } 157 | 158 | @Step { 159 | Use the ESP-IDF export script to add the tools to your environment. 160 | 161 | @Code(name: "Setup.shell", file: "setup-macOS-01.sh", previousFile: "setup-macOS-00.sh") 162 | } 163 | 164 | @Step { 165 | Use the ESP-Matter export script to add the tools to your environment. 166 | 167 | @Code(name: "Setup.shell", file: "setup-macOS-02.sh", previousFile: "setup-macOS-01.sh") 168 | } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /smart-light/Matter/Matter.swift: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // This source file is part of the Swift open source project 4 | // 5 | // Copyright (c) 2024 Apple Inc. and the Swift project authors. 6 | // Licensed under Apache License v2.0 with Runtime Library Exception 7 | // 8 | // See https://swift.org/LICENSE.txt for license information 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | enum Matter {} 13 | 14 | extension Matter { 15 | class Node { 16 | var identifyHandler: (() -> Void)? = nil 17 | 18 | var endpoints: [Endpoint] = [] 19 | 20 | func addEndpoint(_ endpoint: Endpoint) { 21 | endpoints.append(endpoint) 22 | } 23 | 24 | // swift-format-ignore: NeverUseImplicitlyUnwrappedOptionals 25 | // This is never actually nil after init(), and inside init we want to form a callback closure that references self. 26 | var innerNode: RootNode! 27 | 28 | init() { 29 | // Initialize persistent storage. 30 | nvs_flash_init() 31 | 32 | // For now, leak the object, to be able to use local variables to declare it. We don't expect this object to be created and destroyed repeatedly. 33 | _ = Unmanaged.passRetained(self) 34 | 35 | // Create the actual root node object, wire up callbacks. 36 | let root = RootNode( 37 | attribute: self.eventHandler, 38 | identify: { _, _, _, _ in self.identifyHandler?() }) 39 | guard let root else { 40 | fatalError("Failed to setup root node.") 41 | } 42 | self.innerNode = root 43 | } 44 | 45 | func eventHandler( 46 | type: MatterAttributeEvent, endpoint: __idf_main.Endpoint, 47 | cluster: Cluster, attribute: UInt32, 48 | value: UnsafeMutablePointer? 49 | ) { 50 | guard type == .didSet else { return } 51 | guard let e = self.endpoints.first(where: { $0.id == endpoint.id }) else { 52 | return 53 | } 54 | let value: Int = Int(value?.pointee.val.u64 ?? 0) 55 | guard let a = Endpoint.Attribute(cluster: cluster, attribute: attribute) 56 | else { return } 57 | e.eventHandler?(Endpoint.Event(type: type, attribute: a, value: value)) 58 | } 59 | } 60 | } 61 | 62 | extension Matter { 63 | class Endpoint { 64 | init(node: Node) { 65 | // For now, leak the object, to be able to use local variables to declare it. We don't expect this object to be created and destroyed repeatedly. 66 | _ = Unmanaged.passRetained(self) 67 | } 68 | 69 | var id: Int = 0 70 | 71 | var eventHandler: ((Event) -> Void)? = nil 72 | 73 | enum ColorControlAttribute { 74 | case currentHue 75 | case currentSaturation 76 | case currentX 77 | case currentY 78 | case colorTemperatureMireds 79 | case colorMode 80 | } 81 | 82 | enum Attribute { 83 | case onOff 84 | case levelControl 85 | case colorControl(ColorControlAttribute) 86 | case unknown(UInt32) 87 | 88 | init?(cluster: Cluster, attribute: UInt32) { 89 | if cluster.as(OnOff.self) != nil { 90 | switch attribute { 91 | case OnOff.AttributeID.state.rawValue: self = .onOff 92 | default: return nil 93 | } 94 | } else if cluster.as(LevelControl.self) != nil { 95 | switch attribute { 96 | case LevelControl.AttributeID.currentLevel 97 | .rawValue: 98 | self = .levelControl 99 | default: return nil 100 | } 101 | } else if cluster.as(ColorControl.self) != nil { 102 | switch attribute { 103 | case ColorControl.AttributeID.currentHue 104 | .rawValue: 105 | self = .colorControl(.currentHue) 106 | case ColorControl.AttributeID 107 | .currentSaturation.rawValue: 108 | self = .colorControl(.currentSaturation) 109 | case ColorControl.AttributeID.currentX.rawValue: 110 | self = .colorControl(.currentX) 111 | case ColorControl.AttributeID.currentY.rawValue: 112 | self = .colorControl(.currentY) 113 | case ColorControl.AttributeID 114 | .colorTemperatureMireds.rawValue: 115 | self = .colorControl(.colorTemperatureMireds) 116 | case ColorControl.AttributeID.colorMode 117 | .rawValue: 118 | self = .colorControl(.colorMode) 119 | default: return nil 120 | } 121 | } else { 122 | self = .unknown(attribute) 123 | } 124 | } 125 | } 126 | 127 | struct Event { 128 | var type: MatterAttributeEvent 129 | var attribute: Attribute 130 | var value: Int 131 | } 132 | } 133 | } 134 | 135 | extension Matter { 136 | class ExtendedColorLight: Endpoint { 137 | override init(node: Node) { 138 | super.init(node: node) 139 | 140 | var lightConfig = esp_matter.endpoint.extended_color_light.config_t() 141 | lightConfig.on_off.on_off = true 142 | lightConfig.level_control.current_level = .init(64) 143 | lightConfig.level_control.lighting.start_up_current_level = .init(64) 144 | lightConfig.color_control.color_mode = 145 | chip.app.Clusters.ColorControl.ColorMode.colorTemperature.rawValue 146 | lightConfig.color_control.enhanced_color_mode = 147 | chip.app.Clusters.ColorControl.ColorMode.colorTemperature.rawValue 148 | 149 | let light = MatterExtendedColorLight( 150 | node.innerNode, configuration: lightConfig) 151 | self.id = Int(light.id) 152 | 153 | var hsv = esp_matter.cluster.color_control.feature.hue_saturation 154 | .config_t() 155 | hsv.current_hue = 255 156 | hsv.current_saturation = 255 157 | light.colorControl.add(hsv) 158 | } 159 | } 160 | } 161 | 162 | extension Matter { 163 | class Application { 164 | var rootNode: Node? = nil 165 | 166 | init() { 167 | // For now, leak the object, to be able to use local variables to declare 168 | // it. We don't expect this object to be created and destroyed repeatedly. 169 | _ = Unmanaged.passRetained(self) 170 | } 171 | 172 | func start() { 173 | func callback( 174 | event: UnsafePointer?, context: Int 175 | ) { 176 | // Ignore callback if event not set. 177 | guard let event else { return } 178 | switch Int(event.pointee.Type) { 179 | case chip.DeviceLayer.DeviceEventType.kFabricRemoved: 180 | recomissionFabric() 181 | default: break 182 | } 183 | } 184 | esp_matter.start(callback, 0) 185 | } 186 | } 187 | } 188 | 189 | func print(_ a: Matter.Endpoint.Attribute) { 190 | switch a { 191 | case .onOff: print("onOff") 192 | case .levelControl: print("levelControl") 193 | case .colorControl(let a): 194 | print("colorControl(", terminator: "") 195 | switch a { 196 | case .currentHue: print("currentHue", terminator: "") 197 | case .currentSaturation: print("currentSaturation", terminator: "") 198 | case .currentX: print("currentX", terminator: "") 199 | case .currentY: print("currentY", terminator: "") 200 | case .colorTemperatureMireds: 201 | print("colorTemperatureMireds", terminator: "") 202 | case .colorMode: print("colorMode", terminator: "") 203 | } 204 | print(")") 205 | case .unknown: print("unknown") 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Sources/SwiftMatterExamples/Documentation.docc/Tutorials/Run-Example-Smart-Light.tutorial: -------------------------------------------------------------------------------- 1 | @Tutorial(time: 20) { 2 | @Intro(title: "Explore the Smart Light example") { 3 | Build, run, and understand the Smart Light application. 4 | } 5 | 6 | @Section(title: "Build and Run") { 7 | @ContentAndMedia { 8 | Build the Smart Light application and run it on your microcontroller. 9 | } 10 | 11 | @Steps { 12 | @Step { 13 | Connect your ESP32-C6 microcontroller to your host machine over USB using the USB Type-C connector closest to the RGB LED. 14 | 15 | @Image(source: "esp32-c6-usb.png", alt: "FIXME-ALT.") 16 | } 17 | 18 | @Step { 19 | If you don't have it yet, clone the `swift-matter-examples` repository. 20 | 21 | @Code(name: "Run.shell", file: "run-example-smart-light-00.sh") 22 | } 23 | 24 | @Step { 25 | Navigate to the smart light example. 26 | 27 | @Code(name: "Run.shell", file: "run-example-smart-light-01.sh", previousFile: "run-example-smart-light-00.sh") 28 | } 29 | 30 | @Step { 31 | Use **idf.py** to configure example for the ESP32-C6 microcontroller. 32 | 33 | @Code(name: "Run.shell", file: "run-example-smart-light-02.sh", previousFile: "run-example-smart-light-01.sh") 34 | } 35 | 36 | @Step { 37 | Use **idf.py** to build the application. 38 | 39 | @Code(name: "Run.shell", file: "run-example-smart-light-03.sh", previousFile: "run-example-smart-light-02.sh") 40 | } 41 | 42 | @Step { 43 | Use **idf.py** to flash the application onto your microcontroller. 44 | 45 | > Important: Use **`Ctrl + ]`** to exit the monitor program. 46 | 47 | @Code(name: "Run.shell", file: "run-example-smart-light-04.sh", previousFile: "run-example-smart-light-03.sh") 48 | } 49 | 50 | @Step { 51 | After flashing completes you should see the microcontroller turn on the LED. 52 | 53 | Additionally you should see `🏎️ Hello, Embedded Swift! (Smart Light)` in the monitor log followed by logs indicating the LED is changing colors. 54 | 55 | @Image(source: "run-example-smart-light-hello.png", alt: "FIXME-ALT.") 56 | } 57 | } 58 | } 59 | 60 | @Section(title: "Connect using Matter") { 61 | @ContentAndMedia { 62 | Pair and control your microcontroller using Matter. 63 | 64 | > Important: These steps use HomeKit via the "Home" app on iOS 17, however similar steps should work for other connected home ecosystems. 65 | 66 | @Image(source: "homekit-logo.png", alt: "FIXME-ALT.") 67 | } 68 | 69 | @Steps { 70 | @Step { 71 | Open the "Home" app and select the "plus" icon to add a new accessory. 72 | 73 | Be sure you already have a Home hub configured, like a HomePod as shown in this setup. 74 | 75 | @Image(source: "pairing-00.png", alt: "Home app open to the \"Home\" tab with an Airport Express and HomePod paired.") 76 | } 77 | @Step { 78 | Select the "More options..." button on the "Add Accessory" overlay. 79 | 80 | @Image(source: "pairing-01.png", alt: "Home app displaying the \"Add Accessory\" overlay.") 81 | } 82 | @Step { 83 | Select the "Matter Accessory" from the list of nearby accessories. 84 | 85 | If the microcontroller doesn't appear in this list you can use `idf.py erase-flash` to reset the device and try again. 86 | 87 | @Image(source: "pairing-02.png", alt: "Home app displaying the \"Select an Accessory\" overlay with one nearby item named \"Matter Accessory\".") 88 | } 89 | @Step { 90 | Enter the setup code **`2020-2021`** to pair the device. 91 | 92 | @Image(source: "pairing-03.png", alt: "Home app display the \"Setup Code\" overlay filled out with the text \"2020-2021\".") 93 | } 94 | @Step { 95 | Your microcontroller should now begin pairing. 96 | 97 | @Image(source: "pairing-04.png", alt: "Home app displaying the \"Accessory\" overlay with the text \"Connecting..\".") 98 | } 99 | @Step { 100 | During the pairing process you may be presented with an "Uncertified Accessory" alert, select "Add Anyway" to continue pairing. 101 | 102 | This alert is shown because the microcontroller is not a certified device. 103 | 104 | @Image(source: "pairing-05.png", alt: "Home app displaying the \"Uncertified Accessory\" alert with two options, \"Add Anyway\" and \"Cancel\" on top of the \"Accessory\" overlay.") 105 | } 106 | @Step { 107 | Once the pairing process completes, you should see an "Accessory Added" overlay indicating success. 108 | 109 | @Image(source: "pairing-06.png", alt: "Home app displaying the \"Accessory Added\" overlay.") 110 | } 111 | @Step { 112 | The microcontroller should now show up in the main list of accessories as a Smart Light. 113 | 114 | @Image(source: "pairing-07.png", alt: "Home app open to the \"Home\" tab with an Airport Express, HomePod, and the microcontroller paired.") 115 | } 116 | @Step { 117 | You can now control the LED on the microcontroller by selecting the accessory. 118 | 119 | @Image(source: "pairing-08.png", alt: "Home app open the \"Matter Accessory\" detail view with the brightness set to 0%.") 120 | } 121 | @Step { 122 | You can change the brightness of the LED using the primary slider. 123 | 124 | @Image(source: "pairing-09.png", alt: "Home app open the \"Matter Accessory\" detail view with the brightness set to 50%.") 125 | } 126 | @Step { 127 | You can adjust the color using the color wheel. 128 | 129 | @Image(source: "pairing-10.png", alt: "Home app open the \"Matter Accessory\" color detail view with the color set to a vivid green.") 130 | } 131 | @Step { 132 | You can also adjust the color using a color temperature. 133 | 134 | @Image(source: "pairing-11.png", alt: "Home app open the \"Matter Accessory\" temperature detail view with the color set to a warm orange.") 135 | } 136 | } 137 | } 138 | 139 | @Section(title: "Understand the code") { 140 | @ContentAndMedia { 141 | Take a brief tour of the code that composes the Smart Light example. 142 | 143 | > Note: This walkthrough skips content covered in . 144 | } 145 | 146 | @Steps { 147 | @Step { 148 | We start the application by declaring an **`app_main`** function with a print statement to show the application has started. 149 | 150 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-01.swift", previousFile: "walkthrough-example-smart-light-00.swift") 151 | } 152 | 153 | @Step { 154 | We then create an LED instance to operate on. The LED type is the same type used in the LED Blink example. 155 | 156 | Next we will start implementing the code required of a Matter accessory. 157 | 158 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-02.swift", previousFile: "walkthrough-example-smart-light-01.swift") 159 | } 160 | 161 | > Important: The Smart Light example uses a Matter overlay, similar to the LED overlay, which provides idiomatic Swift APIs for Matter C++ APIs. 162 | 163 | @Step { 164 | In order to create a Matter accessory, we start by initializing a Matter "root node", which represents the entire accessory. 165 | 166 | The `identifyHandler` callback is designed to help identify the physical accessory. In this example, we log a message, but in a real-world application, a smart light might use this callback to flash its light, providing a clear visual indicator of its location. 167 | 168 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-03.swift", previousFile: "walkthrough-example-smart-light-02.swift") 169 | } 170 | 171 | @Step { 172 | Second, we create an "endpoint", which represents the RGB LED light and an event handler which we will use to convert Matter events to LED adjustments. 173 | 174 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-04.swift", previousFile: "walkthrough-example-smart-light-03.swift") 175 | } 176 | 177 | @Step { 178 | We start the event handler by switching over the kind of Matter event (called an **`attribute`**) to determine which LED property to adjust. 179 | 180 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-04-a.swift", previousFile: "walkthrough-example-smart-light-04.swift") 181 | } 182 | 183 | @Step { 184 | Next, we add cases for the **`.onOff`** and **`.levelControl`** events. We use each event's **`value`** to set the **`led.enabled`** and **`led.brightness`** properties respectively. 185 | 186 | With just these two controls implemented, we are be able to use the light as a switchable and dimmable light. 187 | 188 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-04-b.swift", previousFile: "walkthrough-example-smart-light-04-a.swift") 189 | } 190 | 191 | @Step { 192 | We then add the support for the **`.colorControl`** event. We can use Swift's pattern matching feature to implement each of the hue, saturation, and temperature controls in individual case statements. 193 | 194 | With all three of these controls implemented, we now have a fully adjustable RGB light. 195 | 196 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-04-c.swift", previousFile: "walkthrough-example-smart-light-04-b.swift") 197 | } 198 | 199 | @Step { 200 | Now we need to connect up the components. We add the light "endpoint" to the "root node" making the light a controllable accessory. 201 | 202 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-05.swift", previousFile: "walkthrough-example-smart-light-04-c.swift") 203 | } 204 | 205 | @Step { 206 | Finally, we create a Matter "Application" object, attach it to the "root node", and start the application. 207 | 208 | The microcontroller is now a fully functional Matter smart light accessory! 209 | 210 | @Code(name: "Main.swift", file: "walkthrough-example-smart-light-06.swift", previousFile: "walkthrough-example-smart-light-05.swift") 211 | } 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | 204 | 205 | ## Runtime Library Exception to the Apache 2.0 License: ## 206 | 207 | 208 | As an exception, if you use this Software to compile your source code and 209 | portions of this Software are embedded into the binary product as a result, 210 | you may redistribute such product without providing attribution as would 211 | otherwise be required by Sections 4(a), 4(b) and 4(d) of the License. 212 | --------------------------------------------------------------------------------