diff --git a/.vscode/settings.json b/.vscode/settings.json
index f1ff58a..7fbbf25 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -42,7 +42,7 @@
         "esp_heap_caps.h": "c",
         "zh_vector.h": "c"
     },
-    "idf.adapterTargetName": "esp32",
+    "idf.adapterTargetName": "esp8266",
     "idf.port": "/dev/cu.usbserial-0001",
     "idf.flashType": "UART",
     "idf.openOcdConfigs": [
diff --git a/components/espressif_ds18b20/.DS_Store b/components/espressif_ds18b20/.DS_Store
new file mode 100644
index 0000000..cd3521a
Binary files /dev/null and b/components/espressif_ds18b20/.DS_Store differ
diff --git a/components/espressif_ds18b20/CHANGELOG.md b/components/espressif_ds18b20/CHANGELOG.md
new file mode 100644
index 0000000..d8c5ad7
--- /dev/null
+++ b/components/espressif_ds18b20/CHANGELOG.md
@@ -0,0 +1,7 @@
+## 0.1.1
+
+- Fix the issue that sign-bit is not extended properly when doing temperature value conversion.
+
+## 0.1.0
+
+- Initial driver version, based on the [onewire_bus](https://components.espressif.com/components/espressif/onewire_bus) library.
diff --git a/components/espressif_ds18b20/CMakeLists.txt b/components/espressif_ds18b20/CMakeLists.txt
new file mode 100644
index 0000000..7793bcd
--- /dev/null
+++ b/components/espressif_ds18b20/CMakeLists.txt
@@ -0,0 +1,2 @@
+idf_component_register(SRCS "src/ds18b20.c"
+                       INCLUDE_DIRS "include")
diff --git a/components/espressif_ds18b20/LICENSE b/components/espressif_ds18b20/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/components/espressif_ds18b20/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/components/espressif_ds18b20/README.md b/components/espressif_ds18b20/README.md
new file mode 100644
index 0000000..f1d55f9
--- /dev/null
+++ b/components/espressif_ds18b20/README.md
@@ -0,0 +1,63 @@
+# DS18B20 Device Driver
+
+[![Component Registry](https://components.espressif.com/components/espressif/ds18b20/badge.svg)](https://components.espressif.com/components/espressif/ds18b20)
+
+DS18B20 temperature sensor only uses a single wire to write and read data, the interface is also called the `1-Wire` bus. This component only contains the sensor driver. For 1-Wire bus setup, you need to use the [onewire_bus](https://components.espressif.com/components/espressif/onewire_bus) library to initialize and enumerate the devices.
+
+## How to enumerate DS18B20 devices on the 1-Wire bus
+
+```c
+    #define EXAMPLE_ONEWIRE_BUS_GPIO    0
+    #define EXAMPLE_ONEWIRE_MAX_DS18B20 2
+
+    // install 1-wire bus
+    onewire_bus_handle_t bus = NULL;
+    onewire_bus_config_t bus_config = {
+        .bus_gpio_num = EXAMPLE_ONEWIRE_BUS_GPIO,
+    };
+    onewire_bus_rmt_config_t rmt_config = {
+        .max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command
+    };
+    ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &bus));
+
+    int ds18b20_device_num = 0;
+    ds18b20_device_handle_t ds18b20s[EXAMPLE_ONEWIRE_MAX_DS18B20];
+    onewire_device_iter_handle_t iter = NULL;
+    onewire_device_t next_onewire_device;
+    esp_err_t search_result = ESP_OK;
+
+    // create 1-wire device iterator, which is used for device search
+    ESP_ERROR_CHECK(onewire_new_device_iter(bus, &iter));
+    ESP_LOGI(TAG, "Device iterator created, start searching...");
+    do {
+        search_result = onewire_device_iter_get_next(iter, &next_onewire_device);
+        if (search_result == ESP_OK) { // found a new device, let's check if we can upgrade it to a DS18B20
+            ds18b20_config_t ds_cfg = {};
+            // check if the device is a DS18B20, if so, return the ds18b20 handle
+            if (ds18b20_new_device(&next_onewire_device, &ds_cfg, &ds18b20s[ds18b20_device_num]) == ESP_OK) {
+                ESP_LOGI(TAG, "Found a DS18B20[%d], address: %016llX", ds18b20_device_num, next_onewire_device.address);
+                ds18b20_device_num++;
+            } else {
+                ESP_LOGI(TAG, "Found an unknown device, address: %016llX", next_onewire_device.address);
+            }
+        }
+    } while (search_result != ESP_ERR_NOT_FOUND);
+    ESP_ERROR_CHECK(onewire_del_device_iter(iter));
+    ESP_LOGI(TAG, "Searching done, %d DS18B20 device(s) found", ds18b20_device_num);
+
+    // Now you have the DS18B20 sensor handle, you can use it to read the temperature
+```
+
+## Trigger a temperature conversion and then read the data
+
+```c
+for (int i = 0; i < ds18b20_device_num; i ++) {
+    ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20s[i]));
+    ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20s[i], &temperature));
+    ESP_LOGI(TAG, "temperature read from DS18B20[%d]: %.2fC", i, temperature);
+}
+```
+
+## Reference
+
+* See [DS18B20 datasheet](https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf)
diff --git a/components/espressif_ds18b20/idf_component.yml b/components/espressif_ds18b20/idf_component.yml
new file mode 100644
index 0000000..4b3714f
--- /dev/null
+++ b/components/espressif_ds18b20/idf_component.yml
@@ -0,0 +1,6 @@
+dependencies:
+  onewire_bus:
+    version: ^1.0.0
+description: DS18B20 device driver
+url: https://github.com/espressif/esp-bsp/tree/master/components/ds18b20
+version: 0.1.1
diff --git a/components/espressif_ds18b20/include/ds18b20.h b/components/espressif_ds18b20/include/ds18b20.h
new file mode 100644
index 0000000..4e1113a
--- /dev/null
+++ b/components/espressif_ds18b20/include/ds18b20.h
@@ -0,0 +1,97 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include "onewire_device.h"
+#include "ds18b20_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Type of DS18B20 device handle
+ */
+typedef struct ds18b20_device_t *ds18b20_device_handle_t;
+
+/**
+ * @brief DS18B20 configuration
+ */
+typedef struct {
+} ds18b20_config_t;
+
+/**
+ * @brief Create a new DS18B20 device based on the general 1-Wire device
+ *
+ * @note The general 1-Wire device can be enumerated during the 1-Wire bus device search process,
+ *       this function is going to check and upgrade that into a DS18B20 device.
+ *
+ * @param[in] device 1-Wire device basic information, including bus handle and device ROM ID
+ * @param[in] config DS18B20 configuration
+ * @param[out] ret_ds18b20 Returned DS18B20 device handle
+ * @return
+ *      - ESP_OK: Create DS18B20 device successfully
+ *      - ESP_ERR_INVALID_ARG: Create DS18B20 device failed due to invalid argument
+ *      - ESP_ERR_NO_MEM: Create DS18B20 device failed due to out of memory
+ *      - ESP_ERR_NOT_SUPPORTED: Create DS18B20 device failed because the device is unknown (e.g. a wrong family ID code)
+ *      - ESP_FAIL: Create DS18B20 device failed due to other reasons
+ */
+esp_err_t ds18b20_new_device(onewire_device_t *device, const ds18b20_config_t *config, ds18b20_device_handle_t *ret_ds18b20);
+
+/**
+ * @brief Delete DS18B20 device
+ *
+ * @param ds18b20 DS18B20 device handle returned by `ds18b20_new_device`
+ * @return
+ *      - ESP_OK: Delete DS18B20 device successfully
+ *      - ESP_ERR_INVALID_ARG: Delete DS18B20 device failed due to invalid argument
+ *      - ESP_FAIL: Delete DS18B20 device failed due to other reasons
+ */
+esp_err_t ds18b20_del_device(ds18b20_device_handle_t ds18b20);
+
+/**
+ * @brief Set DS18B20's temperature conversion resolution
+ *
+ * @param[in] ds18b20 DS18B20 device handle returned by `ds18b20_new_device`
+ * @param[in] resolution resolution of DS18B20's temperature conversion
+ * @return
+ *      - ESP_OK: Set resolution successfully
+ *      - ESP_ERR_INVALID_ARG: Set resolution failed due to invalid argument
+ *      - ESP_FAIL: Set resolution failed due to other reasons
+ */
+esp_err_t ds18b20_set_resolution(ds18b20_device_handle_t ds18b20, ds18b20_resolution_t resolution);
+
+/**
+ * @brief Trigger temperature conversion of DS18B20
+ *
+ * @note After send the trigger command, the DS18B20 will start temperature conversion.
+ *       This function will delay for some while, to ensure the temperature conversion won't be interrupted.
+ *
+ * @param[in] ds18b20 DS18B20 device handle returned by `ds18b20_new_device`
+ * @return
+ *      - ESP_OK: Trigger temperature conversion successfully
+ *      - ESP_ERR_INVALID_ARG: Trigger temperature conversion failed due to invalid argument
+ *      - ESP_FAIL: Trigger temperature conversion failed due to other reasons
+ */
+esp_err_t ds18b20_trigger_temperature_conversion(ds18b20_device_handle_t ds18b20);
+
+/**
+ * @brief Get temperature from DS18B20
+ *
+ * @param[in] ds18b20 DS18B20 device handle returned by `ds18b20_new_device`
+ * @param[out] temperature conversion result from DS18B20
+ * @return
+ *      - ESP_OK: Get temperature successfully
+ *      - ESP_ERR_INVALID_ARG: Get temperature failed due to invalid argument
+ *      - ESP_ERR_INVALID_CRC: Get temperature failed due to CRC check error
+ *      - ESP_FAIL: Get temperature failed due to other reasons
+ */
+esp_err_t ds18b20_get_temperature(ds18b20_device_handle_t ds18b20, float *temperature);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_ds18b20/include/ds18b20_types.h b/components/espressif_ds18b20/include/ds18b20_types.h
new file mode 100644
index 0000000..478089c
--- /dev/null
+++ b/components/espressif_ds18b20/include/ds18b20_types.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief DS18B20 supported resolutions
+ */
+typedef enum {
+    DS18B20_RESOLUTION_9B,  /*!<  9bit, needs ~93.75ms convert time */
+    DS18B20_RESOLUTION_10B, /*!< 10bit, needs ~187.5ms convert time */
+    DS18B20_RESOLUTION_11B, /*!< 11bit, needs ~375ms convert time */
+    DS18B20_RESOLUTION_12B, /*!< 12bit, needs ~750ms convert time */
+} ds18b20_resolution_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_ds18b20/src/ds18b20.c b/components/espressif_ds18b20/src/ds18b20.c
new file mode 100644
index 0000000..012a84f
--- /dev/null
+++ b/components/espressif_ds18b20/src/ds18b20.c
@@ -0,0 +1,143 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_check.h"
+#include "onewire_bus.h"
+#include "onewire_cmd.h"
+#include "onewire_crc.h"
+#include "ds18b20.h"
+
+static const char *TAG = "ds18b20";
+
+#define DS18B20_CMD_CONVERT_TEMP      0x44
+#define DS18B20_CMD_WRITE_SCRATCHPAD  0x4E
+#define DS18B20_CMD_READ_SCRATCHPAD   0xBE
+
+/**
+ * @brief Structure of DS18B20's scratchpad
+ */
+typedef struct  {
+    uint8_t temp_lsb;      /*!< lsb of temperature */
+    uint8_t temp_msb;      /*!< msb of temperature */
+    uint8_t th_user1;      /*!< th register or user byte 1 */
+    uint8_t tl_user2;      /*!< tl register or user byte 2 */
+    uint8_t configuration; /*!< resolution configuration register */
+    uint8_t _reserved1;
+    uint8_t _reserved2;
+    uint8_t _reserved3;
+    uint8_t crc_value;     /*!< crc value of scratchpad data */
+} __attribute__((packed)) ds18b20_scratchpad_t;
+
+typedef struct ds18b20_device_t {
+    onewire_bus_handle_t bus;
+    onewire_device_address_t addr;
+    uint8_t th_user1;
+    uint8_t tl_user2;
+    ds18b20_resolution_t resolution;
+} ds18b20_device_t;
+
+esp_err_t ds18b20_new_device(onewire_device_t *device, const ds18b20_config_t *config, ds18b20_device_handle_t *ret_ds18b20)
+{
+    ds18b20_device_t *ds18b20 = NULL;
+    ESP_RETURN_ON_FALSE(device && config && ret_ds18b20, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    // check ROM ID, the family code of DS18B20 is 0x28
+    if ((device->address & 0xFF) != 0x28) {
+        ESP_LOGD(TAG, "%016llX is not a DS18B20 device", device->address);
+        return ESP_ERR_NOT_SUPPORTED;
+    }
+
+    ds18b20 = calloc(1, sizeof(ds18b20_device_t));
+    ESP_RETURN_ON_FALSE(ds18b20, ESP_ERR_NO_MEM, TAG, "no mem for ds18b20");
+    ds18b20->bus = device->bus;
+    ds18b20->addr = device->address;
+    ds18b20->resolution = DS18B20_RESOLUTION_12B; // DS18B20 default resolution is 12 bits
+
+    *ret_ds18b20 = ds18b20;
+    return ESP_OK;
+}
+
+esp_err_t ds18b20_del_device(ds18b20_device_handle_t ds18b20)
+{
+    ESP_RETURN_ON_FALSE(ds18b20, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    free(ds18b20);
+    return ESP_OK;
+}
+
+static esp_err_t ds18b20_send_command(ds18b20_device_handle_t ds18b20, uint8_t cmd)
+{
+    // send command
+    uint8_t tx_buffer[10] = {0};
+    tx_buffer[0] = ONEWIRE_CMD_MATCH_ROM;
+    memcpy(&tx_buffer[1], &ds18b20->addr, sizeof(ds18b20->addr));
+    tx_buffer[sizeof(ds18b20->addr) + 1] = cmd;
+
+    return onewire_bus_write_bytes(ds18b20->bus, tx_buffer, sizeof(tx_buffer));
+}
+
+esp_err_t ds18b20_set_resolution(ds18b20_device_handle_t ds18b20, ds18b20_resolution_t resolution)
+{
+    ESP_RETURN_ON_FALSE(ds18b20, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    // reset bus and check if the ds18b20 is present
+    ESP_RETURN_ON_ERROR(onewire_bus_reset(ds18b20->bus), TAG, "reset bus error");
+
+    // send command: DS18B20_CMD_WRITE_SCRATCHPAD
+    ESP_RETURN_ON_ERROR(ds18b20_send_command(ds18b20, DS18B20_CMD_WRITE_SCRATCHPAD), TAG, "send DS18B20_CMD_WRITE_SCRATCHPAD failed");
+
+    // write new resolution to scratchpad
+    const uint8_t resolution_data[] = {0x1F, 0x3F, 0x5F, 0x7F};
+    uint8_t tx_buffer[3] = {0};
+    tx_buffer[0] = ds18b20->th_user1;
+    tx_buffer[1] = ds18b20->tl_user2;
+    tx_buffer[2] = resolution_data[resolution];
+    ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(ds18b20->bus, tx_buffer, sizeof(tx_buffer)), TAG, "send new resolution failed");
+
+    ds18b20->resolution = resolution;
+    return ESP_OK;
+}
+
+esp_err_t ds18b20_trigger_temperature_conversion(ds18b20_device_handle_t ds18b20)
+{
+    ESP_RETURN_ON_FALSE(ds18b20, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    // reset bus and check if the ds18b20 is present
+    ESP_RETURN_ON_ERROR(onewire_bus_reset(ds18b20->bus), TAG, "reset bus error");
+
+    // send command: DS18B20_CMD_CONVERT_TEMP
+    ESP_RETURN_ON_ERROR(ds18b20_send_command(ds18b20, DS18B20_CMD_CONVERT_TEMP), TAG, "send DS18B20_CMD_CONVERT_TEMP failed");
+
+    // delay proper time for temperature conversion
+    const uint32_t delays_ms[] = {100, 200, 400, 800};
+    vTaskDelay(pdMS_TO_TICKS(delays_ms[ds18b20->resolution]));
+
+    return ESP_OK;
+}
+
+esp_err_t ds18b20_get_temperature(ds18b20_device_handle_t ds18b20, float *ret_temperature)
+{
+    ESP_RETURN_ON_FALSE(ds18b20 && ret_temperature, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    // reset bus and check if the ds18b20 is present
+    ESP_RETURN_ON_ERROR(onewire_bus_reset(ds18b20->bus), TAG, "reset bus error");
+
+    // send command: DS18B20_CMD_READ_SCRATCHPAD
+    ESP_RETURN_ON_ERROR(ds18b20_send_command(ds18b20, DS18B20_CMD_READ_SCRATCHPAD), TAG, "send DS18B20_CMD_READ_SCRATCHPAD failed");
+
+    // read scratchpad data
+    ds18b20_scratchpad_t scratchpad;
+    ESP_RETURN_ON_ERROR(onewire_bus_read_bytes(ds18b20->bus, (uint8_t *)&scratchpad, sizeof(scratchpad)),
+                        TAG, "error while reading scratchpad data");
+    // check crc
+    ESP_RETURN_ON_FALSE(onewire_crc8(0, (uint8_t *)&scratchpad, 8) == scratchpad.crc_value, ESP_ERR_INVALID_CRC, TAG, "scratchpad crc error");
+
+    const uint8_t lsb_mask[4] = {0x07, 0x03, 0x01, 0x00}; // mask bits not used in low resolution
+    uint8_t lsb_masked = scratchpad.temp_lsb & (~lsb_mask[scratchpad.configuration >> 5]);
+    // Combine the MSB and masked LSB into a signed 16-bit integer
+    int16_t temperature_raw = (((int16_t)scratchpad.temp_msb << 8) | lsb_masked);
+    // Convert the raw temperature to a float,
+    *ret_temperature = temperature_raw / 16.0f;
+
+    return ESP_OK;
+}
diff --git a/components/espressif_onewire_bus/.DS_Store b/components/espressif_onewire_bus/.DS_Store
new file mode 100644
index 0000000..314644f
Binary files /dev/null and b/components/espressif_onewire_bus/.DS_Store differ
diff --git a/components/espressif_onewire_bus/CHANGELOG.md b/components/espressif_onewire_bus/CHANGELOG.md
new file mode 100644
index 0000000..4e7a21c
--- /dev/null
+++ b/components/espressif_onewire_bus/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.0.0
+
+- Initial driver version, with the RMT driver as backend controller
diff --git a/components/espressif_onewire_bus/CMakeLists.txt b/components/espressif_onewire_bus/CMakeLists.txt
new file mode 100644
index 0000000..b1b7296
--- /dev/null
+++ b/components/espressif_onewire_bus/CMakeLists.txt
@@ -0,0 +1,6 @@
+idf_component_register(SRCS "src/onewire_bus_api.c"
+                            "src/onewire_bus_impl_rmt.c"
+                            "src/onewire_crc.c"
+                            "src/onewire_device.c"
+                       INCLUDE_DIRS "include" "interface"
+                       PRIV_REQUIRES driver)
diff --git a/components/espressif_onewire_bus/LICENSE b/components/espressif_onewire_bus/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/components/espressif_onewire_bus/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/components/espressif_onewire_bus/README.md b/components/espressif_onewire_bus/README.md
new file mode 100644
index 0000000..afc865e
--- /dev/null
+++ b/components/espressif_onewire_bus/README.md
@@ -0,0 +1,5 @@
+# Dallas 1-Wire Bus Driver
+
+[![Component Registry](https://components.espressif.com/components/espressif/onewire_bus/badge.svg)](https://components.espressif.com/components/espressif/onewire_bus)
+
+This directory contains an implementation for Dallas 1-Wire bus by different peripherals. Currently only RMT is supported as the backend.
diff --git a/components/espressif_onewire_bus/idf_component.yml b/components/espressif_onewire_bus/idf_component.yml
new file mode 100644
index 0000000..35c1ae6
--- /dev/null
+++ b/components/espressif_onewire_bus/idf_component.yml
@@ -0,0 +1,7 @@
+dependencies:
+  idf:
+    version: '>=5.0'
+description: Driver for Dalas 1-Wire bus
+issues: https://github.com/espressif/idf-extra-components/issues
+url: https://github.com/espressif/idf-extra-components/tree/master/onewire_bus
+version: 1.0.1
diff --git a/components/espressif_onewire_bus/include/onewire_bus.h b/components/espressif_onewire_bus/include/onewire_bus.h
new file mode 100644
index 0000000..51206da
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_bus.h
@@ -0,0 +1,90 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include "esp_err.h"
+#include "onewire_types.h"
+#include "onewire_bus_impl_rmt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Write bytes to 1-wire bus
+ *
+ * @param[in] bus 1-Wire bus handle
+ * @param[in] tx_data pointer to data to be sent
+ * @param[in] tx_data_size size of data to be sent, in bytes
+ * @return
+ *      - ESP_OK: Write bytes to 1-Wire bus successfully
+ *      - ESP_ERR_INVALID_ARG: Write bytes to 1-Wire bus failed because of invalid argument
+ *      - ESP_FAIL: Write bytes to 1-Wire bus failed because of other errors
+ */
+esp_err_t onewire_bus_write_bytes(onewire_bus_handle_t bus, const uint8_t *tx_data, uint8_t tx_data_size);
+
+/**
+ * @brief Read bytes from 1-wire bus
+ *
+ * @param[in] bus 1-wire bus handle
+ * @param[out] rx_buf pointer to buffer to store received data
+ * @param[in] rx_buf_size size of buffer to store received data, in bytes
+ * @return
+ *      - ESP_OK: Read bytes from 1-Wire bus successfully
+ *      - ESP_ERR_INVALID_ARG: Read bytes from 1-Wire bus failed because of invalid argument
+ *      - ESP_FAIL: Read bytes from 1-Wire bus failed because of other errors
+ */
+esp_err_t onewire_bus_read_bytes(onewire_bus_handle_t bus, uint8_t *rx_buf, size_t rx_buf_size);
+
+/**
+ * @brief Write a bit to 1-wire bus, this is a blocking function
+ *
+ * @param[in] handle 1-wire bus handle
+ * @param[in] tx_bit bit to transmit, 0 for zero bit, other for one bit
+ * @return
+ *         - ESP_OK                Write bit to 1-wire bus successfully.
+ *         - ESP_ERR_INVALID_ARG   Invalid argument.
+ */
+esp_err_t onewire_bus_write_bit(onewire_bus_handle_t bus, uint8_t tx_bit);
+
+/**
+ * @brief Read a bit from 1-wire bus
+ *
+ * @param[in] handle 1-wire bus handle
+ * @param[out] rx_bit received bit, 0 for zero bit, 1 for one bit
+ * @return
+ *         - ESP_OK                Read bit from 1-wire bus successfully.
+ *         - ESP_ERR_INVALID_ARG   Invalid argument.
+ */
+esp_err_t onewire_bus_read_bit(onewire_bus_handle_t bus, uint8_t *rx_bit);
+
+/**
+ * @brief Send reset pulse to the bus, and check if there are devices attached to the bus
+ *
+ * @param[in] bus 1-Wire bus handle
+ *
+ * @return
+ *      - ESP_OK: Reset 1-Wire bus successfully and find device on the bus
+ *      - ESP_ERR_NOT_FOUND: Reset 1-Wire bus successfully but no device found on the bus
+ *      - ESP_FAIL: Reset 1-Wire bus failed because of other errors
+ */
+esp_err_t onewire_bus_reset(onewire_bus_handle_t bus);
+
+/**
+ * @brief Free 1-Wire bus resources
+ *
+ * @param[in] bus 1-Wire bus handle
+ *
+ * @return
+ *      - ESP_OK: Free resources successfully
+ *      - ESP_FAIL: Free resources failed because error occurred
+ */
+esp_err_t onewire_bus_del(onewire_bus_handle_t bus);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/include/onewire_bus_impl_rmt.h b/components/espressif_onewire_bus/include/onewire_bus_impl_rmt.h
new file mode 100644
index 0000000..6aaee46
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_bus_impl_rmt.h
@@ -0,0 +1,42 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include "esp_err.h"
+#include "onewire_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief 1-Wire bus RMT specific configuration
+ */
+typedef struct {
+    uint32_t max_rx_bytes; /*!< Set the largest possible single receive size,
+                                which determins the size of the internal buffer that used to save the receiving RMT symbols */
+} onewire_bus_rmt_config_t;
+
+/**
+ * @brief Create 1-Wire bus with RMT backend
+ *
+ * @note One 1-Wire bus utilizes a pair of RMT TX and RX channels
+ *
+ * @param[in] bus_config 1-Wire bus configuration
+ * @param[in] rmt_config RMT specific configuration
+ * @param[out] ret_bus Returned 1-Wire bus handle
+ * @return
+ *      - ESP_OK: create 1-Wire bus handle successfully
+ *      - ESP_ERR_INVALID_ARG: create 1-Wire bus handle failed because of invalid argument
+ *      - ESP_ERR_NO_MEM: create 1-Wire bus handle failed because of out of memory
+ *      - ESP_FAIL: create 1-Wire bus handle failed because some other error
+ */
+esp_err_t onewire_new_bus_rmt(const onewire_bus_config_t *bus_config, const onewire_bus_rmt_config_t *rmt_config, onewire_bus_handle_t *ret_bus);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/include/onewire_cmd.h b/components/espressif_onewire_bus/include/onewire_cmd.h
new file mode 100644
index 0000000..5a091b5
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_cmd.h
@@ -0,0 +1,12 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#define ONEWIRE_CMD_SEARCH_NORMAL      0xF0
+#define ONEWIRE_CMD_MATCH_ROM          0x55
+#define ONEWIRE_CMD_SKIP_ROM           0xCC
+#define ONEWIRE_CMD_SEARCH_ALARM       0xEC
+#define ONEWIRE_CMD_READ_POWER_SUPPLY  0xB4
diff --git a/components/espressif_onewire_bus/include/onewire_crc.h b/components/espressif_onewire_bus/include/onewire_crc.h
new file mode 100644
index 0000000..c754d1f
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_crc.h
@@ -0,0 +1,27 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Calculate Dallas CRC8 value of a given buffer
+ *
+ * @param[in] init_crc Initial CRC value
+ * @param[in] input Input buffer to calculate CRC value
+ * @param[in] input_size Size of input buffer, in bytes
+ * @return CRC8 result of the input buffer
+ */
+uint8_t onewire_crc8(uint8_t init_crc, uint8_t *input, size_t input_size);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/include/onewire_device.h b/components/espressif_onewire_bus/include/onewire_device.h
new file mode 100644
index 0000000..fee0c1f
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_device.h
@@ -0,0 +1,63 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include "esp_err.h"
+#include "onewire_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief 1-Wire device generic type
+ */
+typedef struct onewire_device_t {
+    onewire_bus_handle_t bus;         /*!< Which bus the 1-Wire device is attached to */
+    onewire_device_address_t address; /*!< Device address (represented by its internal ROM ID) */
+} onewire_device_t;
+
+/**
+ * @brief Create an iterator to enumerate the 1-Wire devices on the bus
+ *
+ * @param[in] bus 1-Wire bus handle
+ * @param[out] ret_iter Returned created device iterator
+ * @return
+ *      - ESP_OK: Create device iterator successfully
+ *      - ESP_ERR_INVALID_ARG: Invalid argument
+ *      - ESP_ERR_NO_MEM: No memory to create device iterator
+ *      - ESP_FAIL: Other errors
+ */
+esp_err_t onewire_new_device_iter(onewire_bus_handle_t bus, onewire_device_iter_handle_t *ret_iter);
+
+/**
+ * @brief Delete the device iterator
+ *
+ * @param[in] iter Device iterator handle
+ * @return
+ *      - ESP_OK: Delete device iterator successfully
+ *      - ESP_ERR_INVALID_ARG: Invalid argument
+ *      - ESP_FAIL: Other errors
+ */
+esp_err_t onewire_del_device_iter(onewire_device_iter_handle_t iter);
+
+/**
+ * @brief Get the next 1-Wire device from the iterator
+ *
+ * @param[in] iter Device iterator handle
+ * @param[out] dev Returned 1-Wire device handle
+ * @return
+ *      - ESP_OK: Get next device successfully
+ *      - ESP_ERR_INVALID_ARG: Invalid argument
+ *      - ESP_ERR_NOT_FOUND: No more device to get
+ *      - ESP_FAIL: Other errors
+ */
+esp_err_t onewire_device_iter_get_next(onewire_device_iter_handle_t iter, onewire_device_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/include/onewire_types.h b/components/espressif_onewire_bus/include/onewire_types.h
new file mode 100644
index 0000000..6d7b120
--- /dev/null
+++ b/components/espressif_onewire_bus/include/onewire_types.h
@@ -0,0 +1,38 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Type of 1-Wire bus handle
+ */
+typedef struct onewire_bus_t *onewire_bus_handle_t;
+
+/**
+ * @brief Type of the address for a 1-Wire compatible device
+ */
+typedef uint64_t onewire_device_address_t;
+
+/**
+ * @brief Type of 1-Wire device iterator handle
+ */
+typedef struct onewire_device_iter_t *onewire_device_iter_handle_t;
+
+/**
+ * @brief 1-Wire bus configuration
+ */
+typedef struct {
+    int bus_gpio_num; /*!< GPIO number that used by the 1-Wire bus */
+} onewire_bus_config_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/interface/onewire_bus_interface.h b/components/espressif_onewire_bus/interface/onewire_bus_interface.h
new file mode 100644
index 0000000..9920c4e
--- /dev/null
+++ b/components/espressif_onewire_bus/interface/onewire_bus_interface.h
@@ -0,0 +1,97 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct onewire_bus_t onewire_bus_t; /*!< Type of 1-Wire bus */
+
+/**
+ * @brief 1-Wire bus interface definition
+ */
+struct onewire_bus_t {
+    /**
+     * @brief Write bytes to 1-wire bus
+     *
+     * @note This is a blocking function
+     *
+     * @param[in] bus 1-Wire bus handle
+     * @param[in] tx_data pointer to data to be sent
+     * @param[in] tx_data_size size of data to be sent, in bytes
+     * @return
+     *      - ESP_OK: Write bytes to 1-Wire bus successfully
+     *      - ESP_ERR_INVALID_ARG: Write bytes to 1-Wire bus failed because of invalid argument
+     *      - ESP_FAIL: Write bytes to 1-Wire bus failed because of other errors
+     */
+    esp_err_t (*write_bytes)(onewire_bus_t *bus, const uint8_t *tx_data, uint8_t tx_data_size);
+
+    /**
+     * @brief Read bytes from 1-wire bus
+     *
+     * @param[in] bus 1-wire bus handle
+     * @param[out] rx_buf pointer to buffer to store received data
+     * @param[in] rx_buf_size size of buffer to store received data, in bytes
+     * @return
+     *      - ESP_OK: Read bytes from 1-Wire bus successfully
+     *      - ESP_ERR_INVALID_ARG: Read bytes from 1-Wire bus failed because of invalid argument
+     *      - ESP_FAIL: Read bytes from 1-Wire bus failed because of other errors
+     */
+    esp_err_t (*read_bytes)(onewire_bus_t *bus, uint8_t *rx_buf, size_t rx_buf_size);
+
+    /**
+     * @brief Write a bit to 1-wire bus, this is a blocking function
+     *
+     * @param[in] handle 1-wire bus handle
+     * @param[in] tx_bit bit to transmit, 0 for zero bit, other for one bit
+     * @return
+     *         - ESP_OK                Write bit to 1-wire bus successfully.
+     *         - ESP_ERR_INVALID_ARG   Invalid argument.
+     */
+    esp_err_t (*write_bit)(onewire_bus_handle_t handle, uint8_t tx_bit);
+
+    /**
+     * @brief Read a bit from 1-wire bus
+     *
+     * @param[in] handle 1-wire bus handle
+     * @param[out] rx_bit received bit, 0 for zero bit, 1 for one bit
+     * @return
+     *         - ESP_OK                Read bit from 1-wire bus successfully.
+     *         - ESP_ERR_INVALID_ARG   Invalid argument.
+     */
+    esp_err_t (*read_bit)(onewire_bus_handle_t handle, uint8_t *rx_bit);
+
+    /**
+     * @brief Send reset pulse to the bus, and check if there are devices attached to the bus
+     *
+     * @param[in] bus 1-Wire bus handle
+     *
+     * @return
+     *      - ESP_OK: Reset 1-Wire bus successfully and find device on the bus
+     *      - ESP_ERR_NOT_FOUND: Reset 1-Wire bus successfully but no device found on the bus
+     *      - ESP_FAIL: Reset 1-Wire bus failed because of other errors
+     */
+    esp_err_t (*reset)(onewire_bus_t *bus);
+
+    /**
+     * @brief Free 1-Wire bus resources
+     *
+     * @param[in] bus 1-Wire bus handle
+     *
+     * @return
+     *      - ESP_OK: Free resources successfully
+     *      - ESP_FAIL: Free resources failed because error occurred
+     */
+    esp_err_t (*del)(onewire_bus_t *bus);
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/components/espressif_onewire_bus/src/onewire_bus_api.c b/components/espressif_onewire_bus/src/onewire_bus_api.c
new file mode 100644
index 0000000..3cded8f
--- /dev/null
+++ b/components/espressif_onewire_bus/src/onewire_bus_api.c
@@ -0,0 +1,47 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "esp_log.h"
+#include "esp_check.h"
+#include "onewire_types.h"
+#include "onewire_bus_interface.h"
+
+static const char *TAG = "1-wire";
+
+esp_err_t onewire_bus_reset(onewire_bus_handle_t bus)
+{
+    ESP_RETURN_ON_FALSE(bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->reset(bus);
+}
+
+esp_err_t onewire_bus_write_bytes(onewire_bus_handle_t bus, const uint8_t *tx_data, uint8_t tx_data_size)
+{
+    ESP_RETURN_ON_FALSE(bus && tx_data && tx_data_size, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->write_bytes(bus, tx_data, tx_data_size);
+}
+
+esp_err_t onewire_bus_read_bytes(onewire_bus_handle_t bus, uint8_t *rx_buf, size_t rx_buf_size)
+{
+    ESP_RETURN_ON_FALSE(bus && rx_buf && rx_buf_size, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->read_bytes(bus, rx_buf, rx_buf_size);
+}
+
+esp_err_t onewire_bus_write_bit(onewire_bus_handle_t bus, uint8_t tx_bit)
+{
+    ESP_RETURN_ON_FALSE(bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->write_bit(bus, tx_bit);
+}
+
+esp_err_t onewire_bus_read_bit(onewire_bus_handle_t bus, uint8_t *rx_bit)
+{
+    ESP_RETURN_ON_FALSE(bus && rx_bit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->read_bit(bus, rx_bit);
+}
+
+esp_err_t onewire_bus_del(onewire_bus_handle_t bus)
+{
+    ESP_RETURN_ON_FALSE(bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    return bus->del(bus);
+}
diff --git a/components/espressif_onewire_bus/src/onewire_bus_impl_rmt.c b/components/espressif_onewire_bus/src/onewire_bus_impl_rmt.c
new file mode 100644
index 0000000..78243e6
--- /dev/null
+++ b/components/espressif_onewire_bus/src/onewire_bus_impl_rmt.c
@@ -0,0 +1,495 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "esp_check.h"
+#include "esp_attr.h"
+#include "driver/rmt_tx.h"
+#include "driver/rmt_rx.h"
+#include "onewire_bus_impl_rmt.h"
+#include "onewire_bus_interface.h"
+
+static const char *TAG = "1-wire.rmt";
+
+#define ONEWIRE_RMT_RESOLUTION_HZ               1000000 // RMT channel default resolution for 1-wire bus, 1MHz, 1tick = 1us
+#define ONEWIRE_RMT_DEFAULT_TRANS_QUEUE_SIZE    4
+
+// the memory size of each RMT channel, in words (4 bytes)
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+#define ONEWIRE_RMT_DEFAULT_MEM_BLOCK_SYMBOLS   64
+#else
+#define ONEWIRE_RMT_DEFAULT_MEM_BLOCK_SYMBOLS   48
+#endif
+
+// for chips whose RMT RX channel doesn't support ping-pong, we need the user to tell the maximum number of bytes will be received
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+// one RMT symbol represents one bit, so x8
+#define ONEWIRE_RMT_RX_MEM_BLOCK_SIZE           (rmt_config->max_rx_bytes * 8)
+#else // otherwise, we just use one memory block, to save resources
+#define ONEWIRE_RMT_RX_MEM_BLOCK_SIZE           ONEWIRE_RMT_DEFAULT_MEM_BLOCK_SYMBOLS
+#endif
+
+/*
+Reset Pulse:
+
+          | RESET_PULSE | RESET_WAIT_DURATION |
+          | _DURATION   |                     |
+          |             |   | | RESET     |   |
+          |             | * | | _PRESENCE |   |
+          |             |   | | _DURATION |   |
+----------+             +-----+           +--------------
+          |             |     |           |
+          |             |     |           |
+          |             |     |           |
+          +-------------+     +-----------+
+*: RESET_PRESENCE_WAIT_DURATION
+*/
+#define ONEWIRE_RESET_PULSE_DURATION            500 // duration of reset bit
+#define ONEWIRE_RESET_WAIT_DURATION             200 // how long should master wait for device to show its presence
+#define ONEWIRE_RESET_PRESENCE_WAIT_DURATION_MIN 15 // minimum duration for master to wait device to show its presence
+#define ONEWIRE_RESET_PRESENCE_DURATION_MIN      60 // minimum duration for master to recognize device as present
+
+/*
+Write 1 bit:
+
+          | SLOT_START | SLOT_BIT  | SLOT_RECOVERY | NEXT
+          | _DURATION  | _DURATION | _DURATION     | SLOT
+          |            |           |               |
+----------+            +-------------------------------------
+          |            |
+          |            |
+          |            |
+          +------------+
+
+Write 0 bit:
+
+          | SLOT_START | SLOT_BIT  | SLOT_RECOVERY | NEXT
+          | _DURATION  | _DURATION | _DURATION     | SLOT
+          |            |           |               |
+----------+                        +-------------------------
+          |                        |
+          |                        |
+          |                        |
+          +------------------------+
+
+Read 1 bit:
+
+
+          | SLOT_START | SLOT_BIT_DURATION | SLOT_RECOVERY | NEXT
+          | _DURATION  |                   | _DURATION     | SLOT
+          |            | SLOT_BIT_   |     |               |
+          |            | SAMPLE_TIME |     |               |
+----------+            +----------------------------------------------
+          |            |
+          |            |
+          |            |
+          +------------+
+
+Read 0 bit:
+
+          | SLOT_START | SLOT_BIT_DURATION | SLOT_RECOVERY | NEXT
+          | _DURATION  |                   | _DURATION     | SLOT
+          |            | SLOT_BIT_   |     |               |
+          |            | SAMPLE_TIME |     |               |
+----------+            |             |  +-----------------------------
+          |            |                |
+          |            |   PULLED DOWN  |
+          |            |    BY DEVICE   |
+          +-----------------------------+
+*/
+#define ONEWIRE_SLOT_START_DURATION             2  // bit start pulse duration
+#define ONEWIRE_SLOT_BIT_DURATION               60 // duration for each bit to transmit
+// refer to https://www.maximintegrated.com/en/design/technical-documents/app-notes/3/3829.html for more information
+#define ONEWIRE_SLOT_RECOVERY_DURATION          2  // recovery time between each bit, should be longer in parasite power mode
+#define ONEWIRE_SLOT_BIT_SAMPLE_TIME            15 // how long after bit start pulse should the master sample from the bus
+
+typedef struct {
+    onewire_bus_t base; /*!< base class */
+    rmt_channel_handle_t tx_channel; /*!< rmt tx channel handler */
+    rmt_channel_handle_t rx_channel; /*!< rmt rx channel handler */
+
+    rmt_encoder_handle_t tx_bytes_encoder; /*!< used to encode commands and data */
+    rmt_encoder_handle_t tx_copy_encoder; /*!< used to encode reset pulse and bits */
+
+    rmt_symbol_word_t *rx_symbols_buf; /*!< hold rmt raw symbols */
+
+    size_t max_rx_bytes; /*!< buffer size in byte for single receive transaction */
+
+    QueueHandle_t receive_queue;
+    SemaphoreHandle_t bus_mutex;
+} onewire_bus_rmt_obj_t;
+
+static rmt_symbol_word_t onewire_reset_pulse_symbol = {
+    .level0 = 0,
+    .duration0 = ONEWIRE_RESET_PULSE_DURATION,
+    .level1 = 1,
+    .duration1 = ONEWIRE_RESET_WAIT_DURATION
+};
+
+static rmt_symbol_word_t onewire_bit0_symbol = {
+    .level0 = 0,
+    .duration0 = ONEWIRE_SLOT_START_DURATION + ONEWIRE_SLOT_BIT_DURATION,
+    .level1 = 1,
+    .duration1 = ONEWIRE_SLOT_RECOVERY_DURATION
+};
+
+static rmt_symbol_word_t onewire_bit1_symbol = {
+    .level0 = 0,
+    .duration0 = ONEWIRE_SLOT_START_DURATION,
+    .level1 = 1,
+    .duration1 = ONEWIRE_SLOT_BIT_DURATION + ONEWIRE_SLOT_RECOVERY_DURATION
+};
+
+const static rmt_transmit_config_t onewire_rmt_tx_config = {
+    .loop_count = 0,     // no transfer loop
+    .flags.eot_level = 1 // onewire bus should be released in IDLE
+};
+
+const static rmt_receive_config_t onewire_rmt_rx_config = {
+    .signal_range_min_ns = 1000000000 / ONEWIRE_RMT_RESOLUTION_HZ,
+    .signal_range_max_ns = (ONEWIRE_RESET_PULSE_DURATION + ONEWIRE_RESET_WAIT_DURATION) * 1000,
+};
+
+static esp_err_t onewire_bus_rmt_read_bit(onewire_bus_handle_t bus, uint8_t *rx_bit);
+static esp_err_t onewire_bus_rmt_write_bit(onewire_bus_handle_t bus, uint8_t tx_bit);
+static esp_err_t onewire_bus_rmt_read_bytes(onewire_bus_handle_t bus, uint8_t *rx_buf, size_t rx_buf_size);
+static esp_err_t onewire_bus_rmt_write_bytes(onewire_bus_handle_t bus, const uint8_t *tx_data, uint8_t tx_data_size);
+static esp_err_t onewire_bus_rmt_reset(onewire_bus_handle_t bus);
+static esp_err_t onewire_bus_rmt_del(onewire_bus_handle_t bus);
+static esp_err_t onewire_bus_rmt_destroy(onewire_bus_rmt_obj_t *bus_rmt);
+
+IRAM_ATTR
+bool onewire_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
+{
+    BaseType_t task_woken = pdFALSE;
+    onewire_bus_rmt_obj_t *bus_rmt = (onewire_bus_rmt_obj_t *)user_data;
+
+    xQueueSendFromISR(bus_rmt->receive_queue, edata, &task_woken);
+
+    return task_woken;
+}
+
+/*
+[0].0 means symbol[0].duration0
+
+First reset pulse after rmt channel init:
+
+Bus is low | Reset | Wait |  Device  |  Bus Idle
+after init | Pulse |      | Presence |
+                   +------+          +-----------
+                   |      |          |
+                   |      |          |
+                   |      |          |
+-------------------+      +----------+
+                   1      2          3
+
+          [0].1     [0].0     [1].1     [1].0
+
+
+Following reset pulses:
+
+Bus is high | Reset | Wait |  Device  |  Bus Idle
+after init  | Pulse |      | Presence |
+------------+       +------+          +-----------
+            |       |      |          |
+            |       |      |          |
+            |       |      |          |
+            +-------+      +----------+
+            1       2      3          4
+
+              [0].0  [0].1     [1].0    [1].1
+*/
+static bool onewire_rmt_check_presence_pulse(rmt_symbol_word_t *rmt_symbols, size_t symbol_num)
+{
+    bool ret = false;
+    if (symbol_num >= 2) { // there should be at lease 2 symbols(3 or 4 edges)
+        if (rmt_symbols[0].level1 == 1) { // bus is high before reset pulse
+            if (rmt_symbols[0].duration1 > ONEWIRE_RESET_PRESENCE_WAIT_DURATION_MIN &&
+                    rmt_symbols[1].duration0 > ONEWIRE_RESET_PRESENCE_DURATION_MIN) {
+                ret = true;
+            }
+        } else { // bus is low before reset pulse(first pulse after rmt channel init)
+            if (rmt_symbols[0].duration0 > ONEWIRE_RESET_PRESENCE_WAIT_DURATION_MIN &&
+                    rmt_symbols[1].duration1 > ONEWIRE_RESET_PRESENCE_DURATION_MIN) {
+                ret = true;
+            }
+        }
+    }
+    return ret;
+}
+
+static void onewire_rmt_decode_data(rmt_symbol_word_t *rmt_symbols, size_t symbol_num, uint8_t *rx_buf, size_t rx_buf_size)
+{
+    size_t byte_pos = 0;
+    size_t bit_pos = 0;
+    for (size_t i = 0; i < symbol_num; i ++) {
+        if (rmt_symbols[i].duration0 > ONEWIRE_SLOT_BIT_SAMPLE_TIME) { // 0 bit
+            rx_buf[byte_pos] &= ~(1 << bit_pos); // LSB first
+        } else { // 1 bit
+            rx_buf[byte_pos] |= 1 << bit_pos;
+        }
+        bit_pos ++;
+        if (bit_pos >= 8) {
+            bit_pos = 0;
+            byte_pos ++;
+            if (byte_pos >= rx_buf_size) {
+                break;
+            }
+        }
+    }
+}
+
+esp_err_t onewire_new_bus_rmt(const onewire_bus_config_t *bus_config, const onewire_bus_rmt_config_t *rmt_config, onewire_bus_handle_t *ret_bus)
+{
+    esp_err_t ret = ESP_OK;
+    onewire_bus_rmt_obj_t *bus_rmt = NULL;
+    ESP_RETURN_ON_FALSE(bus_config && rmt_config && ret_bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+
+    bus_rmt = calloc(1, sizeof(onewire_bus_rmt_obj_t));
+    ESP_RETURN_ON_FALSE(bus_rmt, ESP_ERR_NO_MEM, TAG, "no mem for onewire_bus_rmt_obj_t");
+
+    // create rmt bytes encoder to transmit 1-wire commands and data
+    rmt_bytes_encoder_config_t bytes_encoder_config = {
+        .bit0 = onewire_bit0_symbol,
+        .bit1 = onewire_bit1_symbol,
+        .flags.msb_first = 0,
+    };
+    ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &bus_rmt->tx_bytes_encoder),
+                      err, TAG, "create bytes encoder failed");
+
+    // create rmt copy encoder to transmit 1-wire reset pulse or bits
+    rmt_copy_encoder_config_t copy_encoder_config = {};
+    ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(&copy_encoder_config, &bus_rmt->tx_copy_encoder),
+                      err, TAG, "create copy encoder failed");
+
+    // Note: must create rmt rx channel before tx channel
+    rmt_rx_channel_config_t onewire_rx_channel_cfg = {
+        .clk_src = RMT_CLK_SRC_DEFAULT,
+        .resolution_hz = ONEWIRE_RMT_RESOLUTION_HZ,
+        .gpio_num = bus_config->bus_gpio_num,
+        .mem_block_symbols = ONEWIRE_RMT_RX_MEM_BLOCK_SIZE,
+    };
+    ESP_GOTO_ON_ERROR(rmt_new_rx_channel(&onewire_rx_channel_cfg, &bus_rmt->rx_channel),
+                      err, TAG, "create rmt rx channel failed");
+
+    // create rmt tx channel
+    rmt_tx_channel_config_t onewire_tx_channel_cfg = {
+        .clk_src = RMT_CLK_SRC_DEFAULT,
+        .resolution_hz = ONEWIRE_RMT_RESOLUTION_HZ,
+        .gpio_num = bus_config->bus_gpio_num,
+        .mem_block_symbols = ONEWIRE_RMT_DEFAULT_MEM_BLOCK_SYMBOLS,
+        .trans_queue_depth = ONEWIRE_RMT_DEFAULT_TRANS_QUEUE_SIZE,
+        .flags.io_loop_back = true, // make tx channel coexist with rx channel on the same gpio pin
+        .flags.io_od_mode = true,   // enable open-drain mode for 1-wire bus
+    };
+    ESP_GOTO_ON_ERROR(rmt_new_tx_channel(&onewire_tx_channel_cfg, &bus_rmt->tx_channel),
+                      err, TAG, "create rmt tx channel failed");
+
+    // allocate rmt rx symbol buffer, one RMT symbol represents one bit, so x8
+    bus_rmt->rx_symbols_buf = malloc(rmt_config->max_rx_bytes * sizeof(rmt_symbol_word_t) * 8);
+    ESP_GOTO_ON_FALSE(bus_rmt->rx_symbols_buf, ESP_ERR_NO_MEM, err, TAG, "no mem to store received RMT symbols");
+    bus_rmt->max_rx_bytes = rmt_config->max_rx_bytes;
+
+    bus_rmt->receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t));
+    ESP_GOTO_ON_FALSE(bus_rmt->receive_queue, ESP_ERR_NO_MEM, err, TAG, "receive queue creation failed");
+
+    bus_rmt->bus_mutex = xSemaphoreCreateMutex();
+    ESP_GOTO_ON_FALSE(bus_rmt->bus_mutex, ESP_ERR_NO_MEM, err, TAG, "bus mutex creation failed");
+
+    // register rmt rx done callback
+    rmt_rx_event_callbacks_t cbs = {
+        .on_recv_done = onewire_rmt_rx_done_callback
+    };
+    ESP_GOTO_ON_ERROR(rmt_rx_register_event_callbacks(bus_rmt->rx_channel, &cbs, bus_rmt),
+                      err, TAG, "enable rmt rx channel failed");
+
+    // enable rmt channels
+    ESP_GOTO_ON_ERROR(rmt_enable(bus_rmt->rx_channel), err, TAG, "enable rmt rx channel failed");
+    ESP_GOTO_ON_ERROR(rmt_enable(bus_rmt->tx_channel), err, TAG, "enable rmt tx channel failed");
+
+    // release the bus by sending a special RMT symbol
+    static rmt_symbol_word_t release_symbol = {
+        .level0 = 1,
+        .duration0 = 1,
+        .level1 = 1,
+        .duration1 = 0,
+    };
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_copy_encoder, &release_symbol,
+                                   sizeof(release_symbol), &onewire_rmt_tx_config), err, TAG, "release bus failed");
+
+    bus_rmt->base.del = onewire_bus_rmt_del;
+    bus_rmt->base.reset = onewire_bus_rmt_reset;
+    bus_rmt->base.write_bit = onewire_bus_rmt_write_bit;
+    bus_rmt->base.write_bytes = onewire_bus_rmt_write_bytes;
+    bus_rmt->base.read_bit = onewire_bus_rmt_read_bit;
+    bus_rmt->base.read_bytes = onewire_bus_rmt_read_bytes;
+    *ret_bus = &bus_rmt->base;
+
+    return ret;
+
+err:
+    if (bus_rmt) {
+        onewire_bus_rmt_destroy(bus_rmt);
+    }
+
+    return ret;
+}
+
+static esp_err_t onewire_bus_rmt_destroy(onewire_bus_rmt_obj_t *bus_rmt)
+{
+    if (bus_rmt->tx_bytes_encoder) {
+        rmt_del_encoder(bus_rmt->tx_bytes_encoder);
+    }
+    if (bus_rmt->tx_copy_encoder) {
+        rmt_del_encoder(bus_rmt->tx_copy_encoder);
+    }
+    if (bus_rmt->rx_channel) {
+        rmt_disable(bus_rmt->rx_channel);
+        rmt_del_channel(bus_rmt->rx_channel);
+    }
+    if (bus_rmt->tx_channel) {
+        rmt_disable(bus_rmt->tx_channel);
+        rmt_del_channel(bus_rmt->tx_channel);
+    }
+    if (bus_rmt->receive_queue) {
+        vQueueDelete(bus_rmt->receive_queue);
+    }
+    if (bus_rmt->bus_mutex) {
+        vSemaphoreDelete(bus_rmt->bus_mutex);
+    }
+    if (bus_rmt->rx_symbols_buf) {
+        free(bus_rmt->rx_symbols_buf);
+    }
+    free(bus_rmt);
+    return ESP_OK;
+}
+
+static esp_err_t onewire_bus_rmt_del(onewire_bus_handle_t bus)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    return onewire_bus_rmt_destroy(bus_rmt);
+}
+
+static esp_err_t onewire_bus_rmt_reset(onewire_bus_handle_t bus)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    esp_err_t ret = ESP_OK;
+
+    xSemaphoreTake(bus_rmt->bus_mutex, portMAX_DELAY);
+    // send reset pulse while receive presence pulse
+    ESP_GOTO_ON_ERROR(rmt_receive(bus_rmt->rx_channel, bus_rmt->rx_symbols_buf, sizeof(rmt_symbol_word_t) * 2, &onewire_rmt_rx_config),
+                      err, TAG, "1-wire reset pulse receive failed");
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_copy_encoder, &onewire_reset_pulse_symbol, sizeof(onewire_reset_pulse_symbol), &onewire_rmt_tx_config),
+                      err, TAG, "1-wire reset pulse transmit failed");
+
+    // wait and check presence pulse
+    rmt_rx_done_event_data_t rmt_rx_evt_data;
+    ESP_GOTO_ON_FALSE(xQueueReceive(bus_rmt->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS,
+                      ESP_ERR_TIMEOUT, err, TAG, "1-wire reset pulse receive timeout");
+    if (onewire_rmt_check_presence_pulse(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols) == false) {
+        ret = ESP_ERR_NOT_FOUND;
+    }
+
+err:
+    xSemaphoreGive(bus_rmt->bus_mutex);
+    return ret;
+}
+
+static esp_err_t onewire_bus_rmt_write_bytes(onewire_bus_handle_t bus, const uint8_t *tx_data, uint8_t tx_data_size)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    esp_err_t ret = ESP_OK;
+
+    xSemaphoreTake(bus_rmt->bus_mutex, portMAX_DELAY);
+    // transmit data with the bytes encoder
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_bytes_encoder, tx_data, tx_data_size, &onewire_rmt_tx_config),
+                      err, TAG, "1-wire data transmit failed");
+    // wait the transmission to complete
+    ESP_GOTO_ON_ERROR(rmt_tx_wait_all_done(bus_rmt->tx_channel, 50), err, TAG, "wait for 1-wire data transmit failed");
+
+err:
+    xSemaphoreGive(bus_rmt->bus_mutex);
+    return ret;
+}
+
+// While receiving data, we use rmt transmit channel to send 0xFF to generate read pulse,
+// at the same time, receive channel is used to record weather the bus is pulled down by device.
+static esp_err_t onewire_bus_rmt_read_bytes(onewire_bus_handle_t bus, uint8_t *rx_buf, size_t rx_buf_size)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE(rx_buf_size <= bus_rmt->max_rx_bytes, ESP_ERR_INVALID_ARG, TAG, "rx_buf_size too large for buffer to hold");
+    memset(rx_buf, 0, rx_buf_size);
+
+    xSemaphoreTake(bus_rmt->bus_mutex, portMAX_DELAY);
+
+    // transmit one bits to generate read clock
+    uint8_t tx_buffer[rx_buf_size];
+    memset(tx_buffer, 0xFF, rx_buf_size);
+    // transmit 1 bits while receiving
+    ESP_GOTO_ON_ERROR(rmt_receive(bus_rmt->rx_channel, bus_rmt->rx_symbols_buf, rx_buf_size * 8 * sizeof(rmt_symbol_word_t), &onewire_rmt_rx_config),
+                      err, TAG, "1-wire data receive failed");
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_bytes_encoder, tx_buffer, sizeof(tx_buffer), &onewire_rmt_tx_config),
+                      err, TAG, "1-wire data transmit failed");
+
+    // wait the transmission finishes and decode data
+    rmt_rx_done_event_data_t rmt_rx_evt_data;
+    ESP_GOTO_ON_FALSE(xQueueReceive(bus_rmt->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS, ESP_ERR_TIMEOUT,
+                      err, TAG, "1-wire data receive timeout");
+    onewire_rmt_decode_data(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols, rx_buf, rx_buf_size);
+
+err:
+    xSemaphoreGive(bus_rmt->bus_mutex);
+    return ret;
+}
+
+static esp_err_t onewire_bus_rmt_write_bit(onewire_bus_handle_t bus, uint8_t tx_bit)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    const rmt_symbol_word_t *symbol_to_transmit = tx_bit ? &onewire_bit1_symbol : &onewire_bit0_symbol;
+    esp_err_t ret = ESP_OK;
+
+    xSemaphoreTake(bus_rmt->bus_mutex, portMAX_DELAY);
+
+    // transmit bit
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_copy_encoder, symbol_to_transmit, sizeof(rmt_symbol_word_t), &onewire_rmt_tx_config),
+                      err, TAG, "1-wire bit transmit failed");
+    // wait the transmission to complete
+    ESP_GOTO_ON_ERROR(rmt_tx_wait_all_done(bus_rmt->tx_channel, 50), err, TAG, "wait for 1-wire bit transmit failed");
+
+err:
+    xSemaphoreGive(bus_rmt->bus_mutex);
+    return ret;
+}
+
+static esp_err_t onewire_bus_rmt_read_bit(onewire_bus_handle_t bus, uint8_t *rx_bit)
+{
+    onewire_bus_rmt_obj_t *bus_rmt = __containerof(bus, onewire_bus_rmt_obj_t, base);
+    esp_err_t ret = ESP_OK;
+
+    xSemaphoreTake(bus_rmt->bus_mutex, portMAX_DELAY);
+
+    // transmit 1 bit while receiving
+    ESP_GOTO_ON_ERROR(rmt_receive(bus_rmt->rx_channel, bus_rmt->rx_symbols_buf, sizeof(rmt_symbol_word_t), &onewire_rmt_rx_config),
+                      err, TAG, "1-wire bit receive failed");
+    ESP_GOTO_ON_ERROR(rmt_transmit(bus_rmt->tx_channel, bus_rmt->tx_copy_encoder, &onewire_bit1_symbol, sizeof(rmt_symbol_word_t), &onewire_rmt_tx_config),
+                      err, TAG, "1-wire bit transmit failed");
+
+    // wait the transmission finishes and decode data
+    rmt_rx_done_event_data_t rmt_rx_evt_data;
+    ESP_GOTO_ON_FALSE(xQueueReceive(bus_rmt->receive_queue, &rmt_rx_evt_data, pdMS_TO_TICKS(1000)) == pdPASS, ESP_ERR_TIMEOUT,
+                      err, TAG, "1-wire bit receive timeout");
+    uint8_t rx_buffer = 0;
+    onewire_rmt_decode_data(rmt_rx_evt_data.received_symbols, rmt_rx_evt_data.num_symbols, &rx_buffer, sizeof(rx_buffer));
+    *rx_bit = rx_buffer & 0x01;
+
+err:
+    xSemaphoreGive(bus_rmt->bus_mutex);
+    return ret;
+}
diff --git a/components/espressif_onewire_bus/src/onewire_crc.c b/components/espressif_onewire_bus/src/onewire_crc.c
new file mode 100644
index 0000000..81595b1
--- /dev/null
+++ b/components/espressif_onewire_bus/src/onewire_crc.c
@@ -0,0 +1,60 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "onewire_crc.h"
+
+#define FAST_CRC 1 // define this to use the fast CRC table
+
+#if FAST_CRC
+
+static const uint8_t dalas_crc8_table[] = {
+    0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
+    157, 195, 33, 127, 252, 162, 64, 30, 95,  1, 227, 189, 62, 96, 130, 220,
+    35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93,  3, 128, 222, 60, 98,
+    190, 224,  2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
+    70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89,  7,
+    219, 133, 103, 57, 186, 228,  6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
+    101, 59, 217, 135,  4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
+    248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91,  5, 231, 185,
+    140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
+    17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
+    175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
+    50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
+    202, 148, 118, 40, 171, 245, 23, 73,  8, 86, 180, 234, 105, 55, 213, 139,
+    87,  9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
+    233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
+    116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
+};
+
+uint8_t onewire_crc8(uint8_t init_crc, uint8_t *input, size_t input_size)
+{
+    uint8_t crc = init_crc;
+    for (size_t i = 0; i < input_size; i ++) {
+        crc = dalas_crc8_table[crc ^ input[i]];
+    }
+    return crc;
+}
+
+#else // FAST_CRC
+
+uint8_t onewire_crc8(uint8_t init_crc, uint8_t *input, size_t input_size)
+{
+    uint8_t crc = init_crc;
+    for (size_t i = 0; i < input_size; i++) {
+        uint8_t byte = input[i];
+        for (int j = 0; j < 8; j++) {
+            uint8_t x = (byte ^ crc) & 0x01;
+            crc >>= 1;
+            if (x != 0) {
+                crc ^= 0x8C;
+            }
+            byte >>= 1;
+        }
+    }
+    return crc;
+}
+
+#endif // FAST_CRC
diff --git a/components/espressif_onewire_bus/src/onewire_device.c b/components/espressif_onewire_bus/src/onewire_device.c
new file mode 100644
index 0000000..82a1e32
--- /dev/null
+++ b/components/espressif_onewire_bus/src/onewire_device.c
@@ -0,0 +1,124 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+#include <stdbool.h>
+#include "esp_check.h"
+#include "esp_log.h"
+#include "onewire_bus.h"
+#include "onewire_device.h"
+#include "onewire_crc.h"
+#include "onewire_cmd.h"
+
+static const char *TAG = "1-wire.device";
+
+typedef struct onewire_device_iter_t {
+    onewire_bus_handle_t bus;
+    uint16_t last_discrepancy;
+    bool is_last_device;
+    uint8_t rom_number[sizeof(onewire_device_address_t)];
+} onewire_device_iter_t;
+
+esp_err_t onewire_new_device_iter(onewire_bus_handle_t bus, onewire_device_iter_handle_t *ret_iter)
+{
+    ESP_RETURN_ON_FALSE(bus && ret_iter, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+
+    onewire_device_iter_t *iter = calloc(1, sizeof(onewire_device_iter_t));
+    ESP_RETURN_ON_FALSE(iter, ESP_ERR_NO_MEM, TAG, "no mem for device iterator");
+
+    iter->bus = bus;
+    *ret_iter = iter;
+
+    return ESP_OK;
+}
+
+esp_err_t onewire_del_device_iter(onewire_device_iter_handle_t iter)
+{
+    ESP_RETURN_ON_FALSE(iter, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+
+    free(iter);
+
+    return ESP_OK;
+}
+
+// Search algorithm inspired by https://www.analog.com/en/app-notes/1wire-search-algorithm.html
+esp_err_t onewire_device_iter_get_next(onewire_device_iter_handle_t iter, onewire_device_t *dev)
+{
+    ESP_RETURN_ON_FALSE(iter && dev, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    // we don't treat iterator ending and ESP_ERR_NOT_FOUND as an error condition, so just print debug message here
+    if (iter->is_last_device) {
+        ESP_LOGD(TAG, "1-wire rom search finished");
+        return ESP_ERR_NOT_FOUND;
+    }
+    onewire_bus_handle_t bus = iter->bus;
+    esp_err_t reset_result = onewire_bus_reset(bus);
+    if (reset_result == ESP_ERR_NOT_FOUND) {
+        ESP_LOGW(TAG, "reset bus failed: no devices found");
+        return ESP_ERR_NOT_FOUND;
+    }
+    ESP_RETURN_ON_ERROR(reset_result, TAG, "reset bus failed");
+
+    // send rom search command and start search algorithm
+    ESP_RETURN_ON_ERROR(onewire_bus_write_bytes(bus, (uint8_t[]) {
+        ONEWIRE_CMD_SEARCH_NORMAL
+    }, 1), TAG, "send ONEWIRE_CMD_SEARCH_NORMAL failed");
+
+    uint8_t last_zero = 0;
+    for (uint16_t rom_bit_index = 0; rom_bit_index < sizeof(onewire_device_address_t) * 8; rom_bit_index ++) {
+        uint8_t rom_byte_index = rom_bit_index / 8;
+        uint8_t rom_bit_mask = 1 << (rom_bit_index % 8); // calculate byte index and bit mask in advance for convenience
+
+        uint8_t rom_bit = 0;
+        uint8_t rom_bit_complement = 0;
+        ESP_RETURN_ON_ERROR(onewire_bus_read_bit(bus, &rom_bit), TAG, "read rom_bit error"); // write 1 bit to read from the bus
+        ESP_RETURN_ON_ERROR(onewire_bus_read_bit(bus, &rom_bit_complement), TAG, "read rom_bit_complement error"); // read a bit and its complement
+
+        // No devices participating in search.
+        if (rom_bit && rom_bit_complement) {
+            ESP_LOGE(TAG, "no devices participating in search");
+            return ESP_ERR_NOT_FOUND;
+        }
+
+        uint8_t search_direction;
+        if (rom_bit != rom_bit_complement) { // There are only 0s or 1s in the bit of the participating ROM numbers.
+            search_direction = rom_bit;  // just go ahead
+        } else { // There are both 0s and 1s in the current bit position of the participating ROM numbers. This is a discrepancy.
+            if (rom_bit_index < iter->last_discrepancy) { // current id bit is before the last discrepancy bit
+                search_direction = (iter->rom_number[rom_byte_index] & rom_bit_mask) ? 0x01 : 0x00; // follow previous way
+            } else {
+                search_direction = (rom_bit_index == iter->last_discrepancy) ? 0x01 : 0x00; // search for 0 bit first
+            }
+
+            if (search_direction == 0) { // record zero's position in last zero
+                last_zero = rom_bit_index;
+            }
+        }
+
+        if (search_direction == 1) { // set corrsponding rom bit by search direction
+            iter->rom_number[rom_byte_index] |= rom_bit_mask;
+        } else {
+            iter->rom_number[rom_byte_index] &= ~rom_bit_mask;
+        }
+
+        // set search direction
+        ESP_RETURN_ON_ERROR(onewire_bus_write_bit(bus, search_direction), TAG, "write direction bit error");
+    }
+
+    // if the search was successful
+    iter->last_discrepancy = last_zero;
+    if (iter->last_discrepancy == 0) { // last zero loops back to the first bit
+        iter->is_last_device = true;
+    }
+
+    // check crc
+    ESP_RETURN_ON_FALSE(onewire_crc8(0, iter->rom_number, 7) == iter->rom_number[7], ESP_ERR_INVALID_CRC, TAG, "bad device crc");
+
+    // save the ROM number as the device address
+    memcpy(&dev->address, iter->rom_number, sizeof(onewire_device_address_t));
+    dev->bus = bus;
+    ESP_LOGD(TAG, "new 1-Wire device found, address: %016llX", dev->address);
+
+    return ESP_OK;
+}
diff --git a/components/onewire/.DS_Store b/components/onewire/.DS_Store
new file mode 100644
index 0000000..87de984
Binary files /dev/null and b/components/onewire/.DS_Store differ
diff --git a/components/onewire/CMakeLists.txt b/components/onewire/CMakeLists.txt
new file mode 100644
index 0000000..8e81547
--- /dev/null
+++ b/components/onewire/CMakeLists.txt
@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's CMakeLists
+# in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(onewire)
diff --git a/components/onewire/README.md b/components/onewire/README.md
new file mode 100644
index 0000000..1cb065e
--- /dev/null
+++ b/components/onewire/README.md
@@ -0,0 +1,74 @@
+| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
+
+# Advanced RMT Transmit & Receive Example -- Simulate 1-Wire Bus
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+RMT peripheral has independent transmit and receive channels. We can simulate the [1-Wire](https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html) bus by attaching a pair of transmit and receive channel to the same GPIO, and turning on the open-drain mode of the GPIO pad.
+
+We've made the 1-Wire protocol implementation into a component called `onewire_bus`, which has been uploaded to the [component registry](https://components.espressif.com/components/espressif/onewire_bus).
+
+This example demonstrates how to use that `onewire_bus` library to read temperature from the [DS18B20](https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf) sensor. Likewise, the DS18B20 device is also made as a single component and pushed to the [component registry](https://components.espressif.com/components/espressif/ds18b20).
+
+One of the amazing feature that offered by the `onewire_bus` driver is that, is can support enumerate the devices on the bus, thus you can connect multiple DS18B20 sensors to the same bus and read their temperature one by one.
+
+## How to Use Example
+
+### Hardware Required
+
+* A development board with any supported Espressif SOC chip (see `Supported Targets` table above)
+* One or more DS18B20 sensors connected to the same bus by a 4.7 KΩ pull-up resistor
+
+Connection :
+
+```plain
+┌──────────────────────────┐
+│                      3.3V├───────┬─────────────┬──────────────────────┐
+│                          │      ┌┴┐            │VDD                   │VDD
+│          ESP Board       │  4.7k│ │     ┌──────┴──────┐        ┌──────┴──────┐
+│                          │      └┬┘   DQ│             │      DQ│             │
+│          ONEWIRE_GPIO_PIN├───────┴──┬───┤   DS18B20   │    ┌───┤   DS18B20   │   ......
+│                          │          └───│-------------│────┴───│-------------│──
+│                          │              └──────┬──────┘        └──────┬──────┘
+│                          │                     │GND                   │GND
+│                       GND├─────────────────────┴──────────────────────┘
+└──────────────────────────┘
+```
+
+The GPIO number used in this example can be changed according to your board, by the macro `EXAMPLE_ONEWIRE_BUS_GPIO` defined in [onewire_example_main.c](main/onewire_example_main.c).
+
+> **Note**
+> Parasite power mode is not supported, you have to connect VDD pin to make DS18B20 functional.
+
+### Build and Flash
+
+Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
+
+## Console Output
+
+```plain
+I (340) main_task: Started on CPU0
+I (350) main_task: Calling app_main()
+I (350) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
+I (360) gpio: GPIO[0]| InputEn: 1| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0
+I (370) example: 1-Wire bus installed on GPIO0
+I (370) example: Device iterator created, start searching...
+I (490) example: Found a DS18B20[0], address: 070822502019FC28
+I (590) example: Found a DS18B20[1], address: FC0921C076034628
+I (590) example: Searching done, 2 DS18B20 device(s) found
+I (1620) example: temperature read from DS18B20[0]: 22.50C
+I (2430) example: temperature read from DS18B20[1]: 22.81C
+I (3440) example: temperature read from DS18B20[0]: 22.50C
+I (4250) example: temperature read from DS18B20[1]: 22.81C
+I (5260) example: temperature read from DS18B20[0]: 22.50C
+I (6070) example: temperature read from DS18B20[1]: 22.81C
+```
+
+## Troubleshooting
+
+For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
diff --git a/components/onewire/main/CMakeLists.txt b/components/onewire/main/CMakeLists.txt
new file mode 100644
index 0000000..cc6bae1
--- /dev/null
+++ b/components/onewire/main/CMakeLists.txt
@@ -0,0 +1,2 @@
+idf_component_register(SRCS "onewire_example_main.c"
+                       INCLUDE_DIRS ".")
diff --git a/components/onewire/main/idf_component.yml b/components/onewire/main/idf_component.yml
new file mode 100644
index 0000000..1ca3e8b
--- /dev/null
+++ b/components/onewire/main/idf_component.yml
@@ -0,0 +1,2 @@
+dependencies:
+  ds18b20: "^0.1.0"
diff --git a/components/onewire/main/onewire_example_main.c b/components/onewire/main/onewire_example_main.c
new file mode 100644
index 0000000..d3c3b41
--- /dev/null
+++ b/components/onewire/main/onewire_example_main.c
@@ -0,0 +1,76 @@
+/*
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "onewire_bus.h"
+#include "ds18b20.h"
+
+static const char *TAG = "example";
+
+#define EXAMPLE_ONEWIRE_BUS_GPIO    0
+#define EXAMPLE_ONEWIRE_MAX_DS18B20 2
+
+void app_main(void)
+{
+    // install new 1-wire bus
+    onewire_bus_handle_t bus;
+    onewire_bus_config_t bus_config = {
+        .bus_gpio_num = EXAMPLE_ONEWIRE_BUS_GPIO,
+    };
+    onewire_bus_rmt_config_t rmt_config = {
+        .max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command
+    };
+    ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &bus));
+    ESP_LOGI(TAG, "1-Wire bus installed on GPIO%d", EXAMPLE_ONEWIRE_BUS_GPIO);
+
+    int ds18b20_device_num = 0;
+    ds18b20_device_handle_t ds18b20s[EXAMPLE_ONEWIRE_MAX_DS18B20];
+    onewire_device_iter_handle_t iter = NULL;
+    onewire_device_t next_onewire_device;
+    esp_err_t search_result = ESP_OK;
+
+    // create 1-wire device iterator, which is used for device search
+    ESP_ERROR_CHECK(onewire_new_device_iter(bus, &iter));
+    ESP_LOGI(TAG, "Device iterator created, start searching...");
+    do {
+        search_result = onewire_device_iter_get_next(iter, &next_onewire_device);
+        if (search_result == ESP_OK) { // found a new device, let's check if we can upgrade it to a DS18B20
+            ds18b20_config_t ds_cfg = {};
+            if (ds18b20_new_device(&next_onewire_device, &ds_cfg, &ds18b20s[ds18b20_device_num]) == ESP_OK) {
+                ESP_LOGI(TAG, "Found a DS18B20[%d], address: %016llX", ds18b20_device_num, next_onewire_device.address);
+                ds18b20_device_num++;
+                if (ds18b20_device_num >= EXAMPLE_ONEWIRE_MAX_DS18B20) {
+                    ESP_LOGI(TAG, "Max DS18B20 number reached, stop searching...");
+                    break;
+                }
+            } else {
+                ESP_LOGI(TAG, "Found an unknown device, address: %016llX", next_onewire_device.address);
+            }
+        }
+    } while (search_result != ESP_ERR_NOT_FOUND);
+    ESP_ERROR_CHECK(onewire_del_device_iter(iter));
+    ESP_LOGI(TAG, "Searching done, %d DS18B20 device(s) found", ds18b20_device_num);
+
+    // set resolution for all DS18B20s
+    for (int i = 0; i < ds18b20_device_num; i++) {
+        // set resolution
+        ESP_ERROR_CHECK(ds18b20_set_resolution(ds18b20s[i], DS18B20_RESOLUTION_12B));
+    }
+
+    // get temperature from sensors one by one
+    float temperature;
+    while (1) {
+        vTaskDelay(pdMS_TO_TICKS(200));
+
+        for (int i = 0; i < ds18b20_device_num; i ++) {
+            ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20s[i]));
+            ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20s[i], &temperature));
+            ESP_LOGI(TAG, "temperature read from DS18B20[%d]: %.2fC", i, temperature);
+        }
+    }
+}
diff --git a/components/onewire/pytest_onewire.py b/components/onewire/pytest_onewire.py
new file mode 100644
index 0000000..fc7c045
--- /dev/null
+++ b/components/onewire/pytest_onewire.py
@@ -0,0 +1,17 @@
+# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: Unlicense OR CC0-1.0
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.esp32s2
+@pytest.mark.esp32s3
+@pytest.mark.esp32c3
+@pytest.mark.esp32c6
+@pytest.mark.esp32h2
+@pytest.mark.generic
+def test_onewire_example(dut: Dut) -> None:
+    dut.expect_exact('example: 1-Wire bus installed on GPIO')
+    dut.expect_exact('example: Device iterator created, start searching')
+    dut.expect_exact('example: Searching done')
diff --git a/components/zh_onewire/zh_onewire.c b/components/zh_onewire/zh_onewire.c
index 4d94a3f..ab8c226 100644
--- a/components/zh_onewire/zh_onewire.c
+++ b/components/zh_onewire/zh_onewire.c
@@ -119,11 +119,29 @@ esp_err_t zh_onewire_reset(void)
 
 void zh_onewire_send_byte(uint8_t byte)
 {
+    ESP_LOGI(TAG, "Onewire send byte begin.");
     for (uint8_t i = 0; i < 8; ++i)
     {
         _send_bit(byte & 1);
         byte >>= 1;
     }
+    ESP_LOGI(TAG, "Onewire send byte success.");
+}
+
+uint8_t zh_onewire_read_byte(void)
+{
+    ESP_LOGI(TAG, "Onewire read byte begin.");
+    uint8_t byte = 0;
+    for (uint8_t i = 0; i < 8; ++i)
+    {
+        byte >>= 1;
+        if (_read_bit() != 0)
+        {
+            byte |= 0x80;
+        }
+    }
+    ESP_LOGI(TAG, "Onewire read byte success.");
+    return byte;
 }
 
 esp_err_t zh_onewire_skip_rom(void)
@@ -287,20 +305,6 @@ uint8_t *zh_onewire_search_rom_next(void)
     return &_rom[0];
 }
 
-uint8_t zh_onewire_read_byte(void)
-{
-    uint8_t byte = 0;
-    for (uint8_t i = 0; i < 8; ++i)
-    {
-        byte >>= 1;
-        if (_read_bit() != 0)
-        {
-            byte |= 0x80;
-        }
-    }
-    return byte;
-}
-
 static uint8_t _read_bit(void)
 {
     gpio_set_direction(_pin, GPIO_MODE_OUTPUT);