mirror of
https://github.com/esphome/esphome.git
synced 2025-11-04 17:11:51 +00:00
Compare commits
170 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75c9823899 | ||
|
|
c8c0bd3351 | ||
|
|
e1cdeb7c8f | ||
|
|
7f97f42552 | ||
|
|
aa7f3569ec | ||
|
|
2d0a08442e | ||
|
|
d2380756b2 | ||
|
|
925e3cb6c9 | ||
|
|
6757acba56 | ||
|
|
5cc91cdd95 | ||
|
|
2b41886819 | ||
|
|
72c6efd6a0 | ||
|
|
a1f1804112 | ||
|
|
a8b1ceb4e9 | ||
|
|
4fb0f7f8c6 | ||
|
|
958cadeca8 | ||
|
|
00f2655f1a | ||
|
|
074f5029eb | ||
|
|
1691976587 | ||
|
|
60e6b4d21e | ||
|
|
5750591df2 | ||
|
|
a75da54455 | ||
|
|
de7f6c3f5f | ||
|
|
4245480656 | ||
|
|
1824c8131e | ||
|
|
4e9606d2e0 | ||
|
|
78500fa933 | ||
|
|
9c69b98a49 | ||
|
|
e6d8ef98d3 | ||
|
|
3f1af1690b | ||
|
|
84374b6b1e | ||
|
|
391316c9b5 | ||
|
|
705c62ebd7 | ||
|
|
cb520c00a5 | ||
|
|
2f24138345 | ||
|
|
96512b80cc | ||
|
|
fcb9b51978 | ||
|
|
f408f1a368 | ||
|
|
7d8d563c62 | ||
|
|
0a1f705fda | ||
|
|
1952c1880b | ||
|
|
b03967dac1 | ||
|
|
bcae2596a6 | ||
|
|
fc0347c86c | ||
|
|
d9563d4de1 | ||
|
|
cc7e2bf8db | ||
|
|
5d98e2923b | ||
|
|
07197d12f6 | ||
|
|
7b0a298497 | ||
|
|
21679cf2ba | ||
|
|
4be7cd12a1 | ||
|
|
dee4d0ccb7 | ||
|
|
c6885c1bf4 | ||
|
|
8b8efb57af | ||
|
|
499e120aa4 | ||
|
|
6f198a4736 | ||
|
|
f500f448b1 | ||
|
|
6ad9baa870 | ||
|
|
f843925301 | ||
|
|
4a3b628946 | ||
|
|
4ffdc38cf5 | ||
|
|
f83f1bff19 | ||
|
|
9370ff3dfa | ||
|
|
2053b02c61 | ||
|
|
f34e797a0d | ||
|
|
30a2fc1273 | ||
|
|
48da5ef1c4 | ||
|
|
7209dd8bae | ||
|
|
ab736c89bb | ||
|
|
6911639617 | ||
|
|
dbbbba3cf8 | ||
|
|
16e523ca68 | ||
|
|
3b2bbd306f | ||
|
|
54caed36f7 | ||
|
|
dfcccda69e | ||
|
|
de352c1609 | ||
|
|
c30068fc97 | ||
|
|
f28f712827 | ||
|
|
b9720d0715 | ||
|
|
47b3267ed4 | ||
|
|
e16ba2adb5 | ||
|
|
0a19b1e32c | ||
|
|
bae9a950c0 | ||
|
|
b63ade298f | ||
|
|
f117d4f50a | ||
|
|
6e4267b797 | ||
|
|
2dd032475b | ||
|
|
db0ed055dd | ||
|
|
106c1bfac2 | ||
|
|
eb2a0f45db | ||
|
|
2b4fdd6c39 | ||
|
|
3669320398 | ||
|
|
d706f40ce1 | ||
|
|
027284c29c | ||
|
|
c55e01ff3f | ||
|
|
a59ce7bfa2 | ||
|
|
a6196267c9 | ||
|
|
eb664b99ba | ||
|
|
8414bb9a7a | ||
|
|
ccef7c322f | ||
|
|
120327866f | ||
|
|
bc5c2d4eb4 | ||
|
|
d5ff8f6117 | ||
|
|
ad0d6f6337 | ||
|
|
873de13b3d | ||
|
|
56de8e5cc4 | ||
|
|
73c82862cf | ||
|
|
75573a3ed1 | ||
|
|
1166d93805 | ||
|
|
ac112a32c9 | ||
|
|
cee45c1221 | ||
|
|
fb56b5388e | ||
|
|
ed42cefeee | ||
|
|
9052947a71 | ||
|
|
53e0af18fb | ||
|
|
c5f59fad62 | ||
|
|
b089a4ea80 | ||
|
|
72b2943332 | ||
|
|
4ec0ef7548 | ||
|
|
25bc6761f6 | ||
|
|
81b6562c25 | ||
|
|
ae74189fc2 | ||
|
|
555bba7698 | ||
|
|
294901fbe9 | ||
|
|
ec576bf9f9 | ||
|
|
9273e3775b | ||
|
|
ce5cedb466 | ||
|
|
b184b01600 | ||
|
|
81b4078871 | ||
|
|
d067c8f80b | ||
|
|
8975b4b3f6 | ||
|
|
20da03f8c6 | ||
|
|
ef26677b67 | ||
|
|
91925b1826 | ||
|
|
1f33ad037d | ||
|
|
fef60e335e | ||
|
|
195c78846f | ||
|
|
0f9c956c04 | ||
|
|
7258a82875 | ||
|
|
c1f696c32a | ||
|
|
f2b63d9c67 | ||
|
|
7896a7783b | ||
|
|
621771e1ee | ||
|
|
2b032e8606 | ||
|
|
5e1b724697 | ||
|
|
e6db61c2f0 | ||
|
|
c2e198311c | ||
|
|
d874626662 | ||
|
|
eead72333e | ||
|
|
719c212009 | ||
|
|
65030e1c37 | ||
|
|
3f88b63920 | ||
|
|
f7b1602adf | ||
|
|
147b113b62 | ||
|
|
392dc8b0db | ||
|
|
2f62426f09 | ||
|
|
cb2d9e4bec | ||
|
|
9e3ee28744 | ||
|
|
472dcebf2c | ||
|
|
9f30f53c6b | ||
|
|
2f18ae00c5 | ||
|
|
27a339fa12 | ||
|
|
2c2e68123a | ||
|
|
fcec7d45cb | ||
|
|
7c8f502e7e | ||
|
|
dc17c47634 | ||
|
|
3d927c2f44 | ||
|
|
0ae61410d2 | ||
|
|
2455589f61 | ||
|
|
3155f02be6 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -177,7 +177,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run yamllint
|
- name: Run yamllint
|
||||||
if: matrix.id == 'yamllint'
|
if: matrix.id == 'yamllint'
|
||||||
uses: frenck/action-yamllint@v1.3.0
|
uses: frenck/action-yamllint@v1.3.1
|
||||||
|
|
||||||
- name: Suggested changes
|
- name: Suggested changes
|
||||||
run: script/ci-suggest-changes
|
run: script/ci-suggest-changes
|
||||||
|
|||||||
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
lock:
|
lock:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v3
|
- uses: dessant/lock-threads@v4
|
||||||
with:
|
with:
|
||||||
pr-inactive-days: "1"
|
pr-inactive-days: "1"
|
||||||
pr-lock-reason: ""
|
pr-lock-reason: ""
|
||||||
|
|||||||
91
.github/workflows/release.yml
vendored
91
.github/workflows/release.yml
vendored
@@ -30,6 +30,10 @@ jobs:
|
|||||||
TAG=$(cat esphome/const.py | sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p")
|
TAG=$(cat esphome/const.py | sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p")
|
||||||
today="$(date --utc '+%Y%m%d')"
|
today="$(date --utc '+%Y%m%d')"
|
||||||
TAG="${TAG}${today}"
|
TAG="${TAG}${today}"
|
||||||
|
BRANCH=${GITHUB_REF#refs/heads/}
|
||||||
|
if [[ "$BRANCH" != "dev" ]]; then
|
||||||
|
TAG="${TAG}-${BRANCH}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||||
# yamllint enable rule:line-length
|
# yamllint enable rule:line-length
|
||||||
@@ -57,7 +61,7 @@ jobs:
|
|||||||
run: twine upload dist/*
|
run: twine upload dist/*
|
||||||
|
|
||||||
deploy-docker:
|
deploy-docker:
|
||||||
name: Build and publish docker containers
|
name: Build and publish ESPHome ${{ matrix.image.title}}
|
||||||
if: github.repository == 'esphome/esphome'
|
if: github.repository == 'esphome/esphome'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -66,8 +70,19 @@ jobs:
|
|||||||
needs: [init]
|
needs: [init]
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: [amd64, armv7, aarch64]
|
image:
|
||||||
build_type: ["ha-addon", "docker", "lint"]
|
- title: "ha-addon"
|
||||||
|
suffix: "hassio"
|
||||||
|
target: "hassio"
|
||||||
|
baseimg: "hassio"
|
||||||
|
- title: "docker"
|
||||||
|
suffix: ""
|
||||||
|
target: "docker"
|
||||||
|
baseimg: "docker"
|
||||||
|
- title: "lint"
|
||||||
|
suffix: "lint"
|
||||||
|
target: "lint"
|
||||||
|
baseimg: "docker"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
@@ -92,54 +107,29 @@ jobs:
|
|||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Generate short tags
|
||||||
|
id: tags
|
||||||
|
run: |
|
||||||
|
docker/generate_tags.py \
|
||||||
|
--tag "${{ needs.init.outputs.tag }}" \
|
||||||
|
--suffix "${{ matrix.image.suffix }}"
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
run: |
|
uses: docker/build-push-action@v3
|
||||||
docker/build.py \
|
|
||||||
--tag "${{ needs.init.outputs.tag }}" \
|
|
||||||
--arch "${{ matrix.arch }}" \
|
|
||||||
--build-type "${{ matrix.build_type }}" \
|
|
||||||
build \
|
|
||||||
--push
|
|
||||||
|
|
||||||
deploy-docker-manifest:
|
|
||||||
if: github.repository == 'esphome/esphome'
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [init, deploy-docker]
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
build_type: ["ha-addon", "docker", "lint"]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
with:
|
||||||
python-version: "3.9"
|
context: .
|
||||||
- name: Enable experimental manifest support
|
file: ./docker/Dockerfile
|
||||||
run: |
|
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||||
mkdir -p ~/.docker
|
target: ${{ matrix.image.target }}
|
||||||
echo "{\"experimental\": \"enabled\"}" > ~/.docker/config.json
|
push: true
|
||||||
|
# yamllint disable rule:line-length
|
||||||
- name: Log in to docker hub
|
cache-from: type=registry,ref=ghcr.io/${{ steps.tags.outputs.image }}:cache-${{ steps.tags.outputs.channel }}
|
||||||
uses: docker/login-action@v2
|
cache-to: type=registry,ref=ghcr.io/${{ steps.tags.outputs.image }}:cache-${{ steps.tags.outputs.channel }},mode=max
|
||||||
with:
|
# yamllint enable rule:line-length
|
||||||
username: ${{ secrets.DOCKER_USER }}
|
tags: ${{ steps.tags.outputs.tags }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
build-args: |
|
||||||
- name: Log in to the GitHub container registry
|
BASEIMGTYPE=${{ matrix.image.baseimg }}
|
||||||
uses: docker/login-action@v2
|
BUILD_VERSION=${{ needs.init.outputs.tag }}
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Run manifest
|
|
||||||
run: |
|
|
||||||
docker/build.py \
|
|
||||||
--tag "${{ needs.init.outputs.tag }}" \
|
|
||||||
--build-type "${{ matrix.build_type }}" \
|
|
||||||
manifest
|
|
||||||
|
|
||||||
deploy-ha-addon-repo:
|
deploy-ha-addon-repo:
|
||||||
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
|
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
|
||||||
@@ -150,11 +140,10 @@ jobs:
|
|||||||
TOKEN: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
|
TOKEN: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
|
||||||
# yamllint disable rule:line-length
|
# yamllint disable rule:line-length
|
||||||
run: |
|
run: |
|
||||||
TAG="${GITHUB_REF#refs/tags/}"
|
|
||||||
curl \
|
curl \
|
||||||
-u ":$TOKEN" \
|
-u ":$TOKEN" \
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
https://api.github.com/repos/esphome/home-assistant-addon/actions/workflows/bump-version.yml/dispatches \
|
https://api.github.com/repos/esphome/home-assistant-addon/actions/workflows/bump-version.yml/dispatches \
|
||||||
-d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$TAG\"}}"
|
-d '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}","content":${{ toJSON(github.event.release.body) }}}}'
|
||||||
# yamllint enable rule:line-length
|
# yamllint enable rule:line-length
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ repos:
|
|||||||
- --quiet
|
- --quiet
|
||||||
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
|
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 5.0.4
|
rev: 6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
@@ -27,7 +27,7 @@ repos:
|
|||||||
- --branch=release
|
- --branch=release
|
||||||
- --branch=beta
|
- --branch=beta
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.2.0
|
rev: v3.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py39-plus]
|
args: [--py39-plus]
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ esphome/components/sim800l/* @glmnet
|
|||||||
esphome/components/sm2135/* @BoukeHaarsma23
|
esphome/components/sm2135/* @BoukeHaarsma23
|
||||||
esphome/components/sml/* @alengwenus
|
esphome/components/sml/* @alengwenus
|
||||||
esphome/components/smt100/* @piechade
|
esphome/components/smt100/* @piechade
|
||||||
|
esphome/components/sn74hc165/* @jesserockz
|
||||||
esphome/components/socket/* @esphome/core
|
esphome/components/socket/* @esphome/core
|
||||||
esphome/components/sonoff_d1/* @anatoly-savchenkov
|
esphome/components/sonoff_d1/* @anatoly-savchenkov
|
||||||
esphome/components/spi/* @esphome/core
|
esphome/components/spi/* @esphome/core
|
||||||
|
|||||||
@@ -6,17 +6,14 @@
|
|||||||
ARG BASEIMGTYPE=docker
|
ARG BASEIMGTYPE=docker
|
||||||
|
|
||||||
# https://github.com/hassio-addons/addon-debian-base/releases
|
# https://github.com/hassio-addons/addon-debian-base/releases
|
||||||
FROM ghcr.io/hassio-addons/debian-base/amd64:5.3.0 AS base-hassio-amd64
|
FROM ghcr.io/hassio-addons/debian-base:6.1.3 AS base-hassio
|
||||||
FROM ghcr.io/hassio-addons/debian-base/aarch64:5.3.0 AS base-hassio-arm64
|
|
||||||
FROM ghcr.io/hassio-addons/debian-base/armv7:5.3.0 AS base-hassio-armv7
|
|
||||||
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye
|
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye
|
||||||
FROM debian:bullseye-20220328-slim AS base-docker-amd64
|
FROM debian:bullseye-20221024-slim AS base-docker
|
||||||
FROM debian:bullseye-20220328-slim AS base-docker-arm64
|
|
||||||
FROM debian:bullseye-20220328-slim AS base-docker-armv7
|
|
||||||
|
|
||||||
# Use TARGETARCH/TARGETVARIANT defined by docker
|
FROM base-${BASEIMGTYPE} AS base
|
||||||
# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
|
|
||||||
FROM base-${BASEIMGTYPE}-${TARGETARCH}${TARGETVARIANT} AS base
|
ARG TARGETARCH
|
||||||
|
ARG TARGETVARIANT
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apt-get update \
|
apt-get update \
|
||||||
@@ -29,8 +26,8 @@ RUN \
|
|||||||
python3-cryptography=3.3.2-1 \
|
python3-cryptography=3.3.2-1 \
|
||||||
iputils-ping=3:20210202-1 \
|
iputils-ping=3:20210202-1 \
|
||||||
git=1:2.30.2-1 \
|
git=1:2.30.2-1 \
|
||||||
curl=7.74.0-1.3+deb11u1 \
|
curl=7.74.0-1.3+deb11u3 \
|
||||||
openssh-client=1:8.4p1-5 \
|
openssh-client=1:8.4p1-5+deb11u1 \
|
||||||
&& rm -rf \
|
&& rm -rf \
|
||||||
/tmp/* \
|
/tmp/* \
|
||||||
/var/{cache,log}/* \
|
/var/{cache,log}/* \
|
||||||
@@ -42,6 +39,14 @@ ENV \
|
|||||||
# Store globally installed pio libs in /piolibs
|
# Store globally installed pio libs in /piolibs
|
||||||
PLATFORMIO_GLOBALLIB_DIR=/piolibs
|
PLATFORMIO_GLOBALLIB_DIR=/piolibs
|
||||||
|
|
||||||
|
# Support legacy binaries on Debian multiarch system. There is no "correct" way
|
||||||
|
# to do this, other than using properly built toolchains...
|
||||||
|
# See: https://unix.stackexchange.com/questions/553743/correct-way-to-add-lib-ld-linux-so-3-in-debian
|
||||||
|
RUN \
|
||||||
|
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
|
||||||
|
ln -s /lib/arm-linux-gnueabihf/ld-linux.so.3 /lib/ld-linux.so.3; \
|
||||||
|
fi
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
# Ubuntu python3-pip is missing wheel
|
# Ubuntu python3-pip is missing wheel
|
||||||
pip3 install --no-cache-dir \
|
pip3 install --no-cache-dir \
|
||||||
@@ -134,7 +139,7 @@ RUN \
|
|||||||
clang-tidy-11=1:11.0.1-2 \
|
clang-tidy-11=1:11.0.1-2 \
|
||||||
patch=2.7.6-7 \
|
patch=2.7.6-7 \
|
||||||
software-properties-common=0.96.20.2-2.1 \
|
software-properties-common=0.96.20.2-2.1 \
|
||||||
nano=5.4-2+deb11u1 \
|
nano=5.4-2+deb11u2 \
|
||||||
build-essential=12.9 \
|
build-essential=12.9 \
|
||||||
python3-dev=3.9.2-3 \
|
python3-dev=3.9.2-3 \
|
||||||
&& rm -rf \
|
&& rm -rf \
|
||||||
|
|||||||
68
docker/generate_tags.py
Executable file
68
docker/generate_tags.py
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
|
||||||
|
CHANNEL_DEV = "dev"
|
||||||
|
CHANNEL_BETA = "beta"
|
||||||
|
CHANNEL_RELEASE = "release"
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--tag",
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help="The main docker tag to push to. If a version number also adds latest and/or beta tag",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--suffix",
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help="The suffix of the tag.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# detect channel from tag
|
||||||
|
match = re.match(r"^(\d+\.\d+)(?:\.\d+)?(b\d+)?$", args.tag)
|
||||||
|
major_minor_version = None
|
||||||
|
if match is None:
|
||||||
|
channel = CHANNEL_DEV
|
||||||
|
elif match.group(2) is None:
|
||||||
|
major_minor_version = match.group(1)
|
||||||
|
channel = CHANNEL_RELEASE
|
||||||
|
else:
|
||||||
|
channel = CHANNEL_BETA
|
||||||
|
|
||||||
|
tags_to_push = [args.tag]
|
||||||
|
if channel == CHANNEL_DEV:
|
||||||
|
tags_to_push.append("dev")
|
||||||
|
elif channel == CHANNEL_BETA:
|
||||||
|
tags_to_push.append("beta")
|
||||||
|
elif channel == CHANNEL_RELEASE:
|
||||||
|
# Additionally push to beta
|
||||||
|
tags_to_push.append("beta")
|
||||||
|
tags_to_push.append("latest")
|
||||||
|
|
||||||
|
if major_minor_version:
|
||||||
|
tags_to_push.append("stable")
|
||||||
|
tags_to_push.append(major_minor_version)
|
||||||
|
|
||||||
|
suffix = f"-{args.suffix}" if args.suffix else ""
|
||||||
|
|
||||||
|
with open(os.environ["GITHUB_OUTPUT"], "w") as f:
|
||||||
|
print(f"channel={channel}", file=f)
|
||||||
|
print(f"image=esphome/esphome{suffix}", file=f)
|
||||||
|
full_tags = []
|
||||||
|
|
||||||
|
for tag in tags_to_push:
|
||||||
|
full_tags += [f"ghcr.io/esphome/esphome{suffix}:{tag}"]
|
||||||
|
full_tags += [f"esphome/esphome{suffix}:{tag}"]
|
||||||
|
print(f"tags={','.join(full_tags)}", file=f)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
0
docker/ha-addon-rootfs/etc/cont-init.d/30-dirs.sh
Normal file → Executable file
0
docker/ha-addon-rootfs/etc/cont-init.d/30-dirs.sh
Normal file → Executable file
@@ -3,7 +3,13 @@
|
|||||||
# Community Hass.io Add-ons: ESPHome
|
# Community Hass.io Add-ons: ESPHome
|
||||||
# Take down the S6 supervision tree when ESPHome fails
|
# Take down the S6 supervision tree when ESPHome fails
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
if -n { s6-test $# -ne 0 }
|
|
||||||
if -n { s6-test ${1} -eq 256 }
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
declare APP_EXIT_CODE=${1}
|
||||||
|
|
||||||
|
if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then
|
||||||
|
bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}"
|
||||||
|
echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode
|
||||||
|
exec /run/s6/basedir/bin/halt
|
||||||
|
fi
|
||||||
|
|
||||||
|
bashio::log.info "Service restart after closing"
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ if bashio::config.has_value 'relative_url'; then
|
|||||||
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
|
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if bashio::config.has_value 'default_compile_process_limit'; then
|
||||||
|
export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=$(bashio::config 'default_compile_process_limit')
|
||||||
|
else
|
||||||
|
if grep -q 'Raspberry Pi 3' /proc/cpuinfo; then
|
||||||
|
export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=1;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
pio_cache_base=/data/cache/platformio
|
pio_cache_base=/data/cache/platformio
|
||||||
# we can't set core_dir, because the settings file is stored in `core_dir/appstate.json`
|
# we can't set core_dir, because the settings file is stored in `core_dir/appstate.json`
|
||||||
# setting `core_dir` would therefore prevent pio from accessing
|
# setting `core_dir` would therefore prevent pio from accessing
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
# Community Hass.io Add-ons: ESPHome
|
# Community Hass.io Add-ons: ESPHome
|
||||||
# Take down the S6 supervision tree when NGINX fails
|
# Take down the S6 supervision tree when NGINX fails
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
if -n { s6-test $# -ne 0 }
|
|
||||||
if -n { s6-test ${1} -eq 256 }
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
declare APP_EXIT_CODE=${1}
|
||||||
|
|
||||||
|
if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then
|
||||||
|
bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}"
|
||||||
|
echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode
|
||||||
|
exec /run/s6/basedir/bin/halt
|
||||||
|
fi
|
||||||
|
|
||||||
|
bashio::log.info "Service restart after closing"
|
||||||
|
|||||||
@@ -254,8 +254,7 @@ def upload_using_esptool(config, port):
|
|||||||
if os.environ.get("ESPHOME_USE_SUBPROCESS") is None:
|
if os.environ.get("ESPHOME_USE_SUBPROCESS") is None:
|
||||||
import esptool
|
import esptool
|
||||||
|
|
||||||
# pylint: disable=protected-access
|
return run_external_command(esptool.main, *cmd) # pylint: disable=no-member
|
||||||
return run_external_command(esptool._main, *cmd)
|
|
||||||
|
|
||||||
return run_external_process(*cmd)
|
return run_external_process(*cmd)
|
||||||
|
|
||||||
@@ -298,6 +297,8 @@ def upload_program(config, args, host):
|
|||||||
ota_conf = config[CONF_OTA]
|
ota_conf = config[CONF_OTA]
|
||||||
remote_port = ota_conf[CONF_PORT]
|
remote_port = ota_conf[CONF_PORT]
|
||||||
password = ota_conf.get(CONF_PASSWORD, "")
|
password = ota_conf.get(CONF_PASSWORD, "")
|
||||||
|
if getattr(args, "file", None) is not None:
|
||||||
|
return espota2.run_ota(host, remote_port, password, args.file)
|
||||||
return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
|
return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
|
||||||
|
|
||||||
|
|
||||||
@@ -687,6 +688,10 @@ def parse_args(argv):
|
|||||||
"--device",
|
"--device",
|
||||||
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
|
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
|
||||||
)
|
)
|
||||||
|
parser_upload.add_argument(
|
||||||
|
"--file",
|
||||||
|
help="Manually specify the binary file to upload.",
|
||||||
|
)
|
||||||
|
|
||||||
parser_logs = subparsers.add_parser(
|
parser_logs = subparsers.add_parser(
|
||||||
"logs",
|
"logs",
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ void A4988::loop() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this->dir_pin_->digital_write(dir == 1);
|
this->dir_pin_->digital_write(dir == 1);
|
||||||
|
delayMicroseconds(50);
|
||||||
this->step_pin_->digital_write(true);
|
this->step_pin_->digital_write(true);
|
||||||
delayMicroseconds(5);
|
delayMicroseconds(5);
|
||||||
this->step_pin_->digital_write(false);
|
this->step_pin_->digital_write(false);
|
||||||
|
|||||||
@@ -117,10 +117,11 @@ void ADCSensor::dump_config() {
|
|||||||
}
|
}
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
if (this->is_temperature_)
|
if (this->is_temperature_) {
|
||||||
ESP_LOGCONFIG(TAG, " Pin: Temperature");
|
ESP_LOGCONFIG(TAG, " Pin: Temperature");
|
||||||
else
|
} else {
|
||||||
LOG_PIN(" Pin: ", pin_);
|
LOG_PIN(" Pin: ", pin_);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/components/display/display_buffer.h"
|
#include "esphome/components/display/display_buffer.h"
|
||||||
#include "esphome/components/light/addressable_light.h"
|
#include "esphome/components/light/addressable_light.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace addressable_light {
|
namespace addressable_light {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/components/i2c/i2c.h"
|
#include "esphome/components/i2c/i2c.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ade7953 {
|
namespace ade7953 {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/components/i2c/i2c.h"
|
#include "esphome/components/i2c/i2c.h"
|
||||||
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ads1115 {
|
namespace ads1115 {
|
||||||
|
|
||||||
|
|||||||
@@ -122,8 +122,9 @@ void AHT10Component::update() {
|
|||||||
this->temperature_sensor_->publish_state(temperature);
|
this->temperature_sensor_->publish_state(temperature);
|
||||||
}
|
}
|
||||||
if (this->humidity_sensor_ != nullptr) {
|
if (this->humidity_sensor_ != nullptr) {
|
||||||
if (std::isnan(humidity))
|
if (std::isnan(humidity)) {
|
||||||
ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum");
|
ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum");
|
||||||
|
}
|
||||||
this->humidity_sensor_->publish_state(humidity);
|
this->humidity_sensor_->publish_state(humidity);
|
||||||
}
|
}
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
|
|||||||
@@ -104,8 +104,9 @@ void Am43::update() {
|
|||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->current_sensor_++;
|
this->current_sensor_++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,9 @@ void Am43Component::control(const CoverCall &call) {
|
|||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
|
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (call.get_position().has_value()) {
|
if (call.get_position().has_value()) {
|
||||||
auto pos = *call.get_position();
|
auto pos = *call.get_position();
|
||||||
@@ -68,8 +69,9 @@ void Am43Component::control(const CoverCall &call) {
|
|||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
|
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,18 +128,21 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
|
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
|
||||||
this->char_handle_, packet->length, packet->data,
|
this->char_handle_, packet->length, packet->data,
|
||||||
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
|
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
|
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_)
|
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
|
||||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
|
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_)
|
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
|
||||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
|
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -37,16 +37,18 @@ void Anova::control(const ClimateCall &call) {
|
|||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (call.get_target_temperature().has_value()) {
|
if (call.get_target_temperature().has_value()) {
|
||||||
auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
|
auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
|
||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,8 +145,9 @@ void Anova::update() {
|
|||||||
auto status =
|
auto status =
|
||||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||||
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status)
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
|
||||||
|
}
|
||||||
this->current_request_++;
|
this->current_request_++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -915,6 +915,7 @@ message ListEntitiesNumberResponse {
|
|||||||
EntityCategory entity_category = 10;
|
EntityCategory entity_category = 10;
|
||||||
string unit_of_measurement = 11;
|
string unit_of_measurement = 11;
|
||||||
NumberMode mode = 12;
|
NumberMode mode = 12;
|
||||||
|
string device_class = 13;
|
||||||
}
|
}
|
||||||
message NumberStateResponse {
|
message NumberStateResponse {
|
||||||
option (id) = 50;
|
option (id) = 50;
|
||||||
@@ -1140,6 +1141,8 @@ message BluetoothLEAdvertisementResponse {
|
|||||||
repeated string service_uuids = 4;
|
repeated string service_uuids = 4;
|
||||||
repeated BluetoothServiceData service_data = 5;
|
repeated BluetoothServiceData service_data = 5;
|
||||||
repeated BluetoothServiceData manufacturer_data = 6;
|
repeated BluetoothServiceData manufacturer_data = 6;
|
||||||
|
|
||||||
|
uint32 address_type = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BluetoothDeviceRequestType {
|
enum BluetoothDeviceRequestType {
|
||||||
@@ -1147,6 +1150,8 @@ enum BluetoothDeviceRequestType {
|
|||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1;
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2;
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
|
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4;
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothDeviceRequest {
|
message BluetoothDeviceRequest {
|
||||||
@@ -1156,6 +1161,8 @@ message BluetoothDeviceRequest {
|
|||||||
|
|
||||||
uint64 address = 1;
|
uint64 address = 1;
|
||||||
BluetoothDeviceRequestType request_type = 2;
|
BluetoothDeviceRequestType request_type = 2;
|
||||||
|
bool has_address_type = 3;
|
||||||
|
uint32 address_type = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothDeviceConnectionResponse {
|
message BluetoothDeviceConnectionResponse {
|
||||||
|
|||||||
@@ -616,6 +616,7 @@ bool APIConnection::send_number_info(number::Number *number) {
|
|||||||
msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
|
msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
|
||||||
msg.unit_of_measurement = number->traits.get_unit_of_measurement();
|
msg.unit_of_measurement = number->traits.get_unit_of_measurement();
|
||||||
msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
|
msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
|
||||||
|
msg.device_class = number->traits.get_device_class();
|
||||||
|
|
||||||
msg.min_value = number->traits.get_min_value();
|
msg.min_value = number->traits.get_min_value();
|
||||||
msg.max_value = number->traits.get_max_value();
|
msg.max_value = number->traits.get_max_value();
|
||||||
@@ -949,7 +950,7 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|||||||
resp.webserver_port = USE_WEBSERVER_PORT;
|
resp.webserver_port = USE_WEBSERVER_PORT;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_BLUETOOTH_PROXY
|
#ifdef USE_BLUETOOTH_PROXY
|
||||||
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active() ? 2 : 1;
|
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active() ? 3 : 1;
|
||||||
#endif
|
#endif
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) {
|
template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::ENTITY_CATEGORY_NONE:
|
case enums::ENTITY_CATEGORY_NONE:
|
||||||
@@ -18,6 +19,8 @@ template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::Entity
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::LegacyCoverState value) {
|
template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::LegacyCoverState value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LEGACY_COVER_STATE_OPEN:
|
case enums::LEGACY_COVER_STATE_OPEN:
|
||||||
@@ -28,6 +31,8 @@ template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::Lega
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverOperation value) {
|
template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverOperation value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::COVER_OPERATION_IDLE:
|
case enums::COVER_OPERATION_IDLE:
|
||||||
@@ -40,6 +45,8 @@ template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverO
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::LegacyCoverCommand>(enums::LegacyCoverCommand value) {
|
template<> const char *proto_enum_to_string<enums::LegacyCoverCommand>(enums::LegacyCoverCommand value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LEGACY_COVER_COMMAND_OPEN:
|
case enums::LEGACY_COVER_COMMAND_OPEN:
|
||||||
@@ -52,6 +59,8 @@ template<> const char *proto_enum_to_string<enums::LegacyCoverCommand>(enums::Le
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::FanSpeed>(enums::FanSpeed value) {
|
template<> const char *proto_enum_to_string<enums::FanSpeed>(enums::FanSpeed value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::FAN_SPEED_LOW:
|
case enums::FAN_SPEED_LOW:
|
||||||
@@ -64,6 +73,8 @@ template<> const char *proto_enum_to_string<enums::FanSpeed>(enums::FanSpeed val
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::FanDirection>(enums::FanDirection value) {
|
template<> const char *proto_enum_to_string<enums::FanDirection>(enums::FanDirection value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::FAN_DIRECTION_FORWARD:
|
case enums::FAN_DIRECTION_FORWARD:
|
||||||
@@ -74,6 +85,8 @@ template<> const char *proto_enum_to_string<enums::FanDirection>(enums::FanDirec
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ColorMode>(enums::ColorMode value) {
|
template<> const char *proto_enum_to_string<enums::ColorMode>(enums::ColorMode value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::COLOR_MODE_UNKNOWN:
|
case enums::COLOR_MODE_UNKNOWN:
|
||||||
@@ -100,6 +113,8 @@ template<> const char *proto_enum_to_string<enums::ColorMode>(enums::ColorMode v
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::SensorStateClass>(enums::SensorStateClass value) {
|
template<> const char *proto_enum_to_string<enums::SensorStateClass>(enums::SensorStateClass value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::STATE_CLASS_NONE:
|
case enums::STATE_CLASS_NONE:
|
||||||
@@ -114,6 +129,8 @@ template<> const char *proto_enum_to_string<enums::SensorStateClass>(enums::Sens
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::SensorLastResetType>(enums::SensorLastResetType value) {
|
template<> const char *proto_enum_to_string<enums::SensorLastResetType>(enums::SensorLastResetType value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LAST_RESET_NONE:
|
case enums::LAST_RESET_NONE:
|
||||||
@@ -126,6 +143,8 @@ template<> const char *proto_enum_to_string<enums::SensorLastResetType>(enums::S
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel value) {
|
template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LOG_LEVEL_NONE:
|
case enums::LOG_LEVEL_NONE:
|
||||||
@@ -148,6 +167,8 @@ template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel val
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) {
|
template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::SERVICE_ARG_TYPE_BOOL:
|
case enums::SERVICE_ARG_TYPE_BOOL:
|
||||||
@@ -170,6 +191,8 @@ template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::Servic
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMode value) {
|
template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMode value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::CLIMATE_MODE_OFF:
|
case enums::CLIMATE_MODE_OFF:
|
||||||
@@ -190,6 +213,8 @@ template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMo
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ClimateFanMode>(enums::ClimateFanMode value) {
|
template<> const char *proto_enum_to_string<enums::ClimateFanMode>(enums::ClimateFanMode value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::CLIMATE_FAN_ON:
|
case enums::CLIMATE_FAN_ON:
|
||||||
@@ -214,6 +239,8 @@ template<> const char *proto_enum_to_string<enums::ClimateFanMode>(enums::Climat
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ClimateSwingMode>(enums::ClimateSwingMode value) {
|
template<> const char *proto_enum_to_string<enums::ClimateSwingMode>(enums::ClimateSwingMode value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::CLIMATE_SWING_OFF:
|
case enums::CLIMATE_SWING_OFF:
|
||||||
@@ -228,6 +255,8 @@ template<> const char *proto_enum_to_string<enums::ClimateSwingMode>(enums::Clim
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::ClimateAction value) {
|
template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::ClimateAction value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::CLIMATE_ACTION_OFF:
|
case enums::CLIMATE_ACTION_OFF:
|
||||||
@@ -246,6 +275,8 @@ template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::Climate
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::ClimatePreset value) {
|
template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::ClimatePreset value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::CLIMATE_PRESET_NONE:
|
case enums::CLIMATE_PRESET_NONE:
|
||||||
@@ -268,6 +299,8 @@ template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::Climate
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode value) {
|
template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::NUMBER_MODE_AUTO:
|
case enums::NUMBER_MODE_AUTO:
|
||||||
@@ -280,6 +313,8 @@ template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::LockState>(enums::LockState value) {
|
template<> const char *proto_enum_to_string<enums::LockState>(enums::LockState value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LOCK_STATE_NONE:
|
case enums::LOCK_STATE_NONE:
|
||||||
@@ -298,6 +333,8 @@ template<> const char *proto_enum_to_string<enums::LockState>(enums::LockState v
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::LockCommand>(enums::LockCommand value) {
|
template<> const char *proto_enum_to_string<enums::LockCommand>(enums::LockCommand value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::LOCK_UNLOCK:
|
case enums::LOCK_UNLOCK:
|
||||||
@@ -310,6 +347,8 @@ template<> const char *proto_enum_to_string<enums::LockCommand>(enums::LockComma
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::MediaPlayerState>(enums::MediaPlayerState value) {
|
template<> const char *proto_enum_to_string<enums::MediaPlayerState>(enums::MediaPlayerState value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::MEDIA_PLAYER_STATE_NONE:
|
case enums::MEDIA_PLAYER_STATE_NONE:
|
||||||
@@ -324,6 +363,8 @@ template<> const char *proto_enum_to_string<enums::MediaPlayerState>(enums::Medi
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<> const char *proto_enum_to_string<enums::MediaPlayerCommand>(enums::MediaPlayerCommand value) {
|
template<> const char *proto_enum_to_string<enums::MediaPlayerCommand>(enums::MediaPlayerCommand value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case enums::MEDIA_PLAYER_COMMAND_PLAY:
|
case enums::MEDIA_PLAYER_COMMAND_PLAY:
|
||||||
@@ -340,6 +381,8 @@ template<> const char *proto_enum_to_string<enums::MediaPlayerCommand>(enums::Me
|
|||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
template<>
|
template<>
|
||||||
const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::BluetoothDeviceRequestType value) {
|
const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::BluetoothDeviceRequestType value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
@@ -351,10 +394,15 @@ const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::Bluet
|
|||||||
return "BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR";
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR";
|
||||||
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR:
|
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR:
|
||||||
return "BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR";
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR";
|
||||||
|
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE:
|
||||||
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE";
|
||||||
|
case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE:
|
||||||
|
return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case 2: {
|
case 2: {
|
||||||
@@ -3942,6 +3990,10 @@ bool ListEntitiesNumberResponse::decode_length(uint32_t field_id, ProtoLengthDel
|
|||||||
this->unit_of_measurement = value.as_string();
|
this->unit_of_measurement = value.as_string();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 13: {
|
||||||
|
this->device_class = value.as_string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3981,6 +4033,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
|
||||||
buffer.encode_string(11, this->unit_of_measurement);
|
buffer.encode_string(11, this->unit_of_measurement);
|
||||||
buffer.encode_enum<enums::NumberMode>(12, this->mode);
|
buffer.encode_enum<enums::NumberMode>(12, this->mode);
|
||||||
|
buffer.encode_string(13, this->device_class);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
||||||
@@ -4037,6 +4090,10 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
|||||||
out.append(" mode: ");
|
out.append(" mode: ");
|
||||||
out.append(proto_enum_to_string<enums::NumberMode>(this->mode));
|
out.append(proto_enum_to_string<enums::NumberMode>(this->mode));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_class: ");
|
||||||
|
out.append("'").append(this->device_class).append("'");
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4984,6 +5041,10 @@ bool BluetoothLEAdvertisementResponse::decode_varint(uint32_t field_id, ProtoVar
|
|||||||
this->rssi = value.as_sint32();
|
this->rssi = value.as_sint32();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 7: {
|
||||||
|
this->address_type = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5023,6 +5084,7 @@ void BluetoothLEAdvertisementResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
for (auto &it : this->manufacturer_data) {
|
for (auto &it : this->manufacturer_data) {
|
||||||
buffer.encode_message<BluetoothServiceData>(6, it, true);
|
buffer.encode_message<BluetoothServiceData>(6, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(7, this->address_type);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const {
|
void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const {
|
||||||
@@ -5059,6 +5121,11 @@ void BluetoothLEAdvertisementResponse::dump_to(std::string &out) const {
|
|||||||
it.dump_to(out);
|
it.dump_to(out);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.append(" address_type: ");
|
||||||
|
sprintf(buffer, "%u", this->address_type);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5072,6 +5139,14 @@ bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value)
|
|||||||
this->request_type = value.as_enum<enums::BluetoothDeviceRequestType>();
|
this->request_type = value.as_enum<enums::BluetoothDeviceRequestType>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 3: {
|
||||||
|
this->has_address_type = value.as_bool();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
this->address_type = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5079,6 +5154,8 @@ bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value)
|
|||||||
void BluetoothDeviceRequest::encode(ProtoWriteBuffer buffer) const {
|
void BluetoothDeviceRequest::encode(ProtoWriteBuffer buffer) const {
|
||||||
buffer.encode_uint64(1, this->address);
|
buffer.encode_uint64(1, this->address);
|
||||||
buffer.encode_enum<enums::BluetoothDeviceRequestType>(2, this->request_type);
|
buffer.encode_enum<enums::BluetoothDeviceRequestType>(2, this->request_type);
|
||||||
|
buffer.encode_bool(3, this->has_address_type);
|
||||||
|
buffer.encode_uint32(4, this->address_type);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void BluetoothDeviceRequest::dump_to(std::string &out) const {
|
void BluetoothDeviceRequest::dump_to(std::string &out) const {
|
||||||
@@ -5092,6 +5169,15 @@ void BluetoothDeviceRequest::dump_to(std::string &out) const {
|
|||||||
out.append(" request_type: ");
|
out.append(" request_type: ");
|
||||||
out.append(proto_enum_to_string<enums::BluetoothDeviceRequestType>(this->request_type));
|
out.append(proto_enum_to_string<enums::BluetoothDeviceRequestType>(this->request_type));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" has_address_type: ");
|
||||||
|
out.append(YESNO(this->has_address_type));
|
||||||
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" address_type: ");
|
||||||
|
sprintf(buffer, "%u", this->address_type);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ enum BluetoothDeviceRequestType : uint32_t {
|
|||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1,
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2,
|
||||||
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
|
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4,
|
||||||
|
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace enums
|
} // namespace enums
|
||||||
@@ -1004,6 +1006,7 @@ class ListEntitiesNumberResponse : public ProtoMessage {
|
|||||||
enums::EntityCategory entity_category{};
|
enums::EntityCategory entity_category{};
|
||||||
std::string unit_of_measurement{};
|
std::string unit_of_measurement{};
|
||||||
enums::NumberMode mode{};
|
enums::NumberMode mode{};
|
||||||
|
std::string device_class{};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
@@ -1256,6 +1259,7 @@ class BluetoothLEAdvertisementResponse : public ProtoMessage {
|
|||||||
std::vector<std::string> service_uuids{};
|
std::vector<std::string> service_uuids{};
|
||||||
std::vector<BluetoothServiceData> service_data{};
|
std::vector<BluetoothServiceData> service_data{};
|
||||||
std::vector<BluetoothServiceData> manufacturer_data{};
|
std::vector<BluetoothServiceData> manufacturer_data{};
|
||||||
|
uint32_t address_type{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
@@ -1269,6 +1273,8 @@ class BluetoothDeviceRequest : public ProtoMessage {
|
|||||||
public:
|
public:
|
||||||
uint64_t address{0};
|
uint64_t address{0};
|
||||||
enums::BluetoothDeviceRequestType request_type{};
|
enums::BluetoothDeviceRequestType request_type{};
|
||||||
|
bool has_address_type{false};
|
||||||
|
uint32_t address_type{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "user_services.h"
|
#include "user_services.h"
|
||||||
#include "api_noise_context.h"
|
#include "api_noise_context.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "api_pb2.h"
|
#include "api_pb2.h"
|
||||||
#include "api_server.h"
|
#include "api_server.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
||||||
#define HAS_PROTO_MESSAGE_DUMP
|
#define HAS_PROTO_MESSAGE_DUMP
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "bedjet_child.h"
|
#include "bedjet_child.h"
|
||||||
#include "bedjet_codec.h"
|
#include "bedjet_codec.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
#include "esphome/components/time/real_time_clock.h"
|
#include "esphome/components/time/real_time_clock.h"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/components/binary_sensor/filter.h"
|
#include "esphome/components/binary_sensor/filter.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
namespace binary_sensor {
|
namespace binary_sensor {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
namespace binary_sensor {
|
namespace binary_sensor {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace binary_sensor_map {
|
namespace binary_sensor_map {
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ CONF_BLE_CLIENT_ID = "ble_client_id"
|
|||||||
|
|
||||||
BLE_CLIENT_SCHEMA = cv.Schema(
|
BLE_CLIENT_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_BLE_CLIENT_ID): cv.use_id(BLEClient),
|
cv.GenerateID(CONF_BLE_CLIENT_ID): cv.use_id(BLEClient),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ async def register_ble_node(var, config):
|
|||||||
|
|
||||||
BLE_WRITE_ACTION_SCHEMA = cv.Schema(
|
BLE_WRITE_ACTION_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.use_id(BLEClient),
|
cv.GenerateID(CONF_ID): cv.use_id(BLEClient),
|
||||||
cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
|
cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
|
||||||
cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid,
|
cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid,
|
||||||
cv.Required(CONF_VALUE): cv.templatable(cv.ensure_list(cv.hex_uint8_t)),
|
cv.Required(CONF_VALUE): cv.templatable(cv.ensure_list(cv.hex_uint8_t)),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
#include "esphome/components/ble_client/ble_client.h"
|
#include "esphome/components/ble_client/ble_client.h"
|
||||||
|
|||||||
@@ -7,12 +7,13 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <array>
|
|
||||||
#include <esp_gap_ble_api.h>
|
|
||||||
#include <esp_gattc_api.h>
|
|
||||||
#include <esp_bt_defs.h>
|
#include <esp_bt_defs.h>
|
||||||
|
#include <esp_gap_ble_api.h>
|
||||||
#include <esp_gatt_common_api.h>
|
#include <esp_gatt_common_api.h>
|
||||||
|
#include <esp_gattc_api.h>
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ble_client {
|
namespace ble_client {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
#include <esp_gattc_api.h>
|
#include <esp_gattc_api.h>
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ from esphome.components import esp32_ble_tracker, esp32_ble_client
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.const import CONF_ACTIVE, CONF_ID
|
from esphome.const import CONF_ACTIVE, CONF_ID
|
||||||
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
|
|
||||||
AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"]
|
AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"]
|
||||||
DEPENDENCIES = ["api", "esp32"]
|
DEPENDENCIES = ["api", "esp32"]
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
|
|
||||||
|
CONF_CACHE_SERVICES = "cache_services"
|
||||||
CONF_CONNECTIONS = "connections"
|
CONF_CONNECTIONS = "connections"
|
||||||
MAX_CONNECTIONS = 3
|
MAX_CONNECTIONS = 3
|
||||||
|
|
||||||
@@ -47,6 +49,9 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(BluetoothProxy),
|
cv.GenerateID(): cv.declare_id(BluetoothProxy),
|
||||||
cv.Optional(CONF_ACTIVE, default=False): cv.boolean,
|
cv.Optional(CONF_ACTIVE, default=False): cv.boolean,
|
||||||
|
cv.SplitDefault(CONF_CACHE_SERVICES, esp32_idf=True): cv.All(
|
||||||
|
cv.only_with_esp_idf, cv.boolean
|
||||||
|
),
|
||||||
cv.Optional(CONF_CONNECTIONS): cv.All(
|
cv.Optional(CONF_CONNECTIONS): cv.All(
|
||||||
cv.ensure_list(CONNECTION_SCHEMA),
|
cv.ensure_list(CONNECTION_SCHEMA),
|
||||||
cv.Length(min=1, max=MAX_CONNECTIONS),
|
cv.Length(min=1, max=MAX_CONNECTIONS),
|
||||||
@@ -72,4 +77,7 @@ async def to_code(config):
|
|||||||
cg.add(var.register_connection(connection_var))
|
cg.add(var.register_connection(connection_var))
|
||||||
await esp32_ble_tracker.register_client(connection_var, connection_conf)
|
await esp32_ble_tracker.register_client(connection_var, connection_conf)
|
||||||
|
|
||||||
|
if config.get(CONF_CACHE_SERVICES):
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_GATTC_CACHE_NVS_FLASH", True)
|
||||||
|
|
||||||
cg.add_define("USE_BLUETOOTH_PROXY")
|
cg.add_define("USE_BLUETOOTH_PROXY")
|
||||||
|
|||||||
@@ -34,12 +34,39 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
|||||||
this->set_address(0);
|
this->set_address(0);
|
||||||
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
||||||
this->proxy_->get_bluetooth_connections_limit());
|
this->proxy_->get_bluetooth_connections_limit());
|
||||||
|
} else if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
|
||||||
|
api::global_api_server->send_bluetooth_device_connection(this->address_, true, this->mtu_);
|
||||||
|
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
||||||
|
this->proxy_->get_bluetooth_connections_limit());
|
||||||
}
|
}
|
||||||
|
this->seen_mtu_or_services_ = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_GATTC_CFG_MTU_EVT: {
|
||||||
|
if (param->cfg_mtu.conn_id != this->conn_id_)
|
||||||
|
break;
|
||||||
|
if (!this->seen_mtu_or_services_) {
|
||||||
|
// We don't know if we will get the MTU or the services first, so
|
||||||
|
// only send the device connection true if we have already received
|
||||||
|
// the services.
|
||||||
|
this->seen_mtu_or_services_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
api::global_api_server->send_bluetooth_device_connection(this->address_, true, this->mtu_);
|
||||||
|
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
||||||
|
this->proxy_->get_bluetooth_connections_limit());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||||
if (param->search_cmpl.conn_id != this->conn_id_)
|
if (param->search_cmpl.conn_id != this->conn_id_)
|
||||||
break;
|
break;
|
||||||
|
if (!this->seen_mtu_or_services_) {
|
||||||
|
// We don't know if we will get the MTU or the services first, so
|
||||||
|
// only send the device connection true if we have already received
|
||||||
|
// the mtu.
|
||||||
|
this->seen_mtu_or_services_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
api::global_api_server->send_bluetooth_device_connection(this->address_, true, this->mtu_);
|
api::global_api_server->send_bluetooth_device_connection(this->address_, true, this->mtu_);
|
||||||
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
api::global_api_server->send_bluetooth_connections_free(this->proxy_->get_bluetooth_connections_free(),
|
||||||
this->proxy_->get_bluetooth_connections_limit());
|
this->proxy_->get_bluetooth_connections_limit());
|
||||||
@@ -82,8 +109,6 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
|
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
|
||||||
if (this->get_characteristic(param->unreg_for_notify.handle) == nullptr) // No conn_id in this event
|
|
||||||
break;
|
|
||||||
if (param->unreg_for_notify.status != ESP_GATT_OK) {
|
if (param->unreg_for_notify.status != ESP_GATT_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
|
ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
|
||||||
this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
|
this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
|
||||||
@@ -99,8 +124,6 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
||||||
if (this->get_characteristic(param->reg_for_notify.handle) == nullptr) // No conn_id in this event
|
|
||||||
break;
|
|
||||||
if (param->reg_for_notify.status != ESP_GATT_OK) {
|
if (param->reg_for_notify.status != ESP_GATT_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
|
this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
|
||||||
@@ -141,18 +164,11 @@ esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
|
|||||||
this->address_str_.c_str());
|
this->address_str_.c_str());
|
||||||
return ESP_GATT_NOT_CONNECTED;
|
return ESP_GATT_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
auto *characteristic = this->get_characteristic(handle);
|
|
||||||
if (characteristic == nullptr) {
|
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not found.", this->connection_index_,
|
|
||||||
this->address_str_.c_str());
|
|
||||||
return ESP_GATT_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Reading GATT characteristic %s", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGV(TAG, "[%d] [%s] Reading GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
|
||||||
characteristic->uuid.to_string().c_str());
|
handle);
|
||||||
|
|
||||||
esp_err_t err =
|
esp_err_t err = esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
|
||||||
esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, characteristic->handle, ESP_GATT_AUTH_REQ_NONE);
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
@@ -167,18 +183,12 @@ esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::
|
|||||||
this->address_str_.c_str());
|
this->address_str_.c_str());
|
||||||
return ESP_GATT_NOT_CONNECTED;
|
return ESP_GATT_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
auto *characteristic = this->get_characteristic(handle);
|
ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
|
||||||
if (characteristic == nullptr) {
|
handle);
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not found.", this->connection_index_,
|
|
||||||
this->address_str_.c_str());
|
|
||||||
return ESP_GATT_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic %s", this->connection_index_, this->address_str_.c_str(),
|
esp_err_t err =
|
||||||
characteristic->uuid.to_string().c_str());
|
esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
|
||||||
|
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
auto err = characteristic->write_value((uint8_t *) data.data(), data.size(),
|
|
||||||
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP);
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
@@ -193,18 +203,10 @@ esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
|
|||||||
this->address_str_.c_str());
|
this->address_str_.c_str());
|
||||||
return ESP_GATT_NOT_CONNECTED;
|
return ESP_GATT_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
auto *descriptor = this->get_descriptor(handle);
|
ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
|
||||||
if (descriptor == nullptr) {
|
handle);
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not found.", this->connection_index_,
|
|
||||||
this->address_str_.c_str());
|
|
||||||
return ESP_GATT_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor %s", this->connection_index_, this->address_str_.c_str(),
|
esp_err_t err = esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
|
||||||
descriptor->uuid.to_string().c_str());
|
|
||||||
|
|
||||||
esp_err_t err =
|
|
||||||
esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, descriptor->handle, ESP_GATT_AUTH_REQ_NONE);
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
@@ -213,25 +215,18 @@ esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data) {
|
esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
|
||||||
if (!this->connected()) {
|
if (!this->connected()) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
|
||||||
this->address_str_.c_str());
|
this->address_str_.c_str());
|
||||||
return ESP_GATT_NOT_CONNECTED;
|
return ESP_GATT_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
auto *descriptor = this->get_descriptor(handle);
|
ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
|
||||||
if (descriptor == nullptr) {
|
handle);
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not found.", this->connection_index_,
|
|
||||||
this->address_str_.c_str());
|
|
||||||
return ESP_GATT_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor %s", this->connection_index_, this->address_str_.c_str(),
|
esp_err_t err = esp_ble_gattc_write_char_descr(
|
||||||
descriptor->uuid.to_string().c_str());
|
this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
|
||||||
|
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
auto err =
|
|
||||||
esp_ble_gattc_write_char_descr(this->gattc_if_, this->conn_id_, descriptor->handle, data.size(),
|
|
||||||
(uint8_t *) data.data(), ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
@@ -246,26 +241,20 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl
|
|||||||
this->address_str_.c_str());
|
this->address_str_.c_str());
|
||||||
return ESP_GATT_NOT_CONNECTED;
|
return ESP_GATT_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
auto *characteristic = this->get_characteristic(handle);
|
|
||||||
if (characteristic == nullptr) {
|
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not found.", this->connection_index_,
|
|
||||||
this->address_str_.c_str());
|
|
||||||
return ESP_GATT_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications %s", this->connection_index_,
|
ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
|
||||||
this->address_str_.c_str(), characteristic->uuid.to_string().c_str());
|
this->address_str_.c_str(), handle);
|
||||||
esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, characteristic->handle);
|
esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, handle);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications %s", this->connection_index_,
|
ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
|
||||||
this->address_str_.c_str(), characteristic->uuid.to_string().c_str());
|
this->address_str_.c_str(), handle);
|
||||||
esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, characteristic->handle);
|
esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
|
||||||
this->address_str_.c_str(), err);
|
this->address_str_.c_str(), err);
|
||||||
|
|||||||
@@ -17,14 +17,15 @@ class BluetoothConnection : public esp32_ble_client::BLEClientBase {
|
|||||||
esp_err_t read_characteristic(uint16_t handle);
|
esp_err_t read_characteristic(uint16_t handle);
|
||||||
esp_err_t write_characteristic(uint16_t handle, const std::string &data, bool response);
|
esp_err_t write_characteristic(uint16_t handle, const std::string &data, bool response);
|
||||||
esp_err_t read_descriptor(uint16_t handle);
|
esp_err_t read_descriptor(uint16_t handle);
|
||||||
esp_err_t write_descriptor(uint16_t handle, const std::string &data);
|
esp_err_t write_descriptor(uint16_t handle, const std::string &data, bool response);
|
||||||
|
|
||||||
esp_err_t notify_characteristic(uint16_t handle, bool enable);
|
esp_err_t notify_characteristic(uint16_t handle, bool enable);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class BluetoothProxy;
|
friend class BluetoothProxy;
|
||||||
|
bool seen_mtu_or_services_{false};
|
||||||
|
|
||||||
int16_t send_service_{-1};
|
int16_t send_service_{-2};
|
||||||
BluetoothProxy *proxy_;
|
BluetoothProxy *proxy_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,19 @@ namespace esphome {
|
|||||||
namespace bluetooth_proxy {
|
namespace bluetooth_proxy {
|
||||||
|
|
||||||
static const char *const TAG = "bluetooth_proxy";
|
static const char *const TAG = "bluetooth_proxy";
|
||||||
|
static const int DONE_SENDING_SERVICES = -2;
|
||||||
|
|
||||||
|
std::vector<uint64_t> get_128bit_uuid_vec(esp_bt_uuid_t uuid_source) {
|
||||||
|
esp_bt_uuid_t uuid = espbt::ESPBTUUID::from_uuid(uuid_source).as_128bit().get_uuid();
|
||||||
|
return std::vector<uint64_t>{((uint64_t) uuid.uuid.uuid128[15] << 56) | ((uint64_t) uuid.uuid.uuid128[14] << 48) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[13] << 40) | ((uint64_t) uuid.uuid.uuid128[12] << 32) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[11] << 24) | ((uint64_t) uuid.uuid.uuid128[10] << 16) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[9] << 8) | ((uint64_t) uuid.uuid.uuid128[8]),
|
||||||
|
((uint64_t) uuid.uuid.uuid128[7] << 56) | ((uint64_t) uuid.uuid.uuid128[6] << 48) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[5] << 40) | ((uint64_t) uuid.uuid.uuid128[4] << 32) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[3] << 24) | ((uint64_t) uuid.uuid.uuid128[2] << 16) |
|
||||||
|
((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0])};
|
||||||
|
}
|
||||||
|
|
||||||
BluetoothProxy::BluetoothProxy() { global_bluetooth_proxy = this; }
|
BluetoothProxy::BluetoothProxy() { global_bluetooth_proxy = this; }
|
||||||
|
|
||||||
@@ -26,6 +39,7 @@ bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
|||||||
void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &device) {
|
void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||||
api::BluetoothLEAdvertisementResponse resp;
|
api::BluetoothLEAdvertisementResponse resp;
|
||||||
resp.address = device.address_uint64();
|
resp.address = device.address_uint64();
|
||||||
|
resp.address_type = device.get_address_type();
|
||||||
if (!device.get_name().empty())
|
if (!device.get_name().empty())
|
||||||
resp.name = device.get_name();
|
resp.name = device.get_name();
|
||||||
resp.rssi = device.get_rssi();
|
resp.rssi = device.get_rssi();
|
||||||
@@ -52,6 +66,20 @@ void BluetoothProxy::dump_config() {
|
|||||||
ESP_LOGCONFIG(TAG, " Active: %s", YESNO(this->active_));
|
ESP_LOGCONFIG(TAG, " Active: %s", YESNO(this->active_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BluetoothProxy::get_bluetooth_connections_free() {
|
||||||
|
int free = 0;
|
||||||
|
for (auto *connection : this->connections_) {
|
||||||
|
if (connection->address_ == 0) {
|
||||||
|
free++;
|
||||||
|
ESP_LOGV(TAG, "[%d] Free connection", connection->get_connection_index());
|
||||||
|
} else {
|
||||||
|
ESP_LOGV(TAG, "[%d] Used connection by [%s]", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return free;
|
||||||
|
}
|
||||||
|
|
||||||
void BluetoothProxy::loop() {
|
void BluetoothProxy::loop() {
|
||||||
if (!api::global_api_server->is_connected()) {
|
if (!api::global_api_server->is_connected()) {
|
||||||
for (auto *connection : this->connections_) {
|
for (auto *connection : this->connections_) {
|
||||||
@@ -62,32 +90,87 @@ void BluetoothProxy::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto *connection : this->connections_) {
|
for (auto *connection : this->connections_) {
|
||||||
if (connection->send_service_ == connection->services_.size()) {
|
if (connection->send_service_ == connection->service_count_) {
|
||||||
connection->send_service_ = -1;
|
connection->send_service_ = DONE_SENDING_SERVICES;
|
||||||
api::global_api_server->send_bluetooth_gatt_services_done(connection->get_address());
|
api::global_api_server->send_bluetooth_gatt_services_done(connection->get_address());
|
||||||
|
if (connection->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
|
||||||
|
connection->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
||||||
|
connection->release_services();
|
||||||
|
}
|
||||||
} else if (connection->send_service_ >= 0) {
|
} else if (connection->send_service_ >= 0) {
|
||||||
auto &service = connection->services_[connection->send_service_];
|
esp_gattc_service_elem_t service_result;
|
||||||
|
uint16_t service_count = 1;
|
||||||
|
esp_gatt_status_t service_status =
|
||||||
|
esp_ble_gattc_get_service(connection->get_gattc_if(), connection->get_conn_id(), nullptr, &service_result,
|
||||||
|
&service_count, connection->send_service_);
|
||||||
|
connection->send_service_++;
|
||||||
|
if (service_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service error at offset=%d, status=%d",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str(), connection->send_service_ - 1,
|
||||||
|
service_status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (service_count == 0) {
|
||||||
|
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service missing, service_count=%d",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str(), service_count);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
api::BluetoothGATTGetServicesResponse resp;
|
api::BluetoothGATTGetServicesResponse resp;
|
||||||
resp.address = connection->get_address();
|
resp.address = connection->get_address();
|
||||||
api::BluetoothGATTService service_resp;
|
api::BluetoothGATTService service_resp;
|
||||||
service_resp.uuid = {service->uuid.get_128bit_high(), service->uuid.get_128bit_low()};
|
service_resp.uuid = get_128bit_uuid_vec(service_result.uuid);
|
||||||
service_resp.handle = service->start_handle;
|
service_resp.handle = service_result.start_handle;
|
||||||
for (auto &characteristic : service->characteristics) {
|
uint16_t char_offset = 0;
|
||||||
|
esp_gattc_char_elem_t char_result;
|
||||||
|
while (true) { // characteristics
|
||||||
|
uint16_t char_count = 1;
|
||||||
|
esp_gatt_status_t char_status = esp_ble_gattc_get_all_char(
|
||||||
|
connection->get_gattc_if(), connection->get_conn_id(), service_result.start_handle,
|
||||||
|
service_result.end_handle, &char_result, &char_count, char_offset);
|
||||||
|
if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (char_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str(), char_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (char_count == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
api::BluetoothGATTCharacteristic characteristic_resp;
|
api::BluetoothGATTCharacteristic characteristic_resp;
|
||||||
characteristic_resp.uuid = {characteristic->uuid.get_128bit_high(), characteristic->uuid.get_128bit_low()};
|
characteristic_resp.uuid = get_128bit_uuid_vec(char_result.uuid);
|
||||||
characteristic_resp.handle = characteristic->handle;
|
characteristic_resp.handle = char_result.char_handle;
|
||||||
characteristic_resp.properties = characteristic->properties;
|
characteristic_resp.properties = char_result.properties;
|
||||||
for (auto &descriptor : characteristic->descriptors) {
|
char_offset++;
|
||||||
|
uint16_t desc_offset = 0;
|
||||||
|
esp_gattc_descr_elem_t desc_result;
|
||||||
|
while (true) { // descriptors
|
||||||
|
uint16_t desc_count = 1;
|
||||||
|
esp_gatt_status_t desc_status =
|
||||||
|
esp_ble_gattc_get_all_descr(connection->get_gattc_if(), connection->get_conn_id(),
|
||||||
|
char_result.char_handle, &desc_result, &desc_count, desc_offset);
|
||||||
|
if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (desc_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_descr error, status=%d", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str(), desc_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (desc_count == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
api::BluetoothGATTDescriptor descriptor_resp;
|
api::BluetoothGATTDescriptor descriptor_resp;
|
||||||
descriptor_resp.uuid = {descriptor->uuid.get_128bit_high(), descriptor->uuid.get_128bit_low()};
|
descriptor_resp.uuid = get_128bit_uuid_vec(desc_result.uuid);
|
||||||
descriptor_resp.handle = descriptor->handle;
|
descriptor_resp.handle = desc_result.handle;
|
||||||
characteristic_resp.descriptors.push_back(std::move(descriptor_resp));
|
characteristic_resp.descriptors.push_back(std::move(descriptor_resp));
|
||||||
|
desc_offset++;
|
||||||
}
|
}
|
||||||
service_resp.characteristics.push_back(std::move(characteristic_resp));
|
service_resp.characteristics.push_back(std::move(characteristic_resp));
|
||||||
}
|
}
|
||||||
resp.services.push_back(std::move(service_resp));
|
resp.services.push_back(std::move(service_resp));
|
||||||
api::global_api_server->send_bluetooth_gatt_services(resp);
|
api::global_api_server->send_bluetooth_gatt_services(resp);
|
||||||
connection->send_service_++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +186,13 @@ BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool rese
|
|||||||
|
|
||||||
for (auto *connection : this->connections_) {
|
for (auto *connection : this->connections_) {
|
||||||
if (connection->get_address() == 0) {
|
if (connection->get_address() == 0) {
|
||||||
|
connection->send_service_ = DONE_SENDING_SERVICES;
|
||||||
connection->set_address(address);
|
connection->set_address(address);
|
||||||
|
// All connections must start at INIT
|
||||||
|
// We only set the state if we allocate the connection
|
||||||
|
// to avoid a race where multiple connection attempts
|
||||||
|
// are made.
|
||||||
|
connection->set_state(espbt::ClientState::INIT);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +202,8 @@ BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool rese
|
|||||||
|
|
||||||
void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest &msg) {
|
void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest &msg) {
|
||||||
switch (msg.request_type) {
|
switch (msg.request_type) {
|
||||||
|
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE:
|
||||||
|
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE:
|
||||||
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: {
|
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: {
|
||||||
auto *connection = this->get_connection_(msg.address, true);
|
auto *connection = this->get_connection_(msg.address, true);
|
||||||
if (connection == nullptr) {
|
if (connection == nullptr) {
|
||||||
@@ -120,9 +211,63 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
|
|||||||
api::global_api_server->send_bluetooth_device_connection(msg.address, false);
|
api::global_api_server->send_bluetooth_device_connection(msg.address, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_LOGV(TAG, "[%d] [%s] Searching to connect", connection->get_connection_index(),
|
if (connection->state() == espbt::ClientState::CONNECTED ||
|
||||||
connection->address_str().c_str());
|
connection->state() == espbt::ClientState::ESTABLISHED) {
|
||||||
connection->set_state(espbt::ClientState::SEARCHING);
|
ESP_LOGW(TAG, "[%d] [%s] Connection already established", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
api::global_api_server->send_bluetooth_device_connection(msg.address, true);
|
||||||
|
api::global_api_server->send_bluetooth_connections_free(this->get_bluetooth_connections_free(),
|
||||||
|
this->get_bluetooth_connections_limit());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() == espbt::ClientState::SEARCHING) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, already searching for device",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() == espbt::ClientState::DISCOVERED) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, device already discovered",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() == espbt::ClientState::READY_TO_CONNECT) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, waiting in line to connect",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() == espbt::ClientState::CONNECTING) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, already connecting", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() == espbt::ClientState::DISCONNECTING) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, device is disconnecting",
|
||||||
|
connection->get_connection_index(), connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
} else if (connection->state() != espbt::ClientState::INIT) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Connection already in progress", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg.request_type == api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE) {
|
||||||
|
connection->set_connection_type(espbt::ConnectionType::V3_WITH_CACHE);
|
||||||
|
ESP_LOGI(TAG, "[%d] [%s] Connecting v3 with cache", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
} else if (msg.request_type == api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE) {
|
||||||
|
connection->set_connection_type(espbt::ConnectionType::V3_WITHOUT_CACHE);
|
||||||
|
ESP_LOGI(TAG, "[%d] [%s] Connecting v3 without cache", connection->get_connection_index(),
|
||||||
|
connection->address_str().c_str());
|
||||||
|
} else {
|
||||||
|
connection->set_connection_type(espbt::ConnectionType::V1);
|
||||||
|
ESP_LOGI(TAG, "[%d] [%s] Connecting v1", connection->get_connection_index(), connection->address_str().c_str());
|
||||||
|
}
|
||||||
|
if (msg.has_address_type) {
|
||||||
|
connection->remote_bda_[0] = (msg.address >> 40) & 0xFF;
|
||||||
|
connection->remote_bda_[1] = (msg.address >> 32) & 0xFF;
|
||||||
|
connection->remote_bda_[2] = (msg.address >> 24) & 0xFF;
|
||||||
|
connection->remote_bda_[3] = (msg.address >> 16) & 0xFF;
|
||||||
|
connection->remote_bda_[4] = (msg.address >> 8) & 0xFF;
|
||||||
|
connection->remote_bda_[5] = (msg.address >> 0) & 0xFF;
|
||||||
|
connection->set_remote_addr_type(static_cast<esp_ble_addr_type_t>(msg.address_type));
|
||||||
|
connection->set_state(espbt::ClientState::DISCOVERED);
|
||||||
|
} else {
|
||||||
|
connection->set_state(espbt::ClientState::SEARCHING);
|
||||||
|
}
|
||||||
api::global_api_server->send_bluetooth_connections_free(this->get_bluetooth_connections_free(),
|
api::global_api_server->send_bluetooth_connections_free(this->get_bluetooth_connections_free(),
|
||||||
this->get_bluetooth_connections_limit());
|
this->get_bluetooth_connections_limit());
|
||||||
break;
|
break;
|
||||||
@@ -201,7 +346,7 @@ void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto err = connection->write_descriptor(msg.handle, msg.data);
|
auto err = connection->write_descriptor(msg.handle, msg.data, true);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
api::global_api_server->send_bluetooth_gatt_error(msg.address, msg.handle, err);
|
||||||
}
|
}
|
||||||
@@ -214,12 +359,13 @@ void BluetoothProxy::bluetooth_gatt_send_services(const api::BluetoothGATTGetSer
|
|||||||
api::global_api_server->send_bluetooth_gatt_error(msg.address, 0, ESP_GATT_NOT_CONNECTED);
|
api::global_api_server->send_bluetooth_gatt_error(msg.address, 0, ESP_GATT_NOT_CONNECTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (connection->services_.empty()) {
|
if (!connection->service_count_) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] No GATT services found", connection->connection_index_, connection->address_str().c_str());
|
ESP_LOGW(TAG, "[%d] [%s] No GATT services found", connection->connection_index_, connection->address_str().c_str());
|
||||||
api::global_api_server->send_bluetooth_gatt_services_done(msg.address);
|
api::global_api_server->send_bluetooth_gatt_services_done(msg.address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (connection->send_service_ == -1) // Don't start sending services again if we're already sending them
|
if (connection->send_service_ ==
|
||||||
|
DONE_SENDING_SERVICES) // Only start sending services if we're not already sending them
|
||||||
connection->send_service_ = 0;
|
connection->send_service_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "esphome/components/api/api_pb2.h"
|
#include "esphome/components/api/api_pb2.h"
|
||||||
#include "esphome/components/esp32_ble_client/ble_client_base.h"
|
#include "esphome/components/esp32_ble_client/ble_client_base.h"
|
||||||
@@ -40,15 +41,7 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
|
|||||||
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg);
|
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg);
|
||||||
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg);
|
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg);
|
||||||
|
|
||||||
int get_bluetooth_connections_free() {
|
int get_bluetooth_connections_free();
|
||||||
int free = 0;
|
|
||||||
for (auto *connection : this->connections_) {
|
|
||||||
if (connection->address_ == 0) {
|
|
||||||
free++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return free;
|
|
||||||
}
|
|
||||||
int get_bluetooth_connections_limit() { return this->connections_.size(); }
|
int get_bluetooth_connections_limit() { return this->connections_.size(); }
|
||||||
|
|
||||||
void set_active(bool active) { this->active_ = active; }
|
void set_active(bool active) { this->active_ = active; }
|
||||||
@@ -59,7 +52,6 @@ class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Com
|
|||||||
|
|
||||||
BluetoothConnection *get_connection_(uint64_t address, bool reserve);
|
BluetoothConnection *get_connection_(uint64_t address, bool reserve);
|
||||||
|
|
||||||
int16_t send_service_{-1};
|
|
||||||
bool active_;
|
bool active_;
|
||||||
|
|
||||||
std::vector<BluetoothConnection *> connections_{};
|
std::vector<BluetoothConnection *> connections_{};
|
||||||
|
|||||||
@@ -88,7 +88,10 @@ void BME280Component::setup() {
|
|||||||
|
|
||||||
// Mark as not failed before initializing. Some devices will turn off sensors to save on batteries
|
// Mark as not failed before initializing. Some devices will turn off sensors to save on batteries
|
||||||
// and when they come back on, the COMPONENT_STATE_FAILED bit must be unset on the component.
|
// and when they come back on, the COMPONENT_STATE_FAILED bit must be unset on the component.
|
||||||
this->component_state_ &= ~COMPONENT_STATE_FAILED;
|
if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) {
|
||||||
|
this->component_state_ &= ~COMPONENT_STATE_MASK;
|
||||||
|
this->component_state_ |= COMPONENT_STATE_CONSTRUCTION;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->read_byte(BME280_REGISTER_CHIPID, &chip_id)) {
|
if (!this->read_byte(BME280_REGISTER_CHIPID, &chip_id)) {
|
||||||
this->error_code_ = COMMUNICATION_FAILED;
|
this->error_code_ = COMMUNICATION_FAILED;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "bmp280.h"
|
#include "bmp280.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@@ -11,8 +12,11 @@ static const uint8_t BMP280_REGISTER_CONTROL = 0xF4;
|
|||||||
static const uint8_t BMP280_REGISTER_CONFIG = 0xF5;
|
static const uint8_t BMP280_REGISTER_CONFIG = 0xF5;
|
||||||
static const uint8_t BMP280_REGISTER_PRESSUREDATA = 0xF7;
|
static const uint8_t BMP280_REGISTER_PRESSUREDATA = 0xF7;
|
||||||
static const uint8_t BMP280_REGISTER_TEMPDATA = 0xFA;
|
static const uint8_t BMP280_REGISTER_TEMPDATA = 0xFA;
|
||||||
|
static const uint8_t BMP280_REGISTER_RESET = 0xE0;
|
||||||
|
|
||||||
static const uint8_t BMP280_MODE_FORCED = 0b01;
|
static const uint8_t BMP280_MODE_FORCED = 0b01;
|
||||||
|
static const uint8_t BMP280_SOFT_RESET = 0xB6;
|
||||||
|
static const uint8_t BMP280_STATUS_IM_UPDATE = 0b01;
|
||||||
|
|
||||||
inline uint16_t combine_bytes(uint8_t msb, uint8_t lsb) { return ((msb & 0xFF) << 8) | (lsb & 0xFF); }
|
inline uint16_t combine_bytes(uint8_t msb, uint8_t lsb) { return ((msb & 0xFF) << 8) | (lsb & 0xFF); }
|
||||||
|
|
||||||
@@ -66,6 +70,28 @@ void BMP280Component::setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send a soft reset.
|
||||||
|
if (!this->write_byte(BMP280_REGISTER_RESET, BMP280_SOFT_RESET)) {
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Wait until the NVM data has finished loading.
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t retry = 5;
|
||||||
|
do {
|
||||||
|
delay(2);
|
||||||
|
if (!this->read_byte(BMP280_REGISTER_STATUS, &status)) {
|
||||||
|
ESP_LOGW(TAG, "Error reading status register.");
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while ((status & BMP280_STATUS_IM_UPDATE) && (--retry));
|
||||||
|
if (status & BMP280_STATUS_IM_UPDATE) {
|
||||||
|
ESP_LOGW(TAG, "Timeout loading NVM.");
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Read calibration
|
// Read calibration
|
||||||
this->calibration_.t1 = this->read_u16_le_(0x88);
|
this->calibration_.t1 = this->read_u16_le_(0x88);
|
||||||
this->calibration_.t2 = this->read_s16_le_(0x8A);
|
this->calibration_.t2 = this->read_s16_le_(0x8A);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/optional.h"
|
#include "esphome/core/optional.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace canbus {
|
namespace canbus {
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "esphome/components/output/binary_output.h"
|
#include "esphome/components/output/binary_output.h"
|
||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace cap1188 {
|
namespace cap1188 {
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ DEFAULT_DELAY = "2ms"
|
|||||||
CONFIG_SCHEMA = cv.Schema(
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(CD74HC4067Component),
|
cv.GenerateID(): cv.declare_id(CD74HC4067Component),
|
||||||
cv.Required(CONF_PIN_S0): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_PIN_S0): pins.gpio_output_pin_schema,
|
||||||
cv.Required(CONF_PIN_S1): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_PIN_S1): pins.gpio_output_pin_schema,
|
||||||
cv.Required(CONF_PIN_S2): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_PIN_S2): pins.gpio_output_pin_schema,
|
||||||
cv.Required(CONF_PIN_S3): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_PIN_S3): pins.gpio_output_pin_schema,
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_DELAY, default=DEFAULT_DELAY
|
CONF_DELAY, default=DEFAULT_DELAY
|
||||||
): cv.positive_time_period_milliseconds,
|
): cv.positive_time_period_milliseconds,
|
||||||
|
|||||||
@@ -19,22 +19,22 @@ class CD74HC4067Component : public Component {
|
|||||||
void activate_pin(uint8_t pin);
|
void activate_pin(uint8_t pin);
|
||||||
|
|
||||||
/// set the pin connected to multiplexer control pin 0
|
/// set the pin connected to multiplexer control pin 0
|
||||||
void set_pin_s0(InternalGPIOPin *pin) { this->pin_s0_ = pin; }
|
void set_pin_s0(GPIOPin *pin) { this->pin_s0_ = pin; }
|
||||||
/// set the pin connected to multiplexer control pin 1
|
/// set the pin connected to multiplexer control pin 1
|
||||||
void set_pin_s1(InternalGPIOPin *pin) { this->pin_s1_ = pin; }
|
void set_pin_s1(GPIOPin *pin) { this->pin_s1_ = pin; }
|
||||||
/// set the pin connected to multiplexer control pin 2
|
/// set the pin connected to multiplexer control pin 2
|
||||||
void set_pin_s2(InternalGPIOPin *pin) { this->pin_s2_ = pin; }
|
void set_pin_s2(GPIOPin *pin) { this->pin_s2_ = pin; }
|
||||||
/// set the pin connected to multiplexer control pin 3
|
/// set the pin connected to multiplexer control pin 3
|
||||||
void set_pin_s3(InternalGPIOPin *pin) { this->pin_s3_ = pin; }
|
void set_pin_s3(GPIOPin *pin) { this->pin_s3_ = pin; }
|
||||||
|
|
||||||
/// set the delay needed after an input switch
|
/// set the delay needed after an input switch
|
||||||
void set_switch_delay(uint32_t switch_delay) { this->switch_delay_ = switch_delay; }
|
void set_switch_delay(uint32_t switch_delay) { this->switch_delay_ = switch_delay; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InternalGPIOPin *pin_s0_;
|
GPIOPin *pin_s0_;
|
||||||
InternalGPIOPin *pin_s1_;
|
GPIOPin *pin_s1_;
|
||||||
InternalGPIOPin *pin_s2_;
|
GPIOPin *pin_s2_;
|
||||||
InternalGPIOPin *pin_s3_;
|
GPIOPin *pin_s3_;
|
||||||
/// the currently active pin
|
/// the currently active pin
|
||||||
uint8_t active_pin_;
|
uint8_t active_pin_;
|
||||||
uint32_t switch_delay_;
|
uint32_t switch_delay_;
|
||||||
|
|||||||
@@ -113,7 +113,9 @@ CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).
|
|||||||
{
|
{
|
||||||
cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature,
|
cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature,
|
||||||
cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature,
|
cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature,
|
||||||
cv.Optional(CONF_TEMPERATURE_STEP): cv.temperature,
|
cv.Optional(CONF_TEMPERATURE_STEP): cv.float_with_unit(
|
||||||
|
"visual_temperature", "(°C|° C|°|C|° K|° K|K|°F|° F|F)?"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ACTION_STATE_TOPIC): cv.All(
|
cv.Optional(CONF_ACTION_STATE_TOPIC): cv.All(
|
||||||
|
|||||||
@@ -540,12 +540,15 @@ void Climate::dump_traits_(const char *tag) {
|
|||||||
ESP_LOGCONFIG(tag, " - Min: %.1f", traits.get_visual_min_temperature());
|
ESP_LOGCONFIG(tag, " - Min: %.1f", traits.get_visual_min_temperature());
|
||||||
ESP_LOGCONFIG(tag, " - Max: %.1f", traits.get_visual_max_temperature());
|
ESP_LOGCONFIG(tag, " - Max: %.1f", traits.get_visual_max_temperature());
|
||||||
ESP_LOGCONFIG(tag, " - Step: %.1f", traits.get_visual_temperature_step());
|
ESP_LOGCONFIG(tag, " - Step: %.1f", traits.get_visual_temperature_step());
|
||||||
if (traits.get_supports_current_temperature())
|
if (traits.get_supports_current_temperature()) {
|
||||||
ESP_LOGCONFIG(tag, " [x] Supports current temperature");
|
ESP_LOGCONFIG(tag, " [x] Supports current temperature");
|
||||||
if (traits.get_supports_two_point_target_temperature())
|
}
|
||||||
|
if (traits.get_supports_two_point_target_temperature()) {
|
||||||
ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature");
|
ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature");
|
||||||
if (traits.get_supports_action())
|
}
|
||||||
|
if (traits.get_supports_action()) {
|
||||||
ESP_LOGCONFIG(tag, " [x] Supports action");
|
ESP_LOGCONFIG(tag, " [x] Supports action");
|
||||||
|
}
|
||||||
if (!traits.get_supported_modes().empty()) {
|
if (!traits.get_supported_modes().empty()) {
|
||||||
ESP_LOGCONFIG(tag, " [x] Supported modes:");
|
ESP_LOGCONFIG(tag, " [x] Supported modes:");
|
||||||
for (ClimateMode m : traits.get_supported_modes())
|
for (ClimateMode m : traits.get_supported_modes())
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ bool CurrentBasedCover::is_closing_blocked_() const {
|
|||||||
if (this->close_obstacle_current_threshold_ == FLT_MAX) {
|
if (this->close_obstacle_current_threshold_ == FLT_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this->open_sensor_->get_state() > this->open_obstacle_current_threshold_;
|
return this->close_sensor_->get_state() > this->close_obstacle_current_threshold_;
|
||||||
}
|
}
|
||||||
bool CurrentBasedCover::is_initial_delay_finished_() const {
|
bool CurrentBasedCover::is_initial_delay_finished_() const {
|
||||||
return millis() - this->start_dir_time_ > this->start_sensing_delay_;
|
return millis() - this->start_dir_time_ > this->start_sensing_delay_;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/climate/climate.h"
|
#include "esphome/components/climate/climate.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "esphome/components/cover/cover.h"
|
#include "esphome/components/cover/cover.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/light/light_output.h"
|
#include "esphome/components/light/light_output.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/components/output/binary_output.h"
|
#include "esphome/components/output/binary_output.h"
|
||||||
#include "esphome/components/output/float_output.h"
|
#include "esphome/components/output/float_output.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/switch/switch.h"
|
#include "esphome/components/switch/switch.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/text_sensor/text_sensor.h"
|
#include "esphome/components/text_sensor/text_sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom {
|
namespace custom {
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace custom_component {
|
namespace custom_component {
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ void DAC7678Output::setup() {
|
|||||||
ESP_LOGE(TAG, "Reset failed");
|
ESP_LOGE(TAG, "Reset failed");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
} else
|
} else {
|
||||||
ESP_LOGV(TAG, "Reset succeeded");
|
ESP_LOGV(TAG, "Reset succeeded");
|
||||||
|
}
|
||||||
|
|
||||||
delayMicroseconds(1000);
|
delayMicroseconds(1000);
|
||||||
|
|
||||||
@@ -40,16 +41,18 @@ void DAC7678Output::setup() {
|
|||||||
ESP_LOGE(TAG, "Set internal reference failed");
|
ESP_LOGE(TAG, "Set internal reference failed");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
} else
|
} else {
|
||||||
ESP_LOGV(TAG, "Internal reference enabled");
|
ESP_LOGV(TAG, "Internal reference enabled");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAC7678Output::dump_config() {
|
void DAC7678Output::dump_config() {
|
||||||
if (this->is_failed()) {
|
if (this->is_failed()) {
|
||||||
ESP_LOGE(TAG, "Setting up DAC7678 failed!");
|
ESP_LOGE(TAG, "Setting up DAC7678 failed!");
|
||||||
} else
|
} else {
|
||||||
ESP_LOGCONFIG(TAG, "DAC7678 initialised");
|
ESP_LOGCONFIG(TAG, "DAC7678 initialised");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAC7678Output::register_channel(DAC7678Channel *channel) {
|
void DAC7678Output::register_channel(DAC7678Channel *channel) {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#include "esp_one_wire.h"
|
#include "esp_one_wire.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace dallas {
|
namespace dallas {
|
||||||
|
|
||||||
|
|||||||
@@ -85,9 +85,7 @@ bool HOT IRAM_ATTR ESPOneWire::read_bit() {
|
|||||||
// whereas on esp-idf it already happens during the pin_mode(OUTPUT)
|
// whereas on esp-idf it already happens during the pin_mode(OUTPUT)
|
||||||
// manually correct for this with these constants.
|
// manually correct for this with these constants.
|
||||||
|
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
#ifdef USE_ESP32
|
||||||
uint32_t timing_constant = 14;
|
|
||||||
#elif defined(USE_ESP32_FRAMEWORK_ESP_IDF)
|
|
||||||
uint32_t timing_constant = 12;
|
uint32_t timing_constant = 12;
|
||||||
#else
|
#else
|
||||||
uint32_t timing_constant = 14;
|
uint32_t timing_constant = 14;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
#include "esphome/components/uart/uart.h"
|
#include "esphome/components/uart/uart.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace daly_bms {
|
namespace daly_bms {
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import requests
|
||||||
|
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components.packages import validate_source_shorthand
|
from esphome.components.packages import validate_source_shorthand
|
||||||
from esphome.const import CONF_WIFI
|
from esphome.const import CONF_WIFI, CONF_REF
|
||||||
from esphome.wizard import wizard_file
|
from esphome.wizard import wizard_file
|
||||||
from esphome.yaml_util import dump
|
from esphome.yaml_util import dump
|
||||||
|
from esphome import git
|
||||||
|
|
||||||
|
|
||||||
dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import")
|
dashboard_import_ns = cg.esphome_ns.namespace("dashboard_import")
|
||||||
@@ -19,16 +21,32 @@ CODEOWNERS = ["@esphome/core"]
|
|||||||
def validate_import_url(value):
|
def validate_import_url(value):
|
||||||
value = cv.string_strict(value)
|
value = cv.string_strict(value)
|
||||||
value = cv.Length(max=255)(value)
|
value = cv.Length(max=255)(value)
|
||||||
# ignore result, only check if it's a valid shorthand
|
|
||||||
validate_source_shorthand(value)
|
validate_source_shorthand(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def validate_full_url(config):
|
||||||
|
if not config[CONF_IMPORT_FULL_CONFIG]:
|
||||||
|
return config
|
||||||
|
source = validate_source_shorthand(config[CONF_PACKAGE_IMPORT_URL])
|
||||||
|
if CONF_REF not in source:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"Must specify a ref (branch or tag) to import from when importing full config"
|
||||||
|
)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
CONF_PACKAGE_IMPORT_URL = "package_import_url"
|
CONF_PACKAGE_IMPORT_URL = "package_import_url"
|
||||||
CONFIG_SCHEMA = cv.Schema(
|
CONF_IMPORT_FULL_CONFIG = "import_full_config"
|
||||||
{
|
|
||||||
cv.Required(CONF_PACKAGE_IMPORT_URL): validate_import_url,
|
CONFIG_SCHEMA = cv.All(
|
||||||
}
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_PACKAGE_IMPORT_URL): validate_import_url,
|
||||||
|
cv.Optional(CONF_IMPORT_FULL_CONFIG, default=False): cv.boolean,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
validate_full_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
WIFI_CONFIG = """
|
WIFI_CONFIG = """
|
||||||
@@ -41,7 +59,10 @@ wifi:
|
|||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_define("USE_DASHBOARD_IMPORT")
|
cg.add_define("USE_DASHBOARD_IMPORT")
|
||||||
cg.add(dashboard_import_ns.set_package_import_url(config[CONF_PACKAGE_IMPORT_URL]))
|
url = config[CONF_PACKAGE_IMPORT_URL]
|
||||||
|
if config[CONF_IMPORT_FULL_CONFIG]:
|
||||||
|
url += "?full_config"
|
||||||
|
cg.add(dashboard_import_ns.set_package_import_url(url))
|
||||||
|
|
||||||
|
|
||||||
def import_config(
|
def import_config(
|
||||||
@@ -64,17 +85,30 @@ def import_config(
|
|||||||
encoding="utf8",
|
encoding="utf8",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
config = {
|
git_file = git.GitFile.from_shorthand(import_url)
|
||||||
"substitutions": {"name": name},
|
|
||||||
"packages": {project_name: import_url},
|
|
||||||
"esphome": {
|
|
||||||
"name": "${name}",
|
|
||||||
"name_add_mac_suffix": False,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
output = dump(config)
|
|
||||||
|
|
||||||
if network == CONF_WIFI:
|
if git_file.query and "full_config" in git_file.query:
|
||||||
output += WIFI_CONFIG
|
url = git_file.raw_url
|
||||||
|
try:
|
||||||
|
req = requests.get(url, timeout=30)
|
||||||
|
req.raise_for_status()
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
raise ValueError(f"Error while fetching {url}: {e}") from e
|
||||||
|
|
||||||
p.write_text(output, encoding="utf8")
|
p.write_text(req.text, encoding="utf8")
|
||||||
|
|
||||||
|
else:
|
||||||
|
config = {
|
||||||
|
"substitutions": {"name": name},
|
||||||
|
"packages": {project_name: import_url},
|
||||||
|
"esphome": {
|
||||||
|
"name": "${name}",
|
||||||
|
"name_add_mac_suffix": False,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output = dump(config)
|
||||||
|
|
||||||
|
if network == CONF_WIFI:
|
||||||
|
output += WIFI_CONFIG
|
||||||
|
|
||||||
|
p.write_text(output, encoding="utf8")
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import esphome.config_validation as cv
|
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
import esphome.final_validate as fv
|
||||||
|
from esphome.components import logger
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
|
||||||
CONF_DEVICE,
|
|
||||||
CONF_FREE,
|
|
||||||
CONF_FRAGMENTATION,
|
|
||||||
CONF_BLOCK,
|
CONF_BLOCK,
|
||||||
|
CONF_DEVICE,
|
||||||
|
CONF_FRAGMENTATION,
|
||||||
|
CONF_FREE,
|
||||||
|
CONF_ID,
|
||||||
|
CONF_LEVEL,
|
||||||
|
CONF_LOGGER,
|
||||||
CONF_LOOP_TIME,
|
CONF_LOOP_TIME,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,6 +43,18 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
).extend(cv.polling_component_schema("60s"))
|
).extend(cv.polling_component_schema("60s"))
|
||||||
|
|
||||||
|
|
||||||
|
def _final_validate(_):
|
||||||
|
logger_conf = fv.full_config.get()[CONF_LOGGER]
|
||||||
|
severity = logger.LOG_LEVEL_SEVERITY.index(logger_conf[CONF_LEVEL])
|
||||||
|
if severity < logger.LOG_LEVEL_SEVERITY.index("DEBUG"):
|
||||||
|
raise cv.Invalid(
|
||||||
|
"The debug component requires the logger to be at least at DEBUG level"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|||||||
@@ -38,14 +38,9 @@ static uint32_t get_free_heap() {
|
|||||||
|
|
||||||
void DebugComponent::dump_config() {
|
void DebugComponent::dump_config() {
|
||||||
std::string device_info;
|
std::string device_info;
|
||||||
|
std::string reset_reason;
|
||||||
device_info.reserve(256);
|
device_info.reserve(256);
|
||||||
|
|
||||||
#ifndef ESPHOME_LOG_HAS_DEBUG
|
|
||||||
ESP_LOGE(TAG, "Debug Component requires debug log level!");
|
|
||||||
this->status_set_error();
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, "Debug component:");
|
ESP_LOGCONFIG(TAG, "Debug component:");
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
LOG_TEXT_SENSOR(" ", "Device info", this->device_info_);
|
LOG_TEXT_SENSOR(" ", "Device info", this->device_info_);
|
||||||
@@ -146,7 +141,6 @@ void DebugComponent::dump_config() {
|
|||||||
device_info += "|EFuse MAC: ";
|
device_info += "|EFuse MAC: ";
|
||||||
device_info += mac;
|
device_info += mac;
|
||||||
|
|
||||||
const char *reset_reason;
|
|
||||||
switch (rtc_get_reset_reason(0)) {
|
switch (rtc_get_reset_reason(0)) {
|
||||||
case POWERON_RESET:
|
case POWERON_RESET:
|
||||||
reset_reason = "Power On Reset";
|
reset_reason = "Power On Reset";
|
||||||
@@ -196,7 +190,7 @@ void DebugComponent::dump_config() {
|
|||||||
default:
|
default:
|
||||||
reset_reason = "Unknown Reset Reason";
|
reset_reason = "Unknown Reset Reason";
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason);
|
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
|
||||||
device_info += "|Reset: ";
|
device_info += "|Reset: ";
|
||||||
device_info += reset_reason;
|
device_info += reset_reason;
|
||||||
|
|
||||||
@@ -270,6 +264,8 @@ void DebugComponent::dump_config() {
|
|||||||
device_info += ESP.getResetReason().c_str();
|
device_info += ESP.getResetReason().c_str();
|
||||||
device_info += "|";
|
device_info += "|";
|
||||||
device_info += ESP.getResetInfo().c_str();
|
device_info += ESP.getResetInfo().c_str();
|
||||||
|
|
||||||
|
reset_reason = ESP.getResetReason().c_str();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
@@ -278,6 +274,9 @@ void DebugComponent::dump_config() {
|
|||||||
device_info.resize(255);
|
device_info.resize(255);
|
||||||
this->device_info_->publish_state(device_info);
|
this->device_info_->publish_state(device_info);
|
||||||
}
|
}
|
||||||
|
if (this->reset_reason_ != nullptr) {
|
||||||
|
this->reset_reason_->publish_state(reset_reason);
|
||||||
|
}
|
||||||
#endif // USE_TEXT_SENSOR
|
#endif // USE_TEXT_SENSOR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class DebugComponent : public PollingComponent {
|
|||||||
|
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
void set_device_info_sensor(text_sensor::TextSensor *device_info) { device_info_ = device_info; }
|
void set_device_info_sensor(text_sensor::TextSensor *device_info) { device_info_ = device_info; }
|
||||||
|
void set_reset_reason_sensor(text_sensor::TextSensor *reset_reason) { reset_reason_ = reset_reason; }
|
||||||
#endif // USE_TEXT_SENSOR
|
#endif // USE_TEXT_SENSOR
|
||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
void set_free_sensor(sensor::Sensor *free_sensor) { free_sensor_ = free_sensor; }
|
void set_free_sensor(sensor::Sensor *free_sensor) { free_sensor_ = free_sensor; }
|
||||||
@@ -50,6 +51,7 @@ class DebugComponent : public PollingComponent {
|
|||||||
|
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
text_sensor::TextSensor *device_info_{nullptr};
|
text_sensor::TextSensor *device_info_{nullptr};
|
||||||
|
text_sensor::TextSensor *reset_reason_{nullptr};
|
||||||
#endif // USE_TEXT_SENSOR
|
#endif // USE_TEXT_SENSOR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
from esphome.components import text_sensor
|
from esphome.components import text_sensor
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.const import CONF_DEVICE, ENTITY_CATEGORY_DIAGNOSTIC
|
from esphome.const import (
|
||||||
|
CONF_DEVICE,
|
||||||
|
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
ICON_CHIP,
|
||||||
|
ICON_RESTART,
|
||||||
|
)
|
||||||
|
|
||||||
from . import CONF_DEBUG_ID, DebugComponent
|
from . import CONF_DEBUG_ID, DebugComponent
|
||||||
|
|
||||||
DEPENDENCIES = ["debug"]
|
DEPENDENCIES = ["debug"]
|
||||||
|
|
||||||
|
|
||||||
|
CONF_RESET_REASON = "reset_reason"
|
||||||
CONFIG_SCHEMA = cv.Schema(
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_DEBUG_ID): cv.use_id(DebugComponent),
|
cv.GenerateID(CONF_DEBUG_ID): cv.use_id(DebugComponent),
|
||||||
cv.Optional(CONF_DEVICE): text_sensor.text_sensor_schema(
|
cv.Optional(CONF_DEVICE): text_sensor.text_sensor_schema(
|
||||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC
|
icon=ICON_CHIP,
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_RESET_REASON): text_sensor.text_sensor_schema(
|
||||||
|
icon=ICON_RESTART,
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -24,3 +35,6 @@ async def to_code(config):
|
|||||||
if CONF_DEVICE in config:
|
if CONF_DEVICE in config:
|
||||||
sens = await text_sensor.new_text_sensor(config[CONF_DEVICE])
|
sens = await text_sensor.new_text_sensor(config[CONF_DEVICE])
|
||||||
cg.add(debug_component.set_device_info_sensor(sens))
|
cg.add(debug_component.set_device_info_sensor(sens))
|
||||||
|
if CONF_RESET_REASON in config:
|
||||||
|
sens = await text_sensor.new_text_sensor(config[CONF_RESET_REASON])
|
||||||
|
cg.add(debug_component.set_reset_reason_sensor(sens))
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ void DeepSleepComponent::begin_sleep(bool manual) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Beginning Deep Sleep");
|
ESP_LOGI(TAG, "Beginning Deep Sleep");
|
||||||
if (this->sleep_duration_.has_value())
|
if (this->sleep_duration_.has_value()) {
|
||||||
ESP_LOGI(TAG, "Sleeping for %" PRId64 "us", *this->sleep_duration_);
|
ESP_LOGI(TAG, "Sleeping for %" PRId64 "us", *this->sleep_duration_);
|
||||||
|
}
|
||||||
App.run_safe_shutdown_hooks();
|
App.run_safe_shutdown_hooks();
|
||||||
|
|
||||||
#if defined(USE_ESP32)
|
#if defined(USE_ESP32)
|
||||||
@@ -147,7 +147,7 @@ void DeepSleepComponent::begin_sleep(bool manual) {
|
|||||||
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
|
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
|
||||||
level = !level;
|
level = !level;
|
||||||
}
|
}
|
||||||
esp_deep_sleep_enable_gpio_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()),
|
esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(),
|
||||||
static_cast<esp_deepsleep_gpio_wake_up_mode_t>(level));
|
static_cast<esp_deepsleep_gpio_wake_up_mode_t>(level));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -77,14 +77,16 @@ void DFPlayer::loop() {
|
|||||||
case 0x3A:
|
case 0x3A:
|
||||||
if (argument == 1) {
|
if (argument == 1) {
|
||||||
ESP_LOGI(TAG, "USB loaded");
|
ESP_LOGI(TAG, "USB loaded");
|
||||||
} else if (argument == 2)
|
} else if (argument == 2) {
|
||||||
ESP_LOGI(TAG, "TF Card loaded");
|
ESP_LOGI(TAG, "TF Card loaded");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3B:
|
case 0x3B:
|
||||||
if (argument == 1) {
|
if (argument == 1) {
|
||||||
ESP_LOGI(TAG, "USB unloaded");
|
ESP_LOGI(TAG, "USB unloaded");
|
||||||
} else if (argument == 2)
|
} else if (argument == 2) {
|
||||||
ESP_LOGI(TAG, "TF Card unloaded");
|
ESP_LOGI(TAG, "TF Card unloaded");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3F:
|
case 0x3F:
|
||||||
if (argument == 1) {
|
if (argument == 1) {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
#include "display_color_utils.h"
|
#include "display_color_utils.h"
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
#include "esphome/components/time/real_time_clock.h"
|
#include "esphome/components/time/real_time_clock.h"
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include <dsmr/parser.h>
|
#include <dsmr/parser.h>
|
||||||
#include <dsmr/fields.h>
|
#include <dsmr/fields.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace dsmr {
|
namespace dsmr {
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ektf2232 {
|
namespace ektf2232 {
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
|||||||
|
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
from esphome.components import i2c, touchscreen
|
from esphome.components import i2c, touchscreen
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
@@ -17,10 +17,8 @@ EKTF2232Touchscreen = ektf2232_ns.class_(
|
|||||||
)
|
)
|
||||||
|
|
||||||
CONF_EKTF2232_ID = "ektf2232_id"
|
CONF_EKTF2232_ID = "ektf2232_id"
|
||||||
CONF_INTERRUPT_PIN = "interrupt_pin"
|
|
||||||
CONF_RTS_PIN = "rts_pin"
|
CONF_RTS_PIN = "rts_pin"
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from .const import ( # noqa
|
|||||||
VARIANT_FRIENDLY,
|
VARIANT_FRIENDLY,
|
||||||
VARIANTS,
|
VARIANTS,
|
||||||
)
|
)
|
||||||
from .boards import BOARD_TO_VARIANT
|
from .boards import BOARDS
|
||||||
|
|
||||||
# force import gpio to register pin schema
|
# force import gpio to register pin schema
|
||||||
from .gpio import esp32_pin_to_code # noqa
|
from .gpio import esp32_pin_to_code # noqa
|
||||||
@@ -129,27 +129,27 @@ def _format_framework_espidf_version(ver: cv.Version) -> str:
|
|||||||
# The default/recommended arduino framework version
|
# The default/recommended arduino framework version
|
||||||
# - https://github.com/espressif/arduino-esp32/releases
|
# - https://github.com/espressif/arduino-esp32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
|
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif32
|
||||||
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(1, 0, 6)
|
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(2, 0, 5)
|
||||||
# The platformio/espressif32 version to use for arduino frameworks
|
# The platformio/espressif32 version to use for arduino frameworks
|
||||||
# - https://github.com/platformio/platform-espressif32/releases
|
# - https://github.com/platformio/platform-espressif32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
||||||
ARDUINO_PLATFORM_VERSION = cv.Version(3, 5, 0)
|
ARDUINO_PLATFORM_VERSION = cv.Version(5, 2, 0)
|
||||||
|
|
||||||
# The default/recommended esp-idf framework version
|
# The default/recommended esp-idf framework version
|
||||||
# - https://github.com/espressif/esp-idf/releases
|
# - https://github.com/espressif/esp-idf/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
|
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
|
||||||
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 3, 2)
|
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 2)
|
||||||
# The platformio/espressif32 version to use for esp-idf frameworks
|
# The platformio/espressif32 version to use for esp-idf frameworks
|
||||||
# - https://github.com/platformio/platform-espressif32/releases
|
# - https://github.com/platformio/platform-espressif32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
||||||
ESP_IDF_PLATFORM_VERSION = cv.Version(3, 5, 0)
|
ESP_IDF_PLATFORM_VERSION = cv.Version(5, 2, 0)
|
||||||
|
|
||||||
|
|
||||||
def _arduino_check_versions(value):
|
def _arduino_check_versions(value):
|
||||||
value = value.copy()
|
value = value.copy()
|
||||||
lookups = {
|
lookups = {
|
||||||
"dev": (cv.Version(2, 0, 0), "https://github.com/espressif/arduino-esp32.git"),
|
"dev": (cv.Version(2, 0, 5), "https://github.com/espressif/arduino-esp32.git"),
|
||||||
"latest": (cv.Version(1, 0, 6), None),
|
"latest": (cv.Version(2, 0, 5), None),
|
||||||
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ def _esp_idf_check_versions(value):
|
|||||||
value = value.copy()
|
value = value.copy()
|
||||||
lookups = {
|
lookups = {
|
||||||
"dev": (cv.Version(5, 0, 0), "https://github.com/espressif/esp-idf.git"),
|
"dev": (cv.Version(5, 0, 0), "https://github.com/espressif/esp-idf.git"),
|
||||||
"latest": (cv.Version(4, 3, 2), None),
|
"latest": (cv.Version(4, 4, 2), None),
|
||||||
"recommended": (RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION, None),
|
"recommended": (RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,14 +230,14 @@ def _parse_platform_version(value):
|
|||||||
def _detect_variant(value):
|
def _detect_variant(value):
|
||||||
if CONF_VARIANT not in value:
|
if CONF_VARIANT not in value:
|
||||||
board = value[CONF_BOARD]
|
board = value[CONF_BOARD]
|
||||||
if board not in BOARD_TO_VARIANT:
|
if board not in BOARDS:
|
||||||
raise cv.Invalid(
|
raise cv.Invalid(
|
||||||
"This board is unknown, please set the variant manually",
|
"This board is unknown, please set the variant manually",
|
||||||
path=[CONF_BOARD],
|
path=[CONF_BOARD],
|
||||||
)
|
)
|
||||||
|
|
||||||
value = value.copy()
|
value = value.copy()
|
||||||
value[CONF_VARIANT] = BOARD_TO_VARIANT[board]
|
value[CONF_VARIANT] = BOARDS[board][KEY_VARIANT]
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -327,6 +327,11 @@ async def to_code(config):
|
|||||||
"platform_packages",
|
"platform_packages",
|
||||||
[f"platformio/framework-espidf @ {conf[CONF_SOURCE]}"],
|
[f"platformio/framework-espidf @ {conf[CONF_SOURCE]}"],
|
||||||
)
|
)
|
||||||
|
# platformio/toolchain-esp32ulp does not support linux_aarch64 yet and has not been updated for over 2 years
|
||||||
|
# This is espressif's own published version which is more up to date.
|
||||||
|
cg.add_platformio_option(
|
||||||
|
"platform_packages", ["espressif/toolchain-esp32ulp @ 2.35.0-20220830"]
|
||||||
|
)
|
||||||
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False)
|
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False)
|
||||||
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True)
|
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True)
|
||||||
add_idf_sdkconfig_option(
|
add_idf_sdkconfig_option(
|
||||||
@@ -393,11 +398,11 @@ spiffs, data, spiffs, 0x391000, 0x00F000
|
|||||||
|
|
||||||
IDF_PARTITIONS_CSV = """\
|
IDF_PARTITIONS_CSV = """\
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, , 0x4000,
|
|
||||||
otadata, data, ota, , 0x2000,
|
otadata, data, ota, , 0x2000,
|
||||||
phy_init, data, phy, , 0x1000,
|
phy_init, data, phy, , 0x1000,
|
||||||
app0, app, ota_0, , 0x1C0000,
|
app0, app, ota_0, , 0x1C0000,
|
||||||
app1, app, ota_1, , 0x1C0000,
|
app1, app, ota_1, , 0x1C0000,
|
||||||
|
nvs, data, nvs, , 0x6d000,
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .const import VARIANT_ESP32, VARIANT_ESP32S2, VARIANT_ESP32C3
|
from .const import VARIANT_ESP32, VARIANT_ESP32S2, VARIANT_ESP32C3, VARIANT_ESP32S3
|
||||||
|
|
||||||
ESP32_BASE_PINS = {
|
ESP32_BASE_PINS = {
|
||||||
"TX": 1,
|
"TX": 1,
|
||||||
@@ -42,6 +42,64 @@ ESP32_BASE_PINS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ESP32_BOARD_PINS = {
|
ESP32_BOARD_PINS = {
|
||||||
|
"adafruit_qtpy_esp32c3": {
|
||||||
|
"A0": 4,
|
||||||
|
"A1": 3,
|
||||||
|
"A2": 1,
|
||||||
|
"A3": 0,
|
||||||
|
"SDA": 5,
|
||||||
|
"SCL": 6,
|
||||||
|
"MOSI": 7,
|
||||||
|
"MISO": 8,
|
||||||
|
"SCK": 10,
|
||||||
|
"RX": 20,
|
||||||
|
"TX": 21,
|
||||||
|
"NEOPIXEL": 2,
|
||||||
|
"PIN_NEOPIXEL": 2,
|
||||||
|
"BUTTON": 9,
|
||||||
|
"SWITCH": 9,
|
||||||
|
},
|
||||||
|
"adafruit_qtpy_esp32s2": {
|
||||||
|
"A0": 18,
|
||||||
|
"A1": 17,
|
||||||
|
"A2": 9,
|
||||||
|
"A3": 8,
|
||||||
|
"SDA": 7,
|
||||||
|
"SCL": 6,
|
||||||
|
"MOSI": 35,
|
||||||
|
"MISO": 37,
|
||||||
|
"SCK": 36,
|
||||||
|
"RX": 16,
|
||||||
|
"TX": 5,
|
||||||
|
"SDA1": 41,
|
||||||
|
"SCL1": 40,
|
||||||
|
"NEOPIXEL": 39,
|
||||||
|
"PIN_NEOPIXEL": 39,
|
||||||
|
"NEOPIXEL_POWER": 38,
|
||||||
|
"D0": 0,
|
||||||
|
"BUTTON": 0,
|
||||||
|
"SWITCH": 0,
|
||||||
|
},
|
||||||
|
"adafruit_qtpy_esp32": {
|
||||||
|
"A0": 26,
|
||||||
|
"A1": 25,
|
||||||
|
"A2": 27,
|
||||||
|
"A3": 15,
|
||||||
|
"SDA": 4,
|
||||||
|
"SCL": 33,
|
||||||
|
"MOSI": 13,
|
||||||
|
"MISO": 12,
|
||||||
|
"SCK": 14,
|
||||||
|
"RX": 7,
|
||||||
|
"TX": 32,
|
||||||
|
"SDA1": 22,
|
||||||
|
"SCL1": 19,
|
||||||
|
"NEOPIXEL": 5,
|
||||||
|
"PIN_NEOPIXEL": 5,
|
||||||
|
"NEOPIXEL_POWER": 8,
|
||||||
|
"BUTTON": 0,
|
||||||
|
"SWITCH": 0,
|
||||||
|
},
|
||||||
"alksesp32": {
|
"alksesp32": {
|
||||||
"A0": 32,
|
"A0": 32,
|
||||||
"A1": 33,
|
"A1": 33,
|
||||||
@@ -550,6 +608,25 @@ ESP32_BOARD_PINS = {
|
|||||||
},
|
},
|
||||||
"lolin_d32": {"LED": 5, "_VBAT": 35},
|
"lolin_d32": {"LED": 5, "_VBAT": 35},
|
||||||
"lolin_d32_pro": {"LED": 5, "_VBAT": 35},
|
"lolin_d32_pro": {"LED": 5, "_VBAT": 35},
|
||||||
|
"lolin_s2_mini": {
|
||||||
|
"TX": 43,
|
||||||
|
"RX": 44,
|
||||||
|
"SPICS1": 29,
|
||||||
|
"SPIHD": 31,
|
||||||
|
"SPIWP": 32,
|
||||||
|
"SPICS0": 33,
|
||||||
|
"SPICLK": 34,
|
||||||
|
"SPIQ": 35,
|
||||||
|
"SPID": 36,
|
||||||
|
"MISO": 9,
|
||||||
|
"MOSI": 11,
|
||||||
|
"SCK": 7,
|
||||||
|
"SCL": 35,
|
||||||
|
"SDA": 33,
|
||||||
|
"DAC1": 17,
|
||||||
|
"DAC2": 18,
|
||||||
|
"LED": 15,
|
||||||
|
},
|
||||||
"lopy": {
|
"lopy": {
|
||||||
"A1": 37,
|
"A1": 37,
|
||||||
"A2": 38,
|
"A2": 38,
|
||||||
@@ -984,127 +1061,743 @@ ESP32_BOARD_PINS = {
|
|||||||
"D13": 2,
|
"D13": 2,
|
||||||
},
|
},
|
||||||
"xinabox_cw02": {"LED": 27},
|
"xinabox_cw02": {"LED": 27},
|
||||||
|
"upesy_wroom": {"LED": 2},
|
||||||
|
"upesy_wrover": {"LED": 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
BOARD_TO_VARIANT generated with:
|
BOARDS generated with:
|
||||||
|
|
||||||
git clone https://github.com/platformio/platform-espressif32
|
git clone https://github.com/platformio/platform-espressif32
|
||||||
for x in platform-espressif32/boards/*.json; do
|
for x in platform-espressif32/boards/*.json; do
|
||||||
mcu=$(jq -r .build.mcu <"$x");
|
mcu=$(jq -r .build.mcu <"$x");
|
||||||
|
name=$(jq -r .name <"$x");
|
||||||
fname=$(basename "$x")
|
fname=$(basename "$x")
|
||||||
board="${fname%.*}"
|
board="${fname%.*}"
|
||||||
variant=$(echo "$mcu" | tr '[:lower:]' '[:upper:]')
|
variant=$(echo "$mcu" | tr '[:lower:]' '[:upper:]')
|
||||||
echo " \"$board\": VARIANT_${variant},"
|
echo " \"$board\": {\"name\": \"$name\", \"variant\": VARIANT_${variant},},"
|
||||||
done | sort
|
done | sort
|
||||||
"""
|
"""
|
||||||
|
|
||||||
BOARD_TO_VARIANT = {
|
BOARDS = {
|
||||||
"alksesp32": VARIANT_ESP32,
|
"adafruit_feather_esp32s2_tft": {
|
||||||
"az-delivery-devkit-v4": VARIANT_ESP32,
|
"name": "Adafruit Feather ESP32-S2 TFT",
|
||||||
"bpi-bit": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"briki_abc_esp32": VARIANT_ESP32,
|
},
|
||||||
"briki_mbc-wb_esp32": VARIANT_ESP32,
|
"adafruit_feather_esp32s3": {
|
||||||
"d-duino-32": VARIANT_ESP32,
|
"name": "Adafruit Feather ESP32-S3 2MB PSRAM",
|
||||||
"esp320": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"esp32-c3-devkitm-1": VARIANT_ESP32C3,
|
},
|
||||||
"esp32cam": VARIANT_ESP32,
|
"adafruit_feather_esp32s3_nopsram": {
|
||||||
"esp32-devkitlipo": VARIANT_ESP32,
|
"name": "Adafruit Feather ESP32-S3 No PSRAM",
|
||||||
"esp32dev": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"esp32doit-devkit-v1": VARIANT_ESP32,
|
},
|
||||||
"esp32doit-espduino": VARIANT_ESP32,
|
"adafruit_feather_esp32s3_tft": {
|
||||||
"esp32-evb": VARIANT_ESP32,
|
"name": "Adafruit Feather ESP32-S3 TFT",
|
||||||
"esp32-gateway": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"esp32-poe-iso": VARIANT_ESP32,
|
},
|
||||||
"esp32-poe": VARIANT_ESP32,
|
"adafruit_feather_esp32_v2": {
|
||||||
"esp32-pro": VARIANT_ESP32,
|
"name": "Adafruit Feather ESP32 V2",
|
||||||
"esp32-s2-kaluga-1": VARIANT_ESP32S2,
|
"variant": VARIANT_ESP32,
|
||||||
"esp32-s2-saola-1": VARIANT_ESP32S2,
|
},
|
||||||
"esp32thing_plus": VARIANT_ESP32,
|
"adafruit_funhouse_esp32s2": {
|
||||||
"esp32thing": VARIANT_ESP32,
|
"name": "Adafruit FunHouse",
|
||||||
"esp32vn-iot-uno": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"espea32": VARIANT_ESP32,
|
},
|
||||||
"espectro32": VARIANT_ESP32,
|
"adafruit_itsybitsy_esp32": {
|
||||||
"espino32": VARIANT_ESP32,
|
"name": "Adafruit ItsyBitsy ESP32",
|
||||||
"esp-wrover-kit": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"etboard": VARIANT_ESP32,
|
},
|
||||||
"featheresp32-s2": VARIANT_ESP32S2,
|
"adafruit_magtag29_esp32s2": {
|
||||||
"featheresp32": VARIANT_ESP32,
|
"name": "Adafruit MagTag 2.9",
|
||||||
"firebeetle32": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"fm-devkit": VARIANT_ESP32,
|
},
|
||||||
"frogboard": VARIANT_ESP32,
|
"adafruit_metro_esp32s2": {
|
||||||
"healthypi4": VARIANT_ESP32,
|
"name": "Adafruit Metro ESP32-S2",
|
||||||
"heltec_wifi_kit_32_v2": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"heltec_wifi_kit_32": VARIANT_ESP32,
|
},
|
||||||
"heltec_wifi_lora_32_V2": VARIANT_ESP32,
|
"adafruit_qtpy_esp32c3": {
|
||||||
"heltec_wifi_lora_32": VARIANT_ESP32,
|
"name": "Adafruit QT Py ESP32-C3",
|
||||||
"heltec_wireless_stick_lite": VARIANT_ESP32,
|
"variant": VARIANT_ESP32C3,
|
||||||
"heltec_wireless_stick": VARIANT_ESP32,
|
},
|
||||||
"honeylemon": VARIANT_ESP32,
|
"adafruit_qtpy_esp32": {
|
||||||
"hornbill32dev": VARIANT_ESP32,
|
"name": "Adafruit QT Py ESP32",
|
||||||
"hornbill32minima": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"imbrios-logsens-v1p1": VARIANT_ESP32,
|
},
|
||||||
"inex_openkb": VARIANT_ESP32,
|
"adafruit_qtpy_esp32s2": {
|
||||||
"intorobot": VARIANT_ESP32,
|
"name": "Adafruit QT Py ESP32-S2",
|
||||||
"iotaap_magnolia": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"iotbusio": VARIANT_ESP32,
|
},
|
||||||
"iotbusproteus": VARIANT_ESP32,
|
"adafruit_qtpy_esp32s3_nopsram": {
|
||||||
"kits-edu": VARIANT_ESP32,
|
"name": "Adafruit QT Py ESP32-S3 No PSRAM",
|
||||||
"labplus_mpython": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"lolin32_lite": VARIANT_ESP32,
|
},
|
||||||
"lolin32": VARIANT_ESP32,
|
"airm2m_core_esp32c3": {
|
||||||
"lolin_c3_mini": VARIANT_ESP32C3,
|
"name": "AirM2M CORE ESP32C3",
|
||||||
"lolin_d32_pro": VARIANT_ESP32,
|
"variant": VARIANT_ESP32C3,
|
||||||
"lolin_d32": VARIANT_ESP32,
|
},
|
||||||
"lopy4": VARIANT_ESP32,
|
"alksesp32": {
|
||||||
"lopy": VARIANT_ESP32,
|
"name": "ALKS ESP32",
|
||||||
"m5stack-atom": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"m5stack-core2": VARIANT_ESP32,
|
},
|
||||||
"m5stack-core-esp32": VARIANT_ESP32,
|
"atmegazero_esp32s2": {
|
||||||
"m5stack-coreink": VARIANT_ESP32,
|
"name": "EspinalLab ATMegaZero ESP32-S2",
|
||||||
"m5stack-fire": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"m5stack-grey": VARIANT_ESP32,
|
},
|
||||||
"m5stack-timer-cam": VARIANT_ESP32,
|
"az-delivery-devkit-v4": {
|
||||||
"m5stick-c": VARIANT_ESP32,
|
"name": "AZ-Delivery ESP-32 Dev Kit C V4",
|
||||||
"magicbit": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"mgbot-iotik32a": VARIANT_ESP32,
|
},
|
||||||
"mgbot-iotik32b": VARIANT_ESP32,
|
"bee_motion_mini": {
|
||||||
"mhetesp32devkit": VARIANT_ESP32,
|
"name": "Smart Bee Motion Mini",
|
||||||
"mhetesp32minikit": VARIANT_ESP32,
|
"variant": VARIANT_ESP32C3,
|
||||||
"microduino-core-esp32": VARIANT_ESP32,
|
},
|
||||||
"nano32": VARIANT_ESP32,
|
"bee_motion": {
|
||||||
"nina_w10": VARIANT_ESP32,
|
"name": "Smart Bee Motion",
|
||||||
"node32s": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S2,
|
||||||
"nodemcu-32s": VARIANT_ESP32,
|
},
|
||||||
"nscreen-32": VARIANT_ESP32,
|
"bee_motion_s3": {
|
||||||
"odroid_esp32": VARIANT_ESP32,
|
"name": "Smart Bee Motion S3",
|
||||||
"onehorse32dev": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"oroca_edubot": VARIANT_ESP32,
|
},
|
||||||
"pico32": VARIANT_ESP32,
|
"bee_s3": {
|
||||||
"piranha_esp32": VARIANT_ESP32,
|
"name": "Smart Bee S3",
|
||||||
"pocket_32": VARIANT_ESP32,
|
"variant": VARIANT_ESP32S3,
|
||||||
"pycom_gpy": VARIANT_ESP32,
|
},
|
||||||
"qchip": VARIANT_ESP32,
|
"bpi-bit": {
|
||||||
"quantum": VARIANT_ESP32,
|
"name": "BPI-Bit",
|
||||||
"sensesiot_weizen": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"sg-o_airMon": VARIANT_ESP32,
|
},
|
||||||
"s_odi_ultra": VARIANT_ESP32,
|
"briki_abc_esp32": {
|
||||||
"sparkfun_lora_gateway_1-channel": VARIANT_ESP32,
|
"name": "Briki ABC (MBC-WB) - ESP32",
|
||||||
"tinypico": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"ttgo-lora32-v1": VARIANT_ESP32,
|
},
|
||||||
"ttgo-lora32-v21": VARIANT_ESP32,
|
"briki_mbc-wb_esp32": {
|
||||||
"ttgo-lora32-v2": VARIANT_ESP32,
|
"name": "Briki MBC-WB - ESP32",
|
||||||
"ttgo-t1": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"ttgo-t7-v13-mini32": VARIANT_ESP32,
|
},
|
||||||
"ttgo-t7-v14-mini32": VARIANT_ESP32,
|
"cnrs_aw2eth": {
|
||||||
"ttgo-t-beam": VARIANT_ESP32,
|
"name": "CNRS AW2ETH",
|
||||||
"ttgo-t-watch": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"turta_iot_node": VARIANT_ESP32,
|
},
|
||||||
"vintlabs-devkit-v1": VARIANT_ESP32,
|
"connaxio_espoir": {
|
||||||
"wemosbat": VARIANT_ESP32,
|
"name": "Connaxio's Espoir",
|
||||||
"wemos_d1_mini32": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
"wesp32": VARIANT_ESP32,
|
},
|
||||||
"widora-air": VARIANT_ESP32,
|
"d-duino-32": {
|
||||||
"wifiduino32": VARIANT_ESP32,
|
"name": "D-duino-32",
|
||||||
"xinabox_cw02": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"deneyapkart1A": {
|
||||||
|
"name": "Deneyap Kart 1A",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"deneyapkartg": {
|
||||||
|
"name": "Deneyap Kart G",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"deneyapkart": {
|
||||||
|
"name": "Deneyap Kart",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"deneyapmini": {
|
||||||
|
"name": "Deneyap Mini",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"denky32": {
|
||||||
|
"name": "Denky32 (WROOM32)",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"denky_d4": {
|
||||||
|
"name": "Denky D4 (PICO-V3-02)",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"dfrobot_beetle_esp32c3": {
|
||||||
|
"name": "DFRobot Beetle ESP32-C3",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"dfrobot_firebeetle2_esp32s3": {
|
||||||
|
"name": "DFRobot Firebeetle 2 ESP32-S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"dpu_esp32": {
|
||||||
|
"name": "TAMC DPU ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp320": {
|
||||||
|
"name": "Electronic SweetPeas ESP320",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-c3-devkitm-1": {
|
||||||
|
"name": "Espressif ESP32-C3-DevKitM-1",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"esp32cam": {
|
||||||
|
"name": "AI Thinker ESP32-CAM",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-devkitlipo": {
|
||||||
|
"name": "OLIMEX ESP32-DevKit-LiPo",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32dev": {
|
||||||
|
"name": "Espressif ESP32 Dev Module",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32doit-devkit-v1": {
|
||||||
|
"name": "DOIT ESP32 DEVKIT V1",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32doit-espduino": {
|
||||||
|
"name": "DOIT ESPduino32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-evb": {
|
||||||
|
"name": "OLIMEX ESP32-EVB",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-gateway": {
|
||||||
|
"name": "OLIMEX ESP32-GATEWAY",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-poe-iso": {
|
||||||
|
"name": "OLIMEX ESP32-PoE-ISO",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-poe": {
|
||||||
|
"name": "OLIMEX ESP32-PoE",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-pro": {
|
||||||
|
"name": "OLIMEX ESP32-PRO",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32-s2-franzininho": {
|
||||||
|
"name": "Franzininho WiFi Board",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"esp32-s2-kaluga-1": {
|
||||||
|
"name": "Espressif ESP32-S2-Kaluga-1 Kit",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"esp32-s2-saola-1": {
|
||||||
|
"name": "Espressif ESP32-S2-Saola-1",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"esp32s3box": {
|
||||||
|
"name": "Espressif ESP32-S3-Box",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"esp32s3camlcd": {
|
||||||
|
"name": "ESP32S3 CAM LCD",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"esp32-s3-devkitc-1": {
|
||||||
|
"name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"esp32thing": {
|
||||||
|
"name": "SparkFun ESP32 Thing",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32thing_plus": {
|
||||||
|
"name": "SparkFun ESP32 Thing Plus",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp32vn-iot-uno": {
|
||||||
|
"name": "ESP32vn IoT Uno",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"espea32": {
|
||||||
|
"name": "April Brother ESPea32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"espectro32": {
|
||||||
|
"name": "ESPectro32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"espino32": {
|
||||||
|
"name": "ESPino32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"esp-wrover-kit": {
|
||||||
|
"name": "Espressif ESP-WROVER-KIT",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"etboard": {
|
||||||
|
"name": "ETBoard",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"featheresp32": {
|
||||||
|
"name": "Adafruit ESP32 Feather",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"featheresp32-s2": {
|
||||||
|
"name": "Adafruit ESP32-S2 Feather Development Board",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"firebeetle32": {
|
||||||
|
"name": "FireBeetle-ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"fm-devkit": {
|
||||||
|
"name": "ESP32 FM DevKit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"franzininho_wifi_esp32s2": {
|
||||||
|
"name": "Franzininho WiFi",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"franzininho_wifi_msc_esp32s2": {
|
||||||
|
"name": "Franzininho WiFi MSC",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"frogboard": {
|
||||||
|
"name": "Frog Board ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"healthypi4": {
|
||||||
|
"name": "ProtoCentral HealthyPi 4",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wifi_kit_32": {
|
||||||
|
"name": "Heltec WiFi Kit 32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wifi_kit_32_v2": {
|
||||||
|
"name": "Heltec WiFi Kit 32 (V2)",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wifi_lora_32": {
|
||||||
|
"name": "Heltec WiFi LoRa 32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wifi_lora_32_V2": {
|
||||||
|
"name": "Heltec WiFi LoRa 32 (V2)",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wireless_stick_lite": {
|
||||||
|
"name": "Heltec Wireless Stick Lite",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"heltec_wireless_stick": {
|
||||||
|
"name": "Heltec Wireless Stick",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"honeylemon": {
|
||||||
|
"name": "HONEYLemon",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"hornbill32dev": {
|
||||||
|
"name": "Hornbill ESP32 Dev",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"hornbill32minima": {
|
||||||
|
"name": "Hornbill ESP32 Minima",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"imbrios-logsens-v1p1": {
|
||||||
|
"name": "Imbrios LogSens V1P1",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"inex_openkb": {
|
||||||
|
"name": "INEX OpenKB",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"intorobot": {
|
||||||
|
"name": "IntoRobot Fig",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"iotaap_magnolia": {
|
||||||
|
"name": "IoTaaP Magnolia",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"iotbusio": {
|
||||||
|
"name": "oddWires IoT-Bus Io",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"iotbusproteus": {
|
||||||
|
"name": "oddWires IoT-Bus Proteus",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"kb32-ft": {
|
||||||
|
"name": "MakerAsia KB32-FT",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"kits-edu": {
|
||||||
|
"name": "KITS ESP32 EDU",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"labplus_mpython": {
|
||||||
|
"name": "Labplus mPython",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lionbit": {
|
||||||
|
"name": "Lion:Bit Dev Board",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lolin32_lite": {
|
||||||
|
"name": "WEMOS LOLIN32 Lite",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lolin32": {
|
||||||
|
"name": "WEMOS LOLIN32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lolin_c3_mini": {
|
||||||
|
"name": "WEMOS LOLIN C3 Mini",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"lolin_d32": {
|
||||||
|
"name": "WEMOS LOLIN D32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lolin_d32_pro": {
|
||||||
|
"name": "WEMOS LOLIN D32 PRO",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lolin_s2_mini": {
|
||||||
|
"name": "WEMOS LOLIN S2 Mini",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"lolin_s2_pico": {
|
||||||
|
"name": "WEMOS LOLIN S2 PICO",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"lolin_s3": {
|
||||||
|
"name": "WEMOS LOLIN S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"lopy4": {
|
||||||
|
"name": "Pycom LoPy4",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"lopy": {
|
||||||
|
"name": "Pycom LoPy",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-atom": {
|
||||||
|
"name": "M5Stack-ATOM",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-core2": {
|
||||||
|
"name": "M5Stack Core2",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-core-esp32": {
|
||||||
|
"name": "M5Stack Core ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-coreink": {
|
||||||
|
"name": "M5Stack-Core Ink",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-fire": {
|
||||||
|
"name": "M5Stack FIRE",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-grey": {
|
||||||
|
"name": "M5Stack GREY ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-station": {
|
||||||
|
"name": "M5Stack Station",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stack-timer-cam": {
|
||||||
|
"name": "M5Stack Timer CAM",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"m5stick-c": {
|
||||||
|
"name": "M5Stick-C",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"magicbit": {
|
||||||
|
"name": "MagicBit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"mgbot-iotik32a": {
|
||||||
|
"name": "MGBOT IOTIK 32A",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"mgbot-iotik32b": {
|
||||||
|
"name": "MGBOT IOTIK 32B",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"mhetesp32devkit": {
|
||||||
|
"name": "MH ET LIVE ESP32DevKIT",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"mhetesp32minikit": {
|
||||||
|
"name": "MH ET LIVE ESP32MiniKit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"microduino-core-esp32": {
|
||||||
|
"name": "Microduino Core ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"micros2": {
|
||||||
|
"name": "microS2",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"minimain_esp32s2": {
|
||||||
|
"name": "Deparment of Alchemy MiniMain ESP32-S2",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"nano32": {
|
||||||
|
"name": "MakerAsia Nano32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"nina_w10": {
|
||||||
|
"name": "u-blox NINA-W10 series",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"node32s": {
|
||||||
|
"name": "Node32s",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"nodemcu-32s2": {
|
||||||
|
"name": "Ai-Thinker NodeMCU-32S2 (ESP-12K)",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"nodemcu-32s": {
|
||||||
|
"name": "NodeMCU-32S",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"nscreen-32": {
|
||||||
|
"name": "YeaCreate NSCREEN-32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"odroid_esp32": {
|
||||||
|
"name": "ODROID-GO",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"onehorse32dev": {
|
||||||
|
"name": "Onehorse ESP32 Dev Module",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"oroca_edubot": {
|
||||||
|
"name": "OROCA EduBot",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"pico32": {
|
||||||
|
"name": "ESP32 Pico Kit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"piranha_esp32": {
|
||||||
|
"name": "Fishino Piranha ESP-32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"pocket_32": {
|
||||||
|
"name": "Dongsen Tech Pocket 32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"pycom_gpy": {
|
||||||
|
"name": "Pycom GPy",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"qchip": {
|
||||||
|
"name": "Qchip",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"quantum": {
|
||||||
|
"name": "Noduino Quantum",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"seeed_xiao_esp32c3": {
|
||||||
|
"name": "Seeed Studio XIAO ESP32C3",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"sensesiot_weizen": {
|
||||||
|
"name": "LOGISENSES Senses Weizen",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"sg-o_airMon": {
|
||||||
|
"name": "SG-O AirMon",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"s_odi_ultra": {
|
||||||
|
"name": "S.ODI Ultra v1",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"sparkfun_esp32_iot_redboard": {
|
||||||
|
"name": "SparkFun ESP32 IoT RedBoard",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"sparkfun_esp32micromod": {
|
||||||
|
"name": "SparkFun ESP32 MicroMod",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"sparkfun_esp32s2_thing_plus_c": {
|
||||||
|
"name": "SparkFun ESP32 Thing Plus C",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"sparkfun_esp32s2_thing_plus": {
|
||||||
|
"name": "SparkFun ESP32-S2 Thing Plus",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"sparkfun_lora_gateway_1-channel": {
|
||||||
|
"name": "SparkFun LoRa Gateway 1-Channel",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"tamc_termod_s3": {
|
||||||
|
"name": "TAMC Termod S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"tinypico": {
|
||||||
|
"name": "Unexpected Maker TinyPICO",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"trueverit-iot-driver-mk2": {
|
||||||
|
"name": "Trueverit ESP32 Universal IoT Driver MK II",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"trueverit-iot-driver-mk3": {
|
||||||
|
"name": "Trueverit ESP32 Universal IoT Driver MK III",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"trueverit-iot-driver": {
|
||||||
|
"name": "Trueverit ESP32 Universal IoT Driver",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-lora32-v1": {
|
||||||
|
"name": "TTGO LoRa32-OLED V1",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-lora32-v21": {
|
||||||
|
"name": "TTGO LoRa32-OLED v2.1.6",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-lora32-v2": {
|
||||||
|
"name": "TTGO LoRa32-OLED V2",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-t1": {
|
||||||
|
"name": "TTGO T1",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-t7-v13-mini32": {
|
||||||
|
"name": "TTGO T7 V1.3 Mini32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-t7-v14-mini32": {
|
||||||
|
"name": "TTGO T7 V1.4 Mini32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-t-beam": {
|
||||||
|
"name": "TTGO T-Beam",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"ttgo-t-oi-plus": {
|
||||||
|
"name": "TTGO T-OI PLUS RISC-V ESP32-C3",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"ttgo-t-watch": {
|
||||||
|
"name": "TTGO T-Watch",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"turta_iot_node": {
|
||||||
|
"name": "Turta IoT Node",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"um_feathers2": {
|
||||||
|
"name": "Unexpected Maker FeatherS2",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"um_feathers2_neo": {
|
||||||
|
"name": "Unexpected Maker FeatherS2 Neo",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"um_feathers3": {
|
||||||
|
"name": "Unexpected Maker FeatherS3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"um_pros3": {
|
||||||
|
"name": "Unexpected Maker PROS3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"um_rmp": {
|
||||||
|
"name": "Unexpected Maker RMP",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"um_tinys2": {
|
||||||
|
"name": "Unexpected Maker TinyS2",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
|
"um_tinys3": {
|
||||||
|
"name": "Unexpected Maker TinyS3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"unphone7": {
|
||||||
|
"name": "unPhone 7",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"unphone8": {
|
||||||
|
"name": "unPhone 8",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"unphone9": {
|
||||||
|
"name": "unPhone 9",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"upesy_wroom": {
|
||||||
|
"name": "uPesy ESP32 Wroom DevKit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"upesy_wrover": {
|
||||||
|
"name": "uPesy ESP32 Wrover DevKit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"vintlabs-devkit-v1": {
|
||||||
|
"name": "VintLabs ESP32 Devkit",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"watchy": {
|
||||||
|
"name": "SQFMI Watchy v2.0",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wemosbat": {
|
||||||
|
"name": "WeMos WiFi and Bluetooth Battery",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wemos_d1_mini32": {
|
||||||
|
"name": "WEMOS D1 MINI ESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wemos_d1_uno32": {
|
||||||
|
"name": "WEMOS D1 R32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wesp32": {
|
||||||
|
"name": "Silicognition wESP32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"widora-air": {
|
||||||
|
"name": "Widora AIR",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wifiduino32c3": {
|
||||||
|
"name": "Blinker WiFiduinoV2 (ESP32-C3)",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
|
"wifiduino32": {
|
||||||
|
"name": "Blinker WiFiduino32",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wifiduino32s3": {
|
||||||
|
"name": "Blinker WiFiduino32S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
|
"wipy3": {
|
||||||
|
"name": "Pycom WiPy3",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"wt32-eth01": {
|
||||||
|
"name": "Wireless-Tag WT32-ETH01 Ethernet Module",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
|
"xinabox_cw02": {
|
||||||
|
"name": "XinaBox CW02",
|
||||||
|
"variant": VARIANT_ESP32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "gpio_idf.h"
|
#include "gpio.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@@ -8,13 +8,11 @@ namespace esp32 {
|
|||||||
|
|
||||||
static const char *const TAG = "esp32";
|
static const char *const TAG = "esp32";
|
||||||
|
|
||||||
bool IDFInternalGPIOPin::isr_service_installed = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
bool ESP32InternalGPIOPin::isr_service_installed = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
|
||||||
static gpio_mode_t IRAM_ATTR flags_to_mode(gpio::Flags flags) {
|
static gpio_mode_t IRAM_ATTR flags_to_mode(gpio::Flags flags) {
|
||||||
flags = (gpio::Flags)(flags & ~(gpio::FLAG_PULLUP | gpio::FLAG_PULLDOWN));
|
flags = (gpio::Flags)(flags & ~(gpio::FLAG_PULLUP | gpio::FLAG_PULLDOWN));
|
||||||
if (flags == gpio::FLAG_NONE) {
|
if (flags == gpio::FLAG_INPUT) {
|
||||||
return GPIO_MODE_DISABLE;
|
|
||||||
} else if (flags == gpio::FLAG_INPUT) {
|
|
||||||
return GPIO_MODE_INPUT;
|
return GPIO_MODE_INPUT;
|
||||||
} else if (flags == gpio::FLAG_OUTPUT) {
|
} else if (flags == gpio::FLAG_OUTPUT) {
|
||||||
return GPIO_MODE_OUTPUT;
|
return GPIO_MODE_OUTPUT;
|
||||||
@@ -25,7 +23,7 @@ static gpio_mode_t IRAM_ATTR flags_to_mode(gpio::Flags flags) {
|
|||||||
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_OUTPUT)) {
|
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_OUTPUT)) {
|
||||||
return GPIO_MODE_INPUT_OUTPUT;
|
return GPIO_MODE_INPUT_OUTPUT;
|
||||||
} else {
|
} else {
|
||||||
// unsupported
|
// unsupported or gpio::FLAG_NONE
|
||||||
return GPIO_MODE_DISABLE;
|
return GPIO_MODE_DISABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,14 +33,14 @@ struct ISRPinArg {
|
|||||||
bool inverted;
|
bool inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
ISRInternalGPIOPin IDFInternalGPIOPin::to_isr() const {
|
ISRInternalGPIOPin ESP32InternalGPIOPin::to_isr() const {
|
||||||
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
arg->pin = pin_;
|
arg->pin = pin_;
|
||||||
arg->inverted = inverted_;
|
arg->inverted = inverted_;
|
||||||
return ISRInternalGPIOPin((void *) arg);
|
return ISRInternalGPIOPin((void *) arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDFInternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
|
void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
|
||||||
gpio_int_type_t idf_type = GPIO_INTR_ANYEDGE;
|
gpio_int_type_t idf_type = GPIO_INTR_ANYEDGE;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case gpio::INTERRUPT_RISING_EDGE:
|
case gpio::INTERRUPT_RISING_EDGE:
|
||||||
@@ -74,13 +72,13 @@ void IDFInternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio:
|
|||||||
gpio_isr_handler_add(pin_, func, arg);
|
gpio_isr_handler_add(pin_, func, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IDFInternalGPIOPin::dump_summary() const {
|
std::string ESP32InternalGPIOPin::dump_summary() const {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
snprintf(buffer, sizeof(buffer), "GPIO%u", static_cast<uint32_t>(pin_));
|
snprintf(buffer, sizeof(buffer), "GPIO%u", static_cast<uint32_t>(pin_));
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDFInternalGPIOPin::setup() {
|
void ESP32InternalGPIOPin::setup() {
|
||||||
gpio_config_t conf{};
|
gpio_config_t conf{};
|
||||||
conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(pin_);
|
conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(pin_);
|
||||||
conf.mode = flags_to_mode(flags_);
|
conf.mode = flags_to_mode(flags_);
|
||||||
@@ -88,14 +86,16 @@ void IDFInternalGPIOPin::setup() {
|
|||||||
conf.pull_down_en = flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
|
conf.pull_down_en = flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
|
||||||
conf.intr_type = GPIO_INTR_DISABLE;
|
conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
gpio_config(&conf);
|
gpio_config(&conf);
|
||||||
gpio_set_drive_capability(pin_, drive_strength_);
|
if (flags_ & gpio::FLAG_OUTPUT) {
|
||||||
|
gpio_set_drive_capability(pin_, drive_strength_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDFInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
|
||||||
// can't call gpio_config here because that logs in esp-idf which may cause issues
|
// can't call gpio_config here because that logs in esp-idf which may cause issues
|
||||||
gpio_set_direction(pin_, flags_to_mode(flags));
|
gpio_set_direction(pin_, flags_to_mode(flags));
|
||||||
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
||||||
if (flags & (gpio::FLAG_PULLUP | gpio::FLAG_PULLDOWN)) {
|
if ((flags & gpio::FLAG_PULLUP) && (flags & gpio::FLAG_PULLDOWN)) {
|
||||||
pull_mode = GPIO_PULLUP_PULLDOWN;
|
pull_mode = GPIO_PULLUP_PULLDOWN;
|
||||||
} else if (flags & gpio::FLAG_PULLUP) {
|
} else if (flags & gpio::FLAG_PULLUP) {
|
||||||
pull_mode = GPIO_PULLUP_ONLY;
|
pull_mode = GPIO_PULLUP_ONLY;
|
||||||
@@ -105,9 +105,9 @@ void IDFInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|||||||
gpio_set_pull_mode(pin_, pull_mode);
|
gpio_set_pull_mode(pin_, pull_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDFInternalGPIOPin::digital_read() { return bool(gpio_get_level(pin_)) != inverted_; }
|
bool ESP32InternalGPIOPin::digital_read() { return bool(gpio_get_level(pin_)) != inverted_; }
|
||||||
void IDFInternalGPIOPin::digital_write(bool value) { gpio_set_level(pin_, value != inverted_ ? 1 : 0); }
|
void ESP32InternalGPIOPin::digital_write(bool value) { gpio_set_level(pin_, value != inverted_ ? 1 : 0); }
|
||||||
void IDFInternalGPIOPin::detach_interrupt() const { gpio_intr_disable(pin_); }
|
void ESP32InternalGPIOPin::detach_interrupt() const { gpio_intr_disable(pin_); }
|
||||||
|
|
||||||
} // namespace esp32
|
} // namespace esp32
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|||||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
||||||
gpio_set_direction(arg->pin, flags_to_mode(flags));
|
gpio_set_direction(arg->pin, flags_to_mode(flags));
|
||||||
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
||||||
if (flags & (gpio::FLAG_PULLUP | gpio::FLAG_PULLDOWN)) {
|
if ((flags & gpio::FLAG_PULLUP) && (flags & gpio::FLAG_PULLDOWN)) {
|
||||||
pull_mode = GPIO_PULLUP_PULLDOWN;
|
pull_mode = GPIO_PULLUP_PULLDOWN;
|
||||||
} else if (flags & gpio::FLAG_PULLUP) {
|
} else if (flags & gpio::FLAG_PULLUP) {
|
||||||
pull_mode = GPIO_PULLUP_ONLY;
|
pull_mode = GPIO_PULLUP_ONLY;
|
||||||
@@ -140,4 +140,4 @@ void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ESP32_FRAMEWORK_ESP_IDF
|
#endif // USE_ESP32
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
#ifdef USE_ESP32
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32 {
|
namespace esp32 {
|
||||||
|
|
||||||
class IDFInternalGPIOPin : public InternalGPIOPin {
|
class ESP32InternalGPIOPin : public InternalGPIOPin {
|
||||||
public:
|
public:
|
||||||
void set_pin(gpio_num_t pin) { pin_ = pin; }
|
void set_pin(gpio_num_t pin) { pin_ = pin; }
|
||||||
void set_inverted(bool inverted) { inverted_ = inverted; }
|
void set_inverted(bool inverted) { inverted_ = inverted; }
|
||||||
@@ -37,4 +37,4 @@ class IDFInternalGPIOPin : public InternalGPIOPin {
|
|||||||
} // namespace esp32
|
} // namespace esp32
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ESP32_FRAMEWORK_ESP_IDF
|
#endif // USE_ESP32
|
||||||
@@ -38,8 +38,7 @@ from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_support
|
|||||||
from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports
|
from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports
|
||||||
|
|
||||||
|
|
||||||
IDFInternalGPIOPin = esp32_ns.class_("IDFInternalGPIOPin", cg.InternalGPIOPin)
|
ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin)
|
||||||
ArduinoInternalGPIOPin = esp32_ns.class_("ArduinoInternalGPIOPin", cg.InternalGPIOPin)
|
|
||||||
|
|
||||||
|
|
||||||
def _lookup_pin(value):
|
def _lookup_pin(value):
|
||||||
@@ -108,6 +107,10 @@ def validate_gpio_pin(value):
|
|||||||
board = CORE.data[KEY_ESP32][KEY_BOARD]
|
board = CORE.data[KEY_ESP32][KEY_BOARD]
|
||||||
board_pins = boards.ESP32_BOARD_PINS.get(board, {})
|
board_pins = boards.ESP32_BOARD_PINS.get(board, {})
|
||||||
|
|
||||||
|
# Resolved aliased board pins (shorthand when two boards have the same pin configuration)
|
||||||
|
while isinstance(board_pins, str):
|
||||||
|
board_pins = boards.ESP32_BOARD_PINS[board_pins]
|
||||||
|
|
||||||
if value in board_pins.values():
|
if value in board_pins.values():
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -169,18 +172,10 @@ DRIVE_STRENGTHS = {
|
|||||||
gpio_num_t = cg.global_ns.enum("gpio_num_t")
|
gpio_num_t = cg.global_ns.enum("gpio_num_t")
|
||||||
|
|
||||||
|
|
||||||
def _choose_pin_declaration(value):
|
|
||||||
if CORE.using_esp_idf:
|
|
||||||
return cv.declare_id(IDFInternalGPIOPin)(value)
|
|
||||||
if CORE.using_arduino:
|
|
||||||
return cv.declare_id(ArduinoInternalGPIOPin)(value)
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
CONF_DRIVE_STRENGTH = "drive_strength"
|
CONF_DRIVE_STRENGTH = "drive_strength"
|
||||||
ESP32_PIN_SCHEMA = cv.All(
|
ESP32_PIN_SCHEMA = cv.All(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): _choose_pin_declaration,
|
cv.GenerateID(): cv.declare_id(ESP32InternalGPIOPin),
|
||||||
cv.Required(CONF_NUMBER): validate_gpio_pin,
|
cv.Required(CONF_NUMBER): validate_gpio_pin,
|
||||||
cv.Optional(CONF_MODE, default={}): cv.Schema(
|
cv.Optional(CONF_MODE, default={}): cv.Schema(
|
||||||
{
|
{
|
||||||
@@ -192,8 +187,7 @@ ESP32_PIN_SCHEMA = cv.All(
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||||
cv.SplitDefault(CONF_DRIVE_STRENGTH, esp32_idf="20mA"): cv.All(
|
cv.Optional(CONF_DRIVE_STRENGTH, default="20mA"): cv.All(
|
||||||
cv.only_with_esp_idf,
|
|
||||||
cv.float_with_unit("current", "mA", optional_unit=True),
|
cv.float_with_unit("current", "mA", optional_unit=True),
|
||||||
cv.enum(DRIVE_STRENGTHS),
|
cv.enum(DRIVE_STRENGTHS),
|
||||||
),
|
),
|
||||||
@@ -206,10 +200,7 @@ ESP32_PIN_SCHEMA = cv.All(
|
|||||||
async def esp32_pin_to_code(config):
|
async def esp32_pin_to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
num = config[CONF_NUMBER]
|
num = config[CONF_NUMBER]
|
||||||
if CORE.using_esp_idf:
|
cg.add(var.set_pin(getattr(gpio_num_t, f"GPIO_NUM_{num}")))
|
||||||
cg.add(var.set_pin(getattr(gpio_num_t, f"GPIO_NUM_{num}")))
|
|
||||||
else:
|
|
||||||
cg.add(var.set_pin(num))
|
|
||||||
cg.add(var.set_inverted(config[CONF_INVERTED]))
|
cg.add(var.set_inverted(config[CONF_INVERTED]))
|
||||||
if CONF_DRIVE_STRENGTH in config:
|
if CONF_DRIVE_STRENGTH in config:
|
||||||
cg.add(var.set_drive_strength(config[CONF_DRIVE_STRENGTH]))
|
cg.add(var.set_drive_strength(config[CONF_DRIVE_STRENGTH]))
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
|
||||||
|
|
||||||
#include "gpio_arduino.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include <esp32-hal-gpio.h>
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace esp32 {
|
|
||||||
|
|
||||||
static const char *const TAG = "esp32";
|
|
||||||
|
|
||||||
static int IRAM_ATTR flags_to_mode(gpio::Flags flags) {
|
|
||||||
if (flags == gpio::FLAG_INPUT) {
|
|
||||||
return INPUT;
|
|
||||||
} else if (flags == gpio::FLAG_OUTPUT) {
|
|
||||||
return OUTPUT;
|
|
||||||
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
|
|
||||||
return INPUT_PULLUP;
|
|
||||||
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) {
|
|
||||||
return INPUT_PULLDOWN;
|
|
||||||
} else if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) {
|
|
||||||
return OUTPUT_OPEN_DRAIN;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ISRPinArg {
|
|
||||||
uint8_t pin;
|
|
||||||
bool inverted;
|
|
||||||
};
|
|
||||||
|
|
||||||
ISRInternalGPIOPin ArduinoInternalGPIOPin::to_isr() const {
|
|
||||||
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
|
||||||
arg->pin = pin_;
|
|
||||||
arg->inverted = inverted_;
|
|
||||||
return ISRInternalGPIOPin((void *) arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArduinoInternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
|
|
||||||
uint8_t arduino_mode = DISABLED;
|
|
||||||
switch (type) {
|
|
||||||
case gpio::INTERRUPT_RISING_EDGE:
|
|
||||||
arduino_mode = inverted_ ? FALLING : RISING;
|
|
||||||
break;
|
|
||||||
case gpio::INTERRUPT_FALLING_EDGE:
|
|
||||||
arduino_mode = inverted_ ? RISING : FALLING;
|
|
||||||
break;
|
|
||||||
case gpio::INTERRUPT_ANY_EDGE:
|
|
||||||
arduino_mode = CHANGE;
|
|
||||||
break;
|
|
||||||
case gpio::INTERRUPT_LOW_LEVEL:
|
|
||||||
arduino_mode = inverted_ ? ONHIGH : ONLOW;
|
|
||||||
break;
|
|
||||||
case gpio::INTERRUPT_HIGH_LEVEL:
|
|
||||||
arduino_mode = inverted_ ? ONLOW : ONHIGH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachInterruptArg(pin_, func, arg, arduino_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArduinoInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|
||||||
pinMode(pin_, flags_to_mode(flags)); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ArduinoInternalGPIOPin::dump_summary() const {
|
|
||||||
char buffer[32];
|
|
||||||
snprintf(buffer, sizeof(buffer), "GPIO%u", pin_);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArduinoInternalGPIOPin::digital_read() {
|
|
||||||
return bool(digitalRead(pin_)) != inverted_; // NOLINT
|
|
||||||
}
|
|
||||||
void ArduinoInternalGPIOPin::digital_write(bool value) {
|
|
||||||
digitalWrite(pin_, value != inverted_ ? 1 : 0); // NOLINT
|
|
||||||
}
|
|
||||||
void ArduinoInternalGPIOPin::detach_interrupt() const {
|
|
||||||
detachInterrupt(pin_); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace esp32
|
|
||||||
|
|
||||||
using namespace esp32;
|
|
||||||
|
|
||||||
bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
|
|
||||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
|
||||||
return bool(digitalRead(arg->pin)) != arg->inverted; // NOLINT
|
|
||||||
}
|
|
||||||
void IRAM_ATTR ISRInternalGPIOPin::digital_write(bool value) {
|
|
||||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
|
||||||
digitalWrite(arg->pin, value != arg->inverted ? 1 : 0); // NOLINT
|
|
||||||
}
|
|
||||||
void IRAM_ATTR ISRInternalGPIOPin::clear_interrupt() {
|
|
||||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
GPIO.status_w1tc.val = 1UL << arg->pin;
|
|
||||||
#else
|
|
||||||
if (arg->pin < 32) {
|
|
||||||
GPIO.status_w1tc = 1UL << arg->pin;
|
|
||||||
} else {
|
|
||||||
GPIO.status1_w1tc.intr_st = 1UL << (arg->pin - 32);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|
||||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
|
||||||
pinMode(arg->pin, flags_to_mode(flags)); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace esphome
|
|
||||||
|
|
||||||
#endif // USE_ESP32_FRAMEWORK_ARDUINO
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
|
||||||
#include "esphome/core/hal.h"
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace esp32 {
|
|
||||||
|
|
||||||
class ArduinoInternalGPIOPin : public InternalGPIOPin {
|
|
||||||
public:
|
|
||||||
void set_pin(uint8_t pin) { pin_ = pin; }
|
|
||||||
void set_inverted(bool inverted) { inverted_ = inverted; }
|
|
||||||
void set_flags(gpio::Flags flags) { flags_ = flags; }
|
|
||||||
|
|
||||||
void setup() override { pin_mode(flags_); }
|
|
||||||
void pin_mode(gpio::Flags flags) override;
|
|
||||||
bool digital_read() override;
|
|
||||||
void digital_write(bool value) override;
|
|
||||||
std::string dump_summary() const override;
|
|
||||||
void detach_interrupt() const override;
|
|
||||||
ISRInternalGPIOPin to_isr() const override;
|
|
||||||
uint8_t get_pin() const override { return pin_; }
|
|
||||||
bool is_inverted() const override { return inverted_; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
|
|
||||||
|
|
||||||
uint8_t pin_;
|
|
||||||
bool inverted_;
|
|
||||||
gpio::Flags flags_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace esp32
|
|
||||||
} // namespace esphome
|
|
||||||
|
|
||||||
#endif // USE_ESP32_FRAMEWORK_ARDUINO
|
|
||||||
@@ -2,12 +2,14 @@ import esphome.codegen as cg
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"]
|
CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"]
|
||||||
|
|
||||||
|
NO_BLUTOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
||||||
|
|
||||||
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
||||||
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)
|
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)
|
||||||
|
|
||||||
@@ -19,6 +21,15 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_variant(_):
|
||||||
|
variant = get_esp32_variant()
|
||||||
|
if variant in NO_BLUTOOTH_VARIANTS:
|
||||||
|
raise cv.Invalid(f"{variant} does not support Bluetooth")
|
||||||
|
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = validate_variant
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER
|
from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER
|
||||||
from esphome.core import CORE, TimePeriod
|
from esphome.core import CORE, TimePeriod
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
|
from esphome.components import esp32_ble
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
CONFLICTS_WITH = ["esp32_ble_tracker"]
|
CONFLICTS_WITH = ["esp32_ble_tracker"]
|
||||||
@@ -54,6 +55,8 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
validate_config,
|
validate_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
uuid = config[CONF_UUID].hex
|
uuid = config[CONF_UUID].hex
|
||||||
|
|||||||
@@ -16,7 +16,15 @@ BLECharacteristic::~BLECharacteristic() {
|
|||||||
delete desc; // NOLINT(cppcoreguidelines-owning-memory)
|
delete desc; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLECharacteristic::release_descriptors() {
|
||||||
|
this->parsed = false;
|
||||||
|
for (auto &desc : this->descriptors)
|
||||||
|
delete desc; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
this->descriptors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void BLECharacteristic::parse_descriptors() {
|
void BLECharacteristic::parse_descriptors() {
|
||||||
|
this->parsed = true;
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
esp_gattc_descr_elem_t result;
|
esp_gattc_descr_elem_t result;
|
||||||
|
|
||||||
@@ -49,6 +57,8 @@ void BLECharacteristic::parse_descriptors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BLEDescriptor *BLECharacteristic::get_descriptor(espbt::ESPBTUUID uuid) {
|
BLEDescriptor *BLECharacteristic::get_descriptor(espbt::ESPBTUUID uuid) {
|
||||||
|
if (!this->parsed)
|
||||||
|
this->parse_descriptors();
|
||||||
for (auto &desc : this->descriptors) {
|
for (auto &desc : this->descriptors) {
|
||||||
if (desc->uuid == uuid)
|
if (desc->uuid == uuid)
|
||||||
return desc;
|
return desc;
|
||||||
@@ -59,6 +69,8 @@ BLEDescriptor *BLECharacteristic::get_descriptor(uint16_t uuid) {
|
|||||||
return this->get_descriptor(espbt::ESPBTUUID::from_uint16(uuid));
|
return this->get_descriptor(espbt::ESPBTUUID::from_uint16(uuid));
|
||||||
}
|
}
|
||||||
BLEDescriptor *BLECharacteristic::get_descriptor_by_handle(uint16_t handle) {
|
BLEDescriptor *BLECharacteristic::get_descriptor_by_handle(uint16_t handle) {
|
||||||
|
if (!this->parsed)
|
||||||
|
this->parse_descriptors();
|
||||||
for (auto &desc : this->descriptors) {
|
for (auto &desc : this->descriptors) {
|
||||||
if (desc->handle == handle)
|
if (desc->handle == handle)
|
||||||
return desc;
|
return desc;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "ble_descriptor.h"
|
#include "ble_descriptor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_ble_client {
|
namespace esp32_ble_client {
|
||||||
|
|
||||||
@@ -16,11 +18,13 @@ class BLEService;
|
|||||||
class BLECharacteristic {
|
class BLECharacteristic {
|
||||||
public:
|
public:
|
||||||
~BLECharacteristic();
|
~BLECharacteristic();
|
||||||
|
bool parsed = false;
|
||||||
espbt::ESPBTUUID uuid;
|
espbt::ESPBTUUID uuid;
|
||||||
uint16_t handle;
|
uint16_t handle;
|
||||||
esp_gatt_char_prop_t properties;
|
esp_gatt_char_prop_t properties;
|
||||||
std::vector<BLEDescriptor *> descriptors;
|
std::vector<BLEDescriptor *> descriptors;
|
||||||
void parse_descriptors();
|
void parse_descriptors();
|
||||||
|
void release_descriptors();
|
||||||
BLEDescriptor *get_descriptor(espbt::ESPBTUUID uuid);
|
BLEDescriptor *get_descriptor(espbt::ESPBTUUID uuid);
|
||||||
BLEDescriptor *get_descriptor(uint16_t uuid);
|
BLEDescriptor *get_descriptor(uint16_t uuid);
|
||||||
BLEDescriptor *get_descriptor_by_handle(uint16_t handle);
|
BLEDescriptor *get_descriptor_by_handle(uint16_t handle);
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ namespace esphome {
|
|||||||
namespace esp32_ble_client {
|
namespace esp32_ble_client {
|
||||||
|
|
||||||
static const char *const TAG = "esp32_ble_client";
|
static const char *const TAG = "esp32_ble_client";
|
||||||
|
static const esp_bt_uuid_t NOTIFY_DESC_UUID = {
|
||||||
|
.len = ESP_UUID_LEN_16,
|
||||||
|
.uuid =
|
||||||
|
{
|
||||||
|
.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
void BLEClientBase::setup() {
|
void BLEClientBase::setup() {
|
||||||
static uint8_t connection_index = 0;
|
static uint8_t connection_index = 0;
|
||||||
@@ -23,7 +30,9 @@ void BLEClientBase::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLEClientBase::loop() {
|
void BLEClientBase::loop() {
|
||||||
if (this->state_ == espbt::ClientState::DISCOVERED) {
|
// READY_TO_CONNECT means we have discovered the device
|
||||||
|
// and the scanner has been stopped by the tracker.
|
||||||
|
if (this->state_ == espbt::ClientState::READY_TO_CONNECT) {
|
||||||
this->connect();
|
this->connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +60,8 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLEClientBase::connect() {
|
void BLEClientBase::connect() {
|
||||||
ESP_LOGI(TAG, "[%d] [%s] Attempting BLE connection", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGI(TAG, "[%d] [%s] 0x%02x Attempting BLE connection", this->connection_index_, this->address_str_.c_str(),
|
||||||
|
this->remote_addr_type_);
|
||||||
auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_, this->remote_addr_type_, true);
|
auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_, this->remote_addr_type_, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_open error, status=%d", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_open error, status=%d", this->connection_index_, this->address_str_.c_str(),
|
||||||
@@ -63,6 +73,8 @@ void BLEClientBase::connect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLEClientBase::disconnect() {
|
void BLEClientBase::disconnect() {
|
||||||
|
if (this->state_ == espbt::ClientState::IDLE || this->state_ == espbt::ClientState::DISCONNECTING)
|
||||||
|
return;
|
||||||
ESP_LOGI(TAG, "[%d] [%s] Disconnecting.", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGI(TAG, "[%d] [%s] Disconnecting.", this->connection_index_, this->address_str_.c_str());
|
||||||
auto err = esp_ble_gattc_close(this->gattc_if_, this->conn_id_);
|
auto err = esp_ble_gattc_close(this->gattc_if_, this->conn_id_);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
@@ -70,12 +82,24 @@ void BLEClientBase::disconnect() {
|
|||||||
err);
|
err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->state_ == espbt::ClientState::SEARCHING) {
|
if (this->state_ == espbt::ClientState::SEARCHING || this->state_ == espbt::ClientState::READY_TO_CONNECT ||
|
||||||
|
this->state_ == espbt::ClientState::DISCOVERED) {
|
||||||
this->set_address(0);
|
this->set_address(0);
|
||||||
this->set_state(espbt::ClientState::IDLE);
|
this->set_state(espbt::ClientState::IDLE);
|
||||||
|
} else {
|
||||||
|
this->set_state(espbt::ClientState::DISCONNECTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLEClientBase::release_services() {
|
||||||
|
for (auto &svc : this->services_)
|
||||||
|
delete svc; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
this->services_.clear();
|
||||||
|
#ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH
|
||||||
|
esp_ble_gattc_cache_clean(this->remote_bda_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
|
bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
|
||||||
esp_ble_gattc_cb_param_t *param) {
|
esp_ble_gattc_cb_param_t *param) {
|
||||||
if (event == ESP_GATTC_REG_EVT && this->app_id != param->reg.app_id)
|
if (event == ESP_GATTC_REG_EVT && this->app_id != param->reg.app_id)
|
||||||
@@ -101,6 +125,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
case ESP_GATTC_OPEN_EVT: {
|
case ESP_GATTC_OPEN_EVT: {
|
||||||
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_OPEN_EVT", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_OPEN_EVT", this->connection_index_, this->address_str_.c_str());
|
||||||
this->conn_id_ = param->open.conn_id;
|
this->conn_id_ = param->open.conn_id;
|
||||||
|
this->service_count_ = 0;
|
||||||
if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
|
if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Connection failed, status=%d", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGW(TAG, "[%d] [%s] Connection failed, status=%d", this->connection_index_, this->address_str_.c_str(),
|
||||||
param->open.status);
|
param->open.status);
|
||||||
@@ -112,6 +137,12 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_send_mtu_req failed, status=%x", this->connection_index_,
|
||||||
this->address_str_.c_str(), ret);
|
this->address_str_.c_str(), ret);
|
||||||
}
|
}
|
||||||
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
|
||||||
|
this->set_state(espbt::ClientState::CONNECTED);
|
||||||
|
this->state_ = espbt::ClientState::ESTABLISHED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_CFG_MTU_EVT: {
|
case ESP_GATTC_CFG_MTU_EVT: {
|
||||||
@@ -124,7 +155,6 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
ESP_LOGV(TAG, "[%d] [%s] cfg_mtu status %d, mtu %d", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGV(TAG, "[%d] [%s] cfg_mtu status %d, mtu %d", this->connection_index_, this->address_str_.c_str(),
|
||||||
param->cfg_mtu.status, param->cfg_mtu.mtu);
|
param->cfg_mtu.status, param->cfg_mtu.mtu);
|
||||||
this->mtu_ = param->cfg_mtu.mtu;
|
this->mtu_ = param->cfg_mtu.mtu;
|
||||||
esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id, nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_DISCONNECT_EVT: {
|
case ESP_GATTC_DISCONNECT_EVT: {
|
||||||
@@ -132,13 +162,17 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
return false;
|
return false;
|
||||||
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->connection_index_,
|
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->connection_index_,
|
||||||
this->address_str_.c_str(), param->disconnect.reason);
|
this->address_str_.c_str(), param->disconnect.reason);
|
||||||
for (auto &svc : this->services_)
|
this->release_services();
|
||||||
delete svc; // NOLINT(cppcoreguidelines-owning-memory)
|
|
||||||
this->services_.clear();
|
|
||||||
this->set_state(espbt::ClientState::IDLE);
|
this->set_state(espbt::ClientState::IDLE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_SEARCH_RES_EVT: {
|
case ESP_GATTC_SEARCH_RES_EVT: {
|
||||||
|
this->service_count_++;
|
||||||
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
||||||
|
// V3 clients don't need services initialized since
|
||||||
|
// they only request by handle after receiving the services.
|
||||||
|
break;
|
||||||
|
}
|
||||||
BLEService *ble_service = new BLEService(); // NOLINT(cppcoreguidelines-owning-memory)
|
BLEService *ble_service = new BLEService(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
ble_service->uuid = espbt::ESPBTUUID::from_uuid(param->search_res.srvc_id.uuid);
|
ble_service->uuid = espbt::ESPBTUUID::from_uuid(param->search_res.srvc_id.uuid);
|
||||||
ble_service->start_handle = param->search_res.start_handle;
|
ble_service->start_handle = param->search_res.start_handle;
|
||||||
@@ -150,27 +184,49 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||||
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_SEARCH_CMPL_EVT", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_SEARCH_CMPL_EVT", this->connection_index_, this->address_str_.c_str());
|
||||||
for (auto &svc : this->services_) {
|
for (auto &svc : this->services_) {
|
||||||
ESP_LOGI(TAG, "[%d] [%s] Service UUID: %s", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGV(TAG, "[%d] [%s] Service UUID: %s", this->connection_index_, this->address_str_.c_str(),
|
||||||
svc->uuid.to_string().c_str());
|
svc->uuid.to_string().c_str());
|
||||||
ESP_LOGI(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_,
|
ESP_LOGV(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_,
|
||||||
this->address_str_.c_str(), svc->start_handle, svc->end_handle);
|
this->address_str_.c_str(), svc->start_handle, svc->end_handle);
|
||||||
svc->parse_characteristics();
|
|
||||||
}
|
}
|
||||||
this->set_state(espbt::ClientState::CONNECTED);
|
this->set_state(espbt::ClientState::CONNECTED);
|
||||||
this->state_ = espbt::ClientState::ESTABLISHED;
|
this->state_ = espbt::ClientState::ESTABLISHED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
||||||
auto *descr = this->get_config_descriptor(param->reg_for_notify.handle);
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
|
||||||
if (descr->uuid.get_uuid().len != ESP_UUID_LEN_16 ||
|
this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
||||||
descr->uuid.get_uuid().uuid.uuid16 != ESP_GATT_UUID_CHAR_CLIENT_CONFIG) {
|
// Client is responsible for flipping the descriptor value
|
||||||
ESP_LOGW(TAG, "[%d] [%s] Handle 0x%x (uuid %s) is not a client config char uuid", this->connection_index_,
|
// when using the cache
|
||||||
this->address_str_.c_str(), param->reg_for_notify.handle, descr->uuid.to_string().c_str());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint16_t notify_en = 1;
|
esp_gattc_descr_elem_t desc_result;
|
||||||
auto status =
|
uint16_t count = 1;
|
||||||
esp_ble_gattc_write_char_descr(this->gattc_if_, this->conn_id_, descr->handle, sizeof(notify_en),
|
esp_gatt_status_t descr_status =
|
||||||
|
esp_ble_gattc_get_descr_by_char_handle(this->gattc_if_, this->connection_index_, param->reg_for_notify.handle,
|
||||||
|
NOTIFY_DESC_UUID, &desc_result, &count);
|
||||||
|
if (descr_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_get_descr_by_char_handle error, status=%d", this->connection_index_,
|
||||||
|
this->address_str_.c_str(), descr_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
esp_gattc_char_elem_t char_result;
|
||||||
|
esp_gatt_status_t char_status =
|
||||||
|
esp_ble_gattc_get_all_char(this->gattc_if_, this->connection_index_, param->reg_for_notify.handle,
|
||||||
|
param->reg_for_notify.handle, &char_result, &count, 0);
|
||||||
|
if (char_status != ESP_GATT_OK) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->connection_index_,
|
||||||
|
this->address_str_.c_str(), char_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1 = notify
|
||||||
|
2 = indicate
|
||||||
|
*/
|
||||||
|
uint16_t notify_en = char_result.properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY ? 1 : 2;
|
||||||
|
esp_err_t status =
|
||||||
|
esp_ble_gattc_write_char_descr(this->gattc_if_, this->conn_id_, desc_result.handle, sizeof(notify_en),
|
||||||
(uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
|
(uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||||
if (status) {
|
if (status) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->connection_index_,
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, status=%d", this->connection_index_,
|
||||||
@@ -234,14 +290,17 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
|
|||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
return (float) encode_uint16(value[1], value[2]);
|
return (float) encode_uint16(value[1], value[2]);
|
||||||
}
|
}
|
||||||
|
// fall through
|
||||||
case 0x7: // uint24.
|
case 0x7: // uint24.
|
||||||
if (length > 3) {
|
if (length > 3) {
|
||||||
return (float) encode_uint24(value[1], value[2], value[3]);
|
return (float) encode_uint24(value[1], value[2], value[3]);
|
||||||
}
|
}
|
||||||
|
// fall through
|
||||||
case 0x8: // uint32.
|
case 0x8: // uint32.
|
||||||
if (length > 4) {
|
if (length > 4) {
|
||||||
return (float) encode_uint32(value[1], value[2], value[3], value[4]);
|
return (float) encode_uint32(value[1], value[2], value[3], value[4]);
|
||||||
}
|
}
|
||||||
|
// fall through
|
||||||
case 0xC: // int8.
|
case 0xC: // int8.
|
||||||
return (float) ((int8_t) value[1]);
|
return (float) ((int8_t) value[1]);
|
||||||
case 0xD: // int12.
|
case 0xD: // int12.
|
||||||
@@ -249,10 +308,12 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
|
|||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
return (float) ((int16_t)(value[1] << 8) + (int16_t) value[2]);
|
return (float) ((int16_t)(value[1] << 8) + (int16_t) value[2]);
|
||||||
}
|
}
|
||||||
|
// fall through
|
||||||
case 0xF: // int24.
|
case 0xF: // int24.
|
||||||
if (length > 3) {
|
if (length > 3) {
|
||||||
return (float) ((int32_t)(value[1] << 16) + (int32_t)(value[2] << 8) + (int32_t)(value[3]));
|
return (float) ((int32_t)(value[1] << 16) + (int32_t)(value[2] << 8) + (int32_t)(value[3]));
|
||||||
}
|
}
|
||||||
|
// fall through
|
||||||
case 0x10: // int32.
|
case 0x10: // int32.
|
||||||
if (length > 4) {
|
if (length > 4) {
|
||||||
return (float) ((int32_t)(value[1] << 24) + (int32_t)(value[2] << 16) + (int32_t)(value[3] << 8) +
|
return (float) ((int32_t)(value[1] << 24) + (int32_t)(value[2] << 16) + (int32_t)(value[3] << 8) +
|
||||||
@@ -287,6 +348,8 @@ BLECharacteristic *BLEClientBase::get_characteristic(uint16_t service, uint16_t
|
|||||||
|
|
||||||
BLECharacteristic *BLEClientBase::get_characteristic(uint16_t handle) {
|
BLECharacteristic *BLEClientBase::get_characteristic(uint16_t handle) {
|
||||||
for (auto *svc : this->services_) {
|
for (auto *svc : this->services_) {
|
||||||
|
if (!svc->parsed)
|
||||||
|
svc->parse_characteristics();
|
||||||
for (auto *chr : svc->characteristics) {
|
for (auto *chr : svc->characteristics) {
|
||||||
if (chr->handle == handle)
|
if (chr->handle == handle)
|
||||||
return chr;
|
return chr;
|
||||||
@@ -298,8 +361,10 @@ BLECharacteristic *BLEClientBase::get_characteristic(uint16_t handle) {
|
|||||||
BLEDescriptor *BLEClientBase::get_config_descriptor(uint16_t handle) {
|
BLEDescriptor *BLEClientBase::get_config_descriptor(uint16_t handle) {
|
||||||
auto *chr = this->get_characteristic(handle);
|
auto *chr = this->get_characteristic(handle);
|
||||||
if (chr != nullptr) {
|
if (chr != nullptr) {
|
||||||
|
if (!chr->parsed)
|
||||||
|
chr->parse_descriptors();
|
||||||
for (auto &desc : chr->descriptors) {
|
for (auto &desc : chr->descriptors) {
|
||||||
if (desc->uuid.get_uuid().uuid.uuid16 == 0x2902)
|
if (desc->uuid.get_uuid().uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG)
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +388,11 @@ BLEDescriptor *BLEClientBase::get_descriptor(uint16_t service, uint16_t chr, uin
|
|||||||
|
|
||||||
BLEDescriptor *BLEClientBase::get_descriptor(uint16_t handle) {
|
BLEDescriptor *BLEClientBase::get_descriptor(uint16_t handle) {
|
||||||
for (auto *svc : this->services_) {
|
for (auto *svc : this->services_) {
|
||||||
|
if (!svc->parsed)
|
||||||
|
svc->parse_characteristics();
|
||||||
for (auto *chr : svc->characteristics) {
|
for (auto *chr : svc->characteristics) {
|
||||||
|
if (!chr->parsed)
|
||||||
|
chr->parse_descriptors();
|
||||||
for (auto *desc : chr->descriptors) {
|
for (auto *desc : chr->descriptors) {
|
||||||
if (desc->handle == handle)
|
if (desc->handle == handle)
|
||||||
return desc;
|
return desc;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <esp_bt_defs.h>
|
#include <esp_bt_defs.h>
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
@@ -33,6 +34,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
|||||||
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
||||||
void connect() override;
|
void connect() override;
|
||||||
void disconnect();
|
void disconnect();
|
||||||
|
void release_services();
|
||||||
|
|
||||||
bool connected() { return this->state_ == espbt::ClientState::ESTABLISHED; }
|
bool connected() { return this->state_ == espbt::ClientState::ESTABLISHED; }
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
|||||||
memset(this->remote_bda_, 0, sizeof(this->remote_bda_));
|
memset(this->remote_bda_, 0, sizeof(this->remote_bda_));
|
||||||
this->address_str_ = "";
|
this->address_str_ = "";
|
||||||
} else {
|
} else {
|
||||||
this->address_str_ = str_snprintf("%02x:%02x:%02x:%02x:%02x:%02x", 17, (uint8_t)(this->address_ >> 40) & 0xff,
|
this->address_str_ = str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, (uint8_t)(this->address_ >> 40) & 0xff,
|
||||||
(uint8_t)(this->address_ >> 32) & 0xff, (uint8_t)(this->address_ >> 24) & 0xff,
|
(uint8_t)(this->address_ >> 32) & 0xff, (uint8_t)(this->address_ >> 24) & 0xff,
|
||||||
(uint8_t)(this->address_ >> 16) & 0xff, (uint8_t)(this->address_ >> 8) & 0xff,
|
(uint8_t)(this->address_ >> 16) & 0xff, (uint8_t)(this->address_ >> 8) & 0xff,
|
||||||
(uint8_t)(this->address_ >> 0) & 0xff);
|
(uint8_t)(this->address_ >> 0) & 0xff);
|
||||||
@@ -66,11 +68,14 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
|||||||
int get_gattc_if() const { return this->gattc_if_; }
|
int get_gattc_if() const { return this->gattc_if_; }
|
||||||
uint8_t *get_remote_bda() { return this->remote_bda_; }
|
uint8_t *get_remote_bda() { return this->remote_bda_; }
|
||||||
esp_ble_addr_type_t get_remote_addr_type() const { return this->remote_addr_type_; }
|
esp_ble_addr_type_t get_remote_addr_type() const { return this->remote_addr_type_; }
|
||||||
|
void set_remote_addr_type(esp_ble_addr_type_t address_type) { this->remote_addr_type_ = address_type; }
|
||||||
uint16_t get_conn_id() const { return this->conn_id_; }
|
uint16_t get_conn_id() const { return this->conn_id_; }
|
||||||
uint64_t get_address() const { return this->address_; }
|
uint64_t get_address() const { return this->address_; }
|
||||||
|
|
||||||
uint8_t get_connection_index() const { return this->connection_index_; }
|
uint8_t get_connection_index() const { return this->connection_index_; }
|
||||||
|
|
||||||
|
virtual void set_connection_type(espbt::ConnectionType ct) { this->connection_type_ = ct; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int gattc_if_;
|
int gattc_if_;
|
||||||
esp_bd_addr_t remote_bda_;
|
esp_bd_addr_t remote_bda_;
|
||||||
@@ -79,7 +84,9 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
|||||||
uint64_t address_{0};
|
uint64_t address_{0};
|
||||||
std::string address_str_{};
|
std::string address_str_{};
|
||||||
uint8_t connection_index_;
|
uint8_t connection_index_;
|
||||||
|
int16_t service_count_{0};
|
||||||
uint16_t mtu_{23};
|
uint16_t mtu_{23};
|
||||||
|
espbt::ConnectionType connection_type_{espbt::ConnectionType::V1};
|
||||||
|
|
||||||
std::vector<BLEService *> services_;
|
std::vector<BLEService *> services_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace esp32_ble_client {
|
|||||||
static const char *const TAG = "esp32_ble_client";
|
static const char *const TAG = "esp32_ble_client";
|
||||||
|
|
||||||
BLECharacteristic *BLEService::get_characteristic(espbt::ESPBTUUID uuid) {
|
BLECharacteristic *BLEService::get_characteristic(espbt::ESPBTUUID uuid) {
|
||||||
|
if (!this->parsed)
|
||||||
|
this->parse_characteristics();
|
||||||
for (auto &chr : this->characteristics) {
|
for (auto &chr : this->characteristics) {
|
||||||
if (chr->uuid == uuid)
|
if (chr->uuid == uuid)
|
||||||
return chr;
|
return chr;
|
||||||
@@ -27,7 +29,15 @@ BLEService::~BLEService() {
|
|||||||
delete chr; // NOLINT(cppcoreguidelines-owning-memory)
|
delete chr; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLEService::release_characteristics() {
|
||||||
|
this->parsed = false;
|
||||||
|
for (auto &chr : this->characteristics)
|
||||||
|
delete chr; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
this->characteristics.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void BLEService::parse_characteristics() {
|
void BLEService::parse_characteristics() {
|
||||||
|
this->parsed = true;
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
esp_gattc_char_elem_t result;
|
esp_gattc_char_elem_t result;
|
||||||
|
|
||||||
@@ -54,10 +64,9 @@ void BLEService::parse_characteristics() {
|
|||||||
characteristic->handle = result.char_handle;
|
characteristic->handle = result.char_handle;
|
||||||
characteristic->service = this;
|
characteristic->service = this;
|
||||||
this->characteristics.push_back(characteristic);
|
this->characteristics.push_back(characteristic);
|
||||||
ESP_LOGI(TAG, "[%d] [%s] characteristic %s, handle 0x%x, properties 0x%x", this->client->get_connection_index(),
|
ESP_LOGV(TAG, "[%d] [%s] characteristic %s, handle 0x%x, properties 0x%x", this->client->get_connection_index(),
|
||||||
this->client->address_str().c_str(), characteristic->uuid.to_string().c_str(), characteristic->handle,
|
this->client->address_str().c_str(), characteristic->uuid.to_string().c_str(), characteristic->handle,
|
||||||
characteristic->properties);
|
characteristic->properties);
|
||||||
characteristic->parse_descriptors();
|
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "ble_characteristic.h"
|
#include "ble_characteristic.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_ble_client {
|
namespace esp32_ble_client {
|
||||||
|
|
||||||
@@ -16,12 +18,14 @@ class BLEClientBase;
|
|||||||
class BLEService {
|
class BLEService {
|
||||||
public:
|
public:
|
||||||
~BLEService();
|
~BLEService();
|
||||||
|
bool parsed = false;
|
||||||
espbt::ESPBTUUID uuid;
|
espbt::ESPBTUUID uuid;
|
||||||
uint16_t start_handle;
|
uint16_t start_handle;
|
||||||
uint16_t end_handle;
|
uint16_t end_handle;
|
||||||
std::vector<BLECharacteristic *> characteristics;
|
std::vector<BLECharacteristic *> characteristics;
|
||||||
BLEClientBase *client;
|
BLEClientBase *client;
|
||||||
void parse_characteristics();
|
void parse_characteristics();
|
||||||
|
void release_characteristics();
|
||||||
BLECharacteristic *get_characteristic(espbt::ESPBTUUID uuid);
|
BLECharacteristic *get_characteristic(espbt::ESPBTUUID uuid);
|
||||||
BLECharacteristic *get_characteristic(uint16_t uuid);
|
BLECharacteristic *get_characteristic(uint16_t uuid);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "ble_characteristic.h"
|
#include "ble_characteristic.h"
|
||||||
#include "esphome/components/esp32_ble/ble_uuid.h"
|
#include "esphome/components/esp32_ble/ble_uuid.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from esphome.const import (
|
|||||||
)
|
)
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
|
from esphome.components import esp32_ble
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
|
|
||||||
@@ -187,6 +188,8 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
|
||||||
|
|
||||||
ESP_BLE_DEVICE_SCHEMA = cv.Schema(
|
ESP_BLE_DEVICE_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker),
|
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker),
|
||||||
@@ -238,6 +241,11 @@ async def to_code(config):
|
|||||||
|
|
||||||
if CORE.using_esp_idf:
|
if CORE.using_esp_idf:
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
||||||
|
# https://github.com/espressif/esp-idf/issues/4101
|
||||||
|
# https://github.com/espressif/esp-idf/issues/2503
|
||||||
|
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
|
||||||
|
# https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BTU_TASK_STACK_SIZE", 8192)
|
||||||
|
|
||||||
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
|
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ void ESP32BLETracker::setup() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (this->scan_continuous_) {
|
if (this->scan_continuous_) {
|
||||||
this->start_scan_(true);
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
this->start_scan_(true);
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "Cannot start scan!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,86 +87,144 @@ void ESP32BLETracker::loop() {
|
|||||||
ble_event = this->ble_events_.pop();
|
ble_event = this->ble_events_.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->scanner_idle_) {
|
int connecting = 0;
|
||||||
return;
|
int discovered = 0;
|
||||||
}
|
int searching = 0;
|
||||||
|
int disconnecting = 0;
|
||||||
bool connecting = false;
|
|
||||||
for (auto *client : this->clients_) {
|
for (auto *client : this->clients_) {
|
||||||
if (client->state() == ClientState::CONNECTING || client->state() == ClientState::DISCOVERED)
|
switch (client->state()) {
|
||||||
connecting = true;
|
case ClientState::DISCONNECTING:
|
||||||
}
|
disconnecting++;
|
||||||
|
break;
|
||||||
if (!connecting && xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
case ClientState::DISCOVERED:
|
||||||
xSemaphoreGive(this->scan_end_lock_);
|
discovered++;
|
||||||
if (this->scan_continuous_) {
|
break;
|
||||||
this->start_scan_(false);
|
case ClientState::SEARCHING:
|
||||||
} else if (xSemaphoreTake(this->scan_end_lock_, 0L) && !this->scanner_idle_) {
|
searching++;
|
||||||
xSemaphoreGive(this->scan_end_lock_);
|
break;
|
||||||
this->end_of_scan_();
|
case ClientState::CONNECTING:
|
||||||
return;
|
case ClientState::READY_TO_CONNECT:
|
||||||
|
connecting++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool promote_to_connecting = discovered && !searching && !connecting;
|
||||||
|
|
||||||
if (xSemaphoreTake(this->scan_result_lock_, 5L / portTICK_PERIOD_MS)) {
|
if (!this->scanner_idle_) {
|
||||||
uint32_t index = this->scan_result_index_;
|
if (this->scan_result_index_ && // if it looks like we have a scan result we will take the lock
|
||||||
xSemaphoreGive(this->scan_result_lock_);
|
xSemaphoreTake(this->scan_result_lock_, 5L / portTICK_PERIOD_MS)) {
|
||||||
|
uint32_t index = this->scan_result_index_;
|
||||||
|
if (index) {
|
||||||
|
if (index >= 16) {
|
||||||
|
ESP_LOGW(TAG, "Too many BLE events to process. Some devices may not show up.");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < index; i++) {
|
||||||
|
ESPBTDevice device;
|
||||||
|
device.parse_scan_rst(this->scan_result_buffer_[i]);
|
||||||
|
|
||||||
if (index >= 16) {
|
bool found = false;
|
||||||
ESP_LOGW(TAG, "Too many BLE events to process. Some devices may not show up.");
|
for (auto *listener : this->listeners_) {
|
||||||
}
|
if (listener->parse_device(device))
|
||||||
for (size_t i = 0; i < index; i++) {
|
found = true;
|
||||||
ESPBTDevice device;
|
}
|
||||||
device.parse_scan_rst(this->scan_result_buffer_[i]);
|
|
||||||
|
|
||||||
bool found = false;
|
for (auto *client : this->clients_) {
|
||||||
for (auto *listener : this->listeners_) {
|
if (client->parse_device(device)) {
|
||||||
if (listener->parse_device(device))
|
found = true;
|
||||||
found = true;
|
if (!connecting && client->state() == ClientState::DISCOVERED) {
|
||||||
}
|
promote_to_connecting = true;
|
||||||
|
}
|
||||||
for (auto *client : this->clients_) {
|
|
||||||
if (client->parse_device(device)) {
|
|
||||||
found = true;
|
|
||||||
if (client->state() == ClientState::DISCOVERED) {
|
|
||||||
esp_ble_gap_stop_scanning();
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
constexpr TickType_t block_time = 10L / portTICK_PERIOD_MS;
|
|
||||||
#else
|
|
||||||
constexpr TickType_t block_time = 0L; // PR #3594
|
|
||||||
#endif
|
|
||||||
if (xSemaphoreTake(this->scan_end_lock_, block_time)) {
|
|
||||||
xSemaphoreGive(this->scan_end_lock_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found && !this->scan_continuous_) {
|
||||||
|
this->print_bt_device_info(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this->scan_result_index_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
this->print_bt_device_info(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xSemaphoreTake(this->scan_result_lock_, 10L / portTICK_PERIOD_MS)) {
|
|
||||||
this->scan_result_index_ = 0;
|
|
||||||
xSemaphoreGive(this->scan_result_lock_);
|
xSemaphoreGive(this->scan_result_lock_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Avoid starting the scanner if:
|
||||||
|
- we are already scanning
|
||||||
|
- we are connecting to a device
|
||||||
|
- we are disconnecting from a device
|
||||||
|
|
||||||
|
Otherwise the scanner could fail to ever start again
|
||||||
|
and our only way to recover is to reboot.
|
||||||
|
|
||||||
|
https://github.com/espressif/esp-idf/issues/6688
|
||||||
|
|
||||||
|
*/
|
||||||
|
if (!connecting && !disconnecting && xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
if (this->scan_continuous_) {
|
||||||
|
if (!promote_to_connecting && !this->scan_start_failed_ && !this->scan_set_param_failed_) {
|
||||||
|
this->start_scan_(false);
|
||||||
|
} else {
|
||||||
|
// We didn't start the scan, so we need to release the lock
|
||||||
|
xSemaphoreGive(this->scan_end_lock_);
|
||||||
|
}
|
||||||
|
} else if (!this->scanner_idle_) {
|
||||||
|
this->end_of_scan_();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->scan_start_failed_ || this->scan_set_param_failed_) {
|
||||||
|
if (this->scan_start_fail_count_ == 255) {
|
||||||
|
ESP_LOGE(TAG, "ESP-IDF BLE scan could not restart after 255 attempts, rebooting to restore BLE stack...");
|
||||||
|
App.reboot();
|
||||||
|
}
|
||||||
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
xSemaphoreGive(this->scan_end_lock_);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "Stopping scan after failure...");
|
||||||
|
esp_ble_gap_stop_scanning();
|
||||||
|
this->cancel_timeout("scan");
|
||||||
|
}
|
||||||
|
if (this->scan_start_failed_) {
|
||||||
|
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
||||||
|
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (this->scan_set_param_failed_) {
|
||||||
|
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
||||||
|
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->scan_set_param_failed_) {
|
// If there is a discovered client and no connecting
|
||||||
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
// clients and no clients using the scanner to search for
|
||||||
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
// devices, then stop scanning and promote the discovered
|
||||||
}
|
// client to ready to connect.
|
||||||
|
if (promote_to_connecting) {
|
||||||
if (this->scan_start_failed_) {
|
for (auto *client : this->clients_) {
|
||||||
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
if (client->state() == ClientState::DISCOVERED) {
|
||||||
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
// Scanner is not running since we got the
|
||||||
|
// lock, so we can promote the client.
|
||||||
|
xSemaphoreGive(this->scan_end_lock_);
|
||||||
|
// We only want to promote one client at a time.
|
||||||
|
// once the scanner is fully stopped.
|
||||||
|
client->set_state(ClientState::READY_TO_CONNECT);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "Pausing scan to make connection...");
|
||||||
|
esp_ble_gap_stop_scanning();
|
||||||
|
this->cancel_timeout("scan");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32BLETracker::start_scan() {
|
void ESP32BLETracker::start_scan() {
|
||||||
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
xSemaphoreGive(this->scan_end_lock_);
|
|
||||||
this->start_scan_(true);
|
this->start_scan_(true);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "Scan requested when a scan is already in progress. Ignoring.");
|
ESP_LOGW(TAG, "Scan requested when a scan is already in progress. Ignoring.");
|
||||||
@@ -256,8 +318,9 @@ bool ESP32BLETracker::ble_setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ESP32BLETracker::start_scan_(bool first) {
|
void ESP32BLETracker::start_scan_(bool first) {
|
||||||
if (!xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
// The lock must be held when calling this function.
|
||||||
ESP_LOGW(TAG, "Cannot start scan!");
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
ESP_LOGE(TAG, "start_scan called without holding scan_end_lock_");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,14 +341,15 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|||||||
esp_ble_gap_start_scanning(this->scan_duration_);
|
esp_ble_gap_start_scanning(this->scan_duration_);
|
||||||
|
|
||||||
this->set_timeout("scan", this->scan_duration_ * 2000, []() {
|
this->set_timeout("scan", this->scan_duration_ * 2000, []() {
|
||||||
ESP_LOGW(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
|
ESP_LOGE(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
|
||||||
App.reboot();
|
App.reboot();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32BLETracker::end_of_scan_() {
|
void ESP32BLETracker::end_of_scan_() {
|
||||||
if (!xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
// The lock must be held when calling this function.
|
||||||
ESP_LOGW(TAG, "Cannot clean up end of scan!");
|
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
||||||
|
ESP_LOGE(TAG, "end_of_scan_ called without holding the scan_end_lock_");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +401,12 @@ void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t:
|
|||||||
|
|
||||||
void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) {
|
void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) {
|
||||||
this->scan_start_failed_ = param.status;
|
this->scan_start_failed_ = param.status;
|
||||||
|
if (param.status == ESP_BT_STATUS_SUCCESS) {
|
||||||
|
this->scan_start_fail_count_ = 0;
|
||||||
|
} else {
|
||||||
|
this->scan_start_fail_count_++;
|
||||||
|
xSemaphoreGive(this->scan_end_lock_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32BLETracker::gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m) {
|
void ESP32BLETracker::gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m) {
|
||||||
@@ -635,8 +705,9 @@ void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_p
|
|||||||
|
|
||||||
while (offset + 2 < len) {
|
while (offset + 2 < len) {
|
||||||
const uint8_t field_length = payload[offset++]; // First byte is length of adv record
|
const uint8_t field_length = payload[offset++]; // First byte is length of adv record
|
||||||
if (field_length == 0)
|
if (field_length == 0) {
|
||||||
break;
|
continue; // Possible zero padded advertisement data
|
||||||
|
}
|
||||||
|
|
||||||
// first byte of adv record is adv record type
|
// first byte of adv record is adv record type
|
||||||
const uint8_t record_type = payload[offset++];
|
const uint8_t record_type = payload[offset++];
|
||||||
@@ -777,6 +848,9 @@ void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_p
|
|||||||
this->service_datas_.push_back(data);
|
this->service_datas_.push_back(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ESP_BLE_AD_TYPE_INT_RANGE:
|
||||||
|
// Avoid logging this as it's very verbose
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
ESP_LOGV(TAG, "Unhandled type: advType: 0x%02x", record_type);
|
ESP_LOGV(TAG, "Unhandled type: advType: 0x%02x", record_type);
|
||||||
break;
|
break;
|
||||||
@@ -831,8 +905,9 @@ void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, " Address Type: %s", address_type_s);
|
ESP_LOGD(TAG, " Address Type: %s", address_type_s);
|
||||||
if (!device.get_name().empty())
|
if (!device.get_name().empty()) {
|
||||||
ESP_LOGD(TAG, " Name: '%s'", device.get_name().c_str());
|
ESP_LOGD(TAG, " Name: '%s'", device.get_name().c_str());
|
||||||
|
}
|
||||||
for (auto &tx_power : device.get_tx_powers()) {
|
for (auto &tx_power : device.get_tx_powers()) {
|
||||||
ESP_LOGD(TAG, " TX Power: %d", tx_power);
|
ESP_LOGD(TAG, " TX Power: %d", tx_power);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <array>
|
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include <esp_gattc_api.h>
|
#include <esp_gattc_api.h>
|
||||||
#include <esp_bt_defs.h>
|
#include <esp_bt_defs.h>
|
||||||
@@ -143,12 +145,18 @@ class ESPBTDeviceListener {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class ClientState {
|
enum class ClientState {
|
||||||
|
// Connection is allocated
|
||||||
|
INIT,
|
||||||
|
// Client is disconnecting
|
||||||
|
DISCONNECTING,
|
||||||
// Connection is idle, no device detected.
|
// Connection is idle, no device detected.
|
||||||
IDLE,
|
IDLE,
|
||||||
// Searching for device.
|
// Searching for device.
|
||||||
SEARCHING,
|
SEARCHING,
|
||||||
// Device advertisement found.
|
// Device advertisement found.
|
||||||
DISCOVERED,
|
DISCOVERED,
|
||||||
|
// Device is discovered and the scanner is stopped
|
||||||
|
READY_TO_CONNECT,
|
||||||
// Connection in progress.
|
// Connection in progress.
|
||||||
CONNECTING,
|
CONNECTING,
|
||||||
// Initial connection established.
|
// Initial connection established.
|
||||||
@@ -157,6 +165,18 @@ enum class ClientState {
|
|||||||
ESTABLISHED,
|
ESTABLISHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ConnectionType {
|
||||||
|
// The default connection type, we hold all the services in ram
|
||||||
|
// for the duration of the connection.
|
||||||
|
V1,
|
||||||
|
// The client has a cache of the services and mtu so we should not
|
||||||
|
// fetch them again
|
||||||
|
V3_WITH_CACHE,
|
||||||
|
// The client does not need the services and mtu once we send them
|
||||||
|
// so we should wipe them from memory as soon as we send them
|
||||||
|
V3_WITHOUT_CACHE
|
||||||
|
};
|
||||||
|
|
||||||
class ESPBTClient : public ESPBTDeviceListener {
|
class ESPBTClient : public ESPBTDeviceListener {
|
||||||
public:
|
public:
|
||||||
virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||||
@@ -233,6 +253,7 @@ class ESP32BLETracker : public Component {
|
|||||||
uint32_t scan_duration_;
|
uint32_t scan_duration_;
|
||||||
uint32_t scan_interval_;
|
uint32_t scan_interval_;
|
||||||
uint32_t scan_window_;
|
uint32_t scan_window_;
|
||||||
|
uint8_t scan_start_fail_count_;
|
||||||
bool scan_continuous_;
|
bool scan_continuous_;
|
||||||
bool scan_active_;
|
bool scan_active_;
|
||||||
bool scanner_idle_;
|
bool scanner_idle_;
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <mutex>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include <esp_gattc_api.h>
|
#include <esp_gattc_api.h>
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ void ESP32Camera::dump_config() {
|
|||||||
ESP_LOGCONFIG(TAG, " HREF Pin: %d", conf.pin_href);
|
ESP_LOGCONFIG(TAG, " HREF Pin: %d", conf.pin_href);
|
||||||
ESP_LOGCONFIG(TAG, " Pixel Clock Pin: %d", conf.pin_pclk);
|
ESP_LOGCONFIG(TAG, " Pixel Clock Pin: %d", conf.pin_pclk);
|
||||||
ESP_LOGCONFIG(TAG, " External Clock: Pin:%d Frequency:%u", conf.pin_xclk, conf.xclk_freq_hz);
|
ESP_LOGCONFIG(TAG, " External Clock: Pin:%d Frequency:%u", conf.pin_xclk, conf.xclk_freq_hz);
|
||||||
|
#ifdef USE_ESP_IDF // Temporary until the espressif/esp32-camera library is updated
|
||||||
ESP_LOGCONFIG(TAG, " I2C Pins: SDA:%d SCL:%d", conf.pin_sscb_sda, conf.pin_sscb_scl);
|
ESP_LOGCONFIG(TAG, " I2C Pins: SDA:%d SCL:%d", conf.pin_sscb_sda, conf.pin_sscb_scl);
|
||||||
|
#else
|
||||||
|
ESP_LOGCONFIG(TAG, " I2C Pins: SDA:%d SCL:%d", conf.pin_sccb_sda, conf.pin_sccb_scl);
|
||||||
|
#endif
|
||||||
ESP_LOGCONFIG(TAG, " Reset Pin: %d", conf.pin_reset);
|
ESP_LOGCONFIG(TAG, " Reset Pin: %d", conf.pin_reset);
|
||||||
switch (this->config_.frame_size) {
|
switch (this->config_.frame_size) {
|
||||||
case FRAMESIZE_QQVGA:
|
case FRAMESIZE_QQVGA:
|
||||||
@@ -209,8 +213,13 @@ void ESP32Camera::set_external_clock(uint8_t pin, uint32_t frequency) {
|
|||||||
this->config_.xclk_freq_hz = frequency;
|
this->config_.xclk_freq_hz = frequency;
|
||||||
}
|
}
|
||||||
void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
|
void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
|
||||||
|
#ifdef USE_ESP_IDF // Temporary until the espressif/esp32-camera library is updated
|
||||||
this->config_.pin_sscb_sda = sda;
|
this->config_.pin_sscb_sda = sda;
|
||||||
this->config_.pin_sscb_scl = scl;
|
this->config_.pin_sscb_scl = scl;
|
||||||
|
#else
|
||||||
|
this->config_.pin_sccb_sda = sda;
|
||||||
|
this->config_.pin_sccb_scl = scl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
||||||
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user