diff --git a/docs/Edge/NVIDIA_Jetson/Application/Generative_AI/Deploy_Ollama_and_AnythingLLM_on_Jetson.md b/docs/Edge/NVIDIA_Jetson/Application/Generative_AI/Deploy_Ollama_and_AnythingLLM_on_Jetson.md new file mode 100644 index 000000000000..ca78cafb451c --- /dev/null +++ b/docs/Edge/NVIDIA_Jetson/Application/Generative_AI/Deploy_Ollama_and_AnythingLLM_on_Jetson.md @@ -0,0 +1,224 @@ +--- +description: This wiki will demonstrate how to set up a local knowledge base on Jetson devices with ollama and AnythingLLM. By leveraging the powerful capabilities of large language models, we aim to enhance our work efficiency. +title: Local AI Assistant +keywords: +- reComputer +- LLM +- Chatbot +- ollama +- AnythingLLM +- llama +image: https://files.seeedstudio.com/wiki/wiki-platform/S-tempor.png +slug: /local_ai_ssistant +last_update: + date: 07/30/2024 + author: Youjiang +--- + + +# Local AI Assistant : Deploy Ollama and AnytingLLM on Jetson + +## Introduction + +Local AI Assistant is an artificial intelligence application that runs on local hardware and software, offering intelligent interaction and data processing capabilities. It operates independently of cloud services, protecting user privacy while providing quick response times and high levels of customization. + +
+ +
+ +In this wiki, we will demonstrate how to set up a local knowledge base on Jetson devices with [ollama](https://ollama.com/) and [AnythingLLM](https://anythingllm.com/). By leveraging the powerful capabilities of large language models, we aim to enhance our work efficiency. + +## Prerequisites + +- Jetson device with more than 16GB of memory. +- The hardware device needs to be pre-flashed with the jetpack [5.1.1](https://wiki.seeedstudio.com/reComputer_Intro/) operating system. + +:::note +In this wiki, we will accomplish the following tasks using the [NVIDIA® Jetson AGX Orin™ 64GB Developer Kit](https://www.seeedstudio.com/NVIDIArJetson-AGX-Orintm-64GB-Developer-Kit-p-5641.html), but you can also try using other Jetson devices. +::: + +
+ +
+ +
+ Get One Now 🖱️ + +
+ +## Getting Started + +### Hardware Connection +- Connect the Jetson device to the network, mouse, keyboard, and monitor. + +:::note +Of course, you can also remotely access the Jetson device via SSH over the local network. +::: + +### Install and Run Ollama + +Here, we highly recommend using [jetson-examples](https://github.com/Seeed-Projects/jetson-examples) to quickly deploy Ollama on your Jetson device. + +**Step1.** Open a terminal on jetson device and run the following command to install `jetson-examples`: + +```bash +sudo apt install python3-pip +pip3 install jetson-examples +``` + +**Step2.** To deploy ollama on Jetson device with a single command, we can run: + +```bash +reComputer run ollama +``` + +**Step3.** Download the Llama3 large model using Ollama: + +```bash +ollama run llama3 +``` + +:::info +Please keep this terminal active. +::: + +### Install and Run AnythingLLM + +We can conveniently install AnythingLLM using a [local Docker setup](https://docs.anythingllm.com/installation/self-hosted/local-docker#recommend-way-to-run-dockerized-anythingllm). + +**Step1.** Run AnythingLLM on Jetson. + +Reopen the terminal and enter the following command: + +```bash +docker pull mintplexlabs/anythingllm + +export STORAGE_LOCATION=$HOME/anythingllm +mkdir -p $STORAGE_LOCATION +touch "$STORAGE_LOCATION/.env" +docker run -d -p 3001:3001 --cap-add SYS_ADMIN \ + -v ${STORAGE_LOCATION}:/app/server/storage \ + -v ${STORAGE_LOCATION}/.env:/app/server/.env \ + -e STORAGE_DIR="/app/server/storage" \ + mintplexlabs/anythingllm +``` + +**Step2.** Configure your own local knowledge base. + +To access the full application, visit `http://:3001` in your browser. + +:::note +You can enter the `ifconfig` command on the Jetson terminal to find its IP address. +::: + +
+ +
+ +Follow the on-screen prompts to complete the configuration of AnythingLLM. + +:::danger +Please note that on the configuration page of `LLM Perference`, we should select Ollama's Llama 3.1 large language model. +::: + +
+ +
+ +Finally, import the necessary documents. The large language model will then answer questions based on the imported documents. + +`import` --> `click to upload or drag and drop` --> `select document` --> `move to Workspace` --> `save and embed` + +
+ +
+ +At this point, you have successfully set up your own local knowledge base. + +:::note +For more in-depth configuration tutorials, please refer to [this link](https://docs.anythingllm.com/). +::: + +### Let's Run It + +Enter questions in the dialogue box, and the large language model will provide answers based on the knowledge base. + +
+ +
+ +
+ + story1.txt + +```txt +Once upon a time in a quaint village nestled between rolling hills, there was a young girl named Eliza who loved to explore the woods behind her home. The forest was a magical place, filled with tall trees that whispered secrets, streams that sang soft melodies, and flowers that seemed to glow under the moonlight. + +One sunny morning, Eliza set out on one of her adventures, her heart brimming with excitement. As she wandered deeper into the forest, she discovered a hidden path she had never seen before. The path was lined with shimmering stones that sparkled like stars. Curious and intrigued, Eliza followed it. + +After a short walk, the path led her to a magnificent clearing where a majestic oak tree stood in the center. At the base of the tree was a small, ornate door. It was covered in intricate carvings of animals and vines. Eliza, with her heart pounding with both excitement and nervousness, gently pushed the door open. + +Inside, she found herself in a cozy, enchanted room. There were shelves lined with books and strange artifacts, and a warm fire crackling in a stone hearth. In the middle of the room, a wise old owl perched on a branch of a large, leafy plant. + +The owl looked at Eliza with kind, knowing eyes. “Welcome, young traveler,” it hooted softly. “I am Oliver, the guardian of this magical realm. Few people find their way here. You must have a special heart.” + +Eliza’s eyes widened in awe. “What is this place?” she asked. + +“This is the Realm of Wonders,” Oliver explained. “It is a place where dreams come to life and where those with pure intentions can find their heart’s true desire.” + +Eliza gazed around the room, her curiosity piqued. “What can I do here?” + +Oliver smiled. “You can make a wish. But remember, wishes made here come with great responsibility. They have the power to change not just your life but the lives of those around you.” + +Eliza thought long and hard. She remembered how her village had been struggling with drought and how her friends and family were suffering. With a determined look, she made her wish. + +“I wish for rain to fall upon my village and bring life back to the land.” + +Oliver nodded approvingly. “A selfless wish. It will be granted.” + +The next morning, as Eliza returned to her village, dark clouds gathered in the sky, and a gentle rain began to fall. The villagers looked up in amazement as the parched earth drank in the life-giving water. The fields began to turn green, and the village flourished once more. + +Eliza’s heart swelled with joy as she realized the impact of her wish. The Realm of Wonders had given her the chance to make a difference, and she learned that true magic comes from caring for others. + +From that day on, Eliza continued to explore the woods, knowing that the true wonders of life were found in kindness and selflessness. + +And so, the village thrived, and Eliza’s adventures became the stuff of legends, reminding everyone that magic, indeed, begins with a kind heart. +``` + +
+ + + +## Effect Demonstration + +Here, we use the configured local personal assistant to query the information we need. + +
+ +
+ +## References +- https://ollama.com/library/llama3.1 +- https://anythingllm.com/ +- https://www.youtube.com/watch?v=4UFrVvy7VlA&t=4s + + +## Tech Support & Product Discussion + +Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs. + +
+ + +
+ +
+ + +
\ No newline at end of file diff --git a/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r.md b/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r.md index 95c3080e12e7..a79fb1f06d97 100644 --- a/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r.md +++ b/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r.md @@ -1328,55 +1328,62 @@ Please note that if you require Zigbee functionality, it is necessary to purchas [Please click here for assemble instruction](/recomputer_r1000_assembly_guide/#assemble-4glorazigbee-module-and-antenna). ::: -#### To test Zigbee communication with two Zigbee modules, follow these steps: +#### Set up reComputer R1000 with Zigbee module as Zigbee Coordinator: **Step 1.** Check Serial Ports: Use the following command to check available serial ports: ```bash -cat /dev/ttyUSB* +cat /dev/ttyACM* ``` -**Step 2.** Install Serial Communication Tool: +**Step 2.** Install Serial Communication Tool, then enter *cutecom* open the UI: ```bash -sudo apt install minicom +sudo apt-get install cutecom ``` -**Step 3.** Open Serial Port for Coordinator (First Zigbee Module): +**Step 3.** Configure the setting and Open communication: +* Configure the baudrate as 115200 +* Tick 'Hex output' at the bottom +* Select correct Device port, for example: /dev/ttyACM0 +* Then click 'Open' to set up communication -```bash -sudo minicom -D /dev/ttyUSB2 -b 1152008n1 -w -H -``` +
-Follow these steps to configure the first Zigbee module: - -- Set as coordinator: Send command `55 04 00 05 00 05`, expect response `55 04 00 05 00 05`.
-- Reset device: Press reset button or send command `55 07 00 04 00 FF FF 00 04`.
-- Network formation: Send command `55 03 00 02 02`.
- -**Step 4.** Open Serial Port for Router (Second Zigbee Module): +:::note +For more detail information, please refer to [E18-MS1PA2-IPX](https://www.ebyte.com/product-view-news.html?id=894). For Hex command instruction, please refer to [Ebyte Zigbee 3.0 Module HEX Command Standard Specification](https://www.ebyte.com/pdf-down.aspx?id=2936). +::: -Open another instance of minicom and configure it for the second serial port with the same settings as before. +**Step 4.** Configure the Zigbee module as Coordinator +Follow these steps to configure the first Zigbee module after checking module is at HEX code mode: -Follow these steps to configure the second Zigbee module: +- Set as coordinator: Send command `55 04 00 05 00 05`, expect response `55 04 00 05 00 05`.
+
-- Set as router: Send command `55 04 00 05 01 04`, expect response `55 04 00 05 00 05`.
- Reset device: Press reset button or send command `55 07 00 04 00 FF FF 00 04`.
+
+ - Network formation: Send command `55 03 00 02 02`.
+
+ +:::note +For check digit calculation, can use such [Block Check Character calculator](https://bcc.beyerleinf.de/) tool; Can also use serial communication tools like SSCOM and XCOM with BCC calculate. +::: **Step 5.** Check Device Status: -Send command `5 03 00 00 00` to check the device status. Expect a response similar to `55 2a 00 00 00 01 XX XX XX XX`, where `XX` represents device information. +Send command `5 03 00 00 00` to check the device status. Expect a response similar to `55 2a 00 00 00 01 XX XX XX XX`, where `XX` represents device information. **Step 6.** Enter Transparent Mode: -If network formation is successful, enter transparent mode by sending command `55 07 00 11 00 03 00 01 13`. Both modules should be in transparent mode for direct communication. To exit transparent mode, send `+++`. +If network formation is successful, enter transparent mode by sending command `55 07 00 11 00 03 00 01 13`. Both modules should be in transparent mode for direct communication. Don't forget to set Input mode as *None*. To exit transparent mode, send `+++`. +
+ **Step 7.** Additional Notes: - If router configuration fails, the device may already be a coordinator. Leave the network using command `55 07 00 04 02 xx xx xx`. - Test transmission power using commands `55 04 0D 00 00 0D` (query) and `55 04 0D 01 XX XX` (set). -Ensure you replace /dev/ttyUSB* with the correct serial port for each Zigbee module. Follow these steps carefully to test Zigbee communication between the two modules successfully. - +Then can connect Zigbee device to reComputer R1000 via ZHA, zigbee2mqtt, Tasmota platforms,etc. ### PoE diff --git a/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r1000_assembly_guide.md b/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r1000_assembly_guide.md index ebda4c4d4569..4ce22a836d87 100644 --- a/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r1000_assembly_guide.md +++ b/docs/Edge/Raspberry_Pi_Devices/reComputer_R1000/recomputer_r1000_assembly_guide.md @@ -44,9 +44,10 @@ You need to prepare the following hardware Following these steps should help you disassemble the device without any issues. -**STEP 1:** Remove the Four Screws at the Bottom: +**STEP 1:** Remove the Four Screws at the Bottom and Grounding Screw from Side Panels: - Locate and unscrew the four screws located at the bottom of the device using an appropriate screwdriver. +- Remove and unscrew the grounding screw from the side panels. **STEP 2:** Take Off the Floor Panel: diff --git a/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee.md b/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee.md index ed8e6f61ae61..dedceb33f563 100644 --- a/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee.md +++ b/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee.md @@ -1,6 +1,6 @@ --- description: In this tutorial, we will embark on a journey to explore Zigbee application development using the XIAO ESP32C6 development board. The XIAO ESP32C6 is a compact yet powerful board that features the ESP32-C6 chip, which offers integrated Wi-Fi and Bluetooth Low Energy (BLE) connectivity. By leveraging the ESP Zigbee SDK, we can harness the full potential of the XIAO ESP32C6 and extend its capabilities to include Zigbee functionality. -title: Quick start with Zigbee on XIAO ESP32C6 +title: Quick start with Zigbee on XIAO ESP32C6 by IDF image: https://files.seeedstudio.com/wiki/xiaoc6_zigbee/3.jpg slug: /xiao_esp32c6_zigbee last_update: @@ -8,7 +8,7 @@ last_update: author: Citric --- -# Quick start with Zigbee on XIAO ESP32C6 +# Quick start with Zigbee on XIAO ESP32C6 by IDF Zigbee is a widely adopted wireless communication protocol that finds extensive use in home automation, smart energy management, and Internet of Things (IoT) applications. Known for its low power consumption, reliable data transmission, and mesh network capabilities, Zigbee is an excellent choice for building scalable and efficient wireless networks. diff --git a/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee_arduino.md b/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee_arduino.md new file mode 100644 index 000000000000..4f1c9baec951 --- /dev/null +++ b/docs/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee_arduino.md @@ -0,0 +1,859 @@ +--- +description: In this tutorial, we will embark on a journey to explore Zigbee application development using the XIAO ESP32C6 development board. The XIAO ESP32C6 is a compact yet powerful board that features the ESP32-C6 chip, which offers integrated Wi-Fi and Bluetooth Low Energy (BLE) connectivity. By leveraging the ESP Zigbee SDK, we can harness the full potential of the XIAO ESP32C6 and extend its capabilities to include Zigbee functionality. +title: Quick start with Zigbee on XIAO ESP32C6 by Arduino +image: https://files.seeedstudio.com/wiki/xiaoc6_zigbee/3.jpg +slug: /xiao_esp32c6_zigbee_arduino +last_update: + date: 07/30/2024 + author: Allen +--- + +# Quick start with Zigbee on XIAO ESP32C6 by Arduino + +
+ +Zigbee is a widely adopted wireless communication protocol that finds extensive use in home automation, smart energy management, and Internet of Things (IoT) applications. Known for its low power consumption, reliable data transmission, and mesh network capabilities, Zigbee is an excellent choice for building scalable and efficient wireless networks. + +Throughout this tutorial, we will cover the following key aspects: + +1. **Development Environment**: Setting up the development environment for XIAO ESP32C6 and ESP Zigbee SDK via Arduino. +2. **Code Structure**: Analyzing the code structure and organization of the Zigbee_Light_Buld and Zigbee_Light_Switch examples. +3. **Zigbee Device Data Models**: Understanding the Zigbee device data models and how they are defined within the code. +4. **Zigbee Handling Mechanisms**: Exploring the initialization process and event handling mechanisms in Zigbee devices. +5. **Communication Patterns**: Examining the communication patterns and message exchanges between Zigbee devices. + +So, let's embark on this exciting journey of Zigbee development with the XIAO ESP32C6 and unlock the full potential of this powerful wireless communication protocol! + +## Part 1.Hardware Preparation + +In this tutorial we will use **two** XIAO ESP32C6s as examples to explain Zigbee. you can jump and buy it through the link below. One as a **Zigbee End Device** and one as a **Zigbee Coordinator**. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Seeed Studio XIAO ESP32C6Grove Shield For XIAO
Seeed Studio Grove Red LEDSeeed Studio Grove Button
+
+ +## Part 2.Enviroment Prepatation +**Step 1.** Launch the Arduino application. + +
+ +
+ Download Arduino IDE + +
+ +**Step 2.** Select your development board model and add it to the Arduino IDE. + +- If you want to use **Seeed Studio XIAO ESP32C6** for the later routines, please refer to **[this tutorial](https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/)** to finish adding. + +## Part 3.Program Structure + +### Zigbee Light Bulb + +In this section, we will explore how the Zigbee HA On/Off Light example code is structured based on the Zigbee data model. By understanding the relationship between the code and the data model, you will gain insights into how to interpret and modify the code according to your specific requirements. + +Before diving into the code, it's essential to grasp the key concepts of the Zigbee data model: + +- **Node**: A node represents a single ESP32-H2 based product and a network node in the Zigbee network. A node can have multiple endpoints. + +- **Endpoint**: An endpoint, identified by a number between 1 and 240, defines an application running on a Zigbee node. A node can have multiple endpoints, each serving a different purpose or representing a separate device. + +- **Cluster**: A cluster, identified by a 16-bit number, is an application object that defines the functionality and data associated with an endpoint. Clusters contain attributes and commands. + +- **Attribute**: An attribute, identified by a 16-bit number, represents the current state or a physical quantity within a cluster. + +
+ +Now, let's examine the HA On/Off Light example code and see how it maps to the Zigbee data model. + + +1. Creating the Endpoint + +In the example code, the `esp_zb_on_off_light_ep_create()` function is used to create a HA on/off light endpoint. This function defines the endpoint ID, device ID, and the associated clusters. + +```cpp +static void esp_zb_task(void *pvParameters) +{ + esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); + esp_zb_init(&zb_nwk_cfg); + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); + esp_zb_device_register(esp_zb_on_off_light_ep); + esp_zb_core_action_handler_register(zb_action_handler); + esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); + + //Erase NVRAM before creating connection to new Coordinator + //esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator + + ESP_ERROR_CHECK(esp_zb_start(false)); + esp_zb_main_loop_iteration(); +} +``` + +2. Registering the Device + +After creating the endpoint, the `esp_zb_device_register()` function is called to register the Zigbee device with the created endpoint. + +```cpp +esp_zb_device_register(esp_zb_on_off_light_ep); +``` + +3. Attribute Callback + +The example code registers an attribute change callback using `esp_zb_core_action_handler_register()`. This callback is invoked when certain attributes are modified, allowing you to handle attribute changes based on your application logic. + +```cpp +esp_zb_core_action_handler_register(zb_action_handler); +``` + +In the `zb_action_handler` function, you can implement the desired behavior when the on/off attribute changes, such as controlling the LED light. + +4. Zigbee Stack Configuration and Starting + +The example code configures the Zigbee end-device using `ESP_ZB_ZED_CONFIG()` and initializes the Zigbee stack using `esp_zb_init()`. The stack is then started with `esp_zb_start()`, and the main loop is handled by `esp_zb_main_loop_iteration()`. + + +```cpp +esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); +esp_zb_init(&zb_nwk_cfg); +... +ESP_ERROR_CHECK(esp_zb_start(false)); +esp_zb_main_loop_iteration(); +``` + +The `esp_zb_app_signal_handler` function is responsible for handling various signals from the Zigbee application layer. + +```cpp +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) +{ + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: + if (err_status == ESP_OK) { + log_i("Start network steering"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + /* commissioning failed */ + log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i("Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], + extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], + esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); + } else { + log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); + } + break; + default: + log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, + esp_err_to_name(err_status)); + break; + } +} +``` + +1. First, the function retrieves the signal type `sig_type` and error status `err_status` from the passed `esp_zb_app_signal_t` structure. + +2. Then, it uses a switch statement to perform different actions based on the signal type: + + - `ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP`: This signal indicates skipping the startup of the Zigbee stack. In this case, we initialize the Zigbee stack and then call the `esp_zb_bdb_start_top_level_commissioning` function to start the top-level commissioning process with the mode set to `ESP_ZB_BDB_MODE_INITIALIZATION`. + + - `ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START` and `ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT`: These signals indicate the first start or reboot of the device. If the error status is `ESP_OK`, we perform some initialization tasks, such as deferred driver initialization. Then, we check if the device is in the factory new state. If it is, we start the network steering process; otherwise, we output a message indicating that the device has rebooted. If the error status is not `ESP_OK`, we output a message indicating that the Zigbee stack initialization failed. + + - `ESP_ZB_BDB_SIGNAL_STEERING`: This signal indicates the result of the network steering process. If the error status is `ESP_OK`, it means the device successfully joined the network. In this case, we output some network information, such as the PAN ID, channel number, and short address. If the error status is not `ESP_OK`, it means the network steering failed, and we output an error message. Then, we use the `esp_zb_scheduler_alarm` function to set a timer to restart the network steering process after a 1-second delay. + + - Other signals: We simply output the signal name, type, and error status. + +The purpose of this function is to perform appropriate actions based on different Zigbee application layer signals. It is one of the core parts of a Zigbee application. It handles critical processes such as device startup, initialization, and network joining. + +### Zigbee Light Switch + +For the Zigbee Coordinator device(Light Switch), its initialisation and RTOS tasks are similar to the End Device, except that in the RTOS tasks, there is less step of registering the callback function. + +So for Zigbee Coordinator, the most critical part is to search and match the corresponding device, and issue control commands to the device. + +```cpp +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) +{ + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: + if (err_status == ESP_OK) { + log_i("Start network formation"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); + } else { + log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_FORMATION: + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i("Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], + extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], + esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: + if (err_status == ESP_OK) { + log_i("Network steering started"); + } + break; + case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: + dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); + log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); + esp_zb_zdo_match_desc_req_param_t cmd_req; + cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; + cmd_req.addr_of_interest = dev_annce_params->device_short_addr; + esp_zb_zdo_find_on_off_light(&cmd_req, user_find_cb, NULL); + break; + default: + log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, + esp_err_to_name(err_status)); + break; + } +} +``` + +Let's go through the different cases and their functionalities: + +1. `ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP`: + - This signal indicates that the Zigbee stack initialization should be skipped. + - It logs a message indicating the initialization of the Zigbee stack. + - It starts the top-level commissioning process with the mode set to `ESP_ZB_BDB_MODE_INITIALIZATION`. + +2. `ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START` and `ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT`: + - These signals indicate that the device has started up for the first time or has rebooted. + - If the error status is `ESP_OK`, it logs messages about the deferred driver initialization status and whether the device started up in factory-reset mode or not. + - If the device is in factory-new mode, it starts the network formation process by calling `esp_zb_bdb_start_top_level_commissioning` with the mode set to `ESP_ZB_BDB_MODE_NETWORK_FORMATION`. + - If the device is not in factory-new mode, it logs a message indicating that the device has rebooted. + - If the error status is not `ESP_OK`, it logs an error message. + +3. `ESP_ZB_BDB_SIGNAL_FORMATION`: + - This signal indicates the status of the network formation process. + - If the error status is `ESP_OK`, it retrieves the extended PAN ID, logs information about the formed network (PAN ID, channel, short address), and starts the network steering process by calling `esp_zb_bdb_start_top_level_commissioning` with the mode set to `ESP_ZB_BDB_MODE_NETWORK_STEERING`. + - If the error status is not `ESP_OK`, it logs a message to restart the network formation and schedules an alarm to call `bdb_start_top_level_commissioning_cb` after a delay of 1000 milliseconds. + +4. `ESP_ZB_BDB_SIGNAL_STEERING`: + - This signal indicates the status of the network steering process. + - If the error status is `ESP_OK`, it logs a message indicating that network steering has started. + +5. `ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE`: + - This signal is triggered when a new device is commissioned or rejoins the network. + - It retrieves the device announcement parameters and logs a message with the short address of the new device. + - It prepares a match descriptor request (`esp_zb_zdo_match_desc_req_param_t`) with the destination and address of interest set to the new device's short address. + - It calls `esp_zb_zdo_find_color_dimmable_light` to find a color dimmable light device and specifies `user_find_cb` as the callback function. + +6. `ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS`: + - This signal indicates the status of the network's permit join state. + - If the error status is `ESP_OK`, it logs a message indicating whether the network is open for joining and the duration for which it is open. If the network is closed, it logs a warning message. + +7. Default case: + - For any other signal types, it logs a general message with the signal type and error status. + +Overall, this code handles various Zigbee-related events and performs actions such as initializing the Zigbee stack, forming a network, steering the network, handling device announcements, and finding color dimmable light devices. + +The rest of the example is addressing the logic for keystroke stabilisation and keystroke interrupts. If you are interested, you can read and understand it by yourself. + + +## Part 4.Zigbee Light Effect + +This section we will connect the devices and upload the codes to two peices of XIAO ESP32C6 and see the effect. + +### Step 1.Hardware Connection + +
+ + + + + + + + + +
XIAO ESP32C6 connect to bulb via D9XIAO ESP32C6 connect to switch via D0
+
+ +### Step 2.Set Arduino Serial Port to Debug Level + +We need to set to debug level to see serial port message from Zigbee light and switch later. + +
+ +### Step 3.Upload Light Bulb Codes + +```cpp + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define LED_PIN D10 + +/* Default End Device config */ +#define ESP_ZB_ZED_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zed_cfg = { \ + .ed_timeout = ED_AGING_TIMEOUT, \ + .keep_alive = ED_KEEP_ALIVE, \ + }, \ + }, \ + } + +#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = ZB_RADIO_MODE_NATIVE, \ + } + +#define ESP_ZB_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ + } + +/* Zigbee configuration */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ + +/********************* Zigbee functions **************************/ +static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) +{ + ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); +} + +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) +{ + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: + if (err_status == ESP_OK) { + log_i("Start network steering"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + /* commissioning failed */ + log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i("Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], + extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], + esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); + } else { + log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); + } + break; + default: + log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, + esp_err_to_name(err_status)); + break; + } +} + +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) +{ + esp_err_t ret = ESP_OK; + switch (callback_id) { + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: + ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); + break; + default: + log_w("Receive Zigbee action(0x%x) callback", callback_id); + break; + } + return ret; +} + +static void esp_zb_task(void *pvParameters) +{ + esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); + esp_zb_init(&zb_nwk_cfg); + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); + esp_zb_device_register(esp_zb_on_off_light_ep); + esp_zb_core_action_handler_register(zb_action_handler); + esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); + + //Erase NVRAM before creating connection to new Coordinator + //esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator + + ESP_ERROR_CHECK(esp_zb_start(false)); + esp_zb_main_loop_iteration(); +} + +/* Handle the light attribute */ + +static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) +{ + esp_err_t ret = ESP_OK; + bool light_state = 0; + + if(!message){ + log_e("Empty message"); + } + if(message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS){ + log_e("Received message: error status(%d)", message->info.status); + } + + log_i("Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, + message->attribute.id, message->attribute.data.size); + if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; + log_i("Light sets to %s", light_state ? "On" : "Off"); + // Here is the code to turn on/off your LED + if(light_state == 1){ + digitalWrite(LED_PIN, HIGH); + }else{ + digitalWrite(LED_PIN, LOW); + } + + } + } + } + return ret; +} + +/********************* Arduino functions **************************/ +void setup() { + // Init Zigbee + esp_zb_platform_config_t config = { + .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), + }; + ESP_ERROR_CHECK(esp_zb_platform_config(&config)); + + // initialize LED pin + pinMode(LED_PIN, OUTPUT); + + // turn off LED + digitalWrite(LED_PIN, LOW); + + // Start Zigbee task + xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); +} + +void loop() { + //empty, zigbee running in task +} +``` + +### Step 4.Upload Light Switch Codes + +```cpp + +#ifndef ZIGBEE_MODE_ZCZR +#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" +#endif + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +/* Switch configuration */ +#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 +#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) + +typedef enum { + SWITCH_ON_CONTROL, + SWITCH_OFF_CONTROL, + SWITCH_ONOFF_TOGGLE_CONTROL, + SWITCH_LEVEL_UP_CONTROL, + SWITCH_LEVEL_DOWN_CONTROL, + SWITCH_LEVEL_CYCLE_CONTROL, + SWITCH_COLOR_CONTROL, +} switch_func_t; + +typedef struct { + uint8_t pin; + switch_func_t func; +} switch_func_pair_t; + +typedef enum { + SWITCH_IDLE, + SWITCH_PRESS_ARMED, + SWITCH_PRESS_DETECTED, + SWITCH_PRESSED, + SWITCH_RELEASE_DETECTED, +} switch_state_t; + +static switch_func_pair_t button_func_pair[] = { + {GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL} +}; + +/* Default Coordinator config */ +#define ESP_ZB_ZC_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zczr_cfg = { \ + .max_children = MAX_CHILDREN, \ + }, \ + } \ + } + +#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = ZB_RADIO_MODE_NATIVE, \ + } + +#define ESP_ZB_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ + } + +typedef struct light_bulb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} light_bulb_device_params_t; + +/* Zigbee configuration */ +#define MAX_CHILDREN 10 /* the max amount of connected devices */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ + +/********************* Define functions **************************/ +static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) +{ + if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { + /* implemented light switch toggle functionality */ + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Send 'on_off toggle' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } +} + +static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) +{ + ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); +} + +static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) +{ + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + free(light); + } + } +} + +static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) +{ + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Found light"); + esp_zb_zdo_bind_req_param_t bind_req; + light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = HA_ONOFF_SWITCH_ENDPOINT; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_i("Try to bind On/Off"); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); + } +} + +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) +{ + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: + if (err_status == ESP_OK) { + log_i("Start network formation"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); + } else { + log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_FORMATION: + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i("Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], + extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], + esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: + if (err_status == ESP_OK) { + log_i("Network steering started"); + } + break; + case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: + dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); + log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); + esp_zb_zdo_match_desc_req_param_t cmd_req; + cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; + cmd_req.addr_of_interest = dev_annce_params->device_short_addr; + esp_zb_zdo_find_on_off_light(&cmd_req, user_find_cb, NULL); + break; + default: + log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, + esp_err_to_name(err_status)); + break; + } +} + +static void esp_zb_task(void *pvParameters) +{ + esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); + esp_zb_init(&zb_nwk_cfg); + esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); + esp_zb_ep_list_t *esp_zb_on_off_switch_ep = esp_zb_on_off_switch_ep_create(HA_ONOFF_SWITCH_ENDPOINT, &switch_cfg); + esp_zb_device_register(esp_zb_on_off_switch_ep); + esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); + ESP_ERROR_CHECK(esp_zb_start(false)); + esp_zb_main_loop_iteration(); +} + +/********************* GPIO functions **************************/ +static QueueHandle_t gpio_evt_queue = NULL; + +static void IRAM_ATTR gpio_isr_handler(void *arg) +{ + xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); +} + +static void switch_gpios_intr_enabled(bool enabled) +{ + for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { + if (enabled) { + enableInterrupt((button_func_pair[i]).pin); + } else { + disableInterrupt((button_func_pair[i]).pin); + } + } +} + +/********************* Arduino functions **************************/ +void setup() { + // Init Zigbee + esp_zb_platform_config_t config = { + .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), + }; + + ESP_ERROR_CHECK(esp_zb_platform_config(&config)); + + // Init button switch + for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { + pinMode(button_func_pair[i].pin, INPUT_PULLUP); + /* create a queue to handle gpio event from isr */ + gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); + if ( gpio_evt_queue == 0) { + log_e("Queue was not created and must not be used"); + while(1); + } + attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *) (button_func_pair + i), FALLING); + } + + // Start Zigbee task + xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); +} + +void loop() { + // Handle button switch in loop() + uint8_t pin = 0; + switch_func_pair_t button_func_pair; + static switch_state_t switch_state = SWITCH_IDLE; + bool evt_flag = false; + + /* check if there is any queue received, if yes read out the button_func_pair */ + if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { + pin = button_func_pair.pin; + switch_gpios_intr_enabled(false); + evt_flag = true; + } + while (evt_flag) { + bool value = digitalRead(pin); + switch (switch_state) { + case SWITCH_IDLE: + switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; + break; + case SWITCH_PRESS_DETECTED: + switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; + break; + case SWITCH_RELEASE_DETECTED: + switch_state = SWITCH_IDLE; + /* callback to button_handler */ + (*esp_zb_buttons_handler)(&button_func_pair); + break; + default: + break; + } + if (switch_state == SWITCH_IDLE) { + switch_gpios_intr_enabled(true); + evt_flag = false; + break; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} +``` + +### Step 5.Final Effect + +After upload the codes to 2 pieces of XIAO ESP32C6(light bulb and light switch), you can see some message from serial port like below image. When you click the switch, the bulb will turn on or off. + +:::tip +If the message from serial port not like below image, you can click the reset button on XIAO ESP32C6 or replug to reboot it. +::: + +
+ + + + + + + + + +
Zigbee bulbZigbee switch
+
+ +Here is the final effect. You can use switch to control the bulb via Zigbee. + +
+ +
+ +Congratulations on successfully completing your Zigbee-controlled lighting project! There are many more exciting Zigbee applications waiting for you to explore. Keep up the great work! + +## Tech Support & Product Discussion + +Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs. + +
+
+ + +
+ +
+ + +
+
\ No newline at end of file diff --git a/docs/Sensor/SenseCAP/SenseCAP_Watcher/Getting_Started/sensecap_watcher_getting_started.md b/docs/Sensor/SenseCAP/SenseCAP_Watcher/Getting_Started/sensecap_watcher_getting_started.md index 511826f63969..f696bedbd847 100644 --- a/docs/Sensor/SenseCAP/SenseCAP_Watcher/Getting_Started/sensecap_watcher_getting_started.md +++ b/docs/Sensor/SenseCAP/SenseCAP_Watcher/Getting_Started/sensecap_watcher_getting_started.md @@ -11,11 +11,11 @@ last_update: # Getting Started with SenseCAP Watcher -
+
- - Learn More 🖱️ + + Get One Now
diff --git a/sidebars.js b/sidebars.js index e73d6c6bfd5a..8c07f3eac820 100644 --- a/sidebars.js +++ b/sidebars.js @@ -1192,6 +1192,7 @@ const sidebars = { 'Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_aws_iot', 'Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_kafka', 'Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee', + 'Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/Application/xiao_esp32c6_zigbee_arduino', ], }, 'Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32C6/XIAO_ESP32C6_Embedded_Swift', @@ -3262,6 +3263,7 @@ const sidebars = { // Projects 'Edge/NVIDIA_Jetson/Application/Generative_AI/Deploy_Riva_and_Llama2_on_reComputer', 'Edge/NVIDIA_Jetson/Application/Generative_AI/Real_Time_Subtitle_Recoder_on_Jetson', + 'Edge/NVIDIA_Jetson/Application/Generative_AI/Deploy_Ollama_and_AnythingLLM_on_Jetson', ] },