|  | 
|  | 1 | +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD | 
|  | 2 | +// | 
|  | 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | +// you may not use this file except in compliance with the License. | 
|  | 5 | +// You may obtain a copy of the License at | 
|  | 6 | + | 
|  | 7 | +// http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | +// | 
|  | 9 | +// Unless required by applicable law or agreed to in writing, software | 
|  | 10 | +// distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | +// See the License for the specific language governing permissions and | 
|  | 13 | +// limitations under the License. | 
|  | 14 | + | 
|  | 15 | +/* | 
|  | 16 | + * This example is the smallest code that will create a Matter Device which can be | 
|  | 17 | + * commissioned and controlled from a Matter Environment APP. | 
|  | 18 | + * It controls a GPIO that could be attached to a LED for visualization. | 
|  | 19 | + * Additionally the ESP32 will send debug messages indicating the Matter activity. | 
|  | 20 | + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. | 
|  | 21 | + * | 
|  | 22 | + * This example is a simple Matter On/Off Light that can be controlled by a Matter Controller. | 
|  | 23 | + * It demonstrates how to use On Identify callback when the Identify Cluster is called. | 
|  | 24 | + * The Matter user APP can be used to request the device to identify itself by blinking the LED. | 
|  | 25 | + */ | 
|  | 26 | + | 
|  | 27 | +// Matter Manager | 
|  | 28 | +#include <Matter.h> | 
|  | 29 | +#include <WiFi.h> | 
|  | 30 | + | 
|  | 31 | +// List of Matter Endpoints for this Node | 
|  | 32 | +// Single On/Off Light Endpoint - at least one per node | 
|  | 33 | +MatterOnOffLight OnOffLight; | 
|  | 34 | + | 
|  | 35 | +// WiFi is manually set and started | 
|  | 36 | +const char *ssid = "your-ssid"; // Change this to your WiFi SSID | 
|  | 37 | +const char *password = "your-password"; // Change this to your WiFi password | 
|  | 38 | + | 
|  | 39 | +// Light GPIO that can be controlled by Matter APP | 
|  | 40 | +#ifdef LED_BUILTIN | 
|  | 41 | +const uint8_t ledPin = LED_BUILTIN; | 
|  | 42 | +#else | 
|  | 43 | +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN | 
|  | 44 | +#endif | 
|  | 45 | + | 
|  | 46 | +// set your board USER BUTTON pin here - decommissioning button | 
|  | 47 | +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. | 
|  | 48 | + | 
|  | 49 | +// Button control - decommision the Matter Node | 
|  | 50 | +uint32_t button_time_stamp = 0; // debouncing control | 
|  | 51 | +bool button_state = false; // false = released | true = pressed | 
|  | 52 | +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission | 
|  | 53 | + | 
|  | 54 | +// Identify Flag and blink time - Blink the LED | 
|  | 55 | +const uint8_t identifyLedPin = ledPin; // uses the same LED as the Light - change if needed | 
|  | 56 | +volatile bool identifyFlag = false; // Flag to start the Blink when in Identify state | 
|  | 57 | +bool identifyBlink = false; // Blink state when in Identify state | 
|  | 58 | + | 
|  | 59 | +// Matter Protocol Endpoint (On/OFF Light) Callback | 
|  | 60 | +bool onOffLightCallback(bool state) { | 
|  | 61 | + digitalWrite(ledPin, state ? HIGH : LOW); | 
|  | 62 | + // This callback must return the success state to Matter core | 
|  | 63 | + return true; | 
|  | 64 | +} | 
|  | 65 | + | 
|  | 66 | +// Identification shall be done by Blink in Red or just the GPIO when no LED_BUILTIN is not defined | 
|  | 67 | +bool onIdentifyLightCallback(bool identifyIsActive) { | 
|  | 68 | + Serial.printf("Identify Cluster is %s\r\n", identifyIsActive ? "Active" : "Inactive"); | 
|  | 69 | + if (identifyIsActive) { | 
|  | 70 | + // Start Blinking the light in loop() | 
|  | 71 | + identifyFlag = true; | 
|  | 72 | + identifyBlink = !OnOffLight; // Start with the inverted light state | 
|  | 73 | + } else { | 
|  | 74 | + // Stop Blinking and restore the light to the its last state | 
|  | 75 | + identifyFlag = false; | 
|  | 76 | + // force returning to the original state by toggling the light twice | 
|  | 77 | + OnOffLight.toggle(); | 
|  | 78 | + OnOffLight.toggle(); | 
|  | 79 | + } | 
|  | 80 | + return true; | 
|  | 81 | +} | 
|  | 82 | + | 
|  | 83 | +void setup() { | 
|  | 84 | + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node | 
|  | 85 | + pinMode(buttonPin, INPUT_PULLUP); | 
|  | 86 | + // Initialize the LED GPIO | 
|  | 87 | + pinMode(ledPin, OUTPUT); | 
|  | 88 | + | 
|  | 89 | + Serial.begin(115200); | 
|  | 90 | + | 
|  | 91 | + // Manually connect to WiFi | 
|  | 92 | + WiFi.begin(ssid, password); | 
|  | 93 | + // Wait for connection | 
|  | 94 | + while (WiFi.status() != WL_CONNECTED) { | 
|  | 95 | + delay(500); | 
|  | 96 | + Serial.print("."); | 
|  | 97 | + } | 
|  | 98 | + Serial.println(); | 
|  | 99 | + | 
|  | 100 | + // Initialize at least one Matter EndPoint | 
|  | 101 | + OnOffLight.begin(); | 
|  | 102 | + | 
|  | 103 | + // On Identify Callback - Blink the LED | 
|  | 104 | + OnOffLight.onIdentify(onIdentifyLightCallback); | 
|  | 105 | + | 
|  | 106 | + // Associate a callback to the Matter Controller | 
|  | 107 | + OnOffLight.onChange(onOffLightCallback); | 
|  | 108 | + | 
|  | 109 | + // Matter beginning - Last step, after all EndPoints are initialized | 
|  | 110 | + Matter.begin(); | 
|  | 111 | + | 
|  | 112 | + // Check Matter Accessory Commissioning state, which may change during execution of loop() | 
|  | 113 | + if (!Matter.isDeviceCommissioned()) { | 
|  | 114 | + Serial.println(""); | 
|  | 115 | + Serial.println("Matter Node is not commissioned yet."); | 
|  | 116 | + Serial.println("Initiate the device discovery in your Matter environment."); | 
|  | 117 | + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); | 
|  | 118 | + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); | 
|  | 119 | + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); | 
|  | 120 | + // waits for Matter Occupancy Sensor Commissioning. | 
|  | 121 | + uint32_t timeCount = 0; | 
|  | 122 | + while (!Matter.isDeviceCommissioned()) { | 
|  | 123 | + delay(100); | 
|  | 124 | + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec | 
|  | 125 | + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); | 
|  | 126 | + } | 
|  | 127 | + } | 
|  | 128 | + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); | 
|  | 129 | + } | 
|  | 130 | +} | 
|  | 131 | + | 
|  | 132 | +void loop() { | 
|  | 133 | + // check if the Light is in identify state and blink it every 500ms (delay loop time) | 
|  | 134 | + if (identifyFlag) { | 
|  | 135 | +#ifdef LED_BUILTIN | 
|  | 136 | + uint8_t brightness = 32 * identifyBlink; | 
|  | 137 | + rgbLedWrite(identifyLedPin, brightness, 0, 0); | 
|  | 138 | +#else | 
|  | 139 | + digitalWrite(identifyLedPin, identifyBlink ? HIGH : LOW); | 
|  | 140 | +#endif | 
|  | 141 | + identifyBlink = !identifyBlink; | 
|  | 142 | + } | 
|  | 143 | + | 
|  | 144 | + // Check if the button has been pressed | 
|  | 145 | + if (digitalRead(buttonPin) == LOW && !button_state) { | 
|  | 146 | + // deals with button debouncing | 
|  | 147 | + button_time_stamp = millis(); // record the time while the button is pressed. | 
|  | 148 | + button_state = true; // pressed. | 
|  | 149 | + } | 
|  | 150 | + | 
|  | 151 | + if (digitalRead(buttonPin) == HIGH && button_state) { | 
|  | 152 | + button_state = false; // released | 
|  | 153 | + } | 
|  | 154 | + | 
|  | 155 | + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node | 
|  | 156 | + uint32_t time_diff = millis() - button_time_stamp; | 
|  | 157 | + if (button_state && time_diff > decommissioningTimeout) { | 
|  | 158 | + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); | 
|  | 159 | + Matter.decommission(); | 
|  | 160 | + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so | 
|  | 161 | + } | 
|  | 162 | + | 
|  | 163 | + delay(500); // works as a debounce for the button and also for the LED blink | 
|  | 164 | +} | 
0 commit comments